// Force strict mode and setup for ESM
"use strict";
import {
  isValidSessionId,
  validateAuthMethod
} from "./chunk-A5AG664O.js";
import {
  contextCommand
} from "./chunk-XL5WDTO5.js";
import {
  VSCODE_SHIFT_ENTER_SEQUENCE,
  calculateCost,
  computeSessionStats,
  diffCommand,
  expandCollapsedHistory,
  filterCommandsForMode,
  getSystemInfoFields,
  levelLabel,
  useKeypress,
  writeOsc52
} from "./chunk-RMXPR6HS.js";
import {
  isTerminalGoalStatusKind
} from "./chunk-KSPVDFE4.js";
import {
  Text
} from "./chunk-4FRUXVSE.js";
import {
  require_react
} from "./chunk-KYMBIKIW.js";
import {
  themeManager
} from "./chunk-HTWHAN44.js";
import {
  isKittyProtocolEnabled
} from "./chunk-JZSY4WP3.js";
import {
  getErrorMessage as getErrorMessage2
} from "./chunk-V655JORE.js";
import {
  GITHUB_WORKFLOW_PATHS,
  setupGithub
} from "./chunk-L7QPM2YD.js";
import {
  require_undici
} from "./chunk-54YZOP7P.js";
import {
  stripUnsafeCharacters,
  toCodePoints
} from "./chunk-UVNBI7NN.js";
import {
  getExtendedSystemInfo,
  getGitVersion,
  getNpmVersion
} from "./chunk-PFS2I5LF.js";
import {
  formatDuration,
  formatMemoryUsage,
  formatTokenCount
} from "./chunk-KHDZHZMH.js";
import {
  isInlineModelOverrideAllowed,
  parseAcpModelOption
} from "./chunk-A76FGLIX.js";
import {
  formatUnsupportedVoiceModelMessage,
  getVoiceSettingsScope,
  isSelectableVoiceModel,
  isVoiceEnabled,
  readVoiceMode,
  readVoiceModel
} from "./chunk-YQARVN3E.js";
import {
  OUTPUT_LANGUAGE_AUTO,
  getAllSettingKeys,
  getFlattenedSchema,
  getNestedProperty,
  getPersistScopeForModelSelection,
  getSettingDefinition,
  isAutoLanguage,
  resolveOutputLanguage,
  validateSettingValue,
  writeOutputLanguageAndRegisterPath
} from "./chunk-AFPB2TZB.js";
import {
  SUPPORTED_LANGUAGES,
  getCurrentLanguage,
  getSupportedLanguageIds,
  resolveSupportedLanguage,
  setLanguageAsync,
  t
} from "./chunk-RYT2ET4O.js";
import {
  isFolderTrustEnabled,
  loadTrustedFolders
} from "./chunk-CJSSVQAR.js";
import {
  require_strip_json_comments
} from "./chunk-QYUE6W3T.js";
import {
  ArenaManager,
  BTW_MAX_INPUT_LENGTH,
  ConditionalRulesRegistry,
  EXTENSIONS_CONFIG_FILENAME,
  ExtensionManager,
  IdeClient,
  Logger,
  QWEN_CODE_COMPANION_EXTENSION_NAME,
  SESSION_TITLE_MAX_LENGTH,
  SessionService,
  ShellExecutionService,
  So,
  appendToLastTextPart,
  buildBackgroundEntryLabel,
  buildBareRememberPrompt,
  buildBtwCacheSafeParams,
  buildBtwPrompt,
  buildManagedRememberPrompt,
  canUseRipgrep,
  checkArgumentSafety,
  checkCommandPermissions,
  collectMemoryDiagnostics,
  encodeInsightErrorMessage,
  encodeInsightProgressMessage,
  encodeInsightReadyMessage,
  escapeShellArg,
  findProviderByCredentials,
  flatMapTextParts,
  generateSessionRecap,
  getActiveGoal,
  getArenaSystemReminder,
  getExtensionDescription,
  getExtensionDisplayName,
  getIdeInstaller,
  getInsightPrompt,
  getLastGoalTerminal,
  getMCPServerPrompts,
  getPlanModeSystemReminder,
  getProjectSummaryPrompt,
  getShellConfiguration,
  glob,
  hookEventSupportsMatcher,
  ideContextStore,
  isGitRepository,
  isImageCapable,
  isSuccessStatus,
  isTerminalStatus,
  listSavedWorkflows,
  listWorkflowSnapshots,
  loadServerHierarchicalMemory,
  normalizeClaudeMcpServer,
  normalizeContent,
  normalizeSkillPriority,
  parse,
  parseInstallSource,
  parseVisionModelSetting,
  partToString,
  persistSessionUsage,
  readPathFromWorkspace,
  redactUrlCredentials,
  registerGoalHook,
  require_toml,
  resolveModelId,
  runForkedAgent,
  setGoalTerminalObserver,
  setLastGoalTerminal,
  stripStartupContext,
  tryGenerateSessionTitle,
  unregisterGoalHook
} from "./chunk-IQ7FOOIH.js";
import {
  external_exports
} from "./chunk-K5PGHDBN.js";
import {
  runSideQuery
} from "./chunk-5ES5YPED.js";
import {
  APPROVAL_MODES,
  FORK_SUBAGENT_TYPE
} from "./chunk-LM3YCCZJ.js";
import {
  applySkillAllowedTools,
  buildSkillLlmContent
} from "./chunk-B236XPGF.js";
import {
  HookEventName,
  sanitizeUserPromptExpansionAdditionalContext
} from "./chunk-NVFJSIAX.js";
import {
  IdeConnectionEvent,
  formatTokenUsageSummaryAsCsv,
  formatTokenUsageSummaryAsJson,
  getCurrentGeminiMdFilename,
  getMCPServerStatus,
  logIdeConnection,
  queryTokenUsage,
  read,
  recordSkillInvocation,
  resolveOpenAILogDir,
  uiTelemetryService
} from "./chunk-4IUH45NF.js";
import {
  getAutoMemoryRoot
} from "./chunk-MOUXUCXQ.js";
import {
  ToolNames
} from "./chunk-MJKMIQMK.js";
import {
  openBrowserSecurely
} from "./chunk-22IFUCVR.js";
import {
  REASONING_EFFORT_TIERS,
  normalizeReasoningEffort
} from "./chunk-SIUQ3YYX.js";
import {
  Storage,
  createDebugLogger,
  expandHomeDir,
  getErrorMessage,
  isSubpath,
  resolvePath,
  updateSymlink
} from "./chunk-AVQDCKNF.js";
import {
  isCpuProfileRecording,
  startCpuProfile,
  stopCpuProfile
} from "./chunk-DTPH7UZK.js";
import {
  init_esbuild_shims
} from "./chunk-A4BMJM77.js";
import {
  __name,
  __toESM
} from "./chunk-J2S4EL5Y.js";

// packages/cli/src/ui/utils/commandUtils.ts
init_esbuild_shims();
import { spawn } from "node:child_process";
var CodePage = {
  UTF8: 65001,
  GBK: 936,
  BIG5: 950,
  LATIN1: 1252
};
var isAtCommand = /* @__PURE__ */ __name((query) => (
  // Check if starts with @ OR has a space, then @
  query.startsWith("@") || /\s@/.test(query)
), "isAtCommand");
var SLASH_PATH_SEPARATOR_RE = /[/\\]/;
var getSlashCommandFirstToken = /* @__PURE__ */ __name((query) => query.slice(1).trimStart().split(/\s+/u)[0] ?? "", "getSlashCommandFirstToken");
var hasSlashCommandPathSeparator = /* @__PURE__ */ __name((query) => SLASH_PATH_SEPARATOR_RE.test(getSlashCommandFirstToken(query)), "hasSlashCommandPathSeparator");
var isSlashCommand = /* @__PURE__ */ __name((query) => {
  if (!query.startsWith("/")) {
    return false;
  }
  if (query.startsWith("//")) {
    return false;
  }
  if (query.startsWith("/*")) {
    return false;
  }
  if (hasSlashCommandPathSeparator(query)) {
    return false;
  }
  return true;
}, "isSlashCommand");
var BTW_COMMAND_RE = /^[/?]btw(?:\s|$)/;
var isBtwCommand = /* @__PURE__ */ __name((query) => {
  const trimmed = query.trim();
  return trimmed.length > 0 && BTW_COMMAND_RE.test(trimmed);
}, "isBtwCommand");
var debugLogger = createDebugLogger("COMMAND_UTILS");
var copyToClipboard = /* @__PURE__ */ __name(async (text) => {
  const run = /* @__PURE__ */ __name((cmd, args, options) => new Promise((resolve5, reject) => {
    const child = options ? spawn(cmd, args, options) : spawn(cmd, args);
    let stderr = "";
    if (child.stderr) {
      child.stderr.on("data", (chunk) => stderr += chunk.toString());
    }
    child.on("error", reject);
    child.on("close", (code) => {
      if (code === 0) return resolve5();
      const errorMsg = stderr.trim();
      reject(
        new Error(
          `'${cmd}' exited with code ${code}${errorMsg ? `: ${errorMsg}` : ""}`
        )
      );
    });
    if (child.stdin) {
      child.stdin.on("error", reject);
      child.stdin.write(text);
      child.stdin.end();
    } else {
      reject(new Error("Child process has no stdin stream to write to."));
    }
  }), "run");
  const linuxOptions = { stdio: ["pipe", "inherit", "pipe"] };
  switch (process.platform) {
    case "win32":
      return run("cmd", ["/c", `chcp ${CodePage.UTF8} >nul && clip`]);
    case "darwin":
      return run("pbcopy", []);
    case "linux":
      try {
        await run("xclip", ["-selection", "clipboard"], linuxOptions);
      } catch (primaryError) {
        try {
          await run("xsel", ["--clipboard", "--input"], linuxOptions);
        } catch (fallbackError) {
          const xclipNotFound = primaryError instanceof Error && primaryError.code === "ENOENT";
          const xselNotFound = fallbackError instanceof Error && fallbackError.code === "ENOENT";
          if (xclipNotFound && xselNotFound) {
            if (!writeOsc52(text)) {
              throw new Error(
                "Clipboard unavailable: xclip/xsel not found and OSC 52 requires a TTY. Try running inside a terminal emulator."
              );
            }
            return;
          }
          let primaryMsg = primaryError instanceof Error ? primaryError.message : String(primaryError);
          if (xclipNotFound) {
            primaryMsg = `xclip not found`;
          }
          let fallbackMsg = fallbackError instanceof Error ? fallbackError.message : String(fallbackError);
          if (xselNotFound) {
            fallbackMsg = `xsel not found`;
          }
          if (writeOsc52(text)) return;
          throw new Error(
            `Clipboard unavailable: xclip/xsel failed ("${primaryMsg}", "${fallbackMsg}") and OSC 52 requires a TTY. Try running inside a terminal emulator.`
          );
        }
      }
      return;
    default:
      throw new Error(`Unsupported platform: ${process.platform}`);
  }
}, "copyToClipboard");
var getUrlOpenCommand = /* @__PURE__ */ __name(() => {
  let openCmd;
  switch (process.platform) {
    case "darwin":
      openCmd = "open";
      break;
    case "win32":
      openCmd = "start";
      break;
    case "linux":
      openCmd = "xdg-open";
      break;
    default:
      openCmd = "xdg-open";
      debugLogger.warn(
        `Unknown platform: ${process.platform}. Attempting to open URLs with: ${openCmd}.`
      );
      break;
  }
  return openCmd;
}, "getUrlOpenCommand");
function isMidInputCompletableCommand(cmd) {
  return cmd.modelInvocable === true && !cmd.hidden;
}
__name(isMidInputCompletableCommand, "isMidInputCompletableCommand");
function findMidInputSlashCommand(input, cursorOffset) {
  if (input.startsWith("/")) return null;
  const codePoints = toCodePoints(input);
  const beforeCursor = codePoints.slice(0, cursorOffset).join("");
  const match = beforeCursor.match(/\s\/([a-zA-Z0-9_:-]*)$/);
  if (!match) return null;
  const partialCommand = match[1];
  const slashPos = cursorOffset - 1 - partialCommand.length;
  const textAfterSlash = codePoints.slice(slashPos + 1).join("");
  const commandMatch = textAfterSlash.match(/^[a-zA-Z0-9_:-]*/);
  const fullCommand = commandMatch ? commandMatch[0] : "";
  if (cursorOffset !== slashPos + 1 + fullCommand.length) return null;
  return {
    token: "/" + fullCommand,
    startPos: slashPos,
    partialCommand
  };
}
__name(findMidInputSlashCommand, "findMidInputSlashCommand");
function getBestSlashCommandMatch(partialCommand, commands, recentCommands) {
  if (!partialCommand) return null;
  const query = partialCommand.toLowerCase();
  const matches = commands.filter((cmd) => {
    if (!isMidInputCompletableCommand(cmd)) return false;
    const name = cmd.name.toLowerCase();
    return name.startsWith(query) && (name !== query || !!cmd.argumentHint);
  }).sort((left, right) => {
    const leftRecent = recentCommands?.get(left.name);
    const rightRecent = recentCommands?.get(right.name);
    const recentOrder = (rightRecent?.usedAt ?? 0) - (leftRecent?.usedAt ?? 0);
    return (right.completionPriority ?? 0) - (left.completionPriority ?? 0) || recentOrder || left.name.localeCompare(right.name);
  });
  const best = matches[0];
  if (!best) return null;
  return {
    suffix: best.name.slice(partialCommand.length),
    fullCommand: best.name,
    command: best,
    argumentHint: best.argumentHint
  };
}
__name(getBestSlashCommandMatch, "getBestSlashCommandMatch");
var SLASH_TOKEN_RE = /(?:^|(?<=\s))\/([a-zA-Z][a-zA-Z0-9:_-]*)/g;
function findSlashCommandTokens(text, commands) {
  if (!text) return [];
  const commandMapEntries = [];
  for (const cmd of commands) {
    commandMapEntries.push([cmd.name.toLowerCase(), cmd]);
    for (const altName of cmd.altNames ?? []) {
      commandMapEntries.push([altName.toLowerCase(), cmd]);
    }
  }
  const commandMap = new Map(commandMapEntries);
  const tokens = [];
  let match;
  SLASH_TOKEN_RE.lastIndex = 0;
  while ((match = SLASH_TOKEN_RE.exec(text)) !== null) {
    const fullMatch = match[0];
    const commandName = match[1];
    const start = match.index;
    const end = start + fullMatch.length;
    const precedingChar = start > 0 ? text[start - 1] : null;
    const isLineStart = start === 0 || precedingChar === "\n";
    const cmd = commandMap.get(commandName.toLowerCase());
    let valid = false;
    if (cmd) {
      if (isLineStart) {
        valid = cmd.userInvocable !== false && !cmd.hidden;
      } else {
        valid = cmd.modelInvocable === true;
      }
    }
    tokens.push({ start, end, commandName, valid });
  }
  return tokens;
}
__name(findSlashCommandTokens, "findSlashCommandTokens");

// packages/cli/src/acp-integration/session/HistoryReplayer.ts
init_esbuild_shims();

// packages/cli/src/acp-integration/session/emitters/MessageEmitter.ts
init_esbuild_shims();

// packages/cli/src/acp-integration/session/emitters/BaseEmitter.ts
init_esbuild_shims();
var BaseEmitter = class {
  constructor(ctx) {
    this.ctx = ctx;
  }
  static {
    __name(this, "BaseEmitter");
  }
  /**
   * Converts an ISO timestamp string or epoch ms to epoch ms number.
   * Returns undefined if the input is not a valid timestamp.
   */
  static toEpochMs(ts) {
    if (typeof ts === "number") {
      return Number.isFinite(ts) ? ts : void 0;
    }
    if (typeof ts === "string") {
      const ms = new Date(ts).getTime();
      return Number.isFinite(ms) ? ms : void 0;
    }
    return void 0;
  }
  /**
   * Sends a session update to the ACP client.
   * If a message rewriter is configured, updates pass through it first
   * (original messages are sent as-is, rewritten versions are appended).
   */
  async sendUpdate(update) {
    if (this.ctx.messageRewriter) {
      return this.ctx.messageRewriter.interceptUpdate(update);
    }
    return this.ctx.sendUpdate(update);
  }
  /**
   * Gets the session configuration.
   */
  get config() {
    return this.ctx.config;
  }
  /**
   * Gets the session ID.
   */
  get sessionId() {
    return this.ctx.sessionId;
  }
};

// packages/cli/src/acp-integration/session/emitters/MessageEmitter.ts
var MessageEmitter = class extends BaseEmitter {
  static {
    __name(this, "MessageEmitter");
  }
  /**
   * Emits a StopHookLoop event when Stop hooks create a loop.
   * This informs the client that Stop hooks have been executed multiple times.
   *
   * @param iterationCount - The current iteration count
   * @param reasons - Array of reasons from each Stop hook execution
   * @param stopHookCount - Number of Stop hooks that were executed
   */
  async emitStopHookLoop(iterationCount, reasons, stopHookCount) {
    const activeGoal = getActiveGoal(this.sessionId);
    await this.sendUpdate({
      sessionUpdate: "agent_message_chunk",
      content: { type: "text", text: "" },
      _meta: {
        stopHookLoop: {
          iterationCount,
          reasons,
          stopHookCount,
          ...activeGoal ? {
            goal: {
              condition: activeGoal.condition,
              iterations: activeGoal.iterations,
              setAt: activeGoal.setAt,
              lastReason: activeGoal.lastReason
            }
          } : {}
        }
      }
    });
  }
  async emitGoalTerminal(event) {
    await this.sendUpdate({
      sessionUpdate: "agent_message_chunk",
      content: { type: "text", text: "" },
      _meta: {
        goalTerminal: event
      }
    });
  }
  async emitGoalStatus(status) {
    await this.sendUpdate({
      sessionUpdate: "agent_message_chunk",
      content: { type: "text", text: "" },
      _meta: {
        goalStatus: status
      }
    });
  }
  /**
   * Emits a user message chunk.
   *
   * @param text - The user message text content
   * @param timestamp - Optional server-side timestamp (ISO string or ms) for message ordering
   */
  async emitUserMessage(text, timestamp) {
    const epochMs = BaseEmitter.toEpochMs(timestamp);
    await this.sendUpdate({
      sessionUpdate: "user_message_chunk",
      content: { type: "text", text },
      ...epochMs != null && { _meta: { timestamp: epochMs } }
    });
  }
  /**
   * Emits an agent thought chunk.
   *
   * @param text - The thought text content
   * @param timestamp - Optional server-side timestamp (ISO string or ms) for message ordering
   */
  async emitAgentThought(text, timestamp, subagentMeta) {
    const _meta = this.buildChunkMeta(
      BaseEmitter.toEpochMs(timestamp),
      subagentMeta
    );
    await this.sendUpdate({
      sessionUpdate: "agent_thought_chunk",
      content: { type: "text", text },
      ..._meta ? { _meta } : {}
    });
  }
  /**
   * Emits an agent message chunk.
   *
   * @param text - The agent message text content
   * @param timestamp - Optional server-side timestamp (ISO string or ms) for message ordering
   */
  async emitAgentMessage(text, timestamp, subagentMeta) {
    const _meta = this.buildChunkMeta(
      BaseEmitter.toEpochMs(timestamp),
      subagentMeta
    );
    await this.sendUpdate({
      sessionUpdate: "agent_message_chunk",
      content: { type: "text", text },
      ..._meta ? { _meta } : {}
    });
  }
  /**
   * Emits usage metadata.
   */
  async emitUsageMetadata(usageMetadata, text = "", durationMs, subagentMeta) {
    const usage2 = {
      inputTokens: usageMetadata.promptTokenCount ?? 0,
      outputTokens: usageMetadata.candidatesTokenCount ?? 0,
      totalTokens: usageMetadata.totalTokenCount ?? 0,
      thoughtTokens: usageMetadata.thoughtsTokenCount,
      cachedReadTokens: usageMetadata.cachedContentTokenCount
    };
    const cumulative = this.ctx.cumulativeUsage;
    if (cumulative) {
      const addFinite = /* @__PURE__ */ __name((total, value) => typeof value === "number" && Number.isFinite(value) ? total + value : total, "addFinite");
      cumulative.promptTokens = addFinite(
        cumulative.promptTokens,
        usage2.inputTokens
      );
      cumulative.candidateTokens = addFinite(
        cumulative.candidateTokens,
        usage2.outputTokens
      );
      cumulative.cachedTokens = addFinite(
        cumulative.cachedTokens,
        usage2.cachedReadTokens
      );
      cumulative.apiTimeMs = addFinite(cumulative.apiTimeMs, durationMs);
    }
    const meta = typeof durationMs === "number" ? { usage: usage2, durationMs, ...subagentMeta } : { usage: usage2, ...subagentMeta };
    await this.sendUpdate({
      sessionUpdate: "agent_message_chunk",
      content: { type: "text", text },
      _meta: meta
    });
  }
  /**
   * Emits a message chunk based on role and thought flag.
   * This is the unified method that handles all message types.
   *
   * @param text - The message text content
   * @param role - Whether this is a user or assistant message
   * @param isThought - Whether this is an assistant thought (only applies to assistant role)
   * @param timestamp - Optional server-side timestamp (ISO string or ms) for message ordering
   */
  async emitMessage(text, role, isThought = false, timestamp, subagentMeta) {
    if (role === "user") {
      return this.emitUserMessage(text, timestamp);
    }
    return isThought ? this.emitAgentThought(text, timestamp, subagentMeta) : this.emitAgentMessage(text, timestamp, subagentMeta);
  }
  buildChunkMeta(epochMs, subagentMeta) {
    const meta = {
      ...subagentMeta?.parentToolCallId ? { parentToolCallId: subagentMeta.parentToolCallId } : {},
      ...subagentMeta?.subagentType ? { subagentType: subagentMeta.subagentType } : {},
      ...epochMs != null ? { timestamp: epochMs } : {}
    };
    return Object.keys(meta).length > 0 ? meta : void 0;
  }
};

// packages/cli/src/acp-integration/session/emitters/ToolCallEmitter.ts
init_esbuild_shims();

// packages/cli/src/acp-integration/session/emitters/PlanEmitter.ts
init_esbuild_shims();
var PlanEmitter = class extends BaseEmitter {
  static {
    __name(this, "PlanEmitter");
  }
  /**
   * Emits a plan update with the given todo items.
   *
   * @param todos - Array of todo items to send as plan entries
   */
  async emitPlan(todos) {
    const entries = todos.map((todo) => ({
      content: todo.content,
      priority: "medium",
      // Default priority since todos don't have priority
      status: todo.status
    }));
    const cumulative = this.ctx.cumulativeUsage;
    await this.sendUpdate({
      sessionUpdate: "plan",
      entries,
      ...cumulative ? { _meta: { stats: { ...cumulative } } } : {}
    });
  }
  /**
   * Extracts todos from tool result display or args.
   * Tries multiple sources in priority order:
   * 1. Result display object with type 'todo_list'
   * 2. Result display as JSON string
   * 3. Args with 'todos' array
   *
   * @param resultDisplay - The tool result display (object, string, or undefined)
   * @param args - The tool call arguments (fallback source)
   * @returns Array of todos if found, null otherwise
   */
  extractTodos(resultDisplay, args) {
    const fromDisplay = this.extractFromResultDisplay(resultDisplay);
    if (fromDisplay) return fromDisplay;
    if (args && Array.isArray(args["todos"])) {
      return args["todos"];
    }
    return null;
  }
  /**
   * Extracts todos from a result display value.
   * Handles both object and JSON string formats.
   */
  extractFromResultDisplay(resultDisplay) {
    if (!resultDisplay) return null;
    if (typeof resultDisplay === "object") {
      const obj = resultDisplay;
      if (obj["type"] === "todo_list" && Array.isArray(obj["todos"])) {
        return obj["todos"];
      }
    }
    if (typeof resultDisplay === "string") {
      try {
        const parsed = JSON.parse(resultDisplay);
        if (parsed?.["type"] === "todo_list" && Array.isArray(parsed["todos"])) {
          return parsed["todos"];
        }
      } catch {
      }
    }
    return null;
  }
};

// packages/cli/src/utils/truncatedDiffPreview.ts
init_esbuild_shims();
function buildTruncatedDiffPreviewText(display) {
  const fileName = typeof display["fileName"] === "string" ? display["fileName"] : "the edited file";
  const fileDiffLength = typeof display["fileDiffLength"] === "number" ? ` Original fileDiff length: ${display["fileDiffLength"]} chars.` : "";
  if (display["fileDiffTruncated"] === true) {
    return `Full diff omitted from saved session history for ${fileName}.${fileDiffLength}`;
  }
  return `Saved session preview only for ${fileName}; full original and new file contents are unavailable.`;
}
__name(buildTruncatedDiffPreviewText, "buildTruncatedDiffPreviewText");

// packages/cli/src/acp-integration/session/emitters/ToolCallEmitter.ts
var KIND_MAP = {
  ["read" /* Read */]: "read",
  ["edit" /* Edit */]: "edit",
  ["delete" /* Delete */]: "delete",
  ["move" /* Move */]: "move",
  ["search" /* Search */]: "search",
  ["execute" /* Execute */]: "execute",
  ["think" /* Think */]: "think",
  ["fetch" /* Fetch */]: "fetch",
  // ACP defines no 'agent' ToolKind (verified through @agentclientprotocol/sdk
  // 0.25.1). The daemon's ClientSideConnection Zod-validates every session/update
  // and session/request_permission from the `qwen --acp` child before fanning out
  // to SSE clients, so emitting 'agent' is rejected at that hop and the frame is
  // dropped. Map the internal Kind.Agent to 'other' on the wire to stay
  // protocol-valid; dedicated agent UI is delivered out-of-band (via _meta.toolName)
  // in a follow-up rather than via a kind the protocol can't carry.
  ["agent" /* Agent */]: "other",
  ["other" /* Other */]: "other"
};
var ToolCallEmitter = class _ToolCallEmitter extends BaseEmitter {
  static {
    __name(this, "ToolCallEmitter");
  }
  planEmitter;
  constructor(ctx) {
    super(ctx);
    this.planEmitter = new PlanEmitter(ctx);
  }
  /**
   * Emits a tool call start event.
   *
   * @param params - Tool call start parameters
   * @returns true if event was emitted, false if skipped (e.g., TodoWriteTool)
   */
  async emitStart(params) {
    if (this.isTodoWriteTool(params.toolName)) {
      return false;
    }
    const { title, locations, kind } = this.resolveToolMetadata(
      params.toolName,
      params.args
    );
    const provenance = _ToolCallEmitter.resolveToolProvenance(
      params.toolName,
      params.subagentMeta
    );
    await this.sendUpdate({
      sessionUpdate: "tool_call",
      toolCallId: params.callId,
      status: params.status || "pending",
      title,
      content: [],
      locations,
      kind,
      rawInput: params.args ?? {},
      _meta: {
        toolName: params.toolName,
        ...params.subagentMeta,
        provenance: provenance.provenance,
        ...provenance.serverId ? { serverId: provenance.serverId } : {},
        ...BaseEmitter.toEpochMs(params.timestamp) != null && {
          timestamp: BaseEmitter.toEpochMs(params.timestamp)
        }
      }
    });
    return true;
  }
  /**
   * Emits a tool call result event.
   * Handles TodoWriteTool specially by routing to plan updates.
   *
   * @param params - Tool call result parameters
   */
  async emitResult(params) {
    if (this.isTodoWriteTool(params.toolName)) {
      const todos = this.planEmitter.extractTodos(
        params.resultDisplay,
        params.args
      );
      if (todos && todos.length > 0) {
        await this.planEmitter.emitPlan(todos);
      } else if (params.args && Array.isArray(params.args["todos"])) {
        await this.planEmitter.emitPlan([]);
      }
      return;
    }
    let contentArray = [];
    const diffContent = this.extractDiffContent(params.resultDisplay);
    if (diffContent) {
      contentArray = [diffContent];
    } else if (params.error) {
      contentArray = [
        {
          type: "content",
          content: { type: "text", text: params.error.message }
        }
      ];
    } else {
      contentArray = this.transformPartsToToolCallContent(params.message);
    }
    const provenance = _ToolCallEmitter.resolveToolProvenance(
      params.toolName,
      params.subagentMeta
    );
    const update = {
      sessionUpdate: "tool_call_update",
      toolCallId: params.callId,
      status: params.success ? "completed" : "failed",
      content: contentArray,
      _meta: {
        toolName: params.toolName,
        ...params.subagentMeta,
        provenance: provenance.provenance,
        ...provenance.serverId ? { serverId: provenance.serverId } : {},
        ...BaseEmitter.toEpochMs(params.timestamp) != null && {
          timestamp: BaseEmitter.toEpochMs(params.timestamp)
        },
        ...params.artifacts && params.artifacts.length > 0 ? { artifacts: params.artifacts } : {}
      }
    };
    if (params.resultDisplay !== void 0 && !this.isTruncatedSessionDiffDisplay(params.resultDisplay)) {
      update["rawOutput"] = params.resultDisplay;
    }
    await this.sendUpdate(update);
  }
  /**
   * Emits a tool call error event.
   * Use this for explicit error handling when not using emitResult.
   *
   * @param callId - The tool call ID
   * @param toolName - The tool name
   * @param error - The error that occurred
   * @param subagentMeta - Optional subagent metadata
   */
  async emitError(callId, toolName, error, subagentMeta) {
    const provenance = _ToolCallEmitter.resolveToolProvenance(
      toolName,
      subagentMeta
    );
    await this.sendUpdate({
      sessionUpdate: "tool_call_update",
      toolCallId: callId,
      status: "failed",
      content: [
        { type: "content", content: { type: "text", text: error.message } }
      ],
      _meta: {
        toolName,
        ...subagentMeta,
        provenance: provenance.provenance,
        ...provenance.serverId ? { serverId: provenance.serverId } : {}
      }
    });
  }
  /**
   * Resolve a tool's provenance for UI dispatch on tool_call events.
   * The SDK reads `_meta.
   * provenance` + `_meta.serverId` to render builtin / MCP-server-badge /
   * subagent-block differently. Without this stamping, the SDK falls
   * back to string-matching the toolName which can't reliably
   * distinguish builtin from subagent.
   *
   * Resolution rules:
   *   - `subagentMeta` present → `'subagent'` (a Task tool / Codex
   *     subagent / etc. wrapping its own tool calls)
   *   - toolName matches `mcp__<server>__<tool>` → `'mcp'` with
   *     `serverId: <server>`. Naming convention from
   *     `packages/core/src/tools/mcp-tool.ts` in the
   *     `@qwen-code/qwen-code-core` package — mirrors the SDK's same
   *     heuristic fallback so SDK consumers stay consistent with
   *     daemon classification.
   *   - everything else → `'builtin'`
   *
   * Static + pure so it can be unit-tested without an emitter
   * instance. Exported via `ToolCallEmitter.resolveToolProvenance`.
   */
  static resolveToolProvenance(toolName, subagentMeta) {
    if (subagentMeta !== void 0) {
      return { provenance: "subagent" };
    }
    if (toolName.startsWith("mcp__")) {
      const parts = toolName.split("__");
      if (parts.length >= 3 && parts[1] && parts[1].length > 0) {
        return { provenance: "mcp", serverId: parts[1] };
      }
    }
    return { provenance: "builtin" };
  }
  // ==================== Public Utilities ====================
  /**
   * Checks if a tool name is the TodoWriteTool.
   * Exposed for external use in components that need to check this.
   */
  isTodoWriteTool(toolName) {
    return toolName === ToolNames.TODO_WRITE;
  }
  /**
   * Checks if a tool name is the ExitPlanModeTool.
   */
  isExitPlanModeTool(toolName) {
    return toolName === ToolNames.EXIT_PLAN_MODE;
  }
  /**
   * Checks if a tool name is the EnterPlanModeTool.
   */
  isEnterPlanModeTool(toolName) {
    return toolName === ToolNames.ENTER_PLAN_MODE;
  }
  /**
   * Resolves tool metadata from the registry.
   * Falls back to defaults if tool not found or build fails.
   *
   * @param toolName - Name of the tool
   * @param args - Tool call arguments (used to build invocation)
   */
  resolveToolMetadata(toolName, args) {
    const toolRegistry = this.config.getToolRegistry();
    const tool = toolRegistry.getTool(toolName);
    let title = tool?.displayName ?? toolName;
    let locations = [];
    let kind = "other";
    if (tool && args) {
      try {
        const invocation = tool.build(args);
        title = `${title}: ${invocation.getDescription()}`;
        locations = invocation.toolLocations().map((loc) => ({
          path: loc.path,
          line: loc.line ?? null
        }));
        kind = this.mapToolKind(tool.kind, toolName);
      } catch {
        if (typeof args["description"] === "string") {
          title = `${title}: ${args["description"]}`;
        }
        if (tool.kind) {
          kind = this.mapToolKind(tool.kind, toolName);
        }
      }
    }
    return { title, locations, kind };
  }
  /**
   * Maps core Tool Kind enum to ACP ToolKind string literals.
   *
   * @param kind - The core Kind enum value
   * @param toolName - Optional tool name to handle special cases like exit_plan_mode
   */
  mapToolKind(kind, toolName) {
    if (toolName && (this.isExitPlanModeTool(toolName) || this.isEnterPlanModeTool(toolName))) {
      return "switch_mode";
    }
    return KIND_MAP[kind] ?? "other";
  }
  // ==================== Private Helpers ====================
  /**
   * Extracts diff content from resultDisplay if it's a diff type (edit tool result).
   * Returns null if not a diff.
   */
  extractDiffContent(resultDisplay) {
    if (!resultDisplay || typeof resultDisplay !== "object") return null;
    const obj = resultDisplay;
    if ("fileName" in obj && "newContent" in obj) {
      if (this.isTruncatedSessionDiffDisplay(resultDisplay)) {
        return {
          type: "content",
          content: {
            type: "text",
            text: buildTruncatedDiffPreviewText(obj)
          }
        };
      }
      return {
        type: "diff",
        path: obj["fileName"],
        oldText: obj["originalContent"] ?? "",
        newText: obj["newContent"]
      };
    }
    return null;
  }
  isTruncatedSessionDiffDisplay(resultDisplay) {
    if (!resultDisplay || typeof resultDisplay !== "object") return false;
    const obj = resultDisplay;
    return obj["truncatedForSession"] === true && "fileName" in obj && "newContent" in obj;
  }
  /**
   * Transforms Part[] to ToolCallContent[].
   * Extracts text from functionResponse parts and text parts.
   */
  transformPartsToToolCallContent(parts) {
    const result = [];
    for (const part of parts) {
      if ("text" in part && part.text) {
        result.push({
          type: "content",
          content: { type: "text", text: part.text }
        });
      }
      if ("functionResponse" in part && part.functionResponse) {
        try {
          const resp = part.functionResponse.response;
          const outputField = resp["output"];
          const errorField = resp["error"];
          const responseText = typeof outputField === "string" ? outputField : typeof errorField === "string" ? errorField : JSON.stringify(resp);
          result.push({
            type: "content",
            content: { type: "text", text: responseText }
          });
        } catch {
        }
      }
    }
    return result;
  }
};

// packages/cli/src/acp-integration/session/HistoryReplayer.ts
var MISSING_TOOL_RESULT_MESSAGE = "Tool result missing from saved history; the previous run likely ended before this tool completed.";
var HistoryReplayer = class {
  static {
    __name(this, "HistoryReplayer");
  }
  ctx;
  messageEmitter;
  toolCallEmitter;
  pendingReplayToolCalls = /* @__PURE__ */ new Map();
  constructor(ctx) {
    this.ctx = ctx;
    this.messageEmitter = new MessageEmitter(ctx);
    this.toolCallEmitter = new ToolCallEmitter(ctx);
  }
  /**
   * Replays all chat records from a loaded session.
   *
   * @param records - Array of chat records to replay
   */
  async replay(records) {
    this.pendingReplayToolCalls.clear();
    try {
      let replayError;
      try {
        for (const record of records) {
          await this.replayRecord(record);
        }
      } catch (error) {
        replayError = error;
      }
      let danglingError;
      try {
        await this.failDanglingToolCalls();
      } catch (error) {
        danglingError = error;
      }
      if (replayError && danglingError) {
        throw new AggregateError(
          [replayError, danglingError],
          "Replay and dangling-cleanup both failed"
        );
      }
      if (replayError) {
        throw replayError;
      }
      if (danglingError) {
        throw danglingError;
      }
    } finally {
      this.pendingReplayToolCalls.clear();
      this.setActiveRecordId(null);
    }
  }
  /**
   * Replays a single chat record.
   */
  async replayRecord(record) {
    this.setActiveRecordId(record.uuid, record.timestamp);
    try {
      switch (record.type) {
        case "user":
          if (record.subtype === "notification" || record.subtype === "cron") {
            const displayText = record.systemPayload?.displayText;
            if (displayText) {
              await this.messageEmitter.emitUserMessage(
                displayText,
                record.timestamp
              );
            }
            break;
          }
          if (record.subtype === "mid_turn_user_message") {
            const displayText = record.systemPayload?.displayText;
            if (displayText) {
              await this.messageEmitter.emitUserMessage(
                displayText,
                record.timestamp
              );
            } else if (record.message) {
              await this.replayContent(
                record.message,
                "user",
                record.timestamp,
                record.uuid
              );
            }
            break;
          }
          if (record.message) {
            await this.replayContent(
              record.message,
              "user",
              record.timestamp,
              record.uuid
            );
          }
          break;
        case "assistant":
          if (record.message) {
            await this.replayContent(
              record.message,
              "assistant",
              record.timestamp,
              record.uuid
            );
          }
          if (record.usageMetadata) {
            await this.replayUsageMetadata(record.usageMetadata);
          }
          break;
        case "tool_result":
          await this.replayToolResult(record);
          break;
        case "system":
          if (record.subtype === "slash_command") {
            await this.replaySlashCommandResult(record);
          }
          break;
        default:
          break;
      }
    } finally {
      this.setActiveRecordId(null);
    }
  }
  /**
   * Replays content from a message (user or assistant).
   * Handles text parts, thought parts, and function calls.
   *
   * @param content - The content to replay
   * @param role - The role (user or assistant)
   * @param timestamp - Optional server-side timestamp from the JSONL record
   */
  async replayContent(content, role, timestamp, recordId) {
    for (const part of content.parts ?? []) {
      if ("text" in part && part.text) {
        const isThought = part.thought ?? false;
        await this.messageEmitter.emitMessage(
          part.text,
          role,
          isThought,
          timestamp
        );
      }
      if ("functionCall" in part && part.functionCall) {
        const functionName = part.functionCall.name ?? "";
        const sourceCallId = part.functionCall.id;
        const callId = sourceCallId ?? `${functionName}-${Date.now()}`;
        const emitted = await this.toolCallEmitter.emitStart({
          toolName: functionName,
          callId,
          args: part.functionCall.args,
          status: "in_progress",
          timestamp
        });
        if (emitted && role === "assistant" && recordId && sourceCallId) {
          this.pendingReplayToolCalls.set(callId, {
            callId,
            toolName: functionName,
            timestamp,
            recordId
          });
        }
      }
    }
  }
  /**
   * Replays usage metadata.
   * @param usageMetadata - The usage metadata to replay
   */
  async replayUsageMetadata(usageMetadata) {
    await this.messageEmitter.emitUsageMetadata(usageMetadata);
  }
  /**
   * Replays a tool result record.
   */
  async replayToolResult(record) {
    if (!record.message?.parts) {
      return;
    }
    const result = record.toolCallResult;
    const callId = this.getToolResultCallId(record);
    this.pendingReplayToolCalls.delete(callId);
    const toolName = this.extractToolNameFromRecord(record);
    await this.toolCallEmitter.emitResult({
      toolName,
      callId,
      success: !result?.error,
      message: record.message.parts,
      resultDisplay: result?.resultDisplay,
      // For TodoWriteTool fallback, try to extract args from the record
      // Note: args aren't stored in tool_result records by default
      args: void 0,
      timestamp: record.timestamp
    });
    const { resultDisplay } = result ?? {};
    if (!!resultDisplay && typeof resultDisplay === "object" && "type" in resultDisplay && resultDisplay.type === "task_execution") {
      await this.emitTaskUsageFromResultDisplay(
        resultDisplay
      );
    }
  }
  async failDanglingToolCalls() {
    let firstError;
    for (const pending of this.pendingReplayToolCalls.values()) {
      this.setActiveRecordId(pending.recordId, pending.timestamp);
      try {
        await this.toolCallEmitter.emitResult({
          toolName: pending.toolName,
          callId: pending.callId,
          success: false,
          message: [],
          error: new Error(MISSING_TOOL_RESULT_MESSAGE),
          timestamp: pending.timestamp
        });
      } catch (error) {
        firstError ??= error;
      } finally {
        this.setActiveRecordId(null);
      }
    }
    if (firstError) {
      throw firstError;
    }
  }
  /**
   * Emits token usage from a AgentResultDisplay execution summary, if present.
   */
  async emitTaskUsageFromResultDisplay(resultDisplay) {
    const summary = resultDisplay.executionSummary;
    if (!summary) {
      return;
    }
    const usageMetadata = {};
    if (Number.isFinite(summary.inputTokens)) {
      usageMetadata.promptTokenCount = summary.inputTokens;
    }
    if (Number.isFinite(summary.outputTokens)) {
      usageMetadata.candidatesTokenCount = summary.outputTokens;
    }
    if (Number.isFinite(summary.thoughtTokens)) {
      usageMetadata.thoughtsTokenCount = summary.thoughtTokens;
    }
    if (Number.isFinite(summary.cachedTokens)) {
      usageMetadata.cachedContentTokenCount = summary.cachedTokens;
    }
    if (Number.isFinite(summary.totalTokens)) {
      usageMetadata.totalTokenCount = summary.totalTokens;
    }
    if (Object.keys(usageMetadata).length > 0) {
      await this.messageEmitter.emitUsageMetadata(usageMetadata);
    }
  }
  /**
   * Replays a slash_command system record by re-emitting its output as an
   * agent message chunk. This allows Zed to reconstruct the correct turn
   * structure (user → agent) on session resume without polluting model context.
   */
  async replaySlashCommandResult(record) {
    const payload = record.systemPayload;
    if (payload?.phase !== "result" || !payload.outputHistoryItems?.length) {
      return;
    }
    for (const item of payload.outputHistoryItems) {
      const text = typeof item["text"] === "string" ? item["text"] : "";
      if (text) {
        await this.messageEmitter.emitAgentMessage(
          text.replace(/\n/g, "  \n"),
          record.timestamp
        );
      }
    }
  }
  /**
   * Extracts tool name from a chat record's function response.
   */
  extractToolNameFromRecord(record) {
    if (record.message?.parts) {
      for (const part of record.message.parts) {
        if ("functionResponse" in part && part.functionResponse?.name) {
          return part.functionResponse.name;
        }
      }
    }
    return "";
  }
  getToolResultCallId(record) {
    const resultCallId = record.toolCallResult?.callId;
    if (typeof resultCallId === "string" && resultCallId.length > 0) {
      return resultCallId;
    }
    return this.extractFunctionResponseIdFromRecord(record) ?? record.uuid;
  }
  extractFunctionResponseIdFromRecord(record) {
    if (record.message?.parts) {
      for (const part of record.message.parts) {
        const id = "functionResponse" in part ? part.functionResponse?.id : void 0;
        if (typeof id === "string" && id.length > 0) {
          return id;
        }
      }
    }
    return void 0;
  }
  setActiveRecordId(recordId, timestamp) {
    const context = this.ctx;
    if (typeof context.setActiveRecordId === "function") {
      context.setActiveRecordId(recordId, timestamp);
    }
  }
};

// packages/cli/src/nonInteractiveCliCommands.ts
init_esbuild_shims();

// packages/cli/src/utils/commands.ts
init_esbuild_shims();
var parseSlashCommand = /* @__PURE__ */ __name((query, commands) => {
  const trimmed = query.trim();
  const commandText = trimmed.substring(1).trim();
  const parts = commandText.split(/\s+/);
  const commandPath = parts.filter((p) => p);
  let currentCommands = commands;
  let commandToExecute;
  let pathIndex = 0;
  const canonicalPath = [];
  let argsStart = 0;
  for (const part of commandPath) {
    let foundCommand = currentCommands.find((cmd) => cmd.name === part);
    if (!foundCommand) {
      foundCommand = currentCommands.find(
        (cmd) => cmd.altNames?.includes(part)
      );
    }
    if (foundCommand) {
      commandToExecute = foundCommand;
      canonicalPath.push(foundCommand.name);
      pathIndex++;
      const partIndex = commandText.indexOf(part, argsStart);
      argsStart = partIndex + part.length;
      if (foundCommand.subCommands) {
        currentCommands = foundCommand.subCommands;
      } else {
        break;
      }
    } else {
      break;
    }
  }
  const args = commandToExecute ? commandText.slice(argsStart).trim() : parts.slice(pathIndex).join(" ");
  return { commandToExecute, args, canonicalPath };
}, "parseSlashCommand");

// packages/cli/src/services/CommandService.ts
init_esbuild_shims();
var debugLogger2 = createDebugLogger("CLI_COMMANDS");
var CommandService = class _CommandService {
  /**
   * Private constructor to enforce the use of the async factory.
   * @param commands A readonly array of the fully loaded and de-duplicated commands.
   */
  constructor(commands) {
    this.commands = commands;
  }
  static {
    __name(this, "CommandService");
  }
  /**
   * Asynchronously creates and initializes a new CommandService instance.
   *
   * This factory method orchestrates the entire command loading process. It
   * runs all provided loaders in parallel, aggregates their results, handles
   * name conflicts for extension commands by renaming them, and then returns a
   * fully constructed `CommandService` instance.
   *
   * Conflict resolution:
   * - Extension commands that conflict with existing commands are renamed to
   *   `extensionName.commandName`
   * - Non-extension commands (built-in, user, project) override earlier commands
   *   with the same name based on loader order
   *
   * @param loaders An array of objects that conform to the `ICommandLoader`
   *   interface. Built-in commands should come first, followed by FileCommandLoader.
   * @param signal An AbortSignal to cancel the loading process.
   * @param disabledNames Optional set of command names to exclude. Matched
   *   case-insensitively against the final (post-rename) command name. Intended
   *   for settings- or flag-driven denylists that gate the CLI surface (see
   *   `slashCommands.disabled` and `--disabled-slash-commands`).
   * @returns A promise that resolves to a new, fully initialized `CommandService` instance.
   */
  static async create(loaders, signal, disabledNames) {
    const results = await Promise.allSettled(
      loaders.map((loader) => loader.loadCommands(signal))
    );
    const allCommands = [];
    for (const result of results) {
      if (result.status === "fulfilled") {
        allCommands.push(...result.value);
      } else {
        debugLogger2.debug("A command loader failed:", result.reason);
      }
    }
    const commandMap = /* @__PURE__ */ new Map();
    for (const cmd of allCommands) {
      let finalName = cmd.name;
      if (cmd.extensionName && commandMap.has(cmd.name)) {
        let renamedName = `${cmd.extensionName}.${cmd.name}`;
        let suffix = 1;
        while (commandMap.has(renamedName)) {
          renamedName = `${cmd.extensionName}.${cmd.name}${suffix}`;
          suffix++;
        }
        finalName = renamedName;
      }
      commandMap.set(finalName, {
        ...cmd,
        name: finalName
      });
    }
    if (disabledNames && disabledNames.size > 0) {
      const normalizedDisabled = /* @__PURE__ */ new Set();
      for (const entry of disabledNames) {
        const trimmed = entry.trim();
        if (trimmed) normalizedDisabled.add(trimmed.toLowerCase());
      }
      if (normalizedDisabled.size > 0) {
        for (const [name, cmd] of Array.from(commandMap.entries())) {
          const matchesPrimary = normalizedDisabled.has(name.toLowerCase());
          const matchesAlias = (cmd.altNames ?? []).some(
            (a) => normalizedDisabled.has(a.toLowerCase())
          );
          if (matchesPrimary || matchesAlias) {
            commandMap.delete(name);
          }
        }
      }
    }
    const finalCommands = Object.freeze(Array.from(commandMap.values()));
    return new _CommandService(finalCommands);
  }
  /**
   * Retrieves the currently loaded and de-duplicated list of slash commands.
   *
   * This method is a safe accessor for the service's state. It returns a
   * readonly array, preventing consumers from modifying the service's internal state.
   *
   * @returns A readonly, unified array of available `SlashCommand` objects.
   */
  getCommands() {
    return this.commands;
  }
  /**
   * Returns commands available in the specified execution mode.
   * Hidden and non-user-invocable commands are excluded.
   */
  getCommandsForMode(mode) {
    return Object.freeze(
      filterCommandsForMode(
        this.commands.filter(
          (cmd) => !cmd.hidden && cmd.userInvocable !== false
        ),
        mode
      )
    );
  }
  /**
   * Returns commands that the model is allowed to invoke (modelInvocable === true).
   * Hidden commands are excluded.
   */
  getModelInvocableCommands() {
    return this.commands.filter(
      (cmd) => !cmd.hidden && cmd.modelInvocable === true
    );
  }
};

// packages/cli/src/services/BuiltinCommandLoader.ts
init_esbuild_shims();

// packages/cli/src/ui/commands/aboutCommand.ts
init_esbuild_shims();

// packages/cli/src/utils/sessionPaths.ts
init_esbuild_shims();
import fs from "node:fs/promises";
import path from "node:path";
var debugLogger3 = createDebugLogger("SESSION_PATHS");
var OPENAI_LOG_SCAN_LIMIT = 100;
async function collectSessionPathInfo(context) {
  const config = context.services.config;
  const sessionId = config?.getSessionId() || context.session.stats.sessionId || "unknown";
  const contentGeneratorConfig = config?.getContentGeneratorConfig();
  const workingDir = config?.getWorkingDir() || process.cwd();
  const openAILogDir = resolveOpenAILogDir(
    contentGeneratorConfig?.openAILoggingDir,
    workingDir
  );
  const openAILoggingEnabled = contentGeneratorConfig?.enableOpenAILogging === true;
  const latestOpenAILog = openAILoggingEnabled && sessionId !== "unknown" ? await findLatestOpenAILogForSession(openAILogDir, sessionId) : void 0;
  const transcriptPath = config?.getTranscriptPath() || "";
  const debugLogPath = config?.getDebugMode() && sessionId !== "unknown" ? Storage.getDebugLogPath(sessionId) : "";
  const planFilePath = config?.getPlanFilePath() || (sessionId === "unknown" ? "" : Storage.getPlanFilePath(sessionId));
  const planFileExists = planFilePath ? await pathExists(planFilePath) : false;
  const sections = [
    {
      title: "Session files",
      entries: [
        { label: "Session ID", value: sessionId },
        ...transcriptPath ? [{ label: "Transcript", value: transcriptPath }] : [],
        ...debugLogPath ? [{ label: "Debug log", value: debugLogPath }] : [],
        ...planFileExists ? [{ label: "Plan file", value: planFilePath }] : []
      ]
    }
  ];
  if (openAILoggingEnabled) {
    sections.push({
      title: "OpenAI logs",
      entries: [
        { label: "Directory", value: openAILogDir },
        { label: "Latest for session", value: latestOpenAILog ?? "none yet" }
      ]
    });
  }
  return {
    sections
  };
}
__name(collectSessionPathInfo, "collectSessionPathInfo");
function formatSessionPathInfo(info) {
  const lines = [];
  for (const [index, section] of info.sections.entries()) {
    if (index > 0) {
      lines.push("");
    }
    lines.push(`${section.title}:`);
    for (const entry of section.entries) {
      lines.push(`  ${entry.label}: ${entry.value}`);
    }
  }
  return lines.join("\n");
}
__name(formatSessionPathInfo, "formatSessionPathInfo");
async function findLatestOpenAILogForSession(logDir, sessionId) {
  const files = await listLogFiles(
    logDir,
    (name) => /^openai-.*\.json$/.test(name)
  );
  for (const file of files) {
    try {
      const raw = await fs.readFile(file, "utf-8");
      const parsed = JSON.parse(raw);
      if (hasContextSessionId(parsed, sessionId)) {
        return file;
      }
    } catch (error) {
      if (error instanceof SyntaxError || error.code === "ENOENT") {
        continue;
      }
      debugLogger3.warn("Error reading OpenAI log file", file, error);
    }
  }
  return void 0;
}
__name(findLatestOpenAILogForSession, "findLatestOpenAILogForSession");
async function listLogFiles(dir, predicate) {
  try {
    const entries = await fs.readdir(dir, { withFileTypes: true });
    const files = [];
    for (const entry of entries) {
      if (!entry.isFile() || !predicate(entry.name)) {
        continue;
      }
      insertRecentFile(files, path.join(dir, entry.name));
    }
    return files;
  } catch (error) {
    if (error.code !== "ENOENT") {
      debugLogger3.warn("Unable to list OpenAI log directory", dir, error);
    }
    return [];
  }
}
__name(listLogFiles, "listLogFiles");
function insertRecentFile(files, file) {
  const insertAt = files.findIndex((existing) => file > existing);
  if (insertAt === -1) {
    if (files.length < OPENAI_LOG_SCAN_LIMIT) {
      files.push(file);
    }
    return;
  }
  files.splice(insertAt, 0, file);
  if (files.length > OPENAI_LOG_SCAN_LIMIT) {
    files.pop();
  }
}
__name(insertRecentFile, "insertRecentFile");
async function pathExists(filePath) {
  try {
    await fs.access(filePath);
    return true;
  } catch {
    return false;
  }
}
__name(pathExists, "pathExists");
function hasContextSessionId(value, sessionId) {
  if (!value || typeof value !== "object") {
    return false;
  }
  const context = value.context;
  if (!context || typeof context !== "object") {
    return false;
  }
  const ctx = context;
  return ctx.sessionId === sessionId || ctx.promptId === sessionId;
}
__name(hasContextSessionId, "hasContextSessionId");

// packages/cli/src/ui/commands/aboutCommand.ts
var aboutCommand = {
  name: "status",
  altNames: ["about"],
  get description() {
    return t("show version info");
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive", "non_interactive", "acp"],
  action: /* @__PURE__ */ __name(async (context) => {
    const systemInfo = await getExtendedSystemInfo(context);
    if (context.executionMode !== "interactive") {
      const lines = [
        `Qwen Code v${systemInfo.cliVersion}`,
        `Model: ${systemInfo.modelVersion}`,
        `Fast Model: ${systemInfo.fastModel ?? "not set"}`,
        `Auth: ${systemInfo.selectedAuthType}`,
        `Platform: ${systemInfo.osPlatform} ${systemInfo.osArch} (${systemInfo.osRelease})`,
        `Node.js: ${systemInfo.nodeVersion}`,
        `Session: ${systemInfo.sessionId}`,
        ...systemInfo.gitCommit ? [`Git commit: ${systemInfo.gitCommit}`] : [],
        ...systemInfo.ideClient ? [`IDE: ${systemInfo.ideClient}`] : [],
        ...systemInfo.lspStatus ? [`LSP: ${systemInfo.lspStatus}`] : []
      ];
      return {
        type: "message",
        messageType: "info",
        content: lines.join("\n")
      };
    }
    const aboutItem = {
      type: "about" /* ABOUT */,
      systemInfo
    };
    context.ui.addItem(aboutItem, Date.now());
    return;
  }, "action"),
  subCommands: [
    {
      name: "paths",
      get description() {
        return t("show paths for current session files and logs");
      },
      kind: "built-in" /* BUILT_IN */,
      supportedModes: ["interactive", "non_interactive", "acp"],
      action: /* @__PURE__ */ __name(async (context) => {
        const info = await collectSessionPathInfo(context);
        const content = formatSessionPathInfo(info);
        return {
          type: "message",
          messageType: "info",
          content
        };
      }, "action")
    }
  ]
};

// packages/cli/src/ui/commands/tasksCommand.ts
init_esbuild_shims();
function statusLabel(entry) {
  switch (entry.kind) {
    case "agent": {
      const status = entry.status;
      switch (status) {
        case "completed":
          return "completed";
        case "failed":
          return `failed: ${entry.error ?? "unknown error"}`;
        case "cancelled":
          return "cancelled";
        case "paused":
          return entry.resumeBlockedReason ? `paused (resume blocked): ${entry.resumeBlockedReason}` : "paused";
        case "running":
          return "running";
        default: {
          const _exhaustive = status;
          throw new Error(
            `statusLabel(agent): unknown status: ${JSON.stringify(_exhaustive)}`
          );
        }
      }
    }
    case "shell": {
      const status = entry.status;
      switch (status) {
        case "completed":
          return `completed (exit ${entry.exitCode ?? "?"})`;
        case "failed":
          return `failed: ${entry.error ?? "unknown error"}`;
        case "cancelled":
          return "cancelled";
        case "running":
          return "running";
        default: {
          const _exhaustive = status;
          throw new Error(
            `statusLabel(shell): unknown status: ${JSON.stringify(_exhaustive)}`
          );
        }
      }
    }
    case "monitor": {
      const events = `${entry.eventCount} event${entry.eventCount === 1 ? "" : "s"}`;
      const status = entry.status;
      switch (status) {
        case "completed":
          return entry.error ? `completed (${entry.error}, ${events})` : `completed (exit ${entry.exitCode ?? "?"}, ${events})`;
        case "failed":
          return `failed: ${entry.error ?? "unknown error"} (${events})`;
        case "cancelled":
          return `cancelled (${events})`;
        case "running":
          return `running (${events})`;
        default: {
          const _exhaustive = status;
          throw new Error(
            `statusLabel(monitor): unknown status: ${JSON.stringify(_exhaustive)}`
          );
        }
      }
    }
    default: {
      const _exhaustive = entry;
      throw new Error(
        `statusLabel: unknown TaskEntry kind: ${JSON.stringify(_exhaustive)}`
      );
    }
  }
}
__name(statusLabel, "statusLabel");
function taskLabel(entry) {
  switch (entry.kind) {
    case "agent":
      return buildBackgroundEntryLabel(entry);
    case "shell":
      return entry.command;
    case "monitor":
      return entry.description;
    default: {
      const _exhaustive = entry;
      throw new Error(
        `taskLabel: unknown TaskEntry kind: ${JSON.stringify(_exhaustive)}`
      );
    }
  }
}
__name(taskLabel, "taskLabel");
function taskId(entry) {
  switch (entry.kind) {
    case "agent":
      return entry.agentId;
    case "shell":
      return entry.shellId;
    case "monitor":
      return entry.monitorId;
    default: {
      const _exhaustive = entry;
      throw new Error(
        `taskId: unknown TaskEntry kind: ${JSON.stringify(_exhaustive)}`
      );
    }
  }
}
__name(taskId, "taskId");
function taskOutputPath(entry) {
  switch (entry.kind) {
    case "agent":
    case "shell":
      return entry.outputFile;
    case "monitor":
      return void 0;
    default: {
      const _exhaustive = entry;
      throw new Error(
        `taskOutputPath: unknown TaskEntry kind: ${JSON.stringify(_exhaustive)}`
      );
    }
  }
}
__name(taskOutputPath, "taskOutputPath");
var tasksCommand = {
  name: "tasks",
  get description() {
    return t(
      "List background tasks (text dump \u2014 interactive dialog opens via the footer pill)"
    );
  },
  kind: "built-in" /* BUILT_IN */,
  // Kept on all three modes: the interactive dialog (reachable via ↓ +
  // Enter on the footer Background tasks pill) is the richer surface
  // when a TTY is available, but `non_interactive` and `acp` consumers
  // (headless `-p`, IDE bridges, SDK) have no dialog and rely on this
  // text dump as the only way to inspect background task state. See the
  // interactive-mode hint at the top of the output for the soft redirect.
  supportedModes: ["interactive", "non_interactive", "acp"],
  action: /* @__PURE__ */ __name(async (context) => {
    const { config } = context.services;
    if (!config) {
      return {
        type: "message",
        messageType: "error",
        content: "Config not available."
      };
    }
    const agentEntries = [
      ...config.getBackgroundTaskRegistry().getAll()
    ];
    const shellEntries = [
      ...config.getBackgroundShellRegistry().getAll()
    ];
    const monitorEntries = [
      ...config.getMonitorRegistry().getAll()
    ];
    const entries = [
      ...agentEntries,
      ...shellEntries,
      ...monitorEntries
    ].sort((a, b) => a.startTime - b.startTime);
    if (entries.length === 0) {
      return {
        type: "message",
        messageType: "info",
        content: "No background tasks."
      };
    }
    const now = Date.now();
    const lines = [];
    if (context.executionMode === "interactive") {
      lines.push(
        t(
          "Tip: focus the Background tasks pill in the footer (use \u2193 from an empty composer) and press Enter for the interactive dialog with detail view + live updates."
        ),
        ""
      );
    }
    lines.push(`Background tasks (${entries.length} total)`, "");
    for (const entry of entries) {
      const endTime = entry.endTime ?? now;
      const runtime = formatDuration(endTime - entry.startTime, {
        hideTrailingZeros: true
      });
      const pidPart = (entry.kind === "shell" || entry.kind === "monitor") && entry.pid !== void 0 ? ` pid=${entry.pid}` : "";
      lines.push(
        `[${taskId(entry)}] ${statusLabel(entry)}  ${runtime}${pidPart}  ${taskLabel(entry)}`
      );
      const outputPath = taskOutputPath(entry);
      if (outputPath) {
        lines.push(`            output: ${outputPath}`);
      }
    }
    return {
      type: "message",
      messageType: "info",
      content: stripUnsafeCharacters(lines.join("\n"))
    };
  }, "action")
};

// packages/cli/src/ui/commands/workflowsCommand.ts
init_esbuild_shims();
function snapshotToTask(s) {
  return {
    id: s.runId,
    kind: "workflow",
    runId: s.runId,
    description: s.meta?.name ?? s.runId,
    meta: s.meta,
    status: s.status,
    currentPhase: null,
    phases: s.phases ?? [],
    agentsDispatched: s.agentsDispatched ?? 0,
    agentsCompleted: s.agentsCompleted ?? 0,
    recentLogs: s.recentLogs ?? [],
    tokensSpent: s.tokensSpent ?? 0,
    tokenBudgetTotal: s.tokenBudgetTotal ?? null,
    perPhaseTokens: new Map(s.perPhaseTokens ?? []),
    script: s.script ?? "",
    scriptPath: s.scriptPath,
    result: s.result,
    error: s.error,
    startTime: s.startTime,
    endTime: s.endTime,
    outputFile: "",
    outputOffset: 0,
    notified: true,
    abortController: new AbortController()
  };
}
__name(snapshotToTask, "snapshotToTask");
function rowLine(entry, now) {
  const endTime = entry.endTime ?? now;
  const runtime = formatDuration(endTime - entry.startTime, {
    hideTrailingZeros: true
  });
  const label = entry.meta?.name ?? entry.runId;
  const phase = entry.currentPhase ? ` \xB7 ${entry.currentPhase}` : "";
  const counts = entry.agentsDispatched > 0 ? ` \xB7 ${entry.agentsCompleted}/${entry.agentsDispatched} agents` : "";
  const phaseCount = entry.phases.length > 0 ? ` \xB7 ${entry.phases.length} ${entry.phases.length === 1 ? "phase" : "phases"}` : "";
  const budgetChip = entry.tokensSpent > 0 || entry.tokenBudgetTotal !== null ? entry.tokenBudgetTotal !== null ? ` \xB7 ${formatTokenCount(entry.tokensSpent)}/${formatTokenCount(entry.tokenBudgetTotal)}t` : ` \xB7 ${formatTokenCount(entry.tokensSpent)}t` : "";
  const errorTail = entry.status === "failed" && entry.error ? ` \u2014 ${entry.error.slice(0, 80)}` : "";
  return `  ${entry.runId.padEnd(20)} ${entry.status.padEnd(10)} ${runtime.padStart(8)}  ${label}${phase}${counts}${phaseCount}${budgetChip}${errorTail}`;
}
__name(rowLine, "rowLine");
function detailLines(entry, now) {
  const lines = [];
  const endTime = entry.endTime ?? now;
  const runtime = formatDuration(endTime - entry.startTime, {
    hideTrailingZeros: true
  });
  lines.push(`Workflow ${entry.runId}`);
  if (entry.meta?.name) {
    lines.push(`  name        : ${entry.meta.name}`);
  }
  if (entry.meta?.description) {
    lines.push(`  description : ${entry.meta.description}`);
  }
  if (entry.meta?.whenToUse) {
    lines.push(`  whenToUse   : ${entry.meta.whenToUse}`);
  }
  lines.push(`  status      : ${entry.status}`);
  lines.push(`  runtime     : ${runtime}`);
  if (entry.currentPhase) {
    lines.push(`  currentPhase: ${entry.currentPhase}`);
  }
  lines.push(
    `  agents      : ${entry.agentsCompleted}/${entry.agentsDispatched}`
  );
  lines.push(`  tokens      : ${formatTokenCount(entry.tokensSpent)}`);
  lines.push(
    `  cap         : ${entry.tokenBudgetTotal !== null ? formatTokenCount(entry.tokenBudgetTotal) : "(no cap)"}`
  );
  if (entry.error) {
    lines.push(`  error       : ${entry.error}`);
  }
  if (entry.phases.length > 0) {
    lines.push("");
    lines.push(`  Phases (${entry.phases.length})`);
    for (const phase of entry.phases) {
      const phaseTokens = entry.perPhaseTokens.get(phase) ?? 0;
      const chip = phaseTokens > 0 ? ` \xB7 ${formatTokenCount(phaseTokens)}t` : "";
      lines.push(`    \xB7 ${phase}${chip}`);
    }
    const prePhaseTokens = entry.perPhaseTokens.get(null) ?? 0;
    if (prePhaseTokens > 0) {
      lines.push(`    \xB7 (no phase) \xB7 ${formatTokenCount(prePhaseTokens)}t`);
    }
  }
  if (entry.recentLogs.length > 0) {
    lines.push("");
    lines.push(`  Logs (last ${entry.recentLogs.length})`);
    for (const line of entry.recentLogs) {
      lines.push(`    ${line}`);
    }
  }
  return lines;
}
__name(detailLines, "detailLines");
var workflowsCommand = {
  name: "workflows",
  get description() {
    return t(
      "List active and completed workflow runs (text dump \u2014 interactive dialog opens via the footer pill)"
    );
  },
  get argumentHint() {
    return t("[runId]");
  },
  kind: "built-in" /* BUILT_IN */,
  // Same triple-mode coverage as `/tasks`: the dialog is richer in
  // interactive mode but headless / acp consumers need the text dump
  // as their only inspection path.
  supportedModes: ["interactive", "non_interactive", "acp"],
  action: /* @__PURE__ */ __name(async (context, args) => {
    const { config } = context.services;
    if (!config) {
      return {
        type: "message",
        messageType: "error",
        content: "Config not available."
      };
    }
    const registry = config.getWorkflowRunRegistry();
    const allEntries = registry.list();
    const trimmedArgs = (args ?? "").trim();
    if (trimmedArgs.length > 0) {
      let target = registry.get(trimmedArgs);
      if (!target) {
        const snapshot = (await listWorkflowSnapshots(config)).find(
          (s) => s.runId === trimmedArgs
        );
        if (snapshot) target = snapshotToTask(snapshot);
      }
      if (!target) {
        return {
          type: "message",
          messageType: "error",
          content: `Unknown workflow runId: ${trimmedArgs}`
        };
      }
      return {
        type: "message",
        messageType: "info",
        content: detailLines(target, Date.now()).join("\n")
      };
    }
    const snapshots = await listWorkflowSnapshots(config);
    const liveRunIds = new Set(allEntries.map((e) => e.runId));
    const snapshotTasks = snapshots.filter((s) => !liveRunIds.has(s.runId)).map(snapshotToTask);
    if (allEntries.length === 0 && snapshotTasks.length === 0) {
      return {
        type: "message",
        messageType: "info",
        content: "No workflow runs recorded yet."
      };
    }
    const now = Date.now();
    const running = allEntries.filter((e) => e.status === "running").sort((a, b) => a.startTime - b.startTime);
    const terminal = [
      ...allEntries.filter((e) => e.status !== "running"),
      ...snapshotTasks
    ].sort((a, b) => (b.endTime ?? 0) - (a.endTime ?? 0));
    const lines = [];
    if (context.executionMode === "interactive") {
      lines.push(
        t(
          "Tip: use `/workflows <runId>` for the per-run detail view (name, description, phase tree, recent logs)."
        ),
        ""
      );
    }
    lines.push(
      `Workflow runs (${running.length + terminal.length} total \xB7 ${running.length} running)`,
      ""
    );
    if (running.length > 0) {
      lines.push("Active");
      for (const entry of running) lines.push(rowLine(entry, now));
      lines.push("");
    }
    if (terminal.length > 0) {
      lines.push("Recent");
      for (const entry of terminal) lines.push(rowLine(entry, now));
    }
    return {
      type: "message",
      messageType: "info",
      content: lines.join("\n")
    };
  }, "action")
};

// packages/cli/src/ui/commands/agentsCommand.ts
init_esbuild_shims();
var agentsCommand = {
  name: "agents",
  get description() {
    return t("Manage subagents for specialized task delegation.");
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive"],
  subCommands: [
    {
      name: "manage",
      get description() {
        return t("Manage existing subagents (view, edit, delete).");
      },
      kind: "built-in" /* BUILT_IN */,
      supportedModes: ["interactive"],
      action: /* @__PURE__ */ __name(() => ({
        type: "dialog",
        dialog: "subagent_list"
      }), "action")
    },
    {
      name: "create",
      get description() {
        return t("Create a new subagent with guided setup.");
      },
      kind: "built-in" /* BUILT_IN */,
      supportedModes: ["interactive"],
      action: /* @__PURE__ */ __name(() => ({
        type: "dialog",
        dialog: "subagent_create"
      }), "action")
    }
  ]
};

// packages/cli/src/ui/commands/arenaCommand.ts
init_esbuild_shims();
function parseArenaArgs(args) {
  const modelsMatch = args.match(/--models\s+(\S+)/);
  let models = [];
  let task = args;
  if (modelsMatch) {
    const modelStrings = modelsMatch[1].split(",").filter(Boolean);
    models = modelStrings.map((str) => {
      const colonIndex = str.indexOf(":");
      if (colonIndex > 0) {
        return {
          authType: str.substring(0, colonIndex),
          modelId: str.substring(colonIndex + 1)
        };
      }
      return { modelId: str };
    });
    task = task.replace(/--models\s+\S+/, "").trim();
  }
  task = task.replace(/^["']|["']$/g, "").trim();
  return { models, task };
}
__name(parseArenaArgs, "parseArenaArgs");
var debugLogger4 = createDebugLogger("ARENA_COMMAND");
function buildArenaExecutionInput(parsed, config) {
  if (!parsed.task) {
    return {
      type: "message",
      messageType: "error",
      content: [
        t("Usage: /arena start --models model1,model2 <task>"),
        "",
        t("Options:"),
        "  --models [authType:]model1,[authType:]model2",
        `                            ${t(
          "Models to compete (required, at least 2)"
        )}`,
        `                            ${t(
          "Format: authType:modelId or just modelId"
        )}`,
        "",
        t("Examples:"),
        '  /arena start --models openai:gpt-4o,anthropic:claude-3 "implement sorting"',
        '  /arena start --models qwen-coder-plus,kimi-for-coding "fix the bug"'
      ].join("\n")
    };
  }
  if (parsed.models.length < 2) {
    return {
      type: "message",
      messageType: "error",
      content: [
        t(
          "Arena requires at least 2 models. Use --models model1,model2 to specify."
        ),
        t("Format: [authType:]modelId (e.g., openai:gpt-4o or just gpt-4o)")
      ].join("\n")
    };
  }
  const contentGeneratorConfig = config.getContentGeneratorConfig();
  const defaultAuthType = contentGeneratorConfig?.authType ?? "openai" /* USE_OPENAI */;
  const modelsConfig = config.getModelsConfig();
  const models = parsed.models.map((parsedModel) => {
    const authType = parsedModel.authType ?? defaultAuthType;
    const registryModels = modelsConfig.getAvailableModelsForAuthType(authType);
    const resolved = registryModels.find((m) => m.id === parsedModel.modelId);
    return {
      modelId: parsedModel.modelId,
      authType,
      displayName: resolved?.label ?? parsedModel.modelId
    };
  });
  return {
    task: parsed.task,
    models,
    approvalMode: config.getApprovalMode()
  };
}
__name(buildArenaExecutionInput, "buildArenaExecutionInput");
function recordArenaItem(config, item) {
  try {
    const chatRecorder = config.getChatRecordingService();
    if (!chatRecorder) return;
    chatRecorder.recordSlashCommand({
      phase: "result",
      rawCommand: "/arena",
      outputHistoryItems: [{ ...item }]
    });
  } catch {
    debugLogger4.error("Failed to record arena history item");
  }
}
__name(recordArenaItem, "recordArenaItem");
function executeArenaCommand(config, ui, input) {
  let chatHistory;
  try {
    const fullHistory = config.getGeminiClient().getChat().getHistoryShallow();
    chatHistory = stripStartupContext(fullHistory);
  } catch {
    debugLogger4.debug("Could not retrieve chat history for arena agents");
  }
  const manager = new ArenaManager(config);
  const emitter = manager.getEventEmitter();
  const detachListeners = [];
  const agentLabels = /* @__PURE__ */ new Map();
  const addArenaMessage = /* @__PURE__ */ __name((type, text) => {
    ui.addItem({ type, text }, Date.now());
  }, "addArenaMessage");
  const addAndRecordArenaMessage = /* @__PURE__ */ __name((type, text) => {
    const item = { type, text };
    ui.addItem(item, Date.now());
    recordArenaItem(config, item);
  }, "addAndRecordArenaMessage");
  const handleSessionStart = /* @__PURE__ */ __name((event) => {
    const modelList = event.models.map((model, index) => `  ${index + 1}. ${model.modelId}`).join("\n");
    addArenaMessage(
      "info" /* INFO */,
      t(
        'Arena started with {{count}} agents on task: "{{task}}"\nModels:\n{{modelList}}',
        {
          count: String(event.models.length),
          task: event.task,
          modelList
        }
      )
    );
  }, "handleSessionStart");
  const handleAgentStart = /* @__PURE__ */ __name((event) => {
    agentLabels.set(event.agentId, event.model.modelId);
    debugLogger4.debug(
      `Arena agent started: ${event.model.modelId} (${event.agentId})`
    );
  }, "handleAgentStart");
  const handleSessionUpdate = /* @__PURE__ */ __name((event) => {
    const attachHintPrefix = "To view agent panes, run: ";
    if (event.message.startsWith(attachHintPrefix)) {
      const command = event.message.slice(attachHintPrefix.length).trim();
      addAndRecordArenaMessage(
        "info" /* INFO */,
        t("Arena panes are running in tmux. Attach with: `{{command}}`", {
          command
        })
      );
      return;
    }
    if (event.type === "success") {
      addAndRecordArenaMessage("success" /* SUCCESS */, event.message);
    } else if (event.type === "info") {
      addAndRecordArenaMessage("info" /* INFO */, event.message);
    } else {
      addAndRecordArenaMessage("warning" /* WARNING */, event.message);
    }
  }, "handleSessionUpdate");
  const handleAgentError = /* @__PURE__ */ __name((event) => {
    const label = agentLabels.get(event.agentId) || event.agentId;
    addAndRecordArenaMessage(
      "error" /* ERROR */,
      t("[{{label}}] failed: {{error}}", {
        label,
        error: event.error
      })
    );
  }, "handleAgentError");
  const buildAgentCardData = /* @__PURE__ */ __name((result) => ({
    label: result.model.modelId,
    status: result.status,
    durationMs: result.stats.durationMs,
    totalTokens: result.stats.totalTokens,
    inputTokens: result.stats.inputTokens,
    outputTokens: result.stats.outputTokens,
    toolCalls: result.stats.toolCalls,
    successfulToolCalls: result.stats.successfulToolCalls,
    failedToolCalls: result.stats.failedToolCalls,
    rounds: result.stats.rounds,
    error: result.error,
    diff: result.diff,
    diffSummary: result.diffSummary,
    modifiedFiles: result.modifiedFiles,
    approachSummary: result.approachSummary
  }), "buildAgentCardData");
  const handleAgentComplete = /* @__PURE__ */ __name((event) => {
    if (!isTerminalStatus(event.result.status)) {
      return;
    }
    const agent = buildAgentCardData(event.result);
    const item = {
      type: "arena_agent_complete",
      agent
    };
    ui.addItem(item, Date.now());
    recordArenaItem(config, item);
  }, "handleAgentComplete");
  const handleSessionError = /* @__PURE__ */ __name((event) => {
    addAndRecordArenaMessage("error" /* ERROR */, `${event.error}`);
  }, "handleSessionError");
  const handleSessionComplete = /* @__PURE__ */ __name((event) => {
    const item = {
      type: "arena_session_complete",
      sessionStatus: event.result.status,
      task: event.result.task,
      totalDurationMs: event.result.totalDurationMs ?? 0,
      agents: event.result.agents.map(buildAgentCardData)
    };
    ui.addItem(item, Date.now());
    recordArenaItem(config, item);
  }, "handleSessionComplete");
  emitter.on("session_start" /* SESSION_START */, handleSessionStart);
  detachListeners.push(
    () => emitter.off("session_start" /* SESSION_START */, handleSessionStart)
  );
  emitter.on("agent_start" /* AGENT_START */, handleAgentStart);
  detachListeners.push(
    () => emitter.off("agent_start" /* AGENT_START */, handleAgentStart)
  );
  emitter.on("session_update" /* SESSION_UPDATE */, handleSessionUpdate);
  detachListeners.push(
    () => emitter.off("session_update" /* SESSION_UPDATE */, handleSessionUpdate)
  );
  emitter.on("agent_error" /* AGENT_ERROR */, handleAgentError);
  detachListeners.push(
    () => emitter.off("agent_error" /* AGENT_ERROR */, handleAgentError)
  );
  emitter.on("agent_complete" /* AGENT_COMPLETE */, handleAgentComplete);
  detachListeners.push(
    () => emitter.off("agent_complete" /* AGENT_COMPLETE */, handleAgentComplete)
  );
  emitter.on("session_error" /* SESSION_ERROR */, handleSessionError);
  detachListeners.push(
    () => emitter.off("session_error" /* SESSION_ERROR */, handleSessionError)
  );
  emitter.on("session_complete" /* SESSION_COMPLETE */, handleSessionComplete);
  detachListeners.push(
    () => emitter.off("session_complete" /* SESSION_COMPLETE */, handleSessionComplete)
  );
  config.setArenaManager(manager);
  const cols = process.stdout.columns || 120;
  const rows = Math.max((process.stdout.rows || 40) - 2, 1);
  const lifecycle = manager.start({
    task: input.task,
    models: input.models,
    cols,
    rows,
    approvalMode: input.approvalMode,
    chatHistory
  }).then(
    () => {
      debugLogger4.debug("Arena agents settled");
    },
    (error) => {
      const message = error instanceof Error ? error.message : String(error);
      addAndRecordArenaMessage("error" /* ERROR */, `${message}`);
      debugLogger4.error("Arena session failed:", error);
      config.setArenaManager(null);
      for (const detach of detachListeners) {
        detach();
      }
    }
  );
  manager.setLifecyclePromise(lifecycle);
}
__name(executeArenaCommand, "executeArenaCommand");
var arenaCommand = {
  name: "arena",
  get description() {
    return t("Manage Arena sessions");
  },
  kind: "built-in" /* BUILT_IN */,
  subCommands: [
    {
      name: "start",
      get description() {
        return t(
          "Start an Arena session with multiple models competing on the same task"
        );
      },
      kind: "built-in" /* BUILT_IN */,
      action: /* @__PURE__ */ __name(async (context, args) => {
        const executionMode = context.executionMode ?? "interactive";
        if (executionMode !== "interactive") {
          return {
            type: "message",
            messageType: "error",
            content: t(
              "Arena is not supported in non-interactive mode. Use interactive mode to start an Arena session."
            )
          };
        }
        const { services, ui } = context;
        const { config } = services;
        if (!config) {
          return {
            type: "message",
            messageType: "error",
            content: t("Configuration not available.")
          };
        }
        const existingManager = config.getArenaManager();
        if (existingManager) {
          return {
            type: "message",
            messageType: "error",
            content: t(
              "An Arena session exists. Use /arena stop or /arena select to end it before starting a new one."
            )
          };
        }
        const parsed = parseArenaArgs(args);
        if (parsed.models.length === 0) {
          return {
            type: "dialog",
            dialog: "arena_start"
          };
        }
        const executionInput = buildArenaExecutionInput(parsed, config);
        if ("type" in executionInput) {
          return executionInput;
        }
        executeArenaCommand(config, ui, executionInput);
      }, "action")
    },
    {
      name: "stop",
      get description() {
        return t("Stop the current Arena session");
      },
      kind: "built-in" /* BUILT_IN */,
      action: /* @__PURE__ */ __name(async (context) => {
        const executionMode = context.executionMode ?? "interactive";
        if (executionMode !== "interactive") {
          return {
            type: "message",
            messageType: "error",
            content: t(
              "Arena is not supported in non-interactive mode. Use interactive mode to stop an Arena session."
            )
          };
        }
        const { config } = context.services;
        if (!config) {
          return {
            type: "message",
            messageType: "error",
            content: t("Configuration not available.")
          };
        }
        const manager = config.getArenaManager();
        if (!manager) {
          return {
            type: "message",
            messageType: "error",
            content: t("No running Arena session found.")
          };
        }
        return {
          type: "dialog",
          dialog: "arena_stop"
        };
      }, "action")
    },
    {
      name: "status",
      get description() {
        return t("Show the current Arena session status");
      },
      kind: "built-in" /* BUILT_IN */,
      action: /* @__PURE__ */ __name(async (context) => {
        const executionMode = context.executionMode ?? "interactive";
        if (executionMode !== "interactive") {
          return {
            type: "message",
            messageType: "error",
            content: t("Arena is not supported in non-interactive mode.")
          };
        }
        const { config } = context.services;
        if (!config) {
          return {
            type: "message",
            messageType: "error",
            content: t("Configuration not available.")
          };
        }
        const manager = config.getArenaManager();
        if (!manager) {
          return {
            type: "message",
            messageType: "error",
            content: t("No Arena session found. Start one with /arena start.")
          };
        }
        return {
          type: "dialog",
          dialog: "arena_status"
        };
      }, "action")
    },
    {
      name: "select",
      altNames: ["choose"],
      get description() {
        return t(
          "Select a model result and merge its diff into the current workspace"
        );
      },
      kind: "built-in" /* BUILT_IN */,
      action: /* @__PURE__ */ __name(async (context, args) => {
        const executionMode = context.executionMode ?? "interactive";
        if (executionMode !== "interactive") {
          return {
            type: "message",
            messageType: "error",
            content: t("Arena is not supported in non-interactive mode.")
          };
        }
        const { config } = context.services;
        if (!config) {
          return {
            type: "message",
            messageType: "error",
            content: t("Configuration not available.")
          };
        }
        const manager = config.getArenaManager();
        if (!manager) {
          return {
            type: "message",
            messageType: "error",
            content: t("No Arena session found. Start one with /arena start.")
          };
        }
        const sessionStatus = manager.getSessionStatus();
        if (sessionStatus === "running" /* RUNNING */ || sessionStatus === "initializing" /* INITIALIZING */) {
          return {
            type: "message",
            messageType: "error",
            content: t(
              "Arena session is still running. Wait for it to complete or use /arena stop first."
            )
          };
        }
        const trimmedArgs = args.trim();
        if (trimmedArgs === "--discard") {
          if (!context.overwriteConfirmed) {
            return {
              type: "confirm_action",
              prompt: t("Discard all Arena results and clean up worktrees?"),
              originalInvocation: {
                raw: context.invocation?.raw || "/arena select --discard"
              }
            };
          }
          await config.cleanupArenaRuntime(true);
          return {
            type: "message",
            messageType: "info",
            content: t("Arena results discarded. All worktrees cleaned up.")
          };
        }
        const agents = manager.getAgentStates();
        const hasSuccessful = agents.some((a) => isSuccessStatus(a.status));
        if (!hasSuccessful) {
          return {
            type: "message",
            messageType: "error",
            content: [
              t(
                "No successful agent results to select from. All agents failed or were cancelled."
              ),
              t("Use /arena stop to end the session.")
            ].join("\n")
          };
        }
        if (trimmedArgs) {
          const matchingAgent = agents.find(
            (a) => isSuccessStatus(a.status) && a.model.modelId.toLowerCase() === trimmedArgs.toLowerCase()
          );
          if (!matchingAgent) {
            return {
              type: "message",
              messageType: "error",
              content: t('No idle agent found matching "{{name}}".', {
                name: trimmedArgs
              })
            };
          }
          const label = matchingAgent.model.modelId;
          const result = await manager.applyAgentResult(matchingAgent.agentId);
          if (!result.success) {
            return {
              type: "message",
              messageType: "error",
              content: t("Failed to apply changes from {{label}}: {{error}}", {
                label,
                error: result.error ?? "Unknown error"
              })
            };
          }
          await config.cleanupArenaRuntime(true);
          return {
            type: "message",
            messageType: "info",
            content: t(
              "Applied changes from {{label}} to workspace. Arena session complete.",
              {
                label
              }
            )
          };
        }
        return {
          type: "dialog",
          dialog: "arena_select"
        };
      }, "action")
    }
  ]
};

// packages/cli/src/ui/commands/approvalModeCommand.ts
init_esbuild_shims();

// packages/cli/src/ui/hooks/useAutoAcceptIndicator.ts
init_esbuild_shims();
var import_react = __toESM(require_react(), 1);
var AUTO_MODE_FIRST_TIME_MESSAGE = "Auto mode enabled.\n   An LLM classifier evaluates each tool call \u2014 safe actions auto-approve,\n   risky ones are blocked. Exit: Shift+Tab or /approval-mode default.";
function useAutoAcceptIndicator({
  config,
  settings,
  addItem,
  onApprovalModeChange,
  shouldBlockTab,
  disabled
}) {
  const currentConfigValue = config.getApprovalMode();
  const [showAutoAcceptIndicator, setShowAutoAcceptIndicator] = (0, import_react.useState)(currentConfigValue);
  (0, import_react.useEffect)(() => {
    setShowAutoAcceptIndicator(currentConfigValue);
  }, [currentConfigValue]);
  (0, import_react.useEffect)(() => {
    if (currentConfigValue === "auto" /* AUTO */) {
      emitAutoModeEntryNotices({ config, settings, addItem });
    }
  }, []);
  useKeypress(
    (key) => {
      const isShiftTab = key.shift && key.name === "tab";
      const isWindowsTab = process.platform === "win32" && key.name === "tab" && !key.ctrl && !key.meta;
      if (isShiftTab || isWindowsTab) {
        if (isWindowsTab && shouldBlockTab?.()) {
          return;
        }
        const currentMode = config.getApprovalMode();
        const currentIndex = APPROVAL_MODES.indexOf(currentMode);
        const nextIndex = currentIndex === -1 ? 0 : (currentIndex + 1) % APPROVAL_MODES.length;
        const nextApprovalMode = APPROVAL_MODES[nextIndex];
        try {
          config.setApprovalMode(nextApprovalMode);
          setShowAutoAcceptIndicator(nextApprovalMode);
          if (nextApprovalMode === "auto" /* AUTO */ && currentMode !== "auto" /* AUTO */) {
            emitAutoModeEntryNotices({ config, settings, addItem });
          }
          onApprovalModeChange?.(nextApprovalMode);
        } catch (e) {
          addItem?.(
            {
              type: "info" /* INFO */,
              text: e.message
            },
            Date.now()
          );
        }
      }
    },
    { isActive: !disabled }
  );
  return showAutoAcceptIndicator;
}
__name(useAutoAcceptIndicator, "useAutoAcceptIndicator");
function emitAutoModeEntryNotices(opts) {
  const { config, settings, addItem } = opts;
  if (!addItem) return;
  const now = Date.now();
  const acknowledged = settings?.merged.ui?.autoModeAcknowledged === true;
  if (!acknowledged) {
    addItem(
      { type: "info" /* INFO */, text: AUTO_MODE_FIRST_TIME_MESSAGE },
      now
    );
    if (settings) {
      try {
        settings.setValue("User" /* User */, "ui.autoModeAcknowledged", true);
      } catch {
      }
    }
  }
  const pm = config.getPermissionManager?.();
  const stripped = pm?.getStrippedDangerousRules?.();
  if (stripped && (stripped.persistent.length > 0 || stripped.session.length > 0)) {
    const lines = [
      "\u2139 Auto mode temporarily disabled these allow rules",
      "   (they would bypass the classifier):",
      ...stripped.persistent.map((r) => `   - ${r.raw} (from user settings)`),
      ...stripped.session.map((r) => `   - ${r.raw} (session)`),
      "   These will be restored when leaving auto mode."
    ];
    addItem({ type: "info" /* INFO */, text: lines.join("\n") }, now + 1);
  }
}
__name(emitAutoModeEntryNotices, "emitAutoModeEntryNotices");

// packages/cli/src/ui/utils/approvalModeDisplay.ts
init_esbuild_shims();
function formatApprovalModeName(mode) {
  switch (mode) {
    case "default" /* DEFAULT */:
      return t("Ask permissions");
    case "yolo" /* YOLO */:
      return "YOLO";
    default:
      return mode;
  }
}
__name(formatApprovalModeName, "formatApprovalModeName");
function formatApprovalModeDescription(mode) {
  switch (mode) {
    case "plan" /* PLAN */:
      return t("Analyze only, do not modify files or execute commands");
    case "default" /* DEFAULT */:
      return t("Require approval for file edits or shell commands");
    case "auto-edit" /* AUTO_EDIT */:
      return t("Automatically approve file edits");
    case "auto" /* AUTO */:
      return t("Use classifier to automatically approve safe tool calls");
    case "yolo" /* YOLO */:
      return t("Automatically approve all tools");
    default:
      return mode;
  }
}
__name(formatApprovalModeDescription, "formatApprovalModeDescription");

// packages/cli/src/ui/commands/approvalModeCommand.ts
function parseApprovalModeArg(arg) {
  const trimmed = arg.trim().toLowerCase();
  if (!trimmed) {
    return void 0;
  }
  return APPROVAL_MODES.find((mode) => mode.toLowerCase() === trimmed);
}
__name(parseApprovalModeArg, "parseApprovalModeArg");
var approvalModeCommand = {
  name: "approval-mode",
  get description() {
    return t("View or change the approval mode for tool usage");
  },
  argumentHint: "<mode>",
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive"],
  action: /* @__PURE__ */ __name(async (context, args) => {
    const mode = parseApprovalModeArg(args);
    if (!args.trim()) {
      return {
        type: "dialog",
        dialog: "approval-mode"
      };
    }
    if (!mode) {
      return {
        type: "message",
        messageType: "error",
        content: t('Invalid approval mode "{{arg}}". Valid modes: {{modes}}', {
          arg: args.trim(),
          modes: APPROVAL_MODES.join(", ")
        })
      };
    }
    const { config, settings } = context.services;
    let priorMode;
    if (config) {
      try {
        priorMode = config.getApprovalMode();
        config.setApprovalMode(mode);
      } catch (e) {
        return {
          type: "message",
          messageType: "error",
          content: e.message
        };
      }
    }
    if (mode === "auto" /* AUTO */ && priorMode !== "auto" /* AUTO */ && config) {
      emitAutoModeEntryNotices({
        config,
        settings,
        addItem: context.ui.addItem
      });
    }
    return {
      type: "message",
      messageType: "info",
      content: t('Approval mode set to "{{mode}}"', {
        mode: formatApprovalModeName(mode)
      })
    };
  }, "action")
};

// packages/cli/src/ui/commands/authCommand.ts
init_esbuild_shims();
var authCommand = {
  name: "auth",
  altNames: ["connect", "login"],
  get description() {
    return t("Connect an LLM provider");
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive", "non_interactive", "acp"],
  action: /* @__PURE__ */ __name((context, _args) => {
    const executionMode = context.executionMode ?? "interactive";
    if (executionMode !== "interactive") {
      return {
        type: "message",
        messageType: "info",
        content: t(
          "Authentication configuration is only available in interactive mode. To configure authentication, run Qwen Code interactively and use /auth, or set environment variables: OPENAI_API_KEY, OPENAI_BASE_URL, OPENAI_MODEL."
        )
      };
    }
    return {
      type: "dialog",
      dialog: "auth"
    };
  }, "action")
};

// packages/cli/src/ui/commands/branchCommand.ts
init_esbuild_shims();
var branchCommand = {
  name: "branch",
  kind: "built-in" /* BUILT_IN */,
  get description() {
    return t("Fork the current conversation into a new session");
  },
  action: /* @__PURE__ */ __name(async (context, args) => {
    const { config } = context.services;
    if (!config) {
      return {
        type: "message",
        messageType: "error",
        content: t("Config is not available.")
      };
    }
    if (context.ui.isIdleRef?.current === false) {
      return {
        type: "message",
        messageType: "error",
        content: t(
          "Cannot branch while a response or tool call is in progress. Wait for it to finish or resolve the pending tool call."
        )
      };
    }
    const sessionService = config.getSessionService();
    const currentId = config.getSessionId();
    const hasRecords = await sessionService.sessionExists(currentId);
    if (!hasRecords) {
      return {
        type: "message",
        messageType: "error",
        content: t("No conversation to branch.")
      };
    }
    const name = args.trim().replace(/[\r\n]+/g, " ");
    return name ? { type: "dialog", dialog: "branch", name } : { type: "dialog", dialog: "branch" };
  }, "action")
};

// packages/cli/src/ui/commands/btwCommand.ts
init_esbuild_shims();
function formatBtwError(error) {
  return t("Failed to answer btw question: {{error}}", {
    error: error instanceof Error ? error.message : String(error || "Unknown error")
  });
}
__name(formatBtwError, "formatBtwError");
function getBtwCacheSafeParams(context) {
  const { config } = context.services;
  if (config) {
    return buildBtwCacheSafeParams(config);
  }
  return null;
}
__name(getBtwCacheSafeParams, "getBtwCacheSafeParams");
async function askBtw(context, question, abortSignal) {
  const { config } = context.services;
  if (!config) throw new Error("Config not loaded");
  const cacheSafeParams = getBtwCacheSafeParams(context);
  if (!cacheSafeParams)
    throw new Error(t("No conversation context available for /btw"));
  const result = await runForkedAgent({
    config,
    userMessage: buildBtwPrompt(question),
    cacheSafeParams,
    abortSignal
  });
  return result.text || t("No response received.");
}
__name(askBtw, "askBtw");
var btwCommand = {
  name: "btw",
  get description() {
    return t(
      "Ask a quick side question without affecting the main conversation"
    );
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive", "acp"],
  action: /* @__PURE__ */ __name(async (context, args) => {
    const question = args.trim();
    if (!question) {
      return {
        type: "message",
        messageType: "error",
        content: t("Please provide a question. Usage: /btw <your question>")
      };
    }
    if (question.length > BTW_MAX_INPUT_LENGTH) {
      return {
        type: "message",
        messageType: "error",
        content: t("Question too long (max {{max}} chars)", {
          max: String(BTW_MAX_INPUT_LENGTH)
        })
      };
    }
    const { config } = context.services;
    const { ui } = context;
    if (!config) {
      return {
        type: "message",
        messageType: "error",
        content: t("Config not loaded.")
      };
    }
    const model = config.getModel();
    if (!model) {
      return {
        type: "message",
        messageType: "error",
        content: t("No model configured.")
      };
    }
    const executionMode = context.executionMode ?? "interactive";
    if (executionMode !== "interactive") {
      try {
        const answer = await askBtw(
          context,
          question,
          context.abortSignal ?? new AbortController().signal
        );
        return { type: "message", messageType: "info", content: answer };
      } catch (error) {
        return {
          type: "message",
          messageType: "error",
          content: formatBtwError(error)
        };
      }
    }
    ui.cancelBtw();
    const btwAbortController = new AbortController();
    const btwSignal = btwAbortController.signal;
    ui.btwAbortControllerRef.current = btwAbortController;
    const pendingItem = {
      type: "btw" /* BTW */,
      btw: {
        question,
        answer: "",
        isPending: true
      }
    };
    ui.setBtwItem(pendingItem);
    void askBtw(context, question, btwSignal).then((answer) => {
      if (btwSignal.aborted) return;
      ui.btwAbortControllerRef.current = null;
      const completedItem = {
        type: "btw" /* BTW */,
        btw: {
          question,
          answer,
          isPending: false
        }
      };
      ui.setBtwItem(completedItem);
    }).catch((error) => {
      if (btwSignal.aborted) return;
      ui.btwAbortControllerRef.current = null;
      ui.setBtwItem(null);
      ui.addItem(
        {
          type: "error" /* ERROR */,
          text: formatBtwError(error)
        },
        Date.now()
      );
    });
  }, "action")
};

// packages/cli/src/ui/commands/bugCommand.ts
init_esbuild_shims();
var bugCommand = {
  name: "bug",
  get description() {
    return t("submit a bug report");
  },
  kind: "built-in" /* BUILT_IN */,
  argumentHint: "<description>",
  supportedModes: ["interactive", "non_interactive", "acp"],
  action: /* @__PURE__ */ __name(async (context, args) => {
    const bugDescription = (args || "").trim();
    const systemInfo = await getExtendedSystemInfo(context);
    const fields = getSystemInfoFields(systemInfo);
    const info = fields.map((field) => `${field.label}: ${field.value}`).join("\n");
    let bugReportUrl = "https://github.com/QwenLM/qwen-code/issues/new?template=bug_report.yml&title={title}&info={info}";
    const bugCommandSettings = context.services.config?.getBugCommand();
    if (bugCommandSettings?.urlTemplate) {
      bugReportUrl = bugCommandSettings.urlTemplate;
    }
    bugReportUrl = bugReportUrl.replace("{title}", encodeURIComponent(bugDescription)).replace("{info}", encodeURIComponent(`
${info}
`));
    const bugReportItem = {
      type: "info" /* INFO */,
      text: "To submit your bug report, please open the following URL in your browser:",
      linkUrl: bugReportUrl,
      linkText: "Open GitHub bug report form"
    };
    context.ui.addItem(bugReportItem, Date.now());
    try {
      await openBrowserSecurely(bugReportUrl);
    } catch (error) {
      const errorMessage2 = error instanceof Error ? error.message : String(error);
      context.ui.addItem(
        {
          type: "error" /* ERROR */,
          text: `Could not open URL in browser: ${errorMessage2}`
        },
        Date.now()
      );
    }
  }, "action")
};

// packages/cli/src/ui/commands/cdCommand.ts
init_esbuild_shims();
import * as fs3 from "node:fs/promises";
import * as path3 from "node:path";

// packages/cli/src/ui/commands/directoryCommand.tsx
init_esbuild_shims();
import * as fs2 from "node:fs";
import * as path2 from "node:path";
function findExistingWorkspaceDirectory(directory, existingDirectories) {
  if (existingDirectories.has(directory)) {
    return directory;
  }
  try {
    const absolutePath = path2.isAbsolute(directory) ? directory : path2.resolve(directory);
    const resolvedDirectory = fs2.realpathSync(absolutePath);
    if (existingDirectories.has(resolvedDirectory)) {
      return resolvedDirectory;
    }
  } catch {
  }
  return void 0;
}
__name(findExistingWorkspaceDirectory, "findExistingWorkspaceDirectory");
function getDirPathCompletions(partialArg) {
  const lastComma = partialArg.lastIndexOf(",");
  const prefix = lastComma >= 0 ? partialArg.substring(0, lastComma + 1) : "";
  const partial = lastComma >= 0 ? partialArg.substring(lastComma + 1).trimStart() : partialArg;
  return getPathCompletions(prefix, partial);
}
__name(getDirPathCompletions, "getDirPathCompletions");
function getSingleDirPathCompletions(partialArg) {
  return getPathCompletions("", partialArg);
}
__name(getSingleDirPathCompletions, "getSingleDirPathCompletions");
function getPathCompletions(prefix, partial) {
  const trimmed = partial.trim();
  if (!trimmed) return [];
  const inputEndsWithSep = trimmed.endsWith("/") || trimmed.endsWith("\\");
  const expanded = expandHomeDir(trimmed);
  const endsWithSep = inputEndsWithSep || expanded.endsWith("/") || expanded.endsWith(path2.sep);
  const searchDir = endsWithSep ? expanded : path2.dirname(expanded);
  const namePrefix = endsWithSep ? "" : path2.basename(expanded);
  try {
    return fs2.readdirSync(searchDir, { withFileTypes: true }).filter(
      (e) => e.isDirectory() && e.name.startsWith(namePrefix) && !e.name.startsWith(".")
    ).map((e) => ({
      value: prefix + path2.join(searchDir, e.name) + path2.sep,
      isDirectory: true
    })).slice(0, 8);
  } catch {
    return [];
  }
}
__name(getPathCompletions, "getPathCompletions");
var directoryCommand = {
  name: "directory",
  altNames: ["dir"],
  get description() {
    return t("Manage workspace directories");
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive", "acp"],
  action: /* @__PURE__ */ __name(async () => ({
    type: "message",
    messageType: "info",
    content: t("Usage: /directory add <path>[,<path>,...] or /directory show")
  }), "action"),
  subCommands: [
    {
      name: "add",
      get description() {
        return t(
          "Add directories to the workspace. Use comma to separate multiple paths"
        );
      },
      kind: "built-in" /* BUILT_IN */,
      supportedModes: ["interactive", "acp"],
      argumentHint: "<path>[,<path>,...]",
      completion: /* @__PURE__ */ __name(async (_context, partialArg) => getDirPathCompletions(partialArg), "completion"),
      action: /* @__PURE__ */ __name(async (context, args) => {
        const { config, settings } = context.services;
        if (!config) {
          return {
            type: "message",
            messageType: "error",
            content: t("Configuration is not available.")
          };
        }
        const workspaceContext = config.getWorkspaceContext();
        const pathsToAdd = args.split(",").filter((p) => p.trim());
        if (pathsToAdd.length === 0) {
          return {
            type: "message",
            messageType: "error",
            content: t("Please provide at least one path to add.")
          };
        }
        if (config.isRestrictiveSandbox()) {
          return {
            type: "message",
            messageType: "error",
            content: t(
              "The /directory add command is not supported in restrictive sandbox profiles. Please use --include-directories when starting the session instead."
            )
          };
        }
        try {
          const added = [];
          const alreadyAdded = [];
          const errors = [];
          const messages = [];
          for (const pathToAdd of pathsToAdd) {
            const directory = expandHomeDir(pathToAdd.trim());
            const directoriesBeforeAdd = new Set(
              workspaceContext.getDirectories()
            );
            try {
              workspaceContext.addDirectory(directory);
              const acceptedDirectories = workspaceContext.getDirectories().filter((dir) => !directoriesBeforeAdd.has(dir));
              if (acceptedDirectories.length > 0) {
                added.push(...acceptedDirectories);
              } else {
                const existingDirectory = findExistingWorkspaceDirectory(
                  directory,
                  directoriesBeforeAdd
                );
                if (existingDirectory) {
                  alreadyAdded.push(existingDirectory);
                }
              }
            } catch (e) {
              const error = e;
              errors.push(
                t("Error adding '{{path}}': {{error}}", {
                  path: pathToAdd.trim(),
                  error: error.message
                })
              );
            }
          }
          if (added.length > 0) {
            try {
              const existingIncludeDirectories = settings.workspace.originalSettings.context?.includeDirectories ?? [];
              const includeDirectories = Array.from(
                /* @__PURE__ */ new Set([...existingIncludeDirectories, ...added])
              );
              settings.setValue(
                "Workspace" /* Workspace */,
                "context.includeDirectories",
                includeDirectories
              );
            } catch (error) {
              errors.push(
                t("Error saving directories to workspace settings: {{error}}", {
                  error: error.message
                })
              );
            }
          }
          if (added.length > 0) {
            try {
              if (config.isSafeMode()) {
                messages.push(
                  t(
                    "Safe mode active \u2014 skipping memory reload from include directories."
                  )
                );
              } else if (config.shouldLoadMemoryFromIncludeDirectories()) {
                const {
                  memoryContent,
                  fileCount,
                  conditionalRules,
                  projectRoot
                } = await loadServerHierarchicalMemory(
                  config.getWorkingDir(),
                  [...config.getWorkspaceContext().getDirectories(), ...added],
                  config.getFileService(),
                  config.getExtensionContextFilePaths(),
                  config.getFolderTrust(),
                  context.services.settings.merged.context?.importFormat || "tree",
                  config.getContextRuleExcludes()
                );
                config.setUserMemory(memoryContent);
                config.setGeminiMdFileCount(fileCount);
                config.setConditionalRulesRegistry(
                  new ConditionalRulesRegistry(conditionalRules, projectRoot)
                );
                context.ui.setGeminiMdFileCount(fileCount);
                messages.push(
                  t(
                    "Successfully added QWEN.md files from the following directories if there are:\n- {{directories}}",
                    { directories: added.join("\n- ") }
                  )
                );
              }
            } catch (error) {
              errors.push(
                t("Error refreshing memory: {{error}}", {
                  error: error.message
                })
              );
            }
          }
          if (added.length > 0) {
            const gemini = config.getGeminiClient();
            if (gemini) {
              try {
                await gemini.addDirectoryContext();
              } catch (error) {
                errors.push(
                  t("Error notifying model of new directories: {{error}}", {
                    error: error.message
                  })
                );
              }
            }
            messages.push(
              t("Successfully added directories:\n- {{directories}}", {
                directories: added.join("\n- ")
              })
            );
          }
          if (alreadyAdded.length > 0) {
            const directories = Array.from(new Set(alreadyAdded));
            messages.push(
              t("Directories already in workspace:\n- {{directories}}", {
                directories: directories.join("\n- ")
              })
            );
          }
          if (errors.length > 0) {
            return {
              type: "message",
              messageType: added.length > 0 ? "warning" : "error",
              content: [...messages, ...errors].join("\n")
            };
          }
          return {
            type: "message",
            messageType: "info",
            content: messages.join("\n") || t("No directories added.")
          };
        } catch (error) {
          return {
            type: "message",
            messageType: "error",
            content: t("Failed to process /directory add: {{message}}", {
              message: error instanceof Error ? error.message : String(error)
            })
          };
        }
      }, "action")
    },
    {
      name: "show",
      get description() {
        return t("Show all directories in the workspace");
      },
      kind: "built-in" /* BUILT_IN */,
      supportedModes: ["interactive", "acp"],
      action: /* @__PURE__ */ __name(async (context) => {
        const { config } = context.services;
        if (!config) {
          return {
            type: "message",
            messageType: "error",
            content: t("Configuration is not available.")
          };
        }
        const directories = config.getWorkspaceContext().getDirectories();
        const directoryList = directories.map((dir) => `- ${dir}`).join("\n");
        return {
          type: "message",
          messageType: "info",
          content: t("Current workspace directories:\n{{directories}}", {
            directories: directoryList
          })
        };
      }, "action")
    }
  ]
};

// packages/cli/src/ui/commands/cdCommand.ts
var MAX_PENDING_TRUST_CONFIRMATIONS = 50;
var pendingTrustedPathConfirmations = /* @__PURE__ */ new Map();
function parsePathArgument(input) {
  const trimmed = input.trim();
  if (trimmed.startsWith('"') && trimmed.endsWith('"') || trimmed.startsWith("'") && trimmed.endsWith("'")) {
    return trimmed.slice(1, -1);
  }
  return trimmed.replace(/\\([\\\s'"])/g, "$1");
}
__name(parsePathArgument, "parsePathArgument");
function resolveCdPath(input, baseDir) {
  if (input.includes("\0") || baseDir.includes("\0")) {
    throw new Error("Path contains null bytes.");
  }
  return path3.normalize(resolvePath(baseDir, input));
}
__name(resolveCdPath, "resolveCdPath");
var cdCommand = {
  name: "cd",
  get description() {
    return t("Move this session to a new working directory");
  },
  kind: "built-in" /* BUILT_IN */,
  argumentHint: "<path>",
  supportedModes: ["interactive"],
  completion: /* @__PURE__ */ __name(async (_context, partialArg) => getSingleDirPathCompletions(partialArg), "completion"),
  action: /* @__PURE__ */ __name(async (context, args) => {
    const targetArg = parsePathArgument(args);
    if (!targetArg) {
      return {
        type: "message",
        messageType: "info",
        content: "Usage: /cd <path>"
      };
    }
    const { config } = context.services;
    if (!config) {
      return {
        type: "message",
        messageType: "error",
        content: "Configuration is not available."
      };
    }
    if (context.ui.isIdleRef.current === false) {
      return {
        type: "message",
        messageType: "error",
        content: "Cannot change directory while a response or tool call is in progress."
      };
    }
    if (config.isRestrictiveSandbox()) {
      return {
        type: "message",
        messageType: "error",
        content: "The /cd command is not supported in restrictive sandbox profiles. Start a new session in the target directory instead."
      };
    }
    const oldDir = config.getTargetDir();
    let targetPath;
    try {
      targetPath = resolveCdPath(targetArg, oldDir);
    } catch (error) {
      return {
        type: "message",
        messageType: "error",
        content: error instanceof Error ? error.message : String(error)
      };
    }
    let stats;
    try {
      stats = await fs3.stat(targetPath);
    } catch {
      return {
        type: "message",
        messageType: "error",
        content: `Couldn't find a directory at ${targetPath}.`
      };
    }
    if (!stats.isDirectory()) {
      return {
        type: "message",
        messageType: "error",
        content: `${targetPath} is not a directory.`
      };
    }
    const [realOldDir, realTargetPath] = await Promise.all([
      fs3.realpath(oldDir).catch(() => oldDir),
      fs3.realpath(targetPath).catch(() => targetPath)
    ]);
    if (realTargetPath === realOldDir) {
      return {
        type: "message",
        messageType: "info",
        content: `Already in ${realTargetPath}.`
      };
    }
    let trustedTargetPath;
    if (isFolderTrustEnabled(context.services.settings.merged)) {
      const trustedFolders = loadTrustedFolders();
      if (trustedFolders.isPathTrusted(realTargetPath) !== true) {
        const rawInvocation = context.invocation?.raw || `/cd ${targetArg}`;
        const confirmedPath = pendingTrustedPathConfirmations.get(rawInvocation);
        if (context.overwriteConfirmed && confirmedPath && confirmedPath === realTargetPath) {
          pendingTrustedPathConfirmations.delete(rawInvocation);
          trustedTargetPath = realTargetPath;
        } else {
          if (!pendingTrustedPathConfirmations.has(rawInvocation) && pendingTrustedPathConfirmations.size >= MAX_PENDING_TRUST_CONFIRMATIONS) {
            pendingTrustedPathConfirmations.clear();
          }
          pendingTrustedPathConfirmations.set(rawInvocation, realTargetPath);
          return {
            type: "confirm_action",
            prompt: `Move this session to ${realTargetPath}? Qwen Code will be able to read, edit, and execute files there. This folder will be trusted for future sessions.`,
            originalInvocation: {
              raw: rawInvocation
            }
          };
        }
      }
    }
    const warnings = [];
    try {
      const relocation = await config.relocateWorkingDirectory(
        realTargetPath,
        realTargetPath
      );
      if (relocation.memoryRefreshError) {
        warnings.push(
          `Memory refresh failed: ${relocation.memoryRefreshError instanceof Error ? relocation.memoryRefreshError.message : String(relocation.memoryRefreshError)}`
        );
      }
    } catch (error) {
      return {
        type: "message",
        messageType: "error",
        content: `Couldn't move to ${realTargetPath}: ${error instanceof Error ? error.message : String(error)}`
      };
    }
    if (trustedTargetPath) {
      loadTrustedFolders().setValue(trustedTargetPath, "TRUST_FOLDER" /* TRUST_FOLDER */);
    }
    try {
      await config.getGeminiClient()?.addWorkingDirectoryChangedContext(realOldDir, realTargetPath);
    } catch (error) {
      warnings.push(
        `Model context refresh failed: ${error instanceof Error ? error.message : String(error)}`
      );
    }
    return {
      type: "message",
      messageType: warnings.length > 0 ? "warning" : "info",
      content: warnings.length > 0 ? `Moved to ${realTargetPath}. ${warnings.join(" ")}` : `Moved to ${realTargetPath}.`
    };
  }, "action")
};

// packages/cli/src/ui/commands/clearCommand.ts
init_esbuild_shims();

// packages/cli/src/ui/utils/backgroundWorkUtils.ts
init_esbuild_shims();
function hasBlockingBackgroundWork(config) {
  return config.getBackgroundTaskRegistry().hasUnfinalizedTasks() || config.getMonitorRegistry().getRunning().length > 0 || config.getBackgroundShellRegistry().hasRunningEntries() || // R7 (wenshao): the WorkflowRunRegistry is a 4th sibling that the
  // earlier P4b commit forgot to wire here. Without this OR clause,
  // /clear and session-resume happily ran while a workflow was
  // mid-run, orphaning the dispatch loop.
  config.getWorkflowRunRegistry().hasRunningEntries();
}
__name(hasBlockingBackgroundWork, "hasBlockingBackgroundWork");
function resetBackgroundStateForSessionSwitch(config) {
  config.getBackgroundTaskRegistry().reset();
  config.getMonitorRegistry().reset();
  config.getBackgroundShellRegistry().reset();
  config.getWorkflowRunRegistry().reset();
}
__name(resetBackgroundStateForSessionSwitch, "resetBackgroundStateForSessionSwitch");

// packages/cli/src/ui/commands/clearCommand.ts
import process2 from "node:process";
var debugLogger5 = createDebugLogger("CLEAR_COMMAND");
var clearCommand = {
  name: "clear",
  altNames: ["reset", "new"],
  get description() {
    return t("Clear conversation history and free up context");
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive", "non_interactive", "acp"],
  action: /* @__PURE__ */ __name(async (context, _args) => {
    const { config } = context.services;
    const memBefore = process2.memoryUsage();
    if (debugLogger5.isEnabled()) {
      debugLogger5.debug(
        `[CLEAR_START] Starting clear command, heapUsed=${(memBefore.heapUsed / 1024 / 1024).toFixed(1)}MB, rss=${(memBefore.rss / 1024 / 1024).toFixed(1)}MB`
      );
    }
    if (config) {
      if (hasBlockingBackgroundWork(config)) {
        const content = "Stop the current session's running background tasks before starting a new session.";
        context.ui.setDebugMessage(content);
        if (context.executionMode !== "interactive") {
          return {
            type: "message",
            messageType: "error",
            content
          };
        }
        return;
      }
      config.getHookSystem()?.fireSessionEndEvent("clear" /* Clear */).catch((err) => {
        config.getDebugLogger().warn(`SessionEnd hook failed: ${err}`);
      });
      config.getBackgroundTaskRegistry().abortAll({ notify: false });
      config.getMonitorRegistry().abortAll({ notify: false });
      config.getBackgroundShellRegistry().abortAll();
      resetBackgroundStateForSessionSwitch(config);
      const metrics = uiTelemetryService.getMetrics();
      const hasActivity = Object.values(metrics.models).some(
        (m) => m.api.totalRequests > 0
      );
      if (hasActivity) {
        try {
          persistSessionUsage({
            sessionId: config.getSessionId(),
            startTime: context.session.stats.sessionStartTime ?? /* @__PURE__ */ new Date(),
            endTime: /* @__PURE__ */ new Date(),
            project: config.getProjectRoot(),
            metrics
          });
        } catch {
        }
      }
      const newSessionId = config.startNewSession();
      uiTelemetryService.reset();
      const skillTool = config.getToolRegistry()?.getAllTools().find((tool) => tool.name === ToolNames.SKILL);
      if (skillTool && "clearLoadedSkills" in skillTool) {
        skillTool.clearLoadedSkills();
      }
      if (newSessionId && context.session.startNewSession) {
        context.session.startNewSession(newSessionId);
      }
      context.ui.clear();
      const geminiClient = config.getGeminiClient();
      if (geminiClient) {
        context.ui.setDebugMessage(
          t("Starting a new session, resetting chat, and clearing terminal.")
        );
        await geminiClient.resetChat();
      } else {
        context.ui.setDebugMessage(t("Starting a new session and clearing."));
      }
    } else {
      context.ui.setDebugMessage(t("Starting a new session and clearing."));
      context.ui.clear();
    }
    const memAfter = process2.memoryUsage();
    if (debugLogger5.isEnabled()) {
      const heapDiff = (memAfter.heapUsed - memBefore.heapUsed) / 1024 / 1024;
      const rssDiff = (memAfter.rss - memBefore.rss) / 1024 / 1024;
      debugLogger5.debug(
        `[CLEAR_END] Clear command completed, heapUsed=${(memAfter.heapUsed / 1024 / 1024).toFixed(1)}MB, rss=${(memAfter.rss / 1024 / 1024).toFixed(1)}MB, heapDiff=${heapDiff.toFixed(1)}MB, rssDiff=${rssDiff.toFixed(1)}MB`
      );
    }
    if (context.executionMode !== "interactive") {
      return {
        type: "message",
        messageType: "info",
        content: "Context cleared. Previous messages are no longer in context."
      };
    }
    return;
  }, "action")
};

// packages/cli/src/ui/commands/config-command.ts
init_esbuild_shims();
var SETTABLE_TYPES = /* @__PURE__ */ new Set(["boolean", "string", "number", "enum"]);
var SENSITIVE_KEY_PATTERNS = [
  /apikey/i,
  /api[_-]?key/i,
  /secret/i,
  /(?:^|\.)token(?:$|\.)/i,
  /password/i,
  /credential/i,
  /private[_-]?key/i
];
var SENSITIVE_URL_PATTERNS = [/baseurl/i, /base_url/i, /proxy/i];
function isSensitiveKey(key) {
  return SENSITIVE_KEY_PATTERNS.some((p) => p.test(key)) || SENSITIVE_URL_PATTERNS.some((p) => p.test(key));
}
__name(isSensitiveKey, "isSensitiveKey");
function maskValue(value) {
  if (value === void 0) return t("(not set)");
  if (typeof value === "string") {
    if (!value) return t("(empty)");
    if (value.length <= 4) return "****";
    return `${value.slice(0, 4)}****`;
  }
  return "****";
}
__name(maskValue, "maskValue");
function findClosestKey(input) {
  const allKeys = getAllSettingKeys();
  let bestMatch;
  let bestDistance = Infinity;
  for (const key of allKeys) {
    const def = getSettingDefinition(key);
    if (!def || !SETTABLE_TYPES.has(def.type)) continue;
    const distance = levenshteinDistance(
      input.toLowerCase(),
      key.toLowerCase()
    );
    if (distance < bestDistance && distance <= 3) {
      bestDistance = distance;
      bestMatch = key;
    }
  }
  return bestMatch;
}
__name(findClosestKey, "findClosestKey");
function levenshteinDistance(a, b) {
  const matrix = [];
  for (let i = 0; i <= a.length; i++) {
    matrix[i] = [i];
  }
  for (let j = 0; j <= b.length; j++) {
    matrix[0][j] = j;
  }
  for (let i = 1; i <= a.length; i++) {
    for (let j = 1; j <= b.length; j++) {
      const cost = a[i - 1] === b[j - 1] ? 0 : 1;
      matrix[i][j] = Math.min(
        matrix[i - 1][j] + 1,
        matrix[i][j - 1] + 1,
        matrix[i - 1][j - 1] + cost
      );
    }
  }
  return matrix[a.length][b.length];
}
__name(levenshteinDistance, "levenshteinDistance");
function coerceValue(def, rawValue) {
  switch (def.type) {
    case "boolean": {
      const normalised = rawValue?.toLowerCase().trim();
      if (normalised === "true" || normalised === "1") return { value: true };
      if (normalised === "false" || normalised === "0") return { value: false };
      return {
        value: void 0,
        error: t('Invalid boolean value: "{{value}}". Use "true" or "false".', {
          value: String(rawValue)
        })
      };
    }
    case "number": {
      if (!rawValue || rawValue.trim() === "") {
        return {
          value: void 0,
          error: t('Invalid number value: "{{value}}".', {
            value: String(rawValue)
          })
        };
      }
      const parsed = Number(rawValue);
      if (Number.isNaN(parsed) || !Number.isFinite(parsed)) {
        return {
          value: void 0,
          error: t('Invalid number value: "{{value}}".', {
            value: String(rawValue)
          })
        };
      }
      const validationError = validateSettingValue(def, parsed);
      if (validationError) {
        return { value: void 0, error: validationError };
      }
      return { value: parsed };
    }
    case "string": {
      const strValue = rawValue ?? "";
      const validationError = validateSettingValue(def, strValue);
      if (validationError) {
        return { value: void 0, error: validationError };
      }
      return { value: strValue };
    }
    case "enum": {
      const validValues = def.options?.map((o) => o.value) ?? [];
      if (!validValues.includes(rawValue)) {
        return {
          value: void 0,
          error: t(
            'Invalid enum value: "{{value}}". Valid values: {{options}}.',
            { value: String(rawValue), options: validValues.join(", ") }
          )
        };
      }
      return { value: rawValue };
    }
    case "array":
    case "object":
      return {
        value: void 0,
        error: t(
          'Setting "{{type}}" type cannot be set via /config. Edit settings.json directly.',
          { type: def.type }
        )
      };
    default:
      return {
        value: void 0,
        error: t('Unsupported setting type: "{{type}}".', {
          type: String(def.type)
        })
      };
  }
}
__name(coerceValue, "coerceValue");
function formatValue(value) {
  if (value === void 0) return t("(not set)");
  if (typeof value === "string") return value || t("(empty)");
  return JSON.stringify(value);
}
__name(formatValue, "formatValue");
function padRight(str, len) {
  if (str.length > len) return str.slice(0, len - 3) + "... ";
  if (str.length === len) return str + " ";
  return str + " ".repeat(len - str.length);
}
__name(padRight, "padRight");
function listAllSettings(context) {
  const flattened = getFlattenedSchema();
  const merged = context.services.settings.merged;
  const lines = [];
  lines.push(t("Available settings:"));
  lines.push("");
  lines.push(
    padRight("Key", 40) + padRight("Type", 10) + padRight("Current", 15) + "Description"
  );
  lines.push("-".repeat(90));
  const keys = Object.keys(flattened).sort();
  for (const key of keys) {
    const def = flattened[key];
    if (!SETTABLE_TYPES.has(def.type)) continue;
    const current = getNestedProperty(merged, key);
    let displayCurrent;
    if (isSensitiveKey(key)) {
      displayCurrent = maskValue(current ?? def.default);
    } else {
      displayCurrent = current !== void 0 ? formatValue(current) : formatValue(def.default);
    }
    lines.push(
      padRight(key, 40) + padRight(def.type, 10) + padRight(displayCurrent, 15) + (def.description ?? def.label)
    );
  }
  return {
    type: "message",
    messageType: "info",
    content: lines.join("\n")
  };
}
__name(listAllSettings, "listAllSettings");
var configCommand = {
  name: "config",
  get description() {
    return t("Get or set any setting by dot-path key");
  },
  argumentHint: "<key>[=<value>] or --help",
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive", "non_interactive", "acp"],
  action: /* @__PURE__ */ __name(async (context, args) => {
    const trimmed = args.trim();
    if (!trimmed || trimmed === "--help" || trimmed === "-h") {
      return listAllSettings(context);
    }
    const eqIndex = trimmed.indexOf("=");
    const isToggle = eqIndex === -1;
    const key = isToggle ? trimmed : trimmed.slice(0, eqIndex).trim();
    const rawValue = isToggle ? void 0 : trimmed.slice(eqIndex + 1).trim();
    const def = getSettingDefinition(key);
    if (!def) {
      const suggestion = findClosestKey(key);
      return {
        type: "message",
        messageType: "error",
        content: suggestion ? t(
          'Unknown setting key: "{{key}}". Did you mean "{{suggestion}}"?',
          { key, suggestion }
        ) : t('Unknown setting key: "{{key}}".', { key })
      };
    }
    const currentValue = getNestedProperty(
      context.services.settings.merged,
      key
    );
    if (isToggle && def.type !== "boolean") {
      const display = isSensitiveKey(key) ? maskValue(currentValue) : formatValue(currentValue);
      return {
        type: "message",
        messageType: "info",
        content: `${key} = ${display}`
      };
    }
    if (isToggle && def.type === "boolean") {
      const newValue = !currentValue;
      try {
        context.services.settings.setValues([
          { scope: "User" /* User */, key, value: newValue }
        ]);
      } catch (error) {
        return {
          type: "message",
          messageType: "error",
          content: t('Failed to set "{{key}}": {{error}}', {
            key,
            error: error instanceof Error ? error.message : String(error)
          })
        };
      }
      let message2 = t("Set {{key}} = {{value}}", {
        key,
        value: String(newValue)
      });
      if (def.requiresRestart) {
        message2 += "\n" + t("(This setting requires a restart to take effect.)");
      }
      return {
        type: "message",
        messageType: "info",
        content: message2
      };
    }
    const result = coerceValue(def, rawValue);
    if (result.error) {
      return {
        type: "message",
        messageType: "error",
        content: result.error
      };
    }
    if (key === "tools.approvalMode" && result.value === "yolo") {
      return {
        type: "message",
        messageType: "error",
        content: t(
          'Setting tools.approvalMode to "yolo" is blocked via /config for security reasons. Edit settings.json directly if you understand the risks.'
        )
      };
    }
    try {
      context.services.settings.setValues([
        { scope: "User" /* User */, key, value: result.value }
      ]);
    } catch (error) {
      return {
        type: "message",
        messageType: "error",
        content: t('Failed to set "{{key}}": {{error}}', {
          key,
          error: error instanceof Error ? error.message : String(error)
        })
      };
    }
    const displayValue = isSensitiveKey(key) ? maskValue(result.value) : formatValue(result.value);
    let message = t("Set {{key}} = {{value}}", {
      key,
      value: displayValue
    });
    if (def.requiresRestart) {
      message += "\n" + t("(This setting requires a restart to take effect.)");
    }
    if (isSensitiveKey(key)) {
      message += "\n" + t(
        "(Security-sensitive setting \u2014 verify you are not exposing credentials.)"
      );
    }
    return {
      type: "message",
      messageType: "info",
      content: message
    };
  }, "action"),
  completion: /* @__PURE__ */ __name(async (_context, partialArg) => {
    const current = partialArg.trimStart();
    if (current.includes("=")) return null;
    const allKeys = getAllSettingKeys();
    return allKeys.filter((k) => {
      if (!k.startsWith(current)) return false;
      const def = getSettingDefinition(k);
      return def && SETTABLE_TYPES.has(def.type);
    }).map((k) => {
      const def = getSettingDefinition(k);
      return {
        value: k,
        description: def?.description ?? ""
      };
    });
  }, "completion")
};

// packages/cli/src/ui/commands/deleteCommand.ts
init_esbuild_shims();
var deleteCommand = {
  name: "delete",
  kind: "built-in" /* BUILT_IN */,
  get description() {
    return t("Delete a previous session");
  },
  action: /* @__PURE__ */ __name(async () => ({
    type: "dialog",
    dialog: "delete"
  }), "action")
};

// packages/cli/src/ui/commands/compressCommand.ts
init_esbuild_shims();
var MAX_COMPRESS_INSTRUCTIONS_CHARS = 2e3;
var compressCommand = {
  name: "compress",
  altNames: ["summarize"],
  get description() {
    return t("Compresses the context by replacing it with a summary.");
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive", "non_interactive", "acp"],
  action: /* @__PURE__ */ __name(async (context) => {
    const { ui } = context;
    const executionMode = context.executionMode ?? "interactive";
    const abortSignal = context.abortSignal;
    if (executionMode === "interactive" && ui.pendingItem) {
      ui.addItem(
        {
          type: "error" /* ERROR */,
          text: t("Already compressing, wait for previous request to complete")
        },
        Date.now()
      );
      return;
    }
    const pendingMessage = {
      type: "compression" /* COMPRESSION */,
      compression: {
        isPending: true,
        originalTokenCount: null,
        newTokenCount: null,
        compressionStatus: null
      }
    };
    const config = context.services.config;
    const geminiClient = config?.getGeminiClient();
    if (!config || !geminiClient) {
      return {
        type: "message",
        messageType: "error",
        content: t("Config not loaded.")
      };
    }
    const rawArgs = context.invocation?.args?.trim() ?? "";
    const wasTruncated = rawArgs.length > MAX_COMPRESS_INSTRUCTIONS_CHARS;
    const customInstructions = rawArgs ? rawArgs.slice(0, MAX_COMPRESS_INSTRUCTIONS_CHARS) : void 0;
    const truncationNotice = wasTruncated ? t("Compression instructions were truncated to {{max}} characters.", {
      max: String(MAX_COMPRESS_INSTRUCTIONS_CHARS)
    }) : void 0;
    const doCompress = /* @__PURE__ */ __name(async () => {
      const promptId = `compress-${Date.now()}`;
      return await geminiClient.tryCompressChat(
        promptId,
        true,
        abortSignal,
        customInstructions
      );
    }, "doCompress");
    if (executionMode === "acp") {
      const messages = /* @__PURE__ */ __name(async function* () {
        try {
          if (truncationNotice) {
            yield {
              messageType: "info",
              content: truncationNotice
            };
          }
          yield {
            messageType: "info",
            content: "Compressing context..."
          };
          const compressed = await doCompress();
          if (!compressed) {
            yield {
              messageType: "error",
              content: t("Failed to compress chat history.")
            };
            return;
          }
          yield {
            messageType: "info",
            content: `Context compressed (${compressed.originalTokenCount} -> ${compressed.newTokenCount}).`
          };
        } catch (e) {
          yield {
            messageType: "error",
            content: t("Failed to compress chat history: {{error}}", {
              error: e instanceof Error ? e.message : String(e)
            })
          };
        }
      }, "messages");
      return { type: "stream_messages", messages: messages() };
    }
    try {
      if (executionMode === "interactive") {
        if (truncationNotice) {
          ui.addItem(
            { type: "info" /* INFO */, text: truncationNotice },
            Date.now()
          );
        }
        ui.setPendingItem(pendingMessage);
      }
      const compressed = await doCompress();
      if (abortSignal?.aborted) {
        return;
      }
      if (!compressed) {
        if (executionMode === "interactive") {
          ui.addItem(
            {
              type: "error" /* ERROR */,
              text: t("Failed to compress chat history.")
            },
            Date.now()
          );
          return;
        }
        return {
          type: "message",
          messageType: "error",
          content: t("Failed to compress chat history.")
        };
      }
      if (executionMode === "interactive") {
        ui.addItem(
          {
            type: "compression" /* COMPRESSION */,
            compression: {
              isPending: false,
              originalTokenCount: compressed.originalTokenCount,
              newTokenCount: compressed.newTokenCount,
              compressionStatus: compressed.compressionStatus
            }
          },
          Date.now()
        );
        return;
      }
      return {
        type: "message",
        messageType: "info",
        content: `${truncationNotice ? `${truncationNotice} ` : ""}Context compressed (${compressed.originalTokenCount} -> ${compressed.newTokenCount}).`
      };
    } catch (e) {
      if (abortSignal?.aborted) {
        return;
      }
      if (executionMode === "interactive") {
        ui.addItem(
          {
            type: "error" /* ERROR */,
            text: t("Failed to compress chat history: {{error}}", {
              error: e instanceof Error ? e.message : String(e)
            })
          },
          Date.now()
        );
        return;
      }
      return {
        type: "message",
        messageType: "error",
        content: t("Failed to compress chat history: {{error}}", {
          error: e instanceof Error ? e.message : String(e)
        })
      };
    } finally {
      if (executionMode === "interactive") {
        ui.setPendingItem(null);
      }
    }
  }, "action")
};

// packages/cli/src/ui/commands/compressFastCommand.ts
init_esbuild_shims();
var compressFastCommand = {
  name: "compress-fast",
  get description() {
    return t(
      "Fast context compression without AI. Strips old tool outputs and thinking parts."
    );
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive", "non_interactive", "acp"],
  action: /* @__PURE__ */ __name(async (context) => {
    const { ui } = context;
    const executionMode = context.executionMode ?? "interactive";
    if (executionMode === "interactive" && ui.pendingItem) {
      ui.addItem(
        {
          type: "error" /* ERROR */,
          text: t("Already compressing, wait for previous request to complete")
        },
        Date.now()
      );
      return;
    }
    const pendingMessage = {
      type: "compression" /* COMPRESSION */,
      compression: {
        isPending: true,
        originalTokenCount: null,
        newTokenCount: null,
        compressionStatus: null
      }
    };
    const config = context.services.config;
    const geminiClient = config?.getGeminiClient();
    if (!config || !geminiClient) {
      return {
        type: "message",
        messageType: "error",
        content: t("Config not loaded.")
      };
    }
    const doCompress = /* @__PURE__ */ __name(async () => await geminiClient.tryCompressChatFast(), "doCompress");
    if (executionMode === "acp") {
      const messages = /* @__PURE__ */ __name(async function* () {
        try {
          yield {
            messageType: "info",
            content: "Compressing context (fast)..."
          };
          const compressed = await doCompress();
          if (!compressed || compressed.compressionStatus === 5 /* NOOP */) {
            yield {
              messageType: "info",
              content: t("No compression needed.")
            };
            return;
          }
          yield {
            messageType: "info",
            content: `Context compressed (${compressed.originalTokenCount} -> ${compressed.newTokenCount}).`
          };
        } catch (e) {
          yield {
            messageType: "error",
            content: t("Failed to compress chat history: {{error}}", {
              error: e instanceof Error ? e.message : String(e)
            })
          };
        }
      }, "messages");
      return { type: "stream_messages", messages: messages() };
    }
    try {
      if (executionMode === "interactive") {
        ui.setPendingItem(pendingMessage);
      }
      const compressed = await doCompress();
      if (!compressed || compressed.compressionStatus === 5 /* NOOP */) {
        if (executionMode === "interactive") {
          ui.addItem(
            {
              type: "info" /* INFO */,
              text: t("No compression needed.")
            },
            Date.now()
          );
          return;
        }
        return {
          type: "message",
          messageType: "info",
          content: t("No compression needed.")
        };
      }
      if (executionMode === "interactive") {
        ui.addItem(
          {
            type: "compression" /* COMPRESSION */,
            compression: {
              isPending: false,
              originalTokenCount: compressed.originalTokenCount,
              newTokenCount: compressed.newTokenCount,
              compressionStatus: compressed.compressionStatus
            }
          },
          Date.now()
        );
        return;
      }
      return {
        type: "message",
        messageType: "info",
        content: `Context compressed (${compressed.originalTokenCount} -> ${compressed.newTokenCount}).`
      };
    } catch (e) {
      if (executionMode === "interactive") {
        ui.addItem(
          {
            type: "error" /* ERROR */,
            text: t("Failed to compress chat history: {{error}}", {
              error: e instanceof Error ? e.message : String(e)
            })
          },
          Date.now()
        );
        return;
      }
      return {
        type: "message",
        messageType: "error",
        content: t("Failed to compress chat history: {{error}}", {
          error: e instanceof Error ? e.message : String(e)
        })
      };
    } finally {
      if (executionMode === "interactive") {
        ui.setPendingItem(null);
      }
    }
  }, "action")
};

// packages/cli/src/ui/commands/copyCommand.ts
init_esbuild_shims();
var INLINE_MATH_MAX_CHARS = 1024;
var INLINE_MATH_REGEX = new RegExp(
  String.raw`(?<![\w$])\$(?![\s\d$])(?=[^$\n]{1,${INLINE_MATH_MAX_CHARS}}\S\$)([^$\n]{1,${INLINE_MATH_MAX_CHARS}})\$(?![\w$])`,
  "g"
);
function parseFencedCodeBlocks(markdown) {
  const blocks = [];
  const lines = markdown.split(/\r?\n/);
  const fenceRegex = /^ *(`{3,}|~{3,}) *([^`]*)$/;
  const languageCounts = /* @__PURE__ */ new Map();
  let activeFence = null;
  let activeLang = null;
  let activeLangIndex = null;
  let activeLines = [];
  for (const line of lines) {
    const match = line.match(fenceRegex);
    if (!activeFence) {
      if (match) {
        activeFence = match[1];
        activeLang = match[2]?.trim().split(/\s+/)[0]?.toLowerCase() || null;
        if (activeLang) {
          const nextLangIndex = (languageCounts.get(activeLang) ?? 0) + 1;
          languageCounts.set(activeLang, nextLangIndex);
          activeLangIndex = nextLangIndex;
        } else {
          activeLangIndex = null;
        }
        activeLines = [];
      }
      continue;
    }
    if (match && match[1].startsWith(activeFence[0]) && match[1].length >= activeFence.length) {
      blocks.push({
        lang: activeLang,
        content: activeLines.join("\n"),
        index: blocks.length + 1,
        langIndex: activeLangIndex
      });
      activeFence = null;
      activeLang = null;
      activeLangIndex = null;
      activeLines = [];
      continue;
    }
    activeLines.push(line);
  }
  return blocks;
}
__name(parseFencedCodeBlocks, "parseFencedCodeBlocks");
function parseInlineLatexExpressions(markdown) {
  const expressions = [];
  const lines = markdown.split(/\r?\n/);
  const codeFenceRegex = /^ *(`{3,}|~{3,}) *([^`]*)$/;
  const mathFenceRegex = /^ *\$\$ *$/;
  let activeCodeFence = null;
  let inLatexBlock = false;
  for (const line of lines) {
    const codeFenceMatch = line.match(codeFenceRegex);
    if (activeCodeFence) {
      if (codeFenceMatch && codeFenceMatch[1].startsWith(activeCodeFence[0]) && codeFenceMatch[1].length >= activeCodeFence.length) {
        activeCodeFence = null;
      }
      continue;
    }
    if (inLatexBlock) {
      if (mathFenceRegex.test(line)) {
        inLatexBlock = false;
      }
      continue;
    }
    if (codeFenceMatch) {
      activeCodeFence = codeFenceMatch[1];
      continue;
    }
    if (mathFenceRegex.test(line)) {
      inLatexBlock = true;
      continue;
    }
    for (const match of line.matchAll(INLINE_MATH_REGEX)) {
      const content = match[1];
      if (content) {
        expressions.push({
          content,
          index: expressions.length + 1
        });
      }
    }
  }
  return expressions;
}
__name(parseInlineLatexExpressions, "parseInlineLatexExpressions");
function selectInlineLatexExpression(markdown, tokens) {
  const expressions = parseInlineLatexExpressions(markdown);
  if (expressions.length === 0) return null;
  let requestedIndex = null;
  for (const token of tokens) {
    if (/^\d+$/.test(token)) {
      requestedIndex = Number(token);
    }
  }
  const selected = requestedIndex !== null ? expressions.find((expression) => expression.index === requestedIndex) : expressions[expressions.length - 1];
  return selected ? {
    expression: selected,
    label: `Inline LaTeX expression ${selected.index}`
  } : null;
}
__name(selectInlineLatexExpression, "selectInlineLatexExpression");
function parseLatexBlocks(markdown) {
  const blocks = [];
  const lines = markdown.split(/\r?\n/);
  const codeFenceRegex = /^ *(`{3,}|~{3,}) *([^`]*)$/;
  const mathFenceRegex = /^ *\$\$ *$/;
  let activeCodeFence = null;
  let inLatexBlock = false;
  let activeLines = [];
  for (const line of lines) {
    const codeFenceMatch = line.match(codeFenceRegex);
    if (activeCodeFence) {
      if (codeFenceMatch && codeFenceMatch[1].startsWith(activeCodeFence[0]) && codeFenceMatch[1].length >= activeCodeFence.length) {
        activeCodeFence = null;
      }
      continue;
    }
    if (!inLatexBlock) {
      if (codeFenceMatch) {
        activeCodeFence = codeFenceMatch[1];
        continue;
      }
      if (mathFenceRegex.test(line)) {
        inLatexBlock = true;
        activeLines = [];
      }
      continue;
    }
    if (mathFenceRegex.test(line)) {
      blocks.push({
        content: activeLines.join("\n"),
        index: blocks.length + 1
      });
      inLatexBlock = false;
      activeLines = [];
      continue;
    }
    activeLines.push(line);
  }
  return blocks;
}
__name(parseLatexBlocks, "parseLatexBlocks");
function selectLatexBlock(markdown, args) {
  const tokens = args.trim().split(/\s+/).filter(Boolean);
  const firstToken = tokens[0]?.toLowerCase();
  if (firstToken !== "latex" && firstToken !== "math" && firstToken !== "inline-latex") {
    return void 0;
  }
  if (firstToken === "inline-latex") {
    return selectInlineLatexExpression(markdown, tokens.slice(1));
  }
  const selectorTokens = tokens.slice(1);
  const inlineSelectorIndex = selectorTokens.findIndex(
    (token) => token.toLowerCase() === "inline"
  );
  if (inlineSelectorIndex !== -1) {
    return selectInlineLatexExpression(
      markdown,
      selectorTokens.filter((_, index) => index !== inlineSelectorIndex)
    );
  }
  const blocks = parseLatexBlocks(markdown);
  if (blocks.length === 0) return null;
  let requestedIndex = null;
  for (const token of selectorTokens) {
    if (/^\d+$/.test(token)) {
      requestedIndex = Number(token);
    }
  }
  const selected = requestedIndex !== null ? blocks.find((block) => block.index === requestedIndex) : blocks[blocks.length - 1];
  return selected ? { block: selected, label: `LaTeX block ${selected.index}` } : null;
}
__name(selectLatexBlock, "selectLatexBlock");
function selectCodeBlock(markdown, args) {
  const tokens = args.trim().split(/\s+/).filter(Boolean);
  const firstToken = tokens[0]?.toLowerCase();
  if (!firstToken) return void 0;
  const blocks = parseFencedCodeBlocks(markdown);
  if (blocks.length === 0) return null;
  let lang = null;
  let requestedIndex = null;
  const selectorTokens = firstToken === "code" ? tokens.slice(1) : tokens.map((token) => token);
  if (firstToken !== "code") {
    lang = firstToken;
  }
  for (const token of selectorTokens) {
    if (/^\d+$/.test(token)) {
      requestedIndex = Number(token);
    } else if (token.toLowerCase() !== "code") {
      lang = token.toLowerCase();
    }
  }
  const candidates = lang ? blocks.filter((block) => block.lang === lang) : blocks;
  if (candidates.length === 0) return null;
  if (requestedIndex !== null) {
    const requested = lang ? candidates.find((block) => block.langIndex === requestedIndex) : blocks.find((block) => block.index === requestedIndex);
    return requested ? { block: requested, label: formatCodeBlockLabel(requested, lang) } : null;
  }
  const selected = candidates[candidates.length - 1];
  return selected ? { block: selected, label: formatCodeBlockLabel(selected, lang) } : null;
}
__name(selectCodeBlock, "selectCodeBlock");
function formatCodeBlockLabel(block, selectedLanguage) {
  if (selectedLanguage && block.langIndex !== null) {
    return `${selectedLanguage} code block ${block.langIndex}`;
  }
  return `Code block ${block.index}`;
}
__name(formatCodeBlockLabel, "formatCodeBlockLabel");
function parseLeadingMessageIndex(args) {
  const trimmed = args.trim();
  if (!trimmed) return { messageIndex: null, subArgs: "" };
  const firstWhitespace = trimmed.search(/\s/);
  const firstToken = firstWhitespace === -1 ? trimmed : trimmed.slice(0, firstWhitespace);
  if (!/^\d+$/.test(firstToken)) {
    return { messageIndex: null, subArgs: args };
  }
  return {
    messageIndex: Number(firstToken),
    subArgs: firstWhitespace === -1 ? "" : trimmed.slice(firstWhitespace + 1)
  };
}
__name(parseLeadingMessageIndex, "parseLeadingMessageIndex");
var copyCommand = {
  name: "copy",
  get description() {
    return t(
      "Copy to clipboard: reply, code (by lang), LaTeX, or Mermaid. N = Nth-latest message, index = block number"
    );
  },
  argumentHint: "[N] [<lang>|code|latex|mermaid] [<index>]",
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive"],
  action: /* @__PURE__ */ __name(async (context, args) => {
    const chat = await context.services.config?.getGeminiClient()?.getChat();
    const history = chat?.getHistoryShallow();
    const aiMessages = history?.filter((item) => item.role === "model") ?? [];
    if (aiMessages.length === 0) {
      return {
        type: "message",
        messageType: "info",
        content: "No output in history"
      };
    }
    const { messageIndex, subArgs } = parseLeadingMessageIndex(args);
    let selectedAiMessage;
    if (messageIndex !== null) {
      if (messageIndex < 1) {
        return {
          type: "message",
          messageType: "info",
          content: "Message index must be a positive integer (1 = last AI message)."
        };
      }
      if (messageIndex > aiMessages.length) {
        const turnLabel = aiMessages.length === 1 ? "AI message" : "AI messages";
        return {
          type: "message",
          messageType: "info",
          content: `Only ${aiMessages.length} ${turnLabel} in this session.`
        };
      }
      selectedAiMessage = aiMessages[aiMessages.length - messageIndex];
    } else {
      selectedAiMessage = aiMessages[aiMessages.length - 1];
    }
    const isIndexed = messageIndex !== null && messageIndex > 1;
    const sourceLabel = isIndexed ? `AI message ${messageIndex}` : "the last AI output";
    const sourceLabelCapitalized = isIndexed ? `AI message ${messageIndex}` : "Last AI output";
    const aiOutput = selectedAiMessage.parts?.filter((part) => part.text && !part.thought).map((part) => part.text).join("");
    if (aiOutput) {
      try {
        const selectedLatexBlock = selectLatexBlock(aiOutput, subArgs);
        if (selectedLatexBlock === null) {
          return {
            type: "message",
            messageType: "info",
            content: subArgs.trim().split(/\s+/).some((token) => token === "inline") || subArgs.trim().toLowerCase().startsWith("inline-latex") ? `No matching inline LaTeX expression found in ${sourceLabel}.` : `No matching LaTeX block found in ${sourceLabel}.`
          };
        }
        if (selectedLatexBlock !== void 0) {
          const copiedLatex = "expression" in selectedLatexBlock ? selectedLatexBlock.expression.content : selectedLatexBlock.block.content;
          await copyToClipboard(copiedLatex);
          return {
            type: "message",
            messageType: "info",
            content: `${selectedLatexBlock.label} copied to the clipboard`
          };
        }
        const selectedCodeBlock = selectCodeBlock(aiOutput, subArgs);
        if (selectedCodeBlock === null) {
          return {
            type: "message",
            messageType: "info",
            content: `No matching code block found in ${sourceLabel}.`
          };
        }
        const copiedText = selectedCodeBlock?.block.content ?? aiOutput;
        await copyToClipboard(copiedText);
        return {
          type: "message",
          messageType: "info",
          content: selectedCodeBlock ? `${selectedCodeBlock.label} copied to the clipboard` : isIndexed ? `AI message ${messageIndex} copied to the clipboard` : "Last output copied to the clipboard"
        };
      } catch (error) {
        const message = error instanceof Error ? error.message : String(error);
        context.services.config?.getDebugLogger().debug(message);
        return {
          type: "message",
          messageType: "error",
          content: `Failed to copy to the clipboard. ${message}`
        };
      }
    } else {
      return {
        type: "message",
        messageType: "info",
        content: `${sourceLabelCapitalized} contains no text to copy.`
      };
    }
  }, "action")
};

// packages/cli/src/ui/commands/docsCommand.ts
init_esbuild_shims();
import process3 from "node:process";
var docsCommand = {
  name: "docs",
  get description() {
    return t("open full Qwen Code documentation in your browser");
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive", "non_interactive", "acp"],
  action: /* @__PURE__ */ __name(async (context) => {
    const langPath = getCurrentLanguage()?.startsWith("zh") ? "zh" : "en";
    const docsUrl = `https://qwenlm.github.io/qwen-code-docs/${langPath}`;
    if (context.executionMode !== "interactive") {
      return {
        type: "message",
        messageType: "info",
        content: `Qwen Code documentation: ${docsUrl}`
      };
    }
    if (process3.env["SANDBOX"] && process3.env["SANDBOX"] !== "sandbox-exec") {
      context.ui.addItem(
        {
          type: "info" /* INFO */,
          text: t(
            "Please open the following URL in your browser to view the documentation:\n{{url}}",
            {
              url: docsUrl
            }
          )
        },
        Date.now()
      );
    } else {
      context.ui.addItem(
        {
          type: "info" /* INFO */,
          text: t("Opening documentation in your browser: {{url}}", {
            url: docsUrl
          })
        },
        Date.now()
      );
      try {
        await openBrowserSecurely(docsUrl);
      } catch (_error) {
        context.ui.addItem(
          {
            type: "error" /* ERROR */,
            text: t("Failed to open browser. View documentation at {{url}}", {
              url: docsUrl
            })
          },
          Date.now()
        );
      }
    }
    return;
  }, "action")
};

// packages/cli/src/ui/commands/doctorCommand.ts
init_esbuild_shims();

// packages/cli/src/utils/doctorChecks.ts
init_esbuild_shims();
import process4 from "node:process";
import os from "node:os";
var MIN_NODE_MAJOR = 22;
function checkNodeVersion() {
  const version = process4.version;
  const major = parseInt(version.replace(/^v/, "").split(".")[0], 10);
  if (isNaN(major) || major < MIN_NODE_MAJOR) {
    return {
      category: t("System"),
      name: t("Node.js version"),
      status: "fail",
      message: version,
      detail: t("Node.js v{{min}}+ is required. Current: {{version}}", {
        min: String(MIN_NODE_MAJOR),
        version
      })
    };
  }
  return {
    category: t("System"),
    name: t("Node.js version"),
    status: "pass",
    message: version
  };
}
__name(checkNodeVersion, "checkNodeVersion");
async function checkNpmVersion() {
  const version = await getNpmVersion();
  if (version === "unknown") {
    return {
      category: t("System"),
      name: t("npm version"),
      status: "warn",
      message: t("not found"),
      detail: t("npm is not available. Some features may not work.")
    };
  }
  return {
    category: t("System"),
    name: t("npm version"),
    status: "pass",
    message: version
  };
}
__name(checkNpmVersion, "checkNpmVersion");
function checkPlatform() {
  return {
    category: t("System"),
    name: t("Platform"),
    status: "pass",
    message: `${process4.platform}/${process4.arch} (${os.release()})`
  };
}
__name(checkPlatform, "checkPlatform");
function checkAuth(context) {
  const config = context.services.config;
  const authType = config?.getAuthType();
  if (!authType) {
    return {
      category: t("Authentication"),
      name: t("API key"),
      status: "fail",
      message: t("not configured"),
      detail: t("Run /auth to configure authentication.")
    };
  }
  const error = validateAuthMethod(authType, config ?? void 0);
  if (error) {
    return {
      category: t("Authentication"),
      name: t("API key"),
      status: "fail",
      message: t("invalid ({{authType}})", { authType }),
      detail: error
    };
  }
  const cgConfig = typeof config?.getContentGeneratorConfig === "function" ? config.getContentGeneratorConfig() : void 0;
  const model = cgConfig?.model ?? config?.getModel();
  const baseUrl = cgConfig?.baseUrl;
  const envKey = cgConfig?.apiKeyEnvKey;
  const provider = findProviderByCredentials(baseUrl, envKey);
  const detailParts = [];
  if (provider) {
    detailParts.push(
      t("Provider: {{provider}}", { provider: t(provider.label) })
    );
  }
  if (baseUrl) {
    detailParts.push(t("Base URL: {{baseUrl}}", { baseUrl }));
  }
  if (model) {
    detailParts.push(t("Model: {{model}}", { model }));
  }
  if (envKey) {
    const hasKey = !!process4.env[envKey];
    detailParts.push(
      hasKey ? t("API key: configured ({{envKey}})", { envKey }) : t("API key: {{envKey}} not set", { envKey })
    );
  }
  return {
    category: t("Authentication"),
    name: t("API key"),
    status: "pass",
    message: t("configured ({{authType}})", { authType }),
    detail: detailParts.length > 0 ? detailParts.join("\n") : void 0
  };
}
__name(checkAuth, "checkAuth");
async function checkApiClient(context) {
  const config = context.services.config;
  if (!config) {
    return {
      category: t("Authentication"),
      name: t("API client"),
      status: "fail",
      message: t("config not loaded")
    };
  }
  try {
    const client = config.getGeminiClient();
    if (client.isInitialized()) {
      return {
        category: t("Authentication"),
        name: t("API client"),
        status: "pass",
        message: t("client initialized")
      };
    }
    return {
      category: t("Authentication"),
      name: t("API client"),
      status: "warn",
      message: t("client not initialized"),
      detail: t("The API client has not been initialized yet.")
    };
  } catch (error) {
    const errorMsg = error instanceof Error ? error.message : String(error);
    return {
      category: t("Authentication"),
      name: t("API client"),
      status: "warn",
      message: t("error"),
      detail: errorMsg
    };
  }
}
__name(checkApiClient, "checkApiClient");
function checkSettings(context) {
  const settings = context.services.settings;
  if (!settings) {
    return {
      category: t("Configuration"),
      name: t("Settings"),
      status: "fail",
      message: t("not loaded"),
      detail: t(
        "Settings could not be loaded. Check your settings files for syntax errors."
      )
    };
  }
  return {
    category: t("Configuration"),
    name: t("Settings"),
    status: "pass",
    message: t("loaded")
  };
}
__name(checkSettings, "checkSettings");
function checkModel(context) {
  const model = context.services.config?.getModel();
  if (!model) {
    return {
      category: t("Configuration"),
      name: t("Model"),
      status: "fail",
      message: t("not configured"),
      detail: t("Run /model to select a model.")
    };
  }
  return {
    category: t("Configuration"),
    name: t("Model"),
    status: "pass",
    message: model
  };
}
__name(checkModel, "checkModel");
function checkMcpServers(context) {
  const config = context.services.config;
  const servers = config?.getMcpServers();
  if (!servers || Object.keys(servers).length === 0) {
    return [
      {
        category: t("MCP Servers"),
        name: t("MCP servers"),
        status: "pass",
        message: t("none configured")
      }
    ];
  }
  if (context.executionMode !== "interactive") {
    return Object.keys(servers).map((name) => ({
      category: t("MCP Servers"),
      name,
      status: "pass",
      message: config?.isMcpServerDisabled(name) ? t("disabled") : t("configured (not checked in non-interactive mode)")
    }));
  }
  return Object.keys(servers).map((name) => {
    if (config?.isMcpServerDisabled(name)) {
      return {
        category: t("MCP Servers"),
        name,
        status: "pass",
        message: t("disabled")
      };
    }
    const status = getMCPServerStatus(name);
    switch (status) {
      case "connected" /* CONNECTED */:
        return {
          category: t("MCP Servers"),
          name,
          status: "pass",
          message: t("connected")
        };
      case "connecting" /* CONNECTING */:
        return {
          category: t("MCP Servers"),
          name,
          status: "warn",
          message: t("connecting"),
          detail: t("Server is still starting up.")
        };
      case "disconnected" /* DISCONNECTED */:
      default:
        return {
          category: t("MCP Servers"),
          name,
          status: "fail",
          message: t("disconnected"),
          detail: t(
            "Check that the server process is running and configuration is correct."
          )
        };
    }
  });
}
__name(checkMcpServers, "checkMcpServers");
function checkToolRegistry(context) {
  const registry = context.services.config?.getToolRegistry();
  if (!registry) {
    return {
      category: t("Tools"),
      name: t("Tool registry"),
      status: "fail",
      message: t("not loaded")
    };
  }
  const count = registry.getAllTools().length;
  return {
    category: t("Tools"),
    name: t("Tool registry"),
    status: "pass",
    message: t("{{count}} tools registered", { count: String(count) })
  };
}
__name(checkToolRegistry, "checkToolRegistry");
async function checkRipgrep(context) {
  try {
    const useBuiltin = context.services.config?.getUseBuiltinRipgrep() ?? false;
    const result = await canUseRipgrep(useBuiltin);
    if (result) {
      return {
        category: t("Tools"),
        name: t("Ripgrep"),
        status: "pass",
        message: t("available")
      };
    }
    return {
      category: t("Tools"),
      name: t("Ripgrep"),
      status: "warn",
      message: t("not available"),
      detail: t(
        "Install ripgrep for faster file search: https://github.com/BurntSushi/ripgrep"
      )
    };
  } catch {
    return {
      category: t("Tools"),
      name: t("Ripgrep"),
      status: "warn",
      message: t("check failed")
    };
  }
}
__name(checkRipgrep, "checkRipgrep");
async function checkGit(_context) {
  const version = await getGitVersion();
  if (version === "unknown") {
    return {
      category: t("Git"),
      name: t("Git"),
      status: "warn",
      message: t("not available"),
      detail: t("Git features will be limited.")
    };
  }
  return {
    category: t("Git"),
    name: t("Git"),
    status: "pass",
    message: version
  };
}
__name(checkGit, "checkGit");
async function runDoctorChecks(context) {
  const [npmResult, ripgrepResult, apiClientResult, gitResult] = await Promise.all([
    checkNpmVersion(),
    checkRipgrep(context),
    checkApiClient(context),
    checkGit(context)
  ]);
  return [
    // System
    checkNodeVersion(),
    npmResult,
    checkPlatform(),
    // Authentication
    checkAuth(context),
    apiClientResult,
    // Configuration
    checkSettings(context),
    checkModel(context),
    // MCP Servers
    ...checkMcpServers(context),
    // Tools
    checkToolRegistry(context),
    ripgrepResult,
    // Git
    gitResult
  ];
}
__name(runDoctorChecks, "runDoctorChecks");

// packages/cli/src/utils/memoryDiagnostics.ts
init_esbuild_shims();
import * as fs4 from "node:fs";
import * as os2 from "node:os";
import * as path4 from "node:path";
import * as v8 from "node:v8";
var HIGH_HEAP_PRESSURE_THRESHOLD = 0.85;
function countProcessInternals(name) {
  const getter = process[name];
  if (typeof getter !== "function") {
    return { count: 0, unavailable: true };
  }
  try {
    const entries = getter();
    if (!Array.isArray(entries)) {
      return { count: 0, unavailable: true };
    }
    return {
      count: entries.length,
      unavailable: false
    };
  } catch {
    return { count: 0, unavailable: true };
  }
}
__name(countProcessInternals, "countProcessInternals");
function getMemoryDiagnostics() {
  let heapStatistics;
  let heapSpaces = [];
  try {
    heapStatistics = v8.getHeapStatistics();
  } catch {
    heapStatistics = void 0;
  }
  try {
    heapSpaces = v8.getHeapSpaceStatistics();
  } catch {
    heapSpaces = [];
  }
  return {
    generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
    process: {
      pid: process.pid,
      nodeVersion: process.version,
      platform: process.platform,
      arch: process.arch,
      uptimeSeconds: process.uptime()
    },
    memory: process.memoryUsage(),
    v8: {
      heapStatistics,
      heapSpaces,
      unavailable: heapStatistics === void 0
    },
    activeHandles: countProcessInternals("_getActiveHandles"),
    activeRequests: countProcessInternals("_getActiveRequests")
  };
}
__name(getMemoryDiagnostics, "getMemoryDiagnostics");
function defaultHeapSnapshotDir() {
  return path4.join(os2.homedir(), ".qwen", "memory-snapshots");
}
__name(defaultHeapSnapshotDir, "defaultHeapSnapshotDir");
function formatSnapshotTimestamp(now) {
  return now.toISOString().replace(/[:.]/g, "-");
}
__name(formatSnapshotTimestamp, "formatSnapshotTimestamp");
function estimateHeapSnapshotBytes() {
  const overheadFactor = 3;
  try {
    const heapStats = v8.getHeapStatistics();
    return Math.max(heapStats.total_heap_size, process.memoryUsage().heapTotal) * overheadFactor;
  } catch {
    return process.memoryUsage().heapTotal * overheadFactor;
  }
}
__name(estimateHeapSnapshotBytes, "estimateHeapSnapshotBytes");
function getAvailableBytes(outputDir) {
  try {
    const stats = fs4.statfsSync(outputDir);
    return stats.bavail * stats.bsize;
  } catch (error) {
    throw new Error(
      `Unable to check available disk space for heap snapshot: ${formatErrorMessage(
        error
      )}`
    );
  }
}
__name(getAvailableBytes, "getAvailableBytes");
function formatErrorMessage(error) {
  return error instanceof Error ? error.message : String(error);
}
__name(formatErrorMessage, "formatErrorMessage");
function cleanupOldHeapSnapshots(outputDir, maxSnapshots) {
  if (maxSnapshots < 1) return;
  const snapshots = fs4.readdirSync(outputDir).filter(
    (name) => name.startsWith("qwen-code-heap-") && name.endsWith(".heapsnapshot")
  ).map((name) => path4.join(outputDir, name)).sort((a, b) => {
    const mtimeDelta = getSnapshotMtimeMs(b) - getSnapshotMtimeMs(a);
    if (mtimeDelta !== 0) return mtimeDelta;
    return extractHeapSnapshotTimestamp(b).localeCompare(
      extractHeapSnapshotTimestamp(a)
    ) || path4.basename(b).localeCompare(path4.basename(a));
  });
  for (const filePath of snapshots.slice(maxSnapshots)) {
    try {
      fs4.rmSync(filePath, { force: true });
    } catch {
    }
  }
}
__name(cleanupOldHeapSnapshots, "cleanupOldHeapSnapshots");
function getSnapshotMtimeMs(filePath) {
  try {
    return fs4.lstatSync(filePath).mtimeMs;
  } catch {
    return 0;
  }
}
__name(getSnapshotMtimeMs, "getSnapshotMtimeMs");
function extractHeapSnapshotTimestamp(filePath) {
  return path4.basename(filePath).match(/^qwen-code-heap-\d+-(.+)\.heapsnapshot$/)?.[1] ?? "";
}
__name(extractHeapSnapshotTimestamp, "extractHeapSnapshotTimestamp");
var lastHeapSnapshotWriteByDir = /* @__PURE__ */ new Map();
function enforceHeapSnapshotRateLimit(outputDir, now, rateLimitMs) {
  if (rateLimitMs <= 0) return;
  const key = path4.resolve(outputDir);
  const nowMs = now.getTime();
  const lastWriteMs = lastHeapSnapshotWriteByDir.get(key);
  if (lastWriteMs !== void 0 && nowMs - lastWriteMs < rateLimitMs) {
    const waitSeconds = Math.ceil((rateLimitMs - (nowMs - lastWriteMs)) / 1e3);
    throw new Error(
      `Heap snapshot rate limit: wait ${waitSeconds}s before writing another snapshot in this directory.`
    );
  }
}
__name(enforceHeapSnapshotRateLimit, "enforceHeapSnapshotRateLimit");
function recordHeapSnapshotWrite(outputDir, now) {
  lastHeapSnapshotWriteByDir.set(path4.resolve(outputDir), now.getTime());
}
__name(recordHeapSnapshotWrite, "recordHeapSnapshotWrite");
function writeMemoryHeapSnapshot({
  outputDir = defaultHeapSnapshotDir(),
  now = /* @__PURE__ */ new Date(),
  writeSnapshot = v8.writeHeapSnapshot,
  estimateSnapshotBytes: estimateSnapshotBytesOption = estimateHeapSnapshotBytes,
  getAvailableBytes: getAvailableBytesOption = getAvailableBytes,
  minFreeBytesAfterSnapshot = 512 * 1024 * 1024,
  maxSnapshots = 5,
  rateLimitMs = 6e4
} = {}) {
  fs4.mkdirSync(outputDir, { recursive: true, mode: 448 });
  try {
    fs4.chmodSync(outputDir, 448);
  } catch {
  }
  enforceHeapSnapshotRateLimit(outputDir, now, rateLimitMs);
  const estimatedSnapshotBytes = estimateSnapshotBytesOption();
  const availableBytes = getAvailableBytesOption(outputDir);
  if (availableBytes - estimatedSnapshotBytes < minFreeBytesAfterSnapshot) {
    throw new Error(
      "Insufficient free disk space for heap snapshot; skipping to avoid filling the disk."
    );
  }
  const filePath = path4.join(
    outputDir,
    `qwen-code-heap-${process.pid}-${formatSnapshotTimestamp(now)}.heapsnapshot`
  );
  let writtenPath;
  try {
    writtenPath = writeSnapshot(filePath);
  } catch (error) {
    try {
      fs4.rmSync(filePath, { force: true });
    } catch {
    }
    throw error;
  }
  try {
    fs4.chmodSync(writtenPath, 384);
  } catch {
  }
  recordHeapSnapshotWrite(outputDir, now);
  try {
    cleanupOldHeapSnapshots(outputDir, maxSnapshots);
  } catch {
  }
  return writtenPath;
}
__name(writeMemoryHeapSnapshot, "writeMemoryHeapSnapshot");
function defaultWait(ms) {
  return new Promise((resolve5) => setTimeout(resolve5, ms));
}
__name(defaultWait, "defaultWait");
function normalizeSampleCount(sampleCount) {
  if (!Number.isFinite(sampleCount) || sampleCount <= 0) {
    return 3;
  }
  return Math.max(1, Math.floor(sampleCount));
}
__name(normalizeSampleCount, "normalizeSampleCount");
async function collectMemoryPressureSamples({
  sampleCount = 3,
  intervalMs = 1e3,
  signal,
  now = /* @__PURE__ */ __name(() => /* @__PURE__ */ new Date(), "now"),
  memoryUsage = process.memoryUsage,
  wait = defaultWait
} = {}) {
  const count = normalizeSampleCount(sampleCount);
  const samples = [];
  for (let index = 1; index <= count; index++) {
    if (signal?.aborted) {
      break;
    }
    const memory = memoryUsage();
    samples.push({
      index,
      timestamp: now().toISOString(),
      rss: memory.rss,
      heapTotal: memory.heapTotal,
      heapUsed: memory.heapUsed,
      external: memory.external,
      arrayBuffers: memory.arrayBuffers
    });
    if (index < count && !signal?.aborted) {
      await wait(intervalMs);
    }
  }
  return samples;
}
__name(collectMemoryPressureSamples, "collectMemoryPressureSamples");
function formatBytes(value) {
  if (typeof value !== "number" || !Number.isFinite(value)) {
    return "unavailable";
  }
  return `${(value / 1024 / 1024).toFixed(1)} MiB`;
}
__name(formatBytes, "formatBytes");
function formatActiveCount(value) {
  return value.unavailable ? "unavailable" : String(value.count);
}
__name(formatActiveCount, "formatActiveCount");
function asFiniteNumber(value) {
  return typeof value === "number" && Number.isFinite(value) ? value : void 0;
}
__name(asFiniteNumber, "asFiniteNumber");
function formatPercent(value) {
  if (value === void 0 || !Number.isFinite(value)) {
    return "unavailable";
  }
  return `${(value * 100).toFixed(1)}%`;
}
__name(formatPercent, "formatPercent");
function buildMemoryInsights(diagnostics) {
  const heapPressure = getHeapPressure(diagnostics);
  const heapIsHigh = isHighHeapPressure(diagnostics);
  const rssHeapGapBytes = Math.max(
    0,
    diagnostics.memory.rss - diagnostics.memory.heapTotal
  );
  const externalAndBuffers = diagnostics.memory.external + diagnostics.memory.arrayBuffers;
  const nonHeapGapIsHigh = rssHeapGapBytes >= 256 * 1024 * 1024 && diagnostics.memory.rss >= diagnostics.memory.heapTotal * 2;
  const externalMemoryIsHigh = externalAndBuffers >= 256 * 1024 * 1024 && externalAndBuffers >= diagnostics.memory.rss * 0.3;
  const signals = [];
  const recommendations = [];
  if (diagnostics.v8.unavailable) {
    signals.push(
      "V8 heap statistics are unavailable; heap pressure assessment may be incomplete."
    );
    recommendations.push(
      "Re-run /doctor memory after restarting Qwen Code; if V8 diagnostics remain unavailable, include this report when filing an issue."
    );
  }
  if (heapIsHigh) {
    signals.push(
      "V8 heap usage is high; the process is close to its configured heap limit."
    );
    recommendations.push(
      "If the CLI is sluggish or near OOM, restart Qwen Code to recover memory, then capture a heap snapshot before the next restart to identify retained objects."
    );
  }
  if (nonHeapGapIsHigh || externalMemoryIsHigh) {
    signals.push(
      "Non-heap memory is high; investigate large tool results, buffers, or native allocations."
    );
    recommendations.push(
      "Compare RSS against heap usage over time; if RSS grows while heap stays flat, inspect external buffers, tool-result payloads, and native dependencies before increasing the V8 heap limit."
    );
  }
  if (diagnostics.activeHandles.count >= 1e3 && !diagnostics.activeHandles.unavailable) {
    signals.push(
      "Active handle count is high; long-lived timers, sockets, or file watchers may be accumulating."
    );
    recommendations.push(
      "Check recently enabled MCP servers, watchers, or streaming sessions for resources that are not being closed."
    );
  }
  return {
    status: signals.length > 0 ? "warn" : "ok",
    heapPressure,
    rssHeapGapBytes,
    signals,
    recommendations
  };
}
__name(buildMemoryInsights, "buildMemoryInsights");
function getHeapPressure(diagnostics) {
  const heapStatistics = diagnostics.v8.heapStatistics ?? {};
  const heapSizeLimit = asFiniteNumber(heapStatistics["heap_size_limit"]);
  return heapSizeLimit !== void 0 && heapSizeLimit > 0 ? diagnostics.memory.heapUsed / heapSizeLimit : void 0;
}
__name(getHeapPressure, "getHeapPressure");
function isHighHeapPressure(diagnostics) {
  const heapPressure = getHeapPressure(diagnostics);
  return heapPressure !== void 0 && heapPressure >= HIGH_HEAP_PRESSURE_THRESHOLD;
}
__name(isHighHeapPressure, "isHighHeapPressure");
function formatMemoryPressureSamples(samples) {
  const first = samples[0];
  const last = samples.at(-1);
  const rssDelta = first && last && samples.length > 1 ? last.rss - first.rss : void 0;
  const heapUsedDelta = first && last && samples.length > 1 ? last.heapUsed - first.heapUsed : void 0;
  const sampleLines = samples.map(
    (sample) => `  #${sample.index} ${sample.timestamp}: RSS ${formatBytes(
      sample.rss
    )}, heap used ${formatBytes(sample.heapUsed)}, external ${formatBytes(
      sample.external
    )}, array buffers ${formatBytes(sample.arrayBuffers)}`
  );
  return [
    "Memory pressure samples",
    `  Sample count: ${samples.length}`,
    `  RSS delta: ${formatBytes(rssDelta)}`,
    `  Heap used delta: ${formatBytes(heapUsedDelta)}`,
    ...sampleLines
  ].join("\n");
}
__name(formatMemoryPressureSamples, "formatMemoryPressureSamples");
function formatMemoryDiagnostics(diagnostics) {
  const heapStatistics = diagnostics.v8.heapStatistics ?? {};
  const insights = buildMemoryInsights(diagnostics);
  const heapSpaceLines = diagnostics.v8.heapSpaces.map((space) => {
    const name = String(space["space_name"] ?? "unknown_space");
    return `  - ${name}: ${formatBytes(space["space_used_size"])} / ${formatBytes(
      space["space_size"]
    )}`;
  });
  return [
    "Memory diagnostics",
    `Generated: ${diagnostics.generatedAt}`,
    "",
    "Process",
    `  PID: ${diagnostics.process.pid}`,
    `  Node.js: ${diagnostics.process.nodeVersion}`,
    `  Platform: ${diagnostics.process.platform} ${diagnostics.process.arch}`,
    `  Uptime: ${diagnostics.process.uptimeSeconds.toFixed(1)}s`,
    "",
    "Memory usage",
    `  RSS: ${formatBytes(diagnostics.memory.rss)}`,
    `  Heap used / total: ${formatBytes(
      diagnostics.memory.heapUsed
    )} / ${formatBytes(diagnostics.memory.heapTotal)}`,
    `  External: ${formatBytes(diagnostics.memory.external)}`,
    `  Array buffers: ${formatBytes(diagnostics.memory.arrayBuffers)}`,
    "",
    "V8 heap",
    `  Heap size limit: ${formatBytes(heapStatistics["heap_size_limit"])}`,
    `  Total available: ${formatBytes(heapStatistics["total_available_size"])}`,
    `  Total heap size executable: ${formatBytes(
      heapStatistics["total_heap_size_executable"]
    )}`,
    `  Used heap size: ${formatBytes(heapStatistics["used_heap_size"])}`,
    "  Heap spaces:",
    ...heapSpaceLines.length > 0 ? heapSpaceLines : ["  - unavailable"],
    "",
    "Runtime internals",
    `  Active handles: ${formatActiveCount(diagnostics.activeHandles)}`,
    `  Active requests: ${formatActiveCount(diagnostics.activeRequests)}`,
    "",
    "Assessment",
    `  Status: ${insights.status}`,
    `  Heap pressure: ${formatPercent(insights.heapPressure)}`,
    `  RSS / heap-total gap: ${formatBytes(insights.rssHeapGapBytes)}`,
    "  Signals:",
    ...insights.signals.length > 0 ? insights.signals.map((signal) => `  - ${signal}`) : ["  - No immediate memory pressure signals detected."],
    "  Recommendations:",
    ...insights.recommendations.length > 0 ? insights.recommendations.map(
      (recommendation) => `  - ${recommendation}`
    ) : [
      "  - Re-run /doctor memory when memory grows, before restarting, to compare snapshots."
    ]
  ].join("\n");
}
__name(formatMemoryDiagnostics, "formatMemoryDiagnostics");

// packages/cli/src/utils/standalone-update.ts
init_esbuild_shims();
var import_undici = __toESM(require_undici(), 1);
import { createHash } from "node:crypto";
import * as fs5 from "node:fs";
import * as os3 from "node:os";
import * as path5 from "node:path";
import { Readable, Transform } from "node:stream";
import { spawn as spawn2, execFile } from "node:child_process";
import { pipeline } from "node:stream/promises";

// packages/cli/src/utils/standalone-update-verify.ts
init_esbuild_shims();
import { createPublicKey, verify } from "node:crypto";
var RELEASE_PUBLIC_KEY_DER_B64 = "MCowBQYDK2VwAyEAr9WRFLDauibZQKCe1oKfuFZn6zRMaEkD5+KVqN6mKM4=";
function verifySignature(sha256sumsContent, signatureBase64) {
  const key = createPublicKey({
    key: Buffer.from(RELEASE_PUBLIC_KEY_DER_B64, "base64"),
    format: "der",
    type: "spki"
  });
  const signature = Buffer.from(signatureBase64, "base64");
  if (signature.length !== 64) {
    throw new Error(
      `Invalid signature length: expected 64 bytes, got ${signature.length}`
    );
  }
  const valid = verify(null, Buffer.from(sha256sumsContent), key, signature);
  if (!valid) {
    throw new Error(
      "SHA256SUMS signature verification failed \u2014 possible tampering detected"
    );
  }
}
__name(verifySignature, "verifySignature");

// packages/cli/src/utils/standalone-update.ts
var debugLogger6 = createDebugLogger("STANDALONE_UPDATE");
var OSS_BASE = "https://qwen-code-assets.oss-cn-hangzhou.aliyuncs.com/releases/qwen-code";
var GITHUB_BASE = "https://github.com/QwenLM/qwen-code/releases/download";
var FETCH_TIMEOUT_MS = 3e4;
var ARCHIVE_TIMEOUT_MS = 3e5;
var VALID_TARGETS = /* @__PURE__ */ new Set([
  "darwin-arm64",
  "darwin-x64",
  "linux-arm64",
  "linux-x64",
  "win-x64"
]);
var SEMVER_RE = /^v?\d+\.\d+\.\d+(-[\w.]+)?$/;
function normalizeVersion(version) {
  if (!SEMVER_RE.test(version)) {
    throw new Error(`Invalid version format: ${version}`);
  }
  return version.startsWith("v") ? version : `v${version}`;
}
__name(normalizeVersion, "normalizeVersion");
function validateTarget(target) {
  if (!VALID_TARGETS.has(target)) {
    throw new Error(`Unknown target: ${target}`);
  }
}
__name(validateTarget, "validateTarget");
function archiveFilename(target) {
  const ext = target.startsWith("win") ? "zip" : "tar.gz";
  return `qwen-code-${target}.${ext}`;
}
__name(archiveFilename, "archiveFilename");
function escapePS(s) {
  return s.replace(/'/g, "''");
}
__name(escapePS, "escapePS");
async function tryFetch(url, timeoutMs = FETCH_TIMEOUT_MS) {
  try {
    const res = await (0, import_undici.fetch)(url, {
      signal: AbortSignal.timeout(timeoutMs)
    });
    if (res.ok) return { response: res };
    await res.body?.cancel().catch(() => {
    });
    return { error: new Error(`HTTP ${res.status} ${res.statusText}`) };
  } catch (err) {
    const error = err instanceof Error ? err : new Error(String(err));
    debugLogger6.debug(`Fetch failed for ${url}: ${error.message}`);
    return { error };
  }
}
__name(tryFetch, "tryFetch");
async function downloadWithFallback(versionPath, filename, timeoutMs = FETCH_TIMEOUT_MS) {
  const ossUrl = `${OSS_BASE}/${versionPath}/${filename}`;
  const ossResult = await tryFetch(ossUrl, timeoutMs);
  if (ossResult.response) return ossResult.response;
  const ghUrl = `${GITHUB_BASE}/${versionPath}/${filename}`;
  const ghResult = await tryFetch(ghUrl, timeoutMs);
  if (ghResult.response) return ghResult.response;
  throw new Error(
    `Failed to download ${filename}: OSS (${ossResult.error?.message ?? "unknown"}), GitHub (${ghResult.error?.message ?? "unknown"})`
  );
}
__name(downloadWithFallback, "downloadWithFallback");
async function verifyChecksum(actualHash, filename, versionPath) {
  const response = await downloadWithFallback(versionPath, "SHA256SUMS");
  const text = await response.text();
  const requireSig = process.env["QWEN_REQUIRE_SIGNATURE"] === "1";
  let sigResponse;
  try {
    sigResponse = await downloadWithFallback(versionPath, "SHA256SUMS.sig");
  } catch (err) {
    debugLogger6.debug("SHA256SUMS.sig not available:", err);
  }
  if (sigResponse) {
    const sigContent = await sigResponse.text();
    verifySignature(text, sigContent.trim());
    debugLogger6.info("SHA256SUMS signature verified.");
  } else if (requireSig) {
    throw new Error(
      "SHA256SUMS.sig not found and QWEN_REQUIRE_SIGNATURE=1 is set"
    );
  } else {
    debugLogger6.warn(
      "SHA256SUMS.sig not available \u2014 update integrity relies on SHA256 checksum only. Set QWEN_REQUIRE_SIGNATURE=1 to enforce signature verification."
    );
  }
  const expectedLine = text.split("\n").find((line) => {
    const parts = line.trim().split(/\s+/);
    if (parts.length < 2) return false;
    const name = parts[parts.length - 1].replace(/^\*/, "");
    return name === filename;
  });
  if (!expectedLine) {
    throw new Error(`No checksum found for ${filename} in SHA256SUMS`);
  }
  const expectedHash = expectedLine.trim().split(/\s+/)[0];
  if (actualHash !== expectedHash) {
    throw new Error(
      `Checksum mismatch: expected ${expectedHash}, got ${actualHash}`
    );
  }
}
__name(verifyChecksum, "verifyChecksum");
var MAX_DOWNLOAD_BYTES = 512 * 1024 * 1024;
async function downloadToFile(versionPath, filename, destPath) {
  const response = await downloadWithFallback(
    versionPath,
    filename,
    ARCHIVE_TIMEOUT_MS
  );
  const body = response.body;
  if (!body) throw new Error("Empty response body");
  const contentLength = response.headers.get("content-length");
  if (contentLength && parseInt(contentLength, 10) > MAX_DOWNLOAD_BYTES) {
    await body.cancel().catch(() => {
    });
    throw new Error(
      `Download too large: ${contentLength} bytes exceeds ${MAX_DOWNLOAD_BYTES} limit`
    );
  }
  const hash = createHash("sha256");
  let bytesWritten = 0;
  const dest = fs5.createWriteStream(destPath);
  const sizeGuard = new Transform({
    transform(chunk, _encoding, callback) {
      bytesWritten += chunk.length;
      if (bytesWritten > MAX_DOWNLOAD_BYTES) {
        callback(
          new Error(`Download exceeded ${MAX_DOWNLOAD_BYTES} byte limit`)
        );
      } else {
        hash.update(chunk);
        callback(null, chunk);
      }
    }
  });
  await pipeline(Readable.fromWeb(body), sizeGuard, dest);
  return hash.digest("hex");
}
__name(downloadToFile, "downloadToFile");
function validateExtractedPaths(resolvedDest) {
  const entries = fs5.readdirSync(resolvedDest, {
    recursive: true,
    withFileTypes: true
  });
  for (const entry of entries) {
    const fullPath = path5.join(
      String(entry.parentPath || entry.path),
      entry.name
    );
    const resolved = fs5.realpathSync(fullPath);
    if (!resolved.startsWith(resolvedDest + path5.sep) && resolved !== resolvedDest) {
      fs5.rmSync(resolvedDest, { recursive: true, force: true });
      throw new Error(
        `Path traversal detected in archive: ${entry.name} resolves to ${resolved}`
      );
    }
  }
}
__name(validateExtractedPaths, "validateExtractedPaths");
function isSafeTarEntryPath(entryPath) {
  if (entryPath.length === 0) return false;
  if (path5.posix.isAbsolute(entryPath) || path5.win32.isAbsolute(entryPath)) {
    return false;
  }
  return !entryPath.split(/[\\/]+/).includes("..");
}
__name(isSafeTarEntryPath, "isSafeTarEntryPath");
async function extractArchive(archivePath, destDir, target) {
  fs5.mkdirSync(destDir, { recursive: true });
  if (target.startsWith("win")) {
    await new Promise((resolve5, reject) => {
      const ps = spawn2(
        "powershell.exe",
        [
          "-NoProfile",
          "-Command",
          `Expand-Archive -Path '${escapePS(archivePath)}' -DestinationPath '${escapePS(destDir)}' -Force`
        ],
        { stdio: "ignore" }
      );
      ps.on(
        "close",
        (code) => code === 0 ? resolve5() : reject(new Error(`Expand-Archive exited with code ${code}`))
      );
      ps.on("error", reject);
    });
    const resolvedDest = fs5.realpathSync(destDir);
    validateExtractedPaths(resolvedDest);
  } else {
    const resolvedDest = path5.resolve(destDir);
    await So({
      file: archivePath,
      cwd: destDir,
      preservePaths: false,
      filter: /* @__PURE__ */ __name((p, entry) => {
        if (!isSafeTarEntryPath(p)) return false;
        if ("type" in entry && entry.type === "SymbolicLink" && "linkpath" in entry) {
          const linkTarget = path5.resolve(
            resolvedDest,
            path5.dirname(p),
            String(entry.linkpath)
          );
          if (!linkTarget.startsWith(resolvedDest + path5.sep) && linkTarget !== resolvedDest) {
            return false;
          }
        }
        return true;
      }, "filter")
    });
    validateExtractedPaths(fs5.realpathSync(destDir));
  }
}
__name(extractArchive, "extractArchive");
function spawnAndCapture(command, args, timeoutMs) {
  return new Promise((resolve5, reject) => {
    let settled = false;
    const child = execFile(
      command,
      args,
      { timeout: timeoutMs },
      (err, out, stderr) => {
        if (settled) return;
        settled = true;
        if (err && ("killed" in err && err.killed || "signal" in err && err.signal)) {
          reject(new Error("Smoke test timed out"));
          return;
        }
        if (err) {
          const exitCode = "code" in err && typeof err.code === "number" ? err.code : 1;
          resolve5({ exitCode, stdout: out || "", stderr: stderr || "" });
          return;
        }
        resolve5({ exitCode: 0, stdout: out || "", stderr: stderr || "" });
      }
    );
    child.on("error", (e) => {
      if (settled) return;
      settled = true;
      reject(e);
    });
  });
}
__name(spawnAndCapture, "spawnAndCapture");
async function smokeTest(newInstallDir, target) {
  const resolvedInstallDir = path5.resolve(newInstallDir);
  const nodeBin = target.startsWith("win") ? path5.join(resolvedInstallDir, "node", "node.exe") : path5.join(resolvedInstallDir, "node", "bin", "node");
  const cliBin = path5.join(resolvedInstallDir, "lib", "cli.js");
  if (!fs5.existsSync(nodeBin)) {
    throw new Error(`Smoke test failed: node binary not found at ${nodeBin}`);
  }
  if (!fs5.existsSync(cliBin)) {
    throw new Error(`Smoke test failed: cli.js not found at ${cliBin}`);
  }
  const { exitCode, stdout, stderr } = await spawnAndCapture(
    nodeBin,
    [cliBin, "--version"],
    1e4
  );
  if (exitCode !== 0) {
    const detail = stderr.trim() ? `: ${stderr.trim()}` : "";
    throw new Error(
      `Smoke test failed: new binary exited with code ${exitCode}${detail}`
    );
  }
  const version = stdout.trim();
  if (!SEMVER_RE.test(version)) {
    throw new Error(
      `Smoke test failed: unexpected version output "${version}"`
    );
  }
  debugLogger6.info(`Smoke test passed: ${version}`);
}
__name(smokeTest, "smokeTest");
function acquireLock(lockPath) {
  try {
    fs5.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
    return true;
  } catch {
    try {
      const pidStr = fs5.readFileSync(lockPath, "utf-8").trim();
      const pid = parseInt(pidStr, 10);
      if (Number.isNaN(pid) || !isProcessAlive(pid)) {
        fs5.unlinkSync(lockPath);
        try {
          fs5.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
          return true;
        } catch {
          return false;
        }
      }
    } catch {
    }
    return false;
  }
}
__name(acquireLock, "acquireLock");
function releaseLock(lockPath) {
  try {
    fs5.unlinkSync(lockPath);
  } catch {
  }
}
__name(releaseLock, "releaseLock");
function cleanupEmptyStandaloneDir(standaloneDir) {
  const manifestPath = path5.join(standaloneDir, "manifest.json");
  if (fs5.existsSync(standaloneDir) && !fs5.existsSync(manifestPath)) {
    fs5.rmSync(standaloneDir, { recursive: true, force: true });
  }
}
__name(cleanupEmptyStandaloneDir, "cleanupEmptyStandaloneDir");
var UNSAFE_SHELL_CHARS = /["`$\\;\n\r]/;
var UNSAFE_CMD_CHARS = /[&|<>^%!"`\n\r]/;
function assertSafeForShellEmbed(p, context) {
  if (UNSAFE_SHELL_CHARS.test(p)) {
    throw new Error(
      `${context} contains characters unsafe for shell embedding: ${p}`
    );
  }
}
__name(assertSafeForShellEmbed, "assertSafeForShellEmbed");
function isProcessAlive(pid) {
  try {
    process.kill(pid, 0);
    return true;
  } catch {
    return false;
  }
}
__name(isProcessAlive, "isProcessAlive");
function atomicReplace(standaloneDir, newDir, lockPath) {
  const oldDir = `${standaloneDir}.old`;
  const pendingDir = `${standaloneDir}.new`;
  if (fs5.existsSync(oldDir)) {
    fs5.rmSync(oldDir, { recursive: true, force: true });
  }
  if (os3.platform() === "win32") {
    if (UNSAFE_CMD_CHARS.test(standaloneDir) || UNSAFE_CMD_CHARS.test(oldDir) || UNSAFE_CMD_CHARS.test(pendingDir)) {
      throw new Error(
        "Installation path contains characters unsafe for deferred update script"
      );
    }
    if (fs5.existsSync(pendingDir)) {
      fs5.rmSync(pendingDir, { recursive: true, force: true });
    }
    fs5.renameSync(newDir, pendingDir);
    const lockFile = lockPath;
    const logFile = path5.join(path5.dirname(standaloneDir), "qwen-update.log");
    const script = [
      "@echo off",
      "set /a TRIES=0",
      ":wait",
      "set /a TRIES+=1",
      "if %TRIES% GTR 30 goto proceed",
      `tasklist /FI "PID eq ${process.pid}" 2>nul | find "${process.pid}" >nul && (timeout /t 1 >nul & goto wait)`,
      ":proceed",
      `echo [%DATE% %TIME%] starting swap >> "${logFile}"`,
      `move /Y "${standaloneDir}" "${oldDir}"`,
      "if errorlevel 1 goto move1_failed",
      `move /Y "${pendingDir}" "${standaloneDir}"`,
      "if errorlevel 1 goto move2_failed",
      `echo [%DATE% %TIME%] swap completed >> "${logFile}"`,
      "goto cleanup",
      ":move1_failed",
      `echo [%DATE% %TIME%] ERROR: failed to rename install to .old (errorlevel %errorlevel%) >> "${logFile}"`,
      "goto cleanup",
      ":move2_failed",
      `echo [%DATE% %TIME%] ERROR: failed to promote .new; rolling back >> "${logFile}"`,
      `move /Y "${oldDir}" "${standaloneDir}"`,
      "if errorlevel 1 (",
      `  echo [%DATE% %TIME%] CRITICAL: rollback also failed; manual recovery: move "${oldDir}" "${standaloneDir}" >> "${logFile}"`,
      ") else (",
      `  echo [%DATE% %TIME%] rollback succeeded >> "${logFile}"`,
      ")",
      ":cleanup",
      `del /F /Q "${lockFile}" 2>nul`,
      `del "%~f0"`
    ].join("\r\n");
    const scriptPath = path5.join(
      path5.dirname(standaloneDir),
      "qwen-update.bat"
    );
    fs5.writeFileSync(scriptPath, script);
    spawn2("cmd.exe", ["/c", scriptPath], {
      detached: true,
      stdio: "ignore",
      windowsHide: true
    }).unref();
    return "deferred";
  } else {
    fs5.renameSync(standaloneDir, oldDir);
    try {
      fs5.renameSync(newDir, standaloneDir);
    } catch (promoteErr) {
      try {
        fs5.renameSync(oldDir, standaloneDir);
      } catch (rollbackErr) {
        const detail = `Standalone update failed AND rollback failed.
Original error: ${promoteErr.message}
Rollback error: ${rollbackErr.message}
Manual recovery: mv "${oldDir}" "${standaloneDir}"`;
        throw new Error(detail);
      }
      throw promoteErr;
    }
    return "done";
  }
}
__name(atomicReplace, "atomicReplace");
function ensureBinWrapper(standaloneDir, target) {
  const binDir = path5.join(path5.dirname(standaloneDir), "..", "bin");
  try {
    fs5.mkdirSync(binDir, { recursive: true });
    if (target.startsWith("win")) {
      if (UNSAFE_CMD_CHARS.test(standaloneDir)) {
        throw new Error(
          "standaloneDir contains characters unsafe for cmd.exe wrapper"
        );
      }
      const wrapperPath = path5.join(binDir, "qwen.cmd");
      if (!fs5.existsSync(wrapperPath)) {
        const content = `@echo off\r
call "${standaloneDir}\\bin\\qwen.cmd" %*\r
`;
        fs5.writeFileSync(wrapperPath, content);
      }
    } else {
      assertSafeForShellEmbed(standaloneDir, "standaloneDir");
      const wrapperPath = path5.join(binDir, "qwen");
      if (!fs5.existsSync(wrapperPath)) {
        const content = `#!/bin/sh
exec "${standaloneDir}/bin/qwen" "$@"
`;
        fs5.writeFileSync(wrapperPath, content, { mode: 493 });
      }
      ensurePathInShellRc(binDir);
    }
  } catch (err) {
    debugLogger6.warn("Failed to create bin wrapper:", err);
  }
}
__name(ensureBinWrapper, "ensureBinWrapper");
function ensurePathInShellRc(binDir) {
  assertSafeForShellEmbed(binDir, "binDir");
  const shell = process.env["SHELL"] || "";
  let rcFile = null;
  const home = process.env["HOME"] || os3.homedir();
  if (shell.endsWith("/zsh")) {
    rcFile = path5.join(home, ".zshrc");
  } else if (shell.endsWith("/bash")) {
    const bashrc = path5.join(home, ".bashrc");
    const profile = path5.join(home, ".bash_profile");
    if (os3.platform() === "darwin") {
      rcFile = fs5.existsSync(profile) ? profile : bashrc;
    } else {
      rcFile = bashrc;
    }
  } else if (shell.endsWith("/fish")) {
    rcFile = path5.join(home, ".config", "fish", "config.fish");
  }
  if (!rcFile) return;
  try {
    const content = fs5.existsSync(rcFile) ? fs5.readFileSync(rcFile, "utf-8") : "";
    const marker = "# Added by Qwen Code standalone installer";
    if (content.includes(marker)) return;
    const exportLine = shell.endsWith("/fish") ? `
${marker}
fish_add_path "${binDir}"
` : `
${marker}
export PATH="${binDir}:$PATH"
`;
    fs5.appendFileSync(rcFile, exportLine);
    debugLogger6.info(`Added ${binDir} to ${rcFile}`);
  } catch (err) {
    debugLogger6.debug("Failed to update shell rc:", err);
  }
}
__name(ensurePathInShellRc, "ensurePathInShellRc");
function detectTarget() {
  const platform3 = os3.platform();
  const arch2 = os3.arch();
  if (platform3 === "darwin") {
    return arch2 === "arm64" ? "darwin-arm64" : "darwin-x64";
  }
  if (platform3 === "win32") return "win-x64";
  if (platform3 === "linux") {
    if (arch2 === "arm64") return "linux-arm64";
    if (arch2 === "x64") return "linux-x64";
  }
  throw new Error(`Unsupported platform: ${platform3}-${arch2}`);
}
__name(detectTarget, "detectTarget");
async function performStandaloneUpdate(standaloneDir, newVersion) {
  const versionPath = normalizeVersion(newVersion);
  let target;
  let isFirstTimeMigration = false;
  const manifestPath = path5.join(standaloneDir, "manifest.json");
  if (fs5.existsSync(manifestPath)) {
    const manifestRaw = fs5.readFileSync(manifestPath, "utf-8");
    const manifest = JSON.parse(manifestRaw);
    target = manifest.target ?? detectTarget();
  } else if (fs5.existsSync(standaloneDir)) {
    throw new Error(
      `${standaloneDir} exists but is not a Qwen Code standalone install. Remove it manually to proceed.`
    );
  } else {
    target = detectTarget();
    isFirstTimeMigration = true;
  }
  validateTarget(target);
  const filename = archiveFilename(target);
  const parentDir = path5.dirname(standaloneDir);
  fs5.mkdirSync(parentDir, { recursive: true });
  const lockPath = path5.join(parentDir, ".qwen-update.lock");
  if (!acquireLock(lockPath)) {
    throw new Error("Another update is already in progress");
  }
  if (isFirstTimeMigration) {
    fs5.mkdirSync(standaloneDir, { recursive: true });
  }
  const tempDir = fs5.mkdtempSync(path5.join(os3.tmpdir(), "qwen-code-update-"));
  let extractDir;
  let updateResult;
  try {
    extractDir = fs5.mkdtempSync(path5.join(parentDir, ".qwen-code-update-"));
  } catch (err) {
    fs5.rmSync(tempDir, { recursive: true, force: true });
    releaseLock(lockPath);
    throw err;
  }
  try {
    const archivePath = path5.join(tempDir, filename);
    debugLogger6.info(`Downloading ${filename} (${versionPath})...`);
    const archiveHash = await downloadToFile(
      versionPath,
      filename,
      archivePath
    );
    debugLogger6.info("Verifying checksum...");
    await verifyChecksum(archiveHash, filename, versionPath);
    debugLogger6.info("Extracting archive...");
    await extractArchive(archivePath, extractDir, target);
    const newInstallDir = path5.join(extractDir, "qwen-code");
    if (!fs5.existsSync(path5.join(newInstallDir, "manifest.json"))) {
      throw new Error(
        "Extracted archive does not contain expected qwen-code directory"
      );
    }
    debugLogger6.info("Running smoke test...");
    await smokeTest(newInstallDir, target);
    debugLogger6.info("Replacing installation...");
    updateResult = atomicReplace(standaloneDir, newInstallDir, lockPath);
    const oldDir = `${standaloneDir}.old`;
    if (fs5.existsSync(oldDir)) {
      if (isFirstTimeMigration) {
        fs5.rmSync(oldDir, { recursive: true, force: true });
      } else {
        try {
          const oldManifestPath = path5.join(oldDir, "manifest.json");
          let oldVersion = "unknown";
          if (fs5.existsSync(oldManifestPath)) {
            const oldManifest = JSON.parse(
              fs5.readFileSync(oldManifestPath, "utf-8")
            );
            oldVersion = oldManifest.version || "unknown";
          }
          const rollbackInfo = {
            preservedVersion: oldVersion,
            updatedTo: versionPath,
            timestamp: (/* @__PURE__ */ new Date()).toISOString(),
            reason: "auto-update"
          };
          fs5.writeFileSync(
            path5.join(oldDir, ".qwen-rollback-info.json"),
            JSON.stringify(rollbackInfo, null, 2)
          );
        } catch {
        }
      }
    }
    ensureBinWrapper(standaloneDir, target);
    debugLogger6.info("Standalone update complete.");
    return updateResult;
  } catch (err) {
    const pendingDir = `${standaloneDir}.new`;
    if (fs5.existsSync(pendingDir)) {
      fs5.rmSync(pendingDir, { recursive: true, force: true });
    }
    cleanupEmptyStandaloneDir(standaloneDir);
    throw err;
  } finally {
    if (updateResult !== "deferred") {
      releaseLock(lockPath);
    }
    try {
      fs5.rmSync(tempDir, { recursive: true, force: true });
    } catch {
    }
    try {
      fs5.rmSync(extractDir, { recursive: true, force: true });
    } catch {
    }
  }
}
__name(performStandaloneUpdate, "performStandaloneUpdate");
function rollbackStandaloneUpdate(standaloneDir) {
  const lockPath = path5.join(path5.dirname(standaloneDir), ".qwen-update.lock");
  try {
    const pidStr = fs5.readFileSync(lockPath, "utf-8").trim();
    const pid = parseInt(pidStr, 10);
    if (!Number.isNaN(pid) && isProcessAlive(pid)) {
      return {
        ok: false,
        reason: "rename-failed",
        detail: "An auto-update is currently in progress. Wait for it to finish before rolling back."
      };
    }
  } catch {
  }
  const oldDir = `${standaloneDir}.old`;
  if (!fs5.existsSync(oldDir)) {
    return { ok: false, reason: "no-old", detail: `${oldDir} does not exist` };
  }
  const oldManifest = path5.join(oldDir, "manifest.json");
  if (!fs5.existsSync(oldManifest)) {
    debugLogger6.error("Rollback failed: .old directory has no manifest.json");
    return {
      ok: false,
      reason: "no-manifest",
      detail: `${oldDir}/manifest.json missing \u2014 .old may be corrupt`
    };
  }
  const failedDir = `${standaloneDir}.failed`;
  try {
    if (fs5.existsSync(failedDir)) {
      fs5.rmSync(failedDir, { recursive: true, force: true });
    }
    fs5.renameSync(standaloneDir, failedDir);
    fs5.renameSync(oldDir, standaloneDir);
    debugLogger6.info("Rollback successful.");
    try {
      fs5.rmSync(failedDir, { recursive: true, force: true });
    } catch {
      debugLogger6.debug(`Leftover .failed dir at ${failedDir}, safe to delete`);
    }
    return { ok: true };
  } catch (err) {
    debugLogger6.error("Rollback failed:", err);
    if (!fs5.existsSync(standaloneDir) && fs5.existsSync(failedDir)) {
      try {
        fs5.renameSync(failedDir, standaloneDir);
        return {
          ok: false,
          reason: "rename-failed",
          detail: `Filesystem error: ${err.message}. Current installation was restored automatically.`
        };
      } catch {
      }
    }
    return {
      ok: false,
      reason: "rename-failed",
      detail: `Filesystem error: ${err.message}. Manual recovery: mv "${oldDir}" "${standaloneDir}"`
    };
  }
}
__name(rollbackStandaloneUpdate, "rollbackStandaloneUpdate");

// packages/cli/src/utils/installationInfo.ts
init_esbuild_shims();
import * as fs6 from "node:fs";
import * as path6 from "node:path";
import * as childProcess from "node:child_process";
var debugLogger7 = createDebugLogger("INSTALLATION_INFO");
var STANDALONE_UNIX_INSTALLER = "https://qwen-code-assets.oss-cn-hangzhou.aliyuncs.com/installation/install-qwen-standalone.sh";
var STANDALONE_WINDOWS_INSTALLER = "https://qwen-code-assets.oss-cn-hangzhou.aliyuncs.com/installation/install-qwen-standalone.ps1";
function getInstallationInfo(projectRoot, isAutoUpdateEnabled) {
  const cliPath = process.argv[1];
  if (!cliPath) {
    return { packageManager: "unknown" /* UNKNOWN */, isGlobal: false };
  }
  try {
    const realPath = fs6.realpathSync(cliPath).replace(/\\/g, "/");
    const normalizedProjectRoot = projectRoot?.replace(/\\/g, "/");
    const isGit = isGitRepository(process.cwd());
    if (isGit && normalizedProjectRoot && isSamePathOrInside(realPath, normalizedProjectRoot) && !realPath.includes("/node_modules/")) {
      return {
        packageManager: "unknown" /* UNKNOWN */,
        // Not managed by a package manager in this sense
        isGlobal: false,
        updateMessage: 'Running from a local git clone. Please update with "git pull".'
      };
    }
    if (realPath.includes("/.npm/_npx") || realPath.includes("/npm/_npx")) {
      return {
        packageManager: "npx" /* NPX */,
        isGlobal: false,
        updateMessage: "Running via npx, update not applicable."
      };
    }
    if (realPath.includes("/.pnpm/_pnpx")) {
      return {
        packageManager: "pnpx" /* PNPX */,
        isGlobal: false,
        updateMessage: "Running via pnpx, update not applicable."
      };
    }
    const standaloneInfo = getStandaloneInstallInfo(
      realPath,
      isAutoUpdateEnabled
    );
    if (standaloneInfo) {
      return standaloneInfo;
    }
    if (process.platform === "darwin") {
      try {
        childProcess.execSync('brew list -1 | grep -q "^qwen-code$"', {
          stdio: "ignore"
        });
        return {
          packageManager: "homebrew" /* HOMEBREW */,
          isGlobal: true,
          updateMessage: 'Installed via Homebrew. Please update with "brew upgrade".'
        };
      } catch (_error) {
      }
    }
    if (realPath.includes("/.pnpm/global")) {
      const updateCommand2 = "pnpm add -g @qwen-code/qwen-code@latest";
      return {
        packageManager: "pnpm" /* PNPM */,
        isGlobal: true,
        updateCommand: updateCommand2,
        updateMessage: isAutoUpdateEnabled ? "Installed with pnpm. Attempting to automatically update now..." : `Please run ${updateCommand2} to update`
      };
    }
    if (realPath.includes("/.yarn/global")) {
      const updateCommand2 = "yarn global add @qwen-code/qwen-code@latest";
      return {
        packageManager: "yarn" /* YARN */,
        isGlobal: true,
        updateCommand: updateCommand2,
        updateMessage: isAutoUpdateEnabled ? "Installed with yarn. Attempting to automatically update now..." : `Please run ${updateCommand2} to update`
      };
    }
    if (realPath.includes("/.bun/install/cache")) {
      return {
        packageManager: "bunx" /* BUNX */,
        isGlobal: false,
        updateMessage: "Running via bunx, update not applicable."
      };
    }
    if (realPath.includes("/.bun/bin")) {
      const updateCommand2 = "bun add -g @qwen-code/qwen-code@latest";
      return {
        packageManager: "bun" /* BUN */,
        isGlobal: true,
        updateCommand: updateCommand2,
        updateMessage: isAutoUpdateEnabled ? "Installed with bun. Attempting to automatically update now..." : `Please run ${updateCommand2} to update`
      };
    }
    if (normalizedProjectRoot && isSamePathOrInside(realPath, `${normalizedProjectRoot}/node_modules`)) {
      let pm = "npm" /* NPM */;
      if (fs6.existsSync(path6.join(projectRoot, "yarn.lock"))) {
        pm = "yarn" /* YARN */;
      } else if (fs6.existsSync(path6.join(projectRoot, "pnpm-lock.yaml"))) {
        pm = "pnpm" /* PNPM */;
      } else if (fs6.existsSync(path6.join(projectRoot, "bun.lockb"))) {
        pm = "bun" /* BUN */;
      }
      return {
        packageManager: pm,
        isGlobal: false,
        updateMessage: "Locally installed. Please update via your project's package.json."
      };
    }
    const npmPackageDir = path6.dirname(path6.dirname(realPath));
    let npmPrefixWritable = false;
    try {
      fs6.accessSync(npmPackageDir, fs6.constants.W_OK);
      npmPrefixWritable = true;
    } catch {
    }
    if (!npmPrefixWritable) {
      return {
        packageManager: "npm" /* NPM */,
        isGlobal: true,
        updateMessage: "Update requires sudo. Please run: sudo npm install -g @qwen-code/qwen-code@latest"
      };
    }
    const updateCommand = "npm install -g @qwen-code/qwen-code@latest";
    return {
      packageManager: "npm" /* NPM */,
      isGlobal: true,
      updateCommand,
      updateMessage: isAutoUpdateEnabled ? "Installed with npm. Attempting to automatically update now..." : `Please run ${updateCommand} to update`
    };
  } catch (error) {
    debugLogger7.error("Failed to detect installation info:", error);
    return { packageManager: "unknown" /* UNKNOWN */, isGlobal: false };
  }
}
__name(getInstallationInfo, "getInstallationInfo");
function stripTrailingSlashes(value) {
  return value.replace(/\/+$/, "") || "/";
}
__name(stripTrailingSlashes, "stripTrailingSlashes");
function isSamePathOrInside(candidate, parent) {
  const normalizedCandidate = stripTrailingSlashes(candidate);
  const normalizedParent = stripTrailingSlashes(parent);
  if (normalizedParent === "/") {
    return normalizedCandidate === "/" || normalizedCandidate.startsWith("/");
  }
  return normalizedCandidate === normalizedParent || normalizedCandidate.startsWith(`${normalizedParent}/`);
}
__name(isSamePathOrInside, "isSamePathOrInside");
function getStandaloneInstallInfo(realPath, isAutoUpdateEnabled) {
  const installDir = standaloneInstallDirForCliPath(realPath);
  if (!installDir || !isStandaloneInstallDir(installDir)) {
    return null;
  }
  const updateCommand = process.platform === "win32" ? `powershell -ExecutionPolicy Bypass -c "irm ${STANDALONE_WINDOWS_INSTALLER} | iex"` : `curl -fsSL ${STANDALONE_UNIX_INSTALLER} | bash`;
  return {
    packageManager: "standalone" /* STANDALONE */,
    isGlobal: true,
    isStandalone: true,
    standaloneDir: installDir,
    updateMessage: isAutoUpdateEnabled ? "Standalone install detected. Attempting to automatically update now..." : `Standalone install detected. Please rerun the standalone installer to update: ${updateCommand}`
  };
}
__name(getStandaloneInstallInfo, "getStandaloneInstallInfo");
function standaloneInstallDirForCliPath(realPath) {
  const normalized = realPath.replace(/\\/g, "/");
  const suffix = "/lib/cli.js";
  if (!normalized.endsWith(suffix)) {
    return null;
  }
  return realPath.slice(0, -suffix.length);
}
__name(standaloneInstallDirForCliPath, "standaloneInstallDirForCliPath");
function isStandaloneInstallDir(installDir) {
  try {
    const manifestPath = path6.join(installDir, "manifest.json");
    if (!fs6.existsSync(manifestPath)) {
      return false;
    }
    const manifest = JSON.parse(fs6.readFileSync(manifestPath, "utf8"));
    if (manifest.name !== "@qwen-code/qwen-code" || typeof manifest.target !== "string" || !isStandaloneTargetForCurrentPlatform(manifest.target)) {
      return false;
    }
    const qwenBin = process.platform === "win32" ? path6.join(installDir, "bin", "qwen.cmd") : path6.join(installDir, "bin", "qwen");
    const nodeBin = process.platform === "win32" ? path6.join(installDir, "node", "node.exe") : path6.join(installDir, "node", "bin", "node");
    return fs6.existsSync(qwenBin) && fs6.existsSync(nodeBin) && isStandaloneRuntimeFile(qwenBin) && isStandaloneRuntimeFile(nodeBin);
  } catch (err) {
    debugLogger7.error("Standalone detection failed:", installDir, err);
    return false;
  }
}
__name(isStandaloneInstallDir, "isStandaloneInstallDir");
function isStandaloneTargetForCurrentPlatform(target) {
  switch (process.platform) {
    case "darwin":
      return /^darwin-(arm64|x64)$/.test(target);
    case "linux":
      return /^linux-(arm64|x64)$/.test(target);
    case "win32":
      return /^win-(arm64|x64)$/.test(target);
    default:
      return false;
  }
}
__name(isStandaloneTargetForCurrentPlatform, "isStandaloneTargetForCurrentPlatform");
function isStandaloneRuntimeFile(filePath) {
  const stats = fs6.lstatSync(filePath);
  if (!stats.isFile() || stats.isSymbolicLink()) {
    return false;
  }
  return process.platform === "win32" || (stats.mode & 73) !== 0;
}
__name(isStandaloneRuntimeFile, "isStandaloneRuntimeFile");

// packages/cli/src/ui/commands/doctorCommand.ts
var MEMORY_SUBCOMMAND = "memory";
var CPU_PROFILE_SUBCOMMAND = "cpu-profile";
var ROLLBACK_SUBCOMMAND = "rollback";
var DOCTOR_SUBCOMMANDS = [
  MEMORY_SUBCOMMAND,
  CPU_PROFILE_SUBCOMMAND,
  ROLLBACK_SUBCOMMAND
];
function getHeapSnapshotSensitiveDataWarning() {
  return t(
    "Heap snapshot may contain prompts, file contents, tool results, and other sensitive data. Do not share it publicly without reviewing it first."
  );
}
__name(getHeapSnapshotSensitiveDataWarning, "getHeapSnapshotSensitiveDataWarning");
function formatErrorMessage2(error) {
  return error instanceof Error ? error.message : String(error);
}
__name(formatErrorMessage2, "formatErrorMessage");
function formatHeapSnapshotErrorMessage(error) {
  const message = formatErrorMessage2(error);
  return message.startsWith("Heap snapshot") ? message : `${t("Heap snapshot failed:")} ${message}`;
}
__name(formatHeapSnapshotErrorMessage, "formatHeapSnapshotErrorMessage");
var doctorCommand = {
  name: "doctor",
  get description() {
    return t("Run installation and environment diagnostics");
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive", "non_interactive", "acp"],
  argumentHint: "[memory|cpu-profile|rollback] [--sample] [--snapshot] [--duration]",
  examples: [
    "/doctor",
    "/doctor memory",
    "/doctor memory --sample",
    "/doctor memory --snapshot",
    "/doctor cpu-profile",
    "/doctor cpu-profile --duration 10",
    "/doctor rollback"
  ],
  completion: /* @__PURE__ */ __name(async (_context, partialArg) => {
    const trimmed = partialArg.trimStart();
    return DOCTOR_SUBCOMMANDS.filter(
      (candidate) => candidate.startsWith(trimmed)
    );
  }, "completion"),
  action: /* @__PURE__ */ __name(async (context, args) => {
    const executionMode = context.executionMode ?? "interactive";
    const abortSignal = context.abortSignal;
    const subCommandArgs = args?.trim().toLowerCase().split(/\s+/).filter(Boolean) ?? [];
    const subCommand = subCommandArgs[0] ?? "";
    const shouldWriteHeapSnapshot = subCommandArgs.includes("--snapshot");
    const shouldSampleMemory = subCommandArgs.includes("--sample");
    if (subCommand === ROLLBACK_SUBCOMMAND) {
      if (executionMode === "acp") {
        return {
          type: "message",
          messageType: "error",
          content: t("Rollback is not available in ACP mode.")
        };
      }
      return rollbackDoctorAction(context);
    }
    if (subCommand === MEMORY_SUBCOMMAND) {
      if (abortSignal?.aborted) {
        return;
      }
      const diagnostics = getMemoryDiagnostics();
      if (abortSignal?.aborted) {
        return;
      }
      let report = formatMemoryDiagnostics(diagnostics);
      let messageType = "info";
      let heapSnapshotWritten = false;
      if (abortSignal?.aborted) {
        return;
      }
      if (shouldSampleMemory) {
        const samples = await collectMemoryPressureSamples({
          sampleCount: 3,
          intervalMs: 1e3,
          signal: abortSignal
        });
        report = `${report}

${formatMemoryPressureSamples(samples)}`;
        if (abortSignal?.aborted) {
          if (executionMode === "interactive") {
            context.ui.addItem(
              {
                type: "info",
                text: report
              },
              Date.now()
            );
            return;
          }
          return {
            type: "message",
            messageType: "info",
            content: report
          };
        }
      }
      if (shouldWriteHeapSnapshot) {
        if (abortSignal?.aborted) {
          return;
        }
        if (executionMode === "interactive") {
          context.ui.setPendingItem({
            type: "info",
            text: t("Writing heap snapshot, this may take a moment...")
          });
        }
        try {
          const latestDiagnostics = shouldSampleMemory ? getMemoryDiagnostics() : diagnostics;
          if (isHighHeapPressure(latestDiagnostics)) {
            throw new Error(
              t(
                "Heap snapshot skipped: V8 heap pressure is already high, and writing a synchronous heap snapshot could make the process unresponsive or trigger OOM. Restart Qwen Code first if it is unstable, or retry before memory pressure reaches the warning threshold."
              )
            );
          }
          const heapSnapshotPath = writeMemoryHeapSnapshot();
          heapSnapshotWritten = true;
          report = `${report}

${t("Heap snapshot written:")} ${heapSnapshotPath}
${getHeapSnapshotSensitiveDataWarning()}`;
        } catch (error) {
          messageType = "error";
          report = `${report}

${formatHeapSnapshotErrorMessage(error)}`;
        } finally {
          if (executionMode === "interactive") {
            context.ui.setPendingItem(null);
          }
        }
      }
      if (abortSignal?.aborted && shouldWriteHeapSnapshot && !heapSnapshotWritten) {
        return;
      }
      if (executionMode === "interactive") {
        context.ui.addItem(
          {
            type: messageType === "error" ? "error" : "info",
            text: report
          },
          Date.now()
        );
        return;
      }
      return {
        type: "message",
        messageType,
        content: report
      };
    }
    if (subCommand === CPU_PROFILE_SUBCOMMAND) {
      return cpuProfileDoctorAction(context, subCommandArgs.slice(1).join(" "));
    }
    if (executionMode === "interactive") {
      context.ui.setPendingItem({
        type: "info",
        text: t("Running diagnostics...")
      });
    }
    try {
      const checks = await runDoctorChecks(context);
      if (abortSignal?.aborted) {
        return;
      }
      const summary = {
        pass: checks.filter((c) => c.status === "pass").length,
        warn: checks.filter((c) => c.status === "warn").length,
        fail: checks.filter((c) => c.status === "fail").length
      };
      if (executionMode === "interactive") {
        const doctorItem = {
          type: "doctor",
          checks,
          summary
        };
        context.ui.addItem(doctorItem, Date.now());
        return;
      }
      return {
        type: "message",
        messageType: summary.fail > 0 ? "error" : "info",
        content: JSON.stringify({ checks, summary }, null, 2)
      };
    } finally {
      if (executionMode === "interactive") {
        context.ui.setPendingItem(null);
      }
    }
  }, "action"),
  subCommands: [
    {
      name: "memory",
      get description() {
        return t("Show current process memory diagnostics");
      },
      kind: "built-in" /* BUILT_IN */,
      supportedModes: ["interactive", "non_interactive", "acp"],
      argumentHint: "[--json] [--sample] [--snapshot]",
      action: memoryDoctorAction
    },
    {
      name: "cpu-profile",
      get description() {
        return t("Record a CPU profile for Chrome DevTools analysis");
      },
      kind: "built-in" /* BUILT_IN */,
      supportedModes: ["interactive", "non_interactive", "acp"],
      argumentHint: "[--duration <seconds>]",
      action: cpuProfileDoctorAction
    },
    {
      name: "rollback",
      get description() {
        return t("Roll back a standalone update to the previous version");
      },
      kind: "built-in" /* BUILT_IN */,
      supportedModes: ["interactive", "non_interactive"],
      action: rollbackDoctorAction
    }
  ]
};
var MEMORY_USAGE_HINT = "/doctor memory [--json] [--sample] [--snapshot]";
async function memoryDoctorAction(context, args = "") {
  if (context.abortSignal?.aborted) {
    return;
  }
  const tokens = args.trim().split(/\s+/).filter(Boolean);
  const unknown = tokens.filter(
    (token) => token !== "--json" && token !== "--sample" && token !== "--snapshot"
  );
  if (unknown.length > 0) {
    return {
      type: "message",
      messageType: "error",
      content: `${t("Unknown argument(s)")}: ${unknown.join(", ")}. ${t("Usage")}: ${MEMORY_USAGE_HINT}`
    };
  }
  const shouldSampleMemory = tokens.includes("--sample");
  const shouldWriteHeapSnapshot = tokens.includes("--snapshot");
  if (shouldSampleMemory || shouldWriteHeapSnapshot) {
    return doctorCommand.action?.(
      context,
      [MEMORY_SUBCOMMAND, ...tokens.filter((token) => token !== "--json")].join(
        " "
      )
    );
  }
  try {
    const diagnostics = await collectMemoryDiagnostics({
      sessionId: context.services.config?.getSessionId(),
      qwenVersion: context.services.config?.getCliVersion()
    });
    if (context.abortSignal?.aborted) {
      return;
    }
    return {
      type: "message",
      messageType: diagnostics.analysis.risks.length > 0 ? "warning" : "info",
      content: tokens.includes("--json") ? JSON.stringify(diagnostics, null, 2) : formatCoreDiagnostics(diagnostics)
    };
  } catch (error) {
    if (context.abortSignal?.aborted) {
      return;
    }
    return {
      type: "message",
      messageType: "error",
      content: `${t("Failed to collect memory diagnostics")}: ${formatErrorMessage2(error)}`
    };
  }
}
__name(memoryDoctorAction, "memoryDoctorAction");
function formatCpuMicroseconds(micros) {
  return `${(micros / 1e6).toFixed(2)}s`;
}
__name(formatCpuMicroseconds, "formatCpuMicroseconds");
function formatHeapSpaces(spaces) {
  if (!spaces || spaces.length === 0) {
    return void 0;
  }
  const top = [...spaces].sort((a, b) => b.used - a.used).slice(0, 4);
  const lines = top.map(
    (space) => `  - ${space.name}: used ${formatMemoryUsage(space.used)} / size ${formatMemoryUsage(space.size)}`
  );
  if (spaces.length > top.length) {
    lines.push(`  - \u2026 ${spaces.length - top.length} more`);
  }
  return lines.join("\n");
}
__name(formatHeapSpaces, "formatHeapSpaces");
function formatSmapsRollup(smapsRollup) {
  if (!smapsRollup) {
    return t("unavailable");
  }
  const rssLine = smapsRollup.split(/\r?\n/).map((line) => line.trim().replace(/\s+/g, " ")).find((line) => line.startsWith("Rss:"));
  if (rssLine) {
    return rssLine;
  }
  const preview = smapsRollup.slice(0, 80).trim().replace(/\s+/g, " ");
  return `${t("parse error")}: ${preview}`;
}
__name(formatSmapsRollup, "formatSmapsRollup");
function formatCoreDiagnostics(diagnostics) {
  const risks = diagnostics.analysis.risks.length > 0 ? diagnostics.analysis.risks.map((risk) => `  - ${risk.type}: ${risk.message}`).join("\n") : `  ${t("none")}`;
  const lines = [
    t("Memory Diagnostics"),
    `timestamp: ${diagnostics.timestamp}`,
    `uptimeSeconds: ${diagnostics.uptimeSeconds.toFixed(1)}`,
    `heapUsed: ${formatMemoryUsage(diagnostics.memoryUsage.heapUsed)}`,
    `heapTotal: ${formatMemoryUsage(diagnostics.memoryUsage.heapTotal)}`,
    `rss: ${formatMemoryUsage(diagnostics.memoryUsage.rss)}`,
    `external: ${formatMemoryUsage(diagnostics.memoryUsage.external)}`,
    `arrayBuffers: ${formatMemoryUsage(diagnostics.memoryUsage.arrayBuffers)}`,
    `v8HeapLimit: ${formatMemoryUsage(diagnostics.v8HeapStats.heapSizeLimit)}`,
    `v8MallocedMemory: ${formatMemoryUsage(diagnostics.v8HeapStats.mallocedMemory)}`,
    `v8PeakMallocedMemory: ${formatMemoryUsage(diagnostics.v8HeapStats.peakMallocedMemory)}`,
    `detachedContexts: ${diagnostics.v8HeapStats.detachedContexts}`,
    `nativeContexts: ${diagnostics.v8HeapStats.nativeContexts}`,
    `maxRSS: ${formatMemoryUsage(diagnostics.resourceUsage.maxRSS)}`,
    `userCPUTime: ${formatCpuMicroseconds(diagnostics.resourceUsage.userCPUTime)}`,
    `systemCPUTime: ${formatCpuMicroseconds(diagnostics.resourceUsage.systemCPUTime)}`,
    `activeHandles: ${diagnostics.activeHandles}`,
    `activeRequests: ${diagnostics.activeRequests}`,
    `openFileDescriptors: ${diagnostics.openFileDescriptors ?? t("unavailable")}`,
    `smapsRollup: ${formatSmapsRollup(diagnostics.smapsRollup)}`
  ];
  const heapSpaces = formatHeapSpaces(diagnostics.v8HeapSpaces);
  if (heapSpaces) {
    lines.push("v8HeapSpaces:", heapSpaces);
  }
  lines.push(
    "risks:",
    risks,
    `recommendation: ${diagnostics.analysis.recommendation}`
  );
  return lines.join("\n");
}
__name(formatCoreDiagnostics, "formatCoreDiagnostics");
var CPU_PROFILE_USAGE_HINT = "/doctor cpu-profile [--duration <seconds>]";
var DEFAULT_CPU_PROFILE_DURATION_SEC = 30;
var MAX_CPU_PROFILE_DURATION_SEC = 300;
function parseCpuProfileDuration(raw) {
  if (!raw || !/^\d+$/.test(raw)) {
    return NaN;
  }
  return Number(raw);
}
__name(parseCpuProfileDuration, "parseCpuProfileDuration");
async function cpuProfileDoctorAction(context, args = "") {
  const executionMode = context.executionMode ?? "interactive";
  const abortSignal = context.abortSignal;
  if (abortSignal?.aborted) return;
  const tokens = args.trim().split(/\s+/).filter(Boolean);
  let durationSec = DEFAULT_CPU_PROFILE_DURATION_SEC;
  const durationIdx = tokens.indexOf("--duration");
  if (durationIdx !== -1) {
    const rawVal = tokens[durationIdx + 1];
    const val = parseCpuProfileDuration(rawVal);
    if (!Number.isFinite(val) || val < 1 || val > MAX_CPU_PROFILE_DURATION_SEC) {
      const errorMsg = `${t("Duration must be between 1 and {max} seconds", { max: String(MAX_CPU_PROFILE_DURATION_SEC) })}. ${t("Usage")}: ${CPU_PROFILE_USAGE_HINT}`;
      if (executionMode === "interactive") {
        context.ui.addItem({ type: "error", text: errorMsg }, Date.now());
        return;
      }
      return { type: "message", messageType: "error", content: errorMsg };
    }
    durationSec = val;
  }
  const knownTokens = /* @__PURE__ */ new Set(["--duration"]);
  const unknown = tokens.filter((token, idx) => {
    if (knownTokens.has(token)) return false;
    if (idx > 0 && tokens[idx - 1] === "--duration") return false;
    return true;
  });
  if (unknown.length > 0) {
    const errorMsg = `${t("Unknown argument(s)")}: ${unknown.join(", ")}. ${t("Usage")}: ${CPU_PROFILE_USAGE_HINT}`;
    if (executionMode === "interactive") {
      context.ui.addItem({ type: "error", text: errorMsg }, Date.now());
      return;
    }
    return { type: "message", messageType: "error", content: errorMsg };
  }
  if (isCpuProfileRecording()) {
    const errorMsg = process.platform === "win32" ? t("CPU profiling is already in progress. Wait for it to complete.") : t(
      "CPU profiling is already in progress. Send SIGUSR1 or wait for it to complete."
    );
    if (executionMode === "interactive") {
      context.ui.addItem({ type: "error", text: errorMsg }, Date.now());
      return;
    }
    return { type: "message", messageType: "error", content: errorMsg };
  }
  const startResult = await startCpuProfile();
  if (!startResult.ok) {
    if (executionMode === "interactive") {
      context.ui.addItem(
        { type: "error", text: startResult.error },
        Date.now()
      );
      return;
    }
    return {
      type: "message",
      messageType: "error",
      content: startResult.error
    };
  }
  if (abortSignal?.aborted) {
    const abortResult = await stopCpuProfile();
    if (abortResult.ok) {
      const msg = t("CPU profile aborted early. Profile saved: {path}", {
        path: abortResult.filePath
      });
      if (executionMode === "interactive") {
        context.ui.addItem({ type: "info", text: msg }, Date.now());
      }
    } else {
      const msg = `${t("CPU profile aborted but failed to stop cleanly")}: ${abortResult.error}`;
      if (executionMode === "interactive") {
        context.ui.addItem({ type: "error", text: msg }, Date.now());
      }
    }
    return;
  }
  if (executionMode === "interactive") {
    context.ui.setPendingItem({
      type: "info",
      text: t("Recording CPU profile for {duration}s...", {
        duration: String(durationSec)
      })
    });
  }
  await new Promise((resolve5) => {
    const timer = setTimeout(resolve5, durationSec * 1e3);
    if (abortSignal) {
      abortSignal.addEventListener(
        "abort",
        () => {
          clearTimeout(timer);
          resolve5();
        },
        { once: true }
      );
    }
  });
  if (executionMode === "interactive") {
    context.ui.setPendingItem(null);
  }
  const stopResult = await stopCpuProfile();
  if (!stopResult.ok) {
    const alreadyStopped = stopResult.error.includes("not recording");
    if (alreadyStopped) {
      const infoMsg = process.platform === "win32" ? t(
        "CPU profile was stopped externally. Check ~/.qwen/cpu-profiles/ for the output."
      ) : t(
        "CPU profile was stopped externally (e.g., via SIGUSR1). Check ~/.qwen/cpu-profiles/ for the output."
      );
      if (executionMode === "interactive") {
        context.ui.addItem({ type: "info", text: infoMsg }, Date.now());
        return;
      }
      return { type: "message", messageType: "info", content: infoMsg };
    }
    if (executionMode === "interactive") {
      context.ui.addItem({ type: "error", text: stopResult.error }, Date.now());
      return;
    }
    return { type: "message", messageType: "error", content: stopResult.error };
  }
  const successMsg = `${t("CPU profile written:")} ${stopResult.filePath}
${t("Open in Chrome DevTools \u2192 Performance tab \u2192 Load profile")}`;
  if (executionMode === "interactive") {
    context.ui.addItem({ type: "info", text: successMsg }, Date.now());
    return;
  }
  return { type: "message", messageType: "info", content: successMsg };
}
__name(cpuProfileDoctorAction, "cpuProfileDoctorAction");
function rollbackDoctorAction(context) {
  const installInfo = getInstallationInfo(process.cwd(), false);
  if (!installInfo.isStandalone || !installInfo.standaloneDir) {
    const msg2 = t("Rollback is only available for standalone installations.");
    if (context.executionMode === "interactive") {
      context.ui.addItem({ type: "info", text: msg2 }, Date.now());
      return;
    }
    return {
      type: "message",
      messageType: "info",
      content: msg2
    };
  }
  if (process.platform === "win32") {
    const winMsg = t(
      "Rollback on Windows requires manual intervention. Rename qwen-code.old to qwen-code in your installation directory."
    );
    if (context.executionMode === "interactive") {
      context.ui.addItem({ type: "info", text: winMsg }, Date.now());
      return;
    }
    return {
      type: "message",
      messageType: "info",
      content: winMsg
    };
  }
  const result = rollbackStandaloneUpdate(installInfo.standaloneDir);
  let msg;
  let messageType;
  if (result.ok) {
    msg = t(
      "Rollback successful. Restart your terminal to use the previous version."
    );
    messageType = "info";
  } else {
    msg = `${t("Rollback failed:")} ${result.detail}`;
    messageType = "error";
  }
  if (context.executionMode === "interactive") {
    context.ui.addItem({ type: messageType, text: msg }, Date.now());
    return;
  }
  return {
    type: "message",
    messageType,
    content: msg
  };
}
__name(rollbackDoctorAction, "rollbackDoctorAction");

// packages/cli/src/ui/commands/editorCommand.ts
init_esbuild_shims();
var editorCommand = {
  name: "editor",
  get description() {
    return t("set external editor preference");
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive"],
  action: /* @__PURE__ */ __name(() => ({
    type: "dialog",
    dialog: "editor"
  }), "action")
};

// packages/cli/src/ui/commands/effort-command.ts
init_esbuild_shims();
var TIER_LIST = REASONING_EFFORT_TIERS.join(", ");
var effortCommand = {
  name: "effort",
  get description() {
    return t(
      "Set how hard reasoning-capable models think ({{tiers}}); mapped and clamped per provider.",
      { tiers: TIER_LIST }
    );
  },
  // The tiers show up as a placeholder via argumentHint rather than as
  // autocompletion suggestions: bare `/effort` should open the picker dialog
  // (no tier auto-selected), while `/effort <tier>` still sets one directly. A
  // completion function would surface the tiers as submenu-like entries and let
  // Enter auto-pick the first one, which we don't want here.
  argumentHint: "[low|medium|high|xhigh|max]",
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive", "non_interactive", "acp"],
  action: /* @__PURE__ */ __name(async (context, actionArgs) => {
    const { services } = context;
    const { config, settings } = services;
    if (!config) {
      return {
        type: "message",
        messageType: "error",
        content: t("Configuration not available.")
      };
    }
    const args = context.invocation?.args?.trim() || actionArgs.trim();
    if (!args) {
      if (context.executionMode === "interactive") {
        return { type: "dialog", dialog: "effort" };
      }
      const current = config.getReasoningEffort();
      return {
        type: "message",
        messageType: "info",
        content: current ? t(
          'Current reasoning effort: {{current}}\nAvailable: {{tiers}}\nUse "/effort <tier>" to change it.',
          { current, tiers: TIER_LIST }
        ) : t(
          'Reasoning effort: not set (using the model/provider default).\nAvailable: {{tiers}}\nUse "/effort <tier>" to set it.',
          { tiers: TIER_LIST }
        )
      };
    }
    const tier = normalizeReasoningEffort(args);
    if (!tier) {
      return {
        type: "message",
        messageType: "error",
        content: t(
          'Unknown reasoning effort "{{value}}". Choose one of: {{tiers}}.',
          { value: args, tiers: TIER_LIST }
        )
      };
    }
    if (!settings) {
      return {
        type: "message",
        messageType: "error",
        content: t("Settings service not available.")
      };
    }
    config.setReasoningEffort(tier);
    settings.setValue(
      getPersistScopeForModelSelection(settings),
      "model.reasoningEffort",
      tier
    );
    if (config.getReasoningEffort() !== tier) {
      return {
        type: "message",
        messageType: "info",
        content: t(
          "Reasoning effort set to {{tier}}, but thinking is currently disabled \u2014 it will take effect when thinking is re-enabled.",
          { tier }
        )
      };
    }
    return {
      type: "message",
      messageType: "info",
      content: t(
        "Reasoning effort: {{tier}} (requested; the effective tier depends on the active provider/model).",
        { tier }
      )
    };
  }, "action")
};

// packages/cli/src/ui/commands/exportCommand.ts
init_esbuild_shims();
import * as fs7 from "node:fs/promises";
import path7 from "node:path";

// packages/cli/src/ui/utils/export/index.ts
init_esbuild_shims();

// packages/cli/src/ui/utils/export/collect.ts
init_esbuild_shims();
import { randomUUID } from "node:crypto";
function extractToolNameFromRecord(record) {
  if (!record.message?.parts) {
    return void 0;
  }
  for (const part of record.message.parts) {
    if ("functionResponse" in part && part.functionResponse?.name) {
      return part.functionResponse.name;
    }
  }
  return void 0;
}
__name(extractToolNameFromRecord, "extractToolNameFromRecord");
function extractFunctionResponseId(record) {
  if (!record.message?.parts) {
    return void 0;
  }
  for (const part of record.message.parts) {
    if ("functionResponse" in part && part.functionResponse?.id) {
      return part.functionResponse.id;
    }
  }
  return void 0;
}
__name(extractFunctionResponseId, "extractFunctionResponseId");
function normalizeFunctionCallArgs(args) {
  if (args && typeof args === "object") {
    return args;
  }
  if (typeof args === "string") {
    try {
      const parsed = JSON.parse(args);
      if (parsed && typeof parsed === "object") {
        return parsed;
      }
    } catch {
    }
  }
  return void 0;
}
__name(normalizeFunctionCallArgs, "normalizeFunctionCallArgs");
function buildToolCallArgsIndex(records) {
  const byId = /* @__PURE__ */ new Map();
  const byName = /* @__PURE__ */ new Map();
  for (const record of records) {
    if (record.type !== "assistant" || !record.message?.parts) continue;
    for (const part of record.message.parts) {
      if (!("functionCall" in part) || !part.functionCall?.name) continue;
      const normalizedArgs = normalizeFunctionCallArgs(part.functionCall.args);
      if (!normalizedArgs) continue;
      const toolName = part.functionCall.name;
      const callId = typeof part.functionCall.id === "string" ? part.functionCall.id : null;
      if (callId) {
        byId.set(callId, normalizedArgs);
      }
      const queue = byName.get(toolName) ?? [];
      queue.push(normalizedArgs);
      byName.set(toolName, queue);
    }
  }
  return { byId, byName };
}
__name(buildToolCallArgsIndex, "buildToolCallArgsIndex");
function calculateFileStats(records) {
  const argsIndex = buildToolCallArgsIndex(records);
  const byNameCursor = /* @__PURE__ */ new Map();
  const stats = {
    filesWritten: 0,
    linesAdded: 0,
    linesRemoved: 0,
    writtenFilePaths: /* @__PURE__ */ new Set()
  };
  for (const record of records) {
    if (record.type !== "tool_result" || !record.toolCallResult) continue;
    const toolName = extractToolNameFromRecord(record);
    const callId = record.toolCallResult.callId ?? extractFunctionResponseId(record);
    const argsFromId = callId && argsIndex.byId.has(callId) ? argsIndex.byId.get(callId) : void 0;
    let args = argsFromId;
    if (!args && toolName) {
      const queue = argsIndex.byName.get(toolName);
      if (queue && queue.length > 0) {
        const cursor = byNameCursor.get(toolName) ?? 0;
        args = queue[cursor];
        byNameCursor.set(toolName, cursor + 1);
      }
    }
    const { resultDisplay } = record.toolCallResult;
    if (resultDisplay && typeof resultDisplay === "object" && "fileName" in resultDisplay) {
      const display = resultDisplay;
      const hasOriginalContent = "originalContent" in display;
      const hasNewContent = "newContent" in display;
      let filePath;
      if (typeof display.fileName === "string") {
        filePath = args?.["file_path"] || display.fileName;
      } else {
        filePath = "unknown";
      }
      if (hasOriginalContent || hasNewContent) {
        stats.filesWritten++;
        stats.writtenFilePaths.add(filePath);
        if (display.diffStat) {
          stats.linesAdded += display.diffStat.model_added_lines ?? 0;
          stats.linesRemoved += display.diffStat.model_removed_lines ?? 0;
        } else if (!display.truncatedForSession) {
          const oldText = String(display.originalContent ?? "");
          const newText = String(display.newContent ?? "");
          const oldLines = oldText.split("\n").filter((line) => line.length > 0).length;
          const newLines = newText.split("\n").filter((line) => line.length > 0).length;
          stats.linesAdded += newLines;
          stats.linesRemoved += oldLines;
        }
      }
    }
  }
  return stats;
}
__name(calculateFileStats, "calculateFileStats");
function extractTaskToolTokens(record) {
  if (record.type !== "tool_result" || !record.toolCallResult?.resultDisplay) {
    return 0;
  }
  const { resultDisplay } = record.toolCallResult;
  if (typeof resultDisplay === "object" && "type" in resultDisplay && resultDisplay.type === "task_execution" && "executionSummary" in resultDisplay) {
    const summary = resultDisplay.executionSummary;
    if (typeof summary.totalTokens === "number") {
      return summary.totalTokens;
    }
    return (summary.inputTokens ?? 0) + (summary.outputTokens ?? 0) + (summary.thoughtTokens ?? 0) + (summary.cachedTokens ?? 0);
  }
  return 0;
}
__name(extractTaskToolTokens, "extractTaskToolTokens");
function calculateTokenStats(records) {
  let totalTokens = 0;
  let lastValidRecord = null;
  for (const record of records) {
    if (record.type === "assistant") {
      if (record.usageMetadata) {
        totalTokens += record.usageMetadata.totalTokenCount ?? 0;
      }
      if (record.usageMetadata?.totalTokenCount !== void 0 && record.contextWindowSize !== void 0) {
        lastValidRecord = {
          totalTokenCount: record.usageMetadata.totalTokenCount,
          contextWindowSize: record.contextWindowSize
        };
      }
    }
    const taskTokens = extractTaskToolTokens(record);
    if (taskTokens > 0) {
      totalTokens += taskTokens;
    }
  }
  if (lastValidRecord) {
    const percent = lastValidRecord.totalTokenCount / lastValidRecord.contextWindowSize * 100;
    return {
      totalTokens,
      contextUsagePercent: Math.round(percent * 10) / 10,
      contextWindowSize: lastValidRecord.contextWindowSize
    };
  }
  const lastAssistantRecord = [...records].reverse().find((r) => r.type === "assistant" && r.contextWindowSize !== void 0);
  return {
    totalTokens,
    contextWindowSize: lastAssistantRecord?.contextWindowSize
  };
}
__name(calculateTokenStats, "calculateTokenStats");
async function extractMetadata(conversation, config) {
  const { sessionId, startTime, messages } = conversation;
  const firstRecord = messages[0];
  const cwd = firstRecord?.cwd ?? "";
  const gitBranch = firstRecord?.gitBranch;
  let gitRepo;
  if (cwd) {
    const { getGitRepoName } = await import("./src-OJMXXMHL.js");
    gitRepo = getGitRepoName(cwd);
  }
  let model;
  for (const record of messages) {
    if (record.type === "assistant" && record.model) {
      model = record.model;
      break;
    }
  }
  const channel = config.getChannel?.();
  const promptCount = messages.filter((m) => m.type === "user").length;
  const fileStats = calculateFileStats(messages);
  const tokenStats = calculateTokenStats(messages);
  return {
    sessionId,
    startTime,
    exportTime: (/* @__PURE__ */ new Date()).toISOString(),
    cwd,
    gitRepo,
    gitBranch,
    model,
    channel,
    promptCount,
    contextUsagePercent: tokenStats.contextUsagePercent,
    contextWindowSize: tokenStats.contextWindowSize,
    totalTokens: tokenStats.totalTokens,
    filesWritten: fileStats.writtenFilePaths.size,
    linesAdded: fileStats.linesAdded,
    linesRemoved: fileStats.linesRemoved,
    uniqueFiles: Array.from(fileStats.writtenFilePaths)
  };
}
__name(extractMetadata, "extractMetadata");
var ExportSessionContext = class {
  static {
    __name(this, "ExportSessionContext");
  }
  sessionId;
  config;
  messages = [];
  currentMessage = null;
  activeRecordId = null;
  activeRecordTimestamp = null;
  toolCallMap = /* @__PURE__ */ new Map();
  constructor(sessionId, config) {
    this.sessionId = sessionId;
    this.config = config;
  }
  async sendUpdate(update) {
    switch (update.sessionUpdate) {
      case "user_message_chunk":
        this.handleMessageChunk("user", update.content);
        break;
      case "agent_message_chunk": {
        const usageMeta = update._meta;
        const usageMetadata = usageMeta?.usage ? {
          promptTokenCount: usageMeta.usage.inputTokens,
          candidatesTokenCount: usageMeta.usage.outputTokens,
          totalTokenCount: usageMeta.usage.totalTokens,
          thoughtsTokenCount: usageMeta.usage.thoughtTokens,
          cachedContentTokenCount: usageMeta.usage.cachedReadTokens
        } : void 0;
        this.handleMessageChunk(
          "assistant",
          update.content,
          "assistant",
          usageMetadata
        );
        break;
      }
      case "agent_thought_chunk":
        this.handleMessageChunk("assistant", update.content, "thinking");
        break;
      case "tool_call":
        this.flushCurrentMessage();
        this.handleToolCallStart(update);
        break;
      case "tool_call_update":
        this.handleToolCallUpdate(update);
        break;
      case "plan":
        this.flushCurrentMessage();
        this.handlePlanUpdate(update);
        break;
      default:
        break;
    }
  }
  setActiveRecordId(recordId, timestamp) {
    this.activeRecordId = recordId;
    this.activeRecordTimestamp = timestamp ?? null;
  }
  getMessageTimestamp() {
    return this.activeRecordTimestamp ?? (/* @__PURE__ */ new Date()).toISOString();
  }
  getMessageUuid() {
    return this.activeRecordId ?? randomUUID();
  }
  handleMessageChunk(role, content, messageRole = role, usageMetadata) {
    if (content.type !== "text" || !content.text) return;
    if (this.currentMessage && (this.currentMessage.type !== role || this.currentMessage.role !== messageRole)) {
      this.flushCurrentMessage();
    }
    if (this.currentMessage && this.currentMessage.type === role && this.currentMessage.role === messageRole) {
      this.currentMessage.parts.push({ text: content.text });
      if (usageMetadata && role === "assistant") {
        this.currentMessage.usageMetadata = usageMetadata;
      }
    } else {
      this.currentMessage = {
        type: role,
        role: messageRole,
        parts: [{ text: content.text }],
        timestamp: Date.now(),
        ...usageMetadata && role === "assistant" ? { usageMetadata } : {}
      };
    }
  }
  handleToolCallStart(update) {
    const toolCall = {
      toolCallId: update.toolCallId,
      kind: update.kind || "other",
      title: typeof update.title === "string" ? update.title : update.title || "",
      status: update.status || "pending",
      rawInput: update.rawInput,
      locations: update.locations,
      timestamp: Date.now()
    };
    this.toolCallMap.set(update.toolCallId, toolCall);
    const uuid = this.getMessageUuid();
    this.messages.push({
      uuid,
      sessionId: this.sessionId,
      timestamp: this.getMessageTimestamp(),
      type: "tool_call",
      toolCall
    });
  }
  handleToolCallUpdate(update) {
    const toolCall = this.toolCallMap.get(update.toolCallId);
    if (toolCall) {
      if (update.status) toolCall.status = update.status;
      if (update.content) toolCall.content = update.content;
      if (update.title)
        toolCall.title = typeof update.title === "string" ? update.title : "";
    }
  }
  handlePlanUpdate(update) {
    const uuid = this.getMessageUuid();
    const timestamp = this.getMessageTimestamp();
    const todoText = update.entries.map((entry) => {
      const checkbox = entry.status === "completed" ? "[x]" : entry.status === "in_progress" ? "[-]" : "[ ]";
      return `- ${checkbox} ${entry.content}`;
    }).join("\n");
    const todoContent = [
      {
        type: "content",
        content: {
          type: "text",
          text: todoText
        }
      }
    ];
    this.messages.push({
      uuid,
      sessionId: this.sessionId,
      timestamp,
      type: "tool_call",
      toolCall: {
        toolCallId: uuid,
        // Use the same uuid as toolCallId for plan updates
        kind: "todowrite",
        title: "TodoList",
        status: "completed",
        content: todoContent,
        timestamp: Date.parse(timestamp)
      }
    });
  }
  flushCurrentMessage() {
    if (!this.currentMessage) return;
    const uuid = this.getMessageUuid();
    const exportMessage = {
      uuid,
      sessionId: this.sessionId,
      timestamp: this.getMessageTimestamp(),
      type: this.currentMessage.type,
      message: {
        role: this.currentMessage.role,
        parts: this.currentMessage.parts
      }
    };
    if (this.currentMessage.type === "assistant" && this.currentMessage.usageMetadata) {
      exportMessage.usageMetadata = this.currentMessage.usageMetadata;
    }
    this.messages.push(exportMessage);
    this.currentMessage = null;
  }
  flushMessages() {
    this.flushCurrentMessage();
  }
  getMessages() {
    return this.messages;
  }
};
async function collectSessionData(conversation, config) {
  const exportContext = new ExportSessionContext(
    conversation.sessionId,
    config
  );
  const replayer = new HistoryReplayer(exportContext);
  await replayer.replay(conversation.messages);
  exportContext.flushMessages();
  const messages = exportContext.getMessages();
  const metadata = await extractMetadata(conversation, config);
  return {
    sessionId: conversation.sessionId,
    startTime: conversation.startTime,
    messages,
    metadata
  };
}
__name(collectSessionData, "collectSessionData");

// packages/cli/src/ui/utils/export/normalize.ts
init_esbuild_shims();
function normalizeSessionData(sessionData, originalRecords, config) {
  const normalized = [...sessionData.messages];
  const toolCallIndexById = /* @__PURE__ */ new Map();
  normalized.forEach((message, index) => {
    if (message.type === "tool_call" && message.toolCall?.toolCallId) {
      toolCallIndexById.set(message.toolCall.toolCallId, index);
    }
  });
  const assistantMessageIndexByUuid = /* @__PURE__ */ new Map();
  normalized.forEach((message, index) => {
    if (message.type === "assistant") {
      assistantMessageIndexByUuid.set(message.uuid, index);
    }
  });
  for (const record of originalRecords) {
    if (record.type !== "tool_result") continue;
    const toolCallMessage = buildToolCallMessageFromResult(record, config);
    if (!toolCallMessage?.toolCall) continue;
    const existingIndex = toolCallIndexById.get(
      toolCallMessage.toolCall.toolCallId
    );
    if (existingIndex === void 0) {
      toolCallIndexById.set(
        toolCallMessage.toolCall.toolCallId,
        normalized.length
      );
      normalized.push(toolCallMessage);
      continue;
    }
    const existingMessage = normalized[existingIndex];
    if (existingMessage.type !== "tool_call" || !existingMessage.toolCall) {
      continue;
    }
    mergeToolCallData(existingMessage.toolCall, toolCallMessage.toolCall);
  }
  for (const record of originalRecords) {
    if (record.type !== "assistant") continue;
    if (!record.usageMetadata) continue;
    const existingIndex = assistantMessageIndexByUuid.get(record.uuid);
    if (existingIndex !== void 0) {
      if (!normalized[existingIndex].usageMetadata) {
        normalized[existingIndex].usageMetadata = record.usageMetadata;
      }
    }
  }
  return {
    ...sessionData,
    messages: normalized
  };
}
__name(normalizeSessionData, "normalizeSessionData");
function mergeToolCallData(existing, incoming) {
  if (!existing.content || existing.content.length === 0) {
    existing.content = incoming.content;
  }
  if (existing.status === "pending" || existing.status === "in_progress") {
    existing.status = incoming.status;
  }
  if (!existing.rawInput && incoming.rawInput) {
    existing.rawInput = incoming.rawInput;
  }
  if (!existing.kind || existing.kind === "other") {
    existing.kind = incoming.kind;
  }
  if ((!existing.title || existing.title === "") && incoming.title) {
    existing.title = incoming.title;
  }
  if ((!existing.locations || existing.locations.length === 0) && incoming.locations && incoming.locations.length > 0) {
    existing.locations = incoming.locations;
  }
}
__name(mergeToolCallData, "mergeToolCallData");
function buildToolCallMessageFromResult(record, config) {
  const toolCallResult = record.toolCallResult;
  const toolName = extractToolNameFromRecord2(record);
  if (toolName === ToolNames.TODO_WRITE) {
    return null;
  }
  const toolCallId = toolCallResult?.callId ?? record.uuid;
  const functionCallArgs = extractFunctionCallArgs(record);
  const { kind, title, locations } = resolveToolMetadata(
    config,
    toolName,
    functionCallArgs ?? toolCallResult?.args
  );
  const rawInput = normalizeRawInput(
    functionCallArgs ?? toolCallResult?.args
  );
  const content = extractDiffContent(toolCallResult?.resultDisplay) ?? transformPartsToToolCallContent(record.message?.parts ?? []);
  return {
    uuid: record.uuid,
    parentUuid: record.parentUuid,
    sessionId: record.sessionId,
    timestamp: record.timestamp,
    type: "tool_call",
    toolCall: {
      toolCallId,
      kind,
      title,
      status: toolCallResult?.error ? "failed" : "completed",
      rawInput,
      content,
      locations,
      timestamp: Date.parse(record.timestamp)
    }
  };
}
__name(buildToolCallMessageFromResult, "buildToolCallMessageFromResult");
function extractToolNameFromRecord2(record) {
  if (!record.message?.parts) {
    return "";
  }
  for (const part of record.message.parts) {
    if ("functionResponse" in part && part.functionResponse?.name) {
      return part.functionResponse.name;
    }
  }
  return "";
}
__name(extractToolNameFromRecord2, "extractToolNameFromRecord");
function extractFunctionCallArgs(record) {
  if (!record.message?.parts) {
    return void 0;
  }
  for (const part of record.message.parts) {
    if ("functionCall" in part && part.functionCall?.args) {
      return part.functionCall.args;
    }
  }
  return void 0;
}
__name(extractFunctionCallArgs, "extractFunctionCallArgs");
function resolveToolMetadata(config, toolName, args) {
  const toolRegistry = config.getToolRegistry?.();
  const tool = toolName ? toolRegistry?.getTool?.(toolName) : void 0;
  let title = tool?.displayName ?? toolName ?? "tool_call";
  let locations;
  const kind = mapToolKind(tool?.kind, toolName);
  if (tool && args) {
    try {
      const invocation = tool.build(args);
      title = `${title}: ${invocation.getDescription()}`;
      locations = invocation.toolLocations().map((loc) => ({
        path: loc.path,
        line: loc.line ?? null
      }));
    } catch {
    }
  }
  return { kind, title, locations };
}
__name(resolveToolMetadata, "resolveToolMetadata");
function mapToolKind(kind, toolName) {
  if (toolName && (toolName === ToolNames.EXIT_PLAN_MODE || toolName === ToolNames.ENTER_PLAN_MODE)) {
    return "switch_mode";
  }
  if (toolName && toolName === ToolNames.TODO_WRITE) {
    return "todowrite";
  }
  const allowedKinds = /* @__PURE__ */ new Set([
    "read",
    "edit",
    "delete",
    "move",
    "search",
    "execute",
    "think",
    "fetch",
    "other"
  ]);
  if (kind && allowedKinds.has(kind)) {
    return kind;
  }
  return "other";
}
__name(mapToolKind, "mapToolKind");
function extractDiffContent(resultDisplay) {
  if (!resultDisplay || typeof resultDisplay !== "object") {
    return null;
  }
  const display = resultDisplay;
  if ("fileName" in display && "newContent" in display) {
    if (display["truncatedForSession"] === true) {
      return [
        {
          type: "content",
          content: {
            type: "text",
            text: buildTruncatedDiffPreviewText(display)
          }
        }
      ];
    }
    return [
      {
        type: "diff",
        path: display["fileName"],
        oldText: display["originalContent"] ?? "",
        newText: display["newContent"]
      }
    ];
  }
  return null;
}
__name(extractDiffContent, "extractDiffContent");
function normalizeRawInput(value) {
  if (typeof value === "string") return value;
  if (typeof value === "object" && value !== null) return value;
  return void 0;
}
__name(normalizeRawInput, "normalizeRawInput");
function transformPartsToToolCallContent(parts) {
  const content = [];
  for (const part of parts) {
    if ("text" in part && part.text) {
      content.push({
        type: "content",
        content: { type: "text", text: part.text }
      });
      continue;
    }
    if ("functionResponse" in part && part.functionResponse) {
      const response = part.functionResponse.response;
      const outputField = response?.["output"];
      const errorField = response?.["error"];
      const responseText = typeof outputField === "string" ? outputField : typeof errorField === "string" ? errorField : JSON.stringify(response);
      content.push({
        type: "content",
        content: { type: "text", text: responseText }
      });
    }
  }
  return content;
}
__name(transformPartsToToolCallContent, "transformPartsToToolCallContent");

// packages/cli/src/ui/utils/export/formatters/markdown.ts
init_esbuild_shims();
function toMarkdown(sessionData) {
  const lines = [];
  const metadata = sessionData.metadata;
  lines.push("# Chat Session Export\n");
  lines.push(`- **Session ID**: \`${sanitizeText(sessionData.sessionId)}\``);
  lines.push(`- **Start Time**: ${sanitizeText(sessionData.startTime)}`);
  lines.push(
    `- **Exported**: ${sanitizeText(metadata?.exportTime ?? (/* @__PURE__ */ new Date()).toISOString())}`
  );
  lines.push("");
  if (metadata?.cwd) {
    lines.push(`- **Working Directory**: \`${sanitizeText(metadata.cwd)}\``);
  }
  if (metadata?.gitRepo) {
    lines.push(`- **Git Repository**: ${sanitizeText(metadata.gitRepo)}`);
  }
  if (metadata?.gitBranch) {
    lines.push(`- **Git Branch**: \`${sanitizeText(metadata.gitBranch)}\``);
  }
  lines.push("");
  if (metadata?.model) {
    lines.push(`- **Model**: ${sanitizeText(metadata.model)}`);
  }
  if (metadata?.channel) {
    lines.push(`- **Channel**: ${sanitizeText(metadata.channel)}`);
  }
  if (metadata?.promptCount !== void 0) {
    lines.push(`- **Prompt Count**: ${metadata.promptCount}`);
  }
  lines.push("");
  if (metadata?.totalTokens !== void 0) {
    lines.push(`- **Total Tokens**: ${metadata.totalTokens}`);
  }
  if (metadata?.contextWindowSize !== void 0) {
    lines.push(`- **Context Window Size**: ${metadata.contextWindowSize}`);
  }
  if (metadata?.contextUsagePercent !== void 0) {
    lines.push(`- **Context Usage**: ${metadata.contextUsagePercent}%`);
  }
  lines.push("");
  if (metadata?.filesWritten !== void 0) {
    lines.push(`- **Files Written**: ${metadata.filesWritten}`);
  }
  if (metadata?.linesAdded !== void 0) {
    lines.push(`- **Lines Added**: ${metadata.linesAdded}`);
  }
  if (metadata?.linesRemoved !== void 0) {
    lines.push(`- **Lines Removed**: ${metadata.linesRemoved}`);
  }
  if (metadata?.uniqueFiles && metadata.uniqueFiles.length > 0) {
    lines.push("");
    lines.push("<details>");
    lines.push(
      `<summary><strong>Unique Files Referenced (${metadata.uniqueFiles.length})</strong></summary>`
    );
    lines.push("");
    for (const file of metadata.uniqueFiles) {
      lines.push(`- \`${sanitizeText(file)}\``);
    }
    lines.push("</details>");
  }
  lines.push("\n---\n");
  for (const message of sessionData.messages) {
    if (message.type === "user") {
      lines.push("## User\n");
      lines.push(formatMessageContent(message));
    } else if (message.type === "assistant") {
      lines.push("## Assistant\n");
      lines.push(formatMessageContent(message));
    } else if (message.type === "tool_call") {
      lines.push(formatToolCall(message));
    } else if (message.type === "system") {
      lines.push("### System\n");
      const text = formatMessageContent(message);
      lines.push(`> ${text.replace(/\n/g, "\n> ")}`);
    }
    lines.push("\n");
  }
  return lines.join("\n");
}
__name(toMarkdown, "toMarkdown");
function formatMessageContent(message) {
  const text = extractTextFromMessage(message);
  const processedText = text.replace(
    /--- Content from referenced files ---\n([\s\S]*?)\n--- End of content ---/g,
    (match, content) => `
> **Referenced Files:**

${createCodeBlock(content)}
`
  );
  return processedText;
}
__name(formatMessageContent, "formatMessageContent");
function formatToolCall(message) {
  if (!message.toolCall) return "";
  const lines = [];
  const { title, status, rawInput, content, locations } = message.toolCall;
  const titleStr = typeof title === "string" ? title : JSON.stringify(title);
  lines.push(`### Tool: ${sanitizeText(titleStr)}`);
  lines.push(`**Status**: ${sanitizeText(status)}
`);
  if (rawInput) {
    lines.push("**Input:**");
    const inputStr = typeof rawInput === "string" ? rawInput : JSON.stringify(rawInput, null, 2);
    lines.push(createCodeBlock(inputStr, "json"));
    lines.push("");
  }
  if (locations && locations.length > 0) {
    lines.push("**Affected Files:**");
    for (const loc of locations) {
      const lineSuffix = loc.line ? `:${loc.line}` : "";
      lines.push(`- \`${sanitizeText(loc.path)}${lineSuffix}\``);
    }
    lines.push("");
  }
  if (content && content.length > 0) {
    lines.push("**Output:**");
    for (const item of content) {
      if (item.type === "content" && item["content"]) {
        const contentData = item["content"];
        if (contentData.type === "text" && contentData.text) {
          let language = "";
          if (locations && locations.length === 1 && locations[0].path) {
            language = getLanguageFromPath(locations[0].path);
          }
          lines.push(createCodeBlock(contentData.text, language));
        }
      } else if (item.type === "diff") {
        const path20 = item["path"];
        const diffText = item["newText"];
        lines.push(`
*Diff for \`${sanitizeText(path20)}\`:*`);
        lines.push(createCodeBlock(diffText, "diff"));
      }
    }
  }
  return lines.join("\n");
}
__name(formatToolCall, "formatToolCall");
function extractTextFromMessage(message) {
  if (!message.message?.parts) return "";
  const textParts = [];
  for (const part of message.message.parts) {
    if ("text" in part) {
      textParts.push(part.text);
    }
  }
  return textParts.join("\n");
}
__name(extractTextFromMessage, "extractTextFromMessage");
function createCodeBlock(content, language = "") {
  const fence = buildFence(content);
  return `${fence}${language}
${content}
${fence}`;
}
__name(createCodeBlock, "createCodeBlock");
function sanitizeText(value) {
  return (value ?? "").replace(/&/g, "&amp;").replace(/</g, "&lt;");
}
__name(sanitizeText, "sanitizeText");
function buildFence(value) {
  const matches = (value ?? "").match(/`+/g);
  const maxRun = matches ? Math.max(...matches.map((match) => match.length)) : 0;
  const fenceLength = Math.max(3, maxRun + 1);
  return "`".repeat(fenceLength);
}
__name(buildFence, "buildFence");
function getLanguageFromPath(path20) {
  const ext = path20.split(".").pop()?.toLowerCase();
  switch (ext) {
    case "ts":
    case "tsx":
      return "typescript";
    case "js":
    case "jsx":
    case "mjs":
    case "cjs":
      return "javascript";
    case "py":
      return "python";
    case "rb":
      return "ruby";
    case "go":
      return "go";
    case "rs":
      return "rust";
    case "java":
      return "java";
    case "c":
    case "cpp":
    case "h":
    case "hpp":
      return "cpp";
    case "cs":
      return "csharp";
    case "html":
      return "html";
    case "css":
      return "css";
    case "json":
      return "json";
    case "md":
      return "markdown";
    case "sh":
    case "bash":
    case "zsh":
      return "bash";
    case "yaml":
    case "yml":
      return "yaml";
    case "xml":
      return "xml";
    case "sql":
      return "sql";
    default:
      return "";
  }
}
__name(getLanguageFromPath, "getLanguageFromPath");

// packages/cli/src/ui/utils/export/formatters/html.ts
init_esbuild_shims();

// packages/web-templates/src/index.ts
init_esbuild_shims();

// packages/web-templates/src/generated/insightTemplate.ts
init_esbuild_shims();
var INSIGHT_JS = '(function(e,B){"use strict";function U({data:t}){const{totalMessages:n=0,totalLinesAdded:l=0,totalLinesRemoved:s=0,totalFiles:r=0}=t,a=Object.keys(t.heatmap||{});let o=0;if(a.length>0){const c=a.map(x=>new Date(x)).map(x=>x.getTime()),d=new Date(Math.min(...c)),g=new Date(Math.max(...c)),E=Math.abs(g.getTime()-d.getTime());o=Math.ceil(E/(1e3*60*60*24))+1}const i=o>0?Math.round(n/o):0;return e.createElement("div",{className:"stats-row"},e.createElement("div",{className:"stat"},e.createElement("div",{className:"stat-value"},n),e.createElement("div",{className:"stat-label"},"Messages")),e.createElement("div",{className:"stat"},e.createElement("div",{className:"stat-value"},"+",l,"/-",s),e.createElement("div",{className:"stat-label"},"Lines")),e.createElement("div",{className:"stat"},e.createElement("div",{className:"stat-value"},r),e.createElement("div",{className:"stat-label"},"Files")),e.createElement("div",{className:"stat"},e.createElement("div",{className:"stat-value"},o),e.createElement("div",{className:"stat-label"},"Days")),e.createElement("div",{className:"stat"},e.createElement("div",{className:"stat-value"},i),e.createElement("div",{className:"stat-label"},"Msgs/Day")))}function K({insights:t}){return e.createElement("div",{className:"grid gap-4 md:grid-cols-2 md:gap-6"},e.createElement(J,{activeHours:t.activeHours,cardClass:"glass-card p-6",sectionTitleClass:"text-lg font-semibold tracking-tight text-slate-900"}))}function J({activeHours:t,cardClass:n,sectionTitleClass:l}){const r=[{label:"Morning",time:"06:00 - 12:00",hours:[6,7,8,9,10,11],color:"#fbbf24"},{label:"Afternoon",time:"12:00 - 18:00",hours:[12,13,14,15,16,17],color:"#0ea5e9"},{label:"Evening",time:"18:00 - 22:00",hours:[18,19,20,21],color:"#6366f1"},{label:"Night",time:"22:00 - 06:00",hours:[22,23,0,1,2,3,4,5],color:"#475569"}].map(o=>{const i=o.hours.reduce((m,c)=>m+(t[c]||0),0);return{...o,total:i}}),a=Math.max(...r.map(o=>o.total));return e.createElement("div",{className:`${n} h-full flex flex-col min-h-[320px]`},e.createElement("div",{className:"flex items-center justify-between mb-4"},e.createElement("h3",{className:l},"Active Hours")),e.createElement("div",{className:"flex-1 flex flex-col justify-center gap-4"},r.map(o=>e.createElement("div",{key:o.label,className:"space-y-2"},e.createElement("div",{className:"flex justify-between items-center text-sm"},e.createElement("div",{className:"flex items-center gap-2"},e.createElement("span",{className:"rounded-full",style:{width:"12px",height:"12px",backgroundColor:o.color}}),e.createElement("span",{className:"font-medium text-slate-700"},o.label),e.createElement("span",{className:"text-xs text-slate-400 hidden xl:inline"},o.time)),e.createElement("span",{className:"font-semibold text-slate-900"},o.total)),e.createElement("div",{className:"w-full rounded-full overflow-hidden",style:{height:"12px",backgroundColor:"#e2e8f0"}},e.createElement("div",{className:"h-full rounded-full",style:{width:`${a>0?o.total/a*100:0}%`,backgroundColor:o.color}}))))))}function V({heatmap:t}){return e.createElement("div",{className:"glass-card p-6 mt-4 md:mt-6"},e.createElement("div",{className:"mb-3"},e.createElement("h3",{className:"text-lg font-semibold tracking-tight text-slate-900"},"Activity Heatmap"),e.createElement("p",{className:"text-xs text-slate-500"},"Showing past year of activity")),e.createElement("div",{className:"heatmap-container"},e.createElement("div",{className:"min-w-[720px] rounded-xl bg-white/70"},e.createElement(X,{heatmapData:t}))),e.createElement(Z,null))}function X({heatmapData:t}){const a=new Date,o=new Date(a);o.setFullYear(a.getFullYear()-1);const i=[],m=new Date(o);for(;m<=a;)i.push(new Date(m)),m.setDate(m.getDate()+1);const c=[0,2,4,10,20],d=["#ebedf0","#9be9a8","#40c463","#30a14e","#216e39"];function g(u){if(u===0)return d[0];for(let f=c.length-1;f>=1;f--)if(u>=c[f])return d[f];return d[1]}const E=50,x=20,A=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],w=o.getDay(),W=[];let h=-1,T=-100;return i.forEach((u,f)=>{const C=f+w,_=Math.floor(C/7),v=E+_*16,N=u.getMonth();N!==h&&(v-T>30&&(W.push({x:v,text:A[N]}),T=v),h=N)}),e.createElement("svg",{className:"heatmap-svg",width:1e3,height:130,viewBox:"0 0 1000 130"},i.map((u,f)=>{const C=f+w,_=Math.floor(C/7),v=u.getDay(),N=E+_*16,j=x+v*16,k=u.toISOString().split("T")[0],S=t[k]||0,L=g(S);return e.createElement("rect",{key:k,className:"heatmap-day",x:N,y:j,width:14,height:14,rx:"2",fill:L,"data-date":k,"data-count":S},e.createElement("title",null,k,": ",S," activities"))}),W.map((u,f)=>e.createElement("text",{key:f,x:u.x,y:"15",fontSize:"12",fill:"#64748b"},u.text)))}function Z(){const t=["#ebedf0","#9be9a8","#40c463","#30a14e","#216e39"];return e.createElement("div",{className:"flex items-center gap-2 mt-4"},e.createElement("span",{className:"text-xs text-slate-500"},"Less"),t.map((n,l)=>e.createElement("span",{key:l,className:"inline-block rounded",style:{width:"10px",height:"10px",backgroundColor:n}})),e.createElement("span",{className:"text-xs text-slate-500"},"More"))}function p({children:t}){if(!t||typeof t!="string")return t;const n=t.split(/(\\*\\*.*?\\*\\*)/g);return e.createElement(e.Fragment,null,n.map((l,s)=>l.startsWith("**")&&l.endsWith("**")&&l.length>=4?e.createElement("strong",{key:s},l.slice(2,-2)):l))}function F({text:t,label:n="Copy"}){const[l,s]=e.useState(!1),r=()=>{navigator.clipboard.writeText(t).then(()=>{s(!0),setTimeout(()=>s(!1),2e3)})};return e.createElement("button",{className:"copy-btn",onClick:r},l?"Copied!":n)}function R(t){return typeof t=="string"&&t.trim().length>0}function ee({qualitative:t,targetSections:n}){const{atAGlance:l}=t;if(!l)return null;const s=[{key:"wins",label:"What\'s working:",body:l.whats_working,href:"#section-wins",link:"Impressive Things You Did \u2192",showLink:n.wins},{key:"friction",label:"What\'s hindering you:",body:l.whats_hindering,href:"#section-friction",link:"Where Things Go Wrong \u2192",showLink:n.friction},{key:"features",label:"Quick wins to try:",body:l.quick_wins,href:"#section-features",link:"Features to Try \u2192",showLink:n.features},{key:"horizon",label:"Ambitious workflows:",body:l.ambitious_workflows,href:"#section-horizon",link:"On the Horizon \u2192",showLink:n.horizon}].filter(r=>R(r.body));return s.length===0?null:e.createElement("div",{className:"at-a-glance"},e.createElement("div",{className:"glance-title"},"At a Glance"),e.createElement("div",{className:"glance-sections"},s.map(r=>e.createElement("div",{key:r.key,className:"glance-section"},e.createElement("strong",null,r.label)," ",e.createElement(p,null,r.body),r.showLink&&e.createElement("a",{href:r.href,className:"see-more"},r.link)))))}function te({sections:t}){return t.length===0?null:e.createElement("nav",{className:"nav-toc"},t.map(n=>e.createElement("a",{key:n.href,href:n.href},n.label)))}function ne({qualitative:t,topGoals:n,topTools:l}){const{projectAreas:s}=t,r=Array.isArray(l)?Object.fromEntries(l):l;return e.createElement(e.Fragment,null,e.createElement("h2",{id:"section-work",className:"text-xl font-semibold text-slate-900 mt-8 mb-4"},"What You Work On"),Array.isArray(s==null?void 0:s.areas)&&s.areas.length>0&&e.createElement("div",{className:"project-areas mb-6"},s.areas.map((a,o)=>e.createElement("div",{key:o,className:"project-area"},e.createElement("div",{className:"area-header"},e.createElement("span",{className:"area-name"},a.name),e.createElement("span",{className:"area-count"},"~",a.session_count," sessions")),e.createElement("div",{className:"area-desc"},e.createElement(p,null,a.description))))),e.createElement("div",{style:{display:"grid",gridTemplateColumns:"repeat(2, 1fr)",gap:"24px",marginBottom:"24px"}},n&&Object.keys(n).length>0&&e.createElement(D,{data:n,title:"What You Wanted",color:"#0ea5e9"}),r&&Object.keys(r).length>0&&e.createElement(D,{data:r,title:"Top Tools Used",color:"#6366f1"})))}function le({qualitative:t,insights:n}){const{interactionStyle:l}=t;return l?e.createElement(e.Fragment,null,e.createElement("h2",{id:"section-usage",className:"text-xl font-semibold text-slate-900 mt-8 mb-4"},"How You Use Qwen Code"),e.createElement("div",{className:"narrative"},e.createElement("p",null,e.createElement(p,null,l.narrative)),l.key_pattern&&e.createElement("div",{className:"key-insight"},e.createElement("strong",null,"Key pattern:")," ",e.createElement(p,null,l.key_pattern))),e.createElement(K,{insights:n}),e.createElement(V,{heatmap:n.heatmap})):null}function re({qualitative:t,primarySuccess:n,outcomes:l}){const s=t==null?void 0:t.impressiveWorkflows;return e.createElement(e.Fragment,null,e.createElement("h2",{id:"section-wins",className:"text-xl font-semibold text-slate-900 mt-8 mb-4"},"Impressive Things You Did"),(s==null?void 0:s.intro)&&e.createElement("p",{className:"section-intro"},e.createElement(p,null,s.intro)),s&&e.createElement("div",{className:"big-wins"},Array.isArray(s.impressive_workflows)&&s.impressive_workflows.map((r,a)=>e.createElement("div",{key:a,className:"big-win"},e.createElement("div",{className:"big-win-title"},r.title),e.createElement("div",{className:"big-win-desc"},e.createElement(p,null,r.description))))),e.createElement("div",{style:{display:"grid",gridTemplateColumns:"repeat(2, 1fr)",gap:"24px",marginTop:"24px",marginBottom:"24px"}},n&&Object.keys(n).length>0&&e.createElement(D,{data:n,title:"What Helped Most (Qwen\'s Capabilities)",color:"#3b82f6",allowedKeys:["fast_accurate_search","correct_code_edits","good_explanations","proactive_help","multi_file_changes","good_debugging"]}),l&&Object.keys(l).length>0&&e.createElement(D,{data:l,title:"Outcomes",color:"#8b5cf6",allowedKeys:["fully_achieved","mostly_achieved","partially_achieved","not_achieved","unclear_from_transcript"]})))}function se(t){return t==="unclear_from_transcript"?"Unclear":t.split("_").map(n=>n.charAt(0).toUpperCase()+n.slice(1)).join(" ")}function D({data:t,title:n,color:l="#3b82f6",allowedKeys:s=null}){if(!t||Object.keys(t).length===0)return null;let r=Object.entries(t).filter(([,o])=>Number.isFinite(o)&&o!==0);if(s&&(r=r.filter(([o])=>s.includes(o))),r.sort((o,i)=>i[1]-o[1]),r=r.slice(0,10),r.length===0)return null;const a=Math.max(...r.map(([,o])=>o));return e.createElement("div",{className:"bar-chart-card",style:{flex:1,minWidth:0,backgroundColor:"#ffffff",borderRadius:"12px",padding:"20px",boxShadow:"0 1px 3px rgba(0, 0, 0, 0.08)",border:"1px solid #e2e8f0"}},e.createElement("h3",{style:{fontSize:"13px",fontWeight:700,color:"#64748b",marginTop:0,marginBottom:"16px",textTransform:"uppercase",letterSpacing:"0.5px"}},n),e.createElement("div",{className:"bar-chart",style:{display:"flex",flexDirection:"column",gap:"10px"}},r.map(([o,i])=>{const m=a>0?i/a*100:0;return e.createElement("div",{key:o,className:"bar-row",style:{display:"flex",alignItems:"center",gap:"12px"}},e.createElement("div",{className:"bar-label",style:{width:"130px",fontSize:"13px",color:"#475569",textAlign:"left",flexShrink:0,whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis"}},se(o)),e.createElement("div",{className:"bar-wrapper",style:{flex:1,display:"flex",alignItems:"center",gap:"10px",minWidth:0}},e.createElement("div",{className:"bar-bg",style:{flex:1,height:"8px",backgroundColor:"#f1f5f9",borderRadius:"4px",overflow:"hidden"}},e.createElement("div",{className:"bar-fill",style:{width:`${m}%`,height:"100%",backgroundColor:l,borderRadius:"4px",transition:"width 0.3s ease"}})),e.createElement("span",{className:"bar-value",style:{fontSize:"13px",fontWeight:600,color:"#475569",minWidth:"24px",textAlign:"right"}},i)))})))}function ae({qualitative:t,satisfaction:n,friction:l}){const s=t==null?void 0:t.frictionPoints;return e.createElement(e.Fragment,null,e.createElement("h2",{id:"section-friction",className:"text-xl font-semibold text-slate-900 mt-8 mb-4"},"Where Things Go Wrong"),(s==null?void 0:s.intro)&&e.createElement("p",{className:"section-intro"},e.createElement(p,null,s.intro)),s&&e.createElement("div",{className:"friction-categories"},Array.isArray(s.categories)&&s.categories.map((r,a)=>e.createElement("div",{key:a,className:"friction-category"},e.createElement("div",{className:"friction-title"},r.category),e.createElement("div",{className:"friction-desc"},e.createElement(p,null,r.description)),Array.isArray(r.examples)&&r.examples.length>0&&e.createElement("ul",{className:"friction-examples"},r.examples.map((o,i)=>e.createElement("li",{key:i},e.createElement(p,null,o))))))),e.createElement("div",{style:{display:"grid",gridTemplateColumns:"repeat(2, 1fr)",gap:"24px",marginTop:"24px",marginBottom:"24px"}},l&&Object.keys(l).length>0&&e.createElement(D,{data:l,title:"Primary Friction Types",color:"#ef4444",allowedKeys:["misunderstood_request","wrong_approach","buggy_code","user_rejected_action","excessive_changes"]}),n&&Object.keys(n).length>0&&e.createElement(D,{data:n,title:"Inferred Satisfaction (model-estimated)",color:"#10b981",allowedKeys:["happy","satisfied","likely_satisfied","dissatisfied","frustrated"]})))}function oe({additions:t}){const[n,l]=e.useState(new Array(t.length).fill(!0)),[s,r]=e.useState(!1),a=m=>{const c=n.map((d,g)=>g===m?!d:d);l(c)},o=()=>{const m=t.filter((c,d)=>n[d]).map(c=>c.addition).join(`\n\n`);m&&navigator.clipboard.writeText(m).then(()=>{r(!0),setTimeout(()=>r(!1),2e3)})},i=n.filter(Boolean).length;return e.createElement("div",{className:"qwen-md-section"},e.createElement("h3",null,"Suggested QWEN.md Additions"),e.createElement("p",{className:"text-xs text-slate-500 mb-3"},"Just copy this into Qwen Code to add it to your QWEN.md."),e.createElement("div",{className:"qwen-md-actions",style:{marginBottom:"12px"}},e.createElement("button",{className:`copy-all-btn ${s?"copied":""}`,onClick:o,disabled:i===0},s?"Copied All!":`Copy All Checked (${i})`)),t.map((m,c)=>e.createElement("div",{key:c,className:"qwen-md-item"},e.createElement("input",{type:"checkbox",checked:n[c],onChange:()=>a(c),className:"cmd-checkbox"}),e.createElement("div",{style:{flex:1}},e.createElement("code",{className:"cmd-code"},m.addition),e.createElement("div",{className:"cmd-why"},e.createElement(p,null,m.why))),e.createElement(F,{text:m.addition}))))}function ie({qualitative:t}){const{improvements:n}=t;if(!n)return null;const l=Array.isArray(n.Qwen_md_additions)&&n.Qwen_md_additions.length>0||Array.isArray(n.features_to_try)&&n.features_to_try.length>0,s=Array.isArray(n.usage_patterns)&&n.usage_patterns.length>0;return!l&&!s?null:e.createElement(e.Fragment,null,l&&e.createElement(e.Fragment,null,e.createElement("h2",{id:"section-features",className:"text-xl font-semibold text-slate-900 mt-8 mb-4"},"Existing Qwen Code Features to Try"),Array.isArray(n.Qwen_md_additions)&&n.Qwen_md_additions.length>0&&e.createElement(oe,{additions:n.Qwen_md_additions}),e.createElement("p",{className:"text-xs text-slate-500 mb-3"},"Just copy this into Qwen Code and it\'ll set it up for you."),e.createElement("div",{className:"features-section"},Array.isArray(n.features_to_try)&&n.features_to_try.map((r,a)=>e.createElement("div",{key:a,className:"feature-card"},e.createElement("div",{className:"feature-title"},r.feature),e.createElement("div",{className:"feature-oneliner"},e.createElement(p,null,r.one_liner)),e.createElement("div",{className:"feature-why"},e.createElement("strong",null,"Why for you:")," ",e.createElement(p,null,r.why_for_you)),e.createElement("div",{className:"feature-examples"},e.createElement("div",{className:"feature-example"},e.createElement("div",{className:"example-code-row"},e.createElement("code",{className:"example-code"},r.example_code),e.createElement(F,{text:r.example_code})))))))),s&&e.createElement(e.Fragment,null,e.createElement("h2",{id:"section-patterns",className:"text-xl font-semibold text-slate-900 mt-8 mb-4"},"New Ways to Use Qwen Code"),e.createElement("p",{className:"text-xs text-slate-500 mb-3"},"Just copy this into Qwen Code and it\'ll walk you through it."),e.createElement("div",{className:"patterns-section"},Array.isArray(n.usage_patterns)&&n.usage_patterns.map((r,a)=>e.createElement("div",{key:a,className:"pattern-card"},e.createElement("div",{className:"pattern-title"},r.title),e.createElement("div",{className:"pattern-summary"},e.createElement(p,null,r.suggestion)),e.createElement("div",{className:"pattern-detail"},e.createElement(p,null,r.detail)),e.createElement("div",{className:"copyable-prompt-section"},e.createElement("div",{className:"prompt-label"},"Paste into Qwen Code:"),e.createElement("div",{className:"copyable-prompt-row"},e.createElement("code",{className:"copyable-prompt"},r.copyable_prompt),e.createElement(F,{text:r.copyable_prompt}))))))))}function me({qualitative:t}){const{futureOpportunities:n}=t;return n?e.createElement(e.Fragment,null,e.createElement("h2",{id:"section-horizon",className:"text-xl font-semibold text-slate-900 mt-8 mb-4"},"On the Horizon"),n.intro&&e.createElement("p",{className:"section-intro"},e.createElement(p,null,n.intro)),e.createElement("div",{className:"horizon-section"},Array.isArray(n.opportunities)&&n.opportunities.map((l,s)=>e.createElement("div",{key:s,className:"horizon-card"},e.createElement("div",{className:"horizon-title"},l.title),e.createElement("div",{className:"horizon-possible"},e.createElement(p,null,l.whats_possible)),e.createElement("div",{className:"horizon-tip"},e.createElement("strong",null,"Getting started:")," ",e.createElement(p,null,l.how_to_try)),e.createElement("div",{className:"pattern-prompt"},e.createElement("div",{className:"prompt-label"},"Paste into Qwen Code:"),e.createElement("div",{style:{display:"flex",alignItems:"flex-start",gap:"8px"}},e.createElement("code",{style:{flex:1}},l.copyable_prompt),e.createElement(F,{text:l.copyable_prompt}))))))):null}function ce({qualitative:t}){const{memorableMoment:n}=t;return n?e.createElement("div",{className:"fun-ending"},e.createElement("div",{className:"fun-headline"},\'"\',n.headline,\'"\'),e.createElement("div",{className:"fun-detail"},e.createElement(p,null,n.detail))):null}const de={light:{background:"linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%)",textPrimary:"#0f172a",textSecondary:"#475569",textMuted:"#64748b",cardBackground:"rgba(255,255,255,0.7)",cardBackgroundSecondary:"rgba(255,255,255,0.5)",borderColor:"#e2e8f0",heatmapColors:["#9be9a8","#40c463","#30a14e","#216e39"],heatmapEmpty:"#ebedf0"},dark:{background:"linear-gradient(135deg, #0f172a 0%, #1e293b 100%)",textPrimary:"#f8fafc",textSecondary:"#e2e8f0",textMuted:"#94a3b8",cardBackground:"rgba(255,255,255,0.05)",cardBackgroundSecondary:"rgba(255,255,255,0.04)",borderColor:"rgba(255,255,255,0.08)",heatmapColors:["#0e4429","#006d32","#26a641","#39d353"],heatmapEmpty:"#2d333b"}};function pe({data:t,theme:n="light"}){var h,T,u,f,C,_;const l=de[n],{totalMessages:s=0,totalSessions:r=0,totalLinesAdded:a=0,totalLinesRemoved:o=0,totalFiles:i=0,currentStreak:m=0,longestStreak:c=0,activeHours:d={}}=t,g=Object.keys(t.heatmap||{});let E=0,x="";if(g.length>0){E=g.length;const v=g.map(S=>new Date(S).getTime()),N=new Date(Math.min(...v)),j=new Date(Math.max(...v)),k=S=>S.toISOString().split("T")[0];x=`${k(N)} \u2014 ${k(j)}`}const A=(u=(T=(h=t.qualitative)==null?void 0:h.interactionStyle)==null?void 0:T.key_pattern)!=null?u:null,w=(_=(C=(f=t.qualitative)==null?void 0:f.memorableMoment)==null?void 0:C.headline)!=null?_:null,W=fe(t.heatmap||{},l);return e.createElement("div",{id:"share-card",style:{width:"1200px",background:l.background,color:l.textPrimary,fontFamily:\'ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"\',display:"flex",flexDirection:"column",padding:"48px 56px",position:"absolute",left:"-9999px",top:"-9999px",overflow:"hidden",boxSizing:"border-box"}},e.createElement("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:"32px"}},e.createElement("div",null,e.createElement("div",{style:{fontSize:"32px",fontWeight:700,letterSpacing:"-0.02em",lineHeight:1.2}},"Qwen Code Insights"),e.createElement("div",{style:{fontSize:"14px",color:l.textMuted,marginTop:"6px"}},x)),e.createElement("div",{style:{fontSize:"11px",color:l.textMuted,textTransform:"uppercase",letterSpacing:"0.15em",paddingTop:"8px"}},"qwen.ai")),e.createElement("div",{style:{display:"grid",gridTemplateColumns:"repeat(6, 1fr)",gap:"16px",marginBottom:"32px"}},e.createElement(M,{value:String(s),label:"Messages",theme:l}),e.createElement(M,{value:String(r),label:"Sessions",theme:l}),e.createElement(M,{value:`+${a}/-${o}`,label:"Lines Changed",small:!0,theme:l}),e.createElement(M,{value:String(i),label:"Files",theme:l}),e.createElement(M,{value:`${m}d`,label:"Streak",theme:l}),e.createElement(M,{value:`${c}d`,label:"Best Streak",theme:l})),e.createElement("div",{style:{display:"grid",gridTemplateColumns:"1fr 1fr",gap:"24px",marginBottom:"16px"}},e.createElement("div",{style:{background:l.cardBackground,borderRadius:"12px",padding:"20px",display:"flex",flexDirection:"column"}},e.createElement("div",{style:{fontSize:"12px",fontWeight:600,color:l.textMuted,textTransform:"uppercase",letterSpacing:"0.08em",marginBottom:"12px"}},"Activity \xB7 ",E," active days"),e.createElement("div",{style:{flex:1,display:"flex",alignItems:"center",justifyContent:"center"}},e.createElement(ge,{cells:W})),e.createElement(ye,{theme:l})),e.createElement("div",{style:{display:"flex",flexDirection:"column",gap:"16px"}},e.createElement("div",{style:{background:l.cardBackground,borderRadius:"12px",padding:"20px",display:"flex",flexDirection:"column"}},e.createElement("div",{style:{fontSize:"12px",fontWeight:600,color:l.textMuted,textTransform:"uppercase",letterSpacing:"0.08em",marginBottom:"12px"}},"Active Hours"),e.createElement("div",{style:{flex:1,display:"flex",flexDirection:"column",justifyContent:"center",gap:"10px"}},e.createElement(ue,{activeHours:d,theme:l}))),e.createElement("div",{style:{background:l.cardBackgroundSecondary,borderRadius:"12px",padding:"16px 16px",position:"relative"}},e.createElement("div",{style:{position:"absolute",left:"12px",fontSize:"64px",fontWeight:700,color:n==="light"?"rgba(99,102,241,0.15)":"rgba(99,102,241,0.2)",lineHeight:1,fontFamily:\'Georgia, "Times New Roman", serif\',userSelect:"none",pointerEvents:"none"}},"\u201C"),e.createElement("div",{style:{paddingLeft:"40px",position:"relative"}},A&&e.createElement("div",{style:{fontSize:"13px",color:l.textSecondary,lineHeight:1.6,marginBottom:w?"8px":0}},A),w&&e.createElement("div",{style:{fontSize:"12px",color:l.textMuted,lineHeight:1.5,fontStyle:"italic"}},w))))),e.createElement("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginTop:"auto",paddingTop:"24px",borderTop:`1px solid ${l.borderColor}`,flexShrink:0}},e.createElement("div",{style:{fontSize:"12px",color:l.textMuted}},"Generated by Qwen Code \xB7 ",new Date().toISOString().split("T")[0]),e.createElement("div",{style:{fontSize:"12px",color:l.textMuted}},"github.com/QwenLM/qwen-code")))}function M({value:t,label:n,small:l,theme:s}){return e.createElement("div",{style:{textAlign:"center"}},e.createElement("div",{style:{fontSize:l?"18px":"28px",fontWeight:700,color:s.textPrimary,lineHeight:1.2}},t),e.createElement("div",{style:{fontSize:"11px",color:s.textMuted,textTransform:"uppercase",letterSpacing:"0.05em",marginTop:"4px"}},n))}function ue({activeHours:t,theme:n}){const s=[{label:"Morning",time:"06\u201312",hours:[6,7,8,9,10,11],color:"#fbbf24"},{label:"Afternoon",time:"12\u201318",hours:[12,13,14,15,16,17],color:"#0ea5e9"},{label:"Evening",time:"18\u201322",hours:[18,19,20,21],color:"#6366f1"},{label:"Night",time:"22\u201306",hours:[22,23,0,1,2,3,4,5],color:"#475569"}].map(a=>({...a,total:a.hours.reduce((o,i)=>o+(t[i]||0),0)})),r=Math.max(...s.map(a=>a.total),1);return e.createElement(e.Fragment,null,s.map(a=>{const o=r>0?a.total/r*100:0;return e.createElement("div",{key:a.label},e.createElement("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",fontSize:"12px",marginBottom:"4px"}},e.createElement("div",{style:{display:"flex",alignItems:"center",gap:"6px"}},e.createElement("span",{style:{width:"8px",height:"8px",borderRadius:"50%",backgroundColor:a.color,display:"inline-block",flexShrink:0}}),e.createElement("span",{style:{color:n.textSecondary,fontWeight:500}},a.label),e.createElement("span",{style:{color:n.textMuted,fontSize:"11px"}},a.time)),e.createElement("span",{style:{color:n.textMuted,fontWeight:600}},a.total)),e.createElement("div",{style:{height:"6px",background:n.borderColor,borderRadius:"3px",overflow:"hidden"}},e.createElement("div",{style:{width:`${o}%`,height:"100%",backgroundColor:a.color,borderRadius:"3px"}})))}))}function fe(t,n){const l=new Date,r=26*7,a=new Date(l);a.setDate(a.getDate()-r+1),a.setDate(a.getDate()-a.getDay());const o=[],i=new Date(l);i.setDate(i.getDate()+(6-i.getDay()));const m=new Date(a);for(;m<=i;){const c=m.toISOString().split("T")[0],d=t[c]||0;o.push({color:he(d,n)}),m.setDate(m.getDate()+1)}return o}function he(t,n){return t===0?n.heatmapEmpty:t<2?n.heatmapColors[0]:t<4?n.heatmapColors[1]:t<10?n.heatmapColors[2]:n.heatmapColors[3]}function ge({cells:t}){const l=Math.ceil(t.length/7),s=14,r=3,a=l*(s+r),o=7*(s+r);return e.createElement("svg",{width:a,height:o,viewBox:`0 0 ${a} ${o}`},t.map((i,m)=>{const c=Math.floor(m/7),d=m%7;return e.createElement("rect",{key:m,x:c*(s+r),y:d*(s+r),width:s,height:s,rx:2,fill:i.color})}))}function ye({theme:t}){return e.createElement("div",{style:{display:"flex",alignItems:"center",gap:"8px",marginTop:"12px"}},e.createElement("span",{style:{fontSize:"11px",color:t.textMuted}},"Less"),[t.heatmapEmpty,t.heatmapColors[0],t.heatmapColors[1],t.heatmapColors[2],t.heatmapColors[3]].map((n,l)=>e.createElement("span",{key:l,style:{width:"10px",height:"10px",borderRadius:"2px",backgroundColor:n,display:"inline-block"}})),e.createElement("span",{style:{fontSize:"11px",color:t.textMuted}},"More"))}function b(t){return typeof t=="string"?t.trim().length>0:typeof t=="number"?Number.isFinite(t)&&t!==0:typeof t=="boolean"?t:Array.isArray(t)?t.some(n=>b(n)):t&&typeof t=="object"?Object.values(t).some(n=>b(n)):!1}function z(t){return Array.isArray(t)?t.some(([,n])=>Number.isFinite(n)&&n!==0):!!t&&Object.values(t).some(n=>Number.isFinite(n)&&n!==0)}function H(t){return Array.isArray(t)&&t.some(n=>b(n))}function xe({data:t}){var u,f,C,_,v,N,j,k,S,L,G,Y;const[n,l]=e.useState("dark"),s=e.useRef(!1),r=async()=>{const q=document.getElementById("share-card");if(!q||!window.html2canvas){alert("Export functionality is not available.");return}try{const y=q.cloneNode(!0);y.style.position="fixed",y.style.left="-9999px",y.style.top="0",y.style.pointerEvents="none",document.body.appendChild(y);const Q=await window.html2canvas(y,{scale:2,useCORS:!0,logging:!1,width:1200,height:y.scrollHeight});document.body.removeChild(y);const P=Q.toDataURL("image/png"),I=document.createElement("a");I.href=P,I.download=`qwen-insights-card-${new Date().toISOString().slice(0,10)}.png`,I.click()}catch(y){console.error("Export card error:",y),alert("Failed to export card. Please try again.")}};e.useEffect(()=>{s.current&&(s.current=!1,r())},[n]);const a=q=>{q===n?r():(s.current=!0,l(q))};if(!t)return e.createElement("div",{className:"text-center text-slate-600"},"No insight data available");const o=Object.keys(t.heatmap||{});let i="";if(o.length>0){const y=o.map(O=>new Date(O)).map(O=>O.getTime()),Q=new Date(Math.min(...y)),P=new Date(Math.max(...y)),I=O=>O.toISOString().split("T")[0];i=`${I(Q)} to ${I(P)}`}const m=b((u=t.qualitative)==null?void 0:u.atAGlance),c=!!t.qualitative&&(b(t.qualitative.projectAreas)||z(t.topGoals)||z(t.topTools)),d=b((f=t.qualitative)==null?void 0:f.interactionStyle),g=!!t.qualitative&&(b(t.qualitative.impressiveWorkflows)||z(t.primarySuccess)||z(t.outcomes)),E=!!t.qualitative&&(b(t.qualitative.frictionPoints)||z(t.satisfaction)||z(t.friction)),x=!!t.qualitative&&(H((C=t.qualitative.improvements)==null?void 0:C.Qwen_md_additions)||H((_=t.qualitative.improvements)==null?void 0:_.features_to_try)),A=!!t.qualitative&&H((v=t.qualitative.improvements)==null?void 0:v.usage_patterns),w=b((N=t.qualitative)==null?void 0:N.futureOpportunities),W=b((j=t.qualitative)==null?void 0:j.memorableMoment),h=[];c&&h.push({href:"#section-work",label:"What You Work On"}),d&&h.push({href:"#section-usage",label:"How You Use Qwen Code"}),g&&h.push({href:"#section-wins",label:"Impressive Things"}),E&&h.push({href:"#section-friction",label:"Where Things Go Wrong"}),x&&h.push({href:"#section-features",label:"Features to Try"}),A&&h.push({href:"#section-patterns",label:"New Usage Patterns"}),w&&h.push({href:"#section-horizon",label:"On the Horizon"});const T={wins:g,friction:E,features:x,horizon:w};return e.createElement("div",null,e.createElement("header",{className:"insights-header"},e.createElement("div",{className:"header-content"},e.createElement("div",{className:"header-title-section"},e.createElement("h1",{className:"header-title"},"Qwen Code Insights"),e.createElement("p",{className:"header-subtitle"},t.totalMessages?`${t.totalMessages.toLocaleString()} messages across ${(k=t.totalSessions)==null?void 0:k.toLocaleString()} sessions`:"Your personalized coding journey and patterns",i&&` \xB7 ${i}`)),e.createElement(Ee,{onExport:a}))),m&&t.qualitative&&e.createElement(ee,{qualitative:t.qualitative,targetSections:T}),h.length>0&&e.createElement(te,{sections:h}),e.createElement(U,{data:t}),c&&t.qualitative&&e.createElement(ne,{qualitative:t.qualitative,topGoals:t.topGoals,topTools:t.topTools}),d&&t.qualitative&&e.createElement(le,{qualitative:t.qualitative,insights:t}),g&&e.createElement(re,{qualitative:t.qualitative,primarySuccess:(S=t.primarySuccess)!=null?S:{},outcomes:(L=t.outcomes)!=null?L:{}}),E&&e.createElement(ae,{qualitative:t.qualitative,satisfaction:(G=t.satisfaction)!=null?G:{},friction:(Y=t.friction)!=null?Y:{}}),(x||A)&&t.qualitative&&e.createElement(ie,{qualitative:t.qualitative}),w&&t.qualitative&&e.createElement(me,{qualitative:t.qualitative}),W&&t.qualitative&&e.createElement(ce,{qualitative:t.qualitative}),e.createElement(pe,{data:t,theme:n}))}function Ee({onExport:t}){const[n,l]=e.useState(!1),s=e.useRef(null);e.useEffect(()=>{if(!n)return;const a=o=>{s.current&&!s.current.contains(o.target)&&l(!1)};return document.addEventListener("mousedown",a),()=>document.removeEventListener("mousedown",a)},[n]);const r=a=>{l(!1),t(a)};return e.createElement("div",{className:"export-dropdown-wrapper",ref:s},e.createElement("button",{className:"export-card-btn",onClick:()=>l(!n)},e.createElement("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"},e.createElement("path",{d:"M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8"}),e.createElement("polyline",{points:"16 6 12 2 8 6"}),e.createElement("line",{x1:"12",y1:"2",x2:"12",y2:"15"})),e.createElement("span",null,"Export Card"),e.createElement("svg",{width:"12",height:"12",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:`export-chevron ${n?"open":""}`},e.createElement("polyline",{points:"6 9 12 15 18 9"}))),n&&e.createElement("div",{className:"export-dropdown"},e.createElement("button",{className:"export-dropdown-item",onClick:()=>r("light")},e.createElement("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"},e.createElement("circle",{cx:"12",cy:"12",r:"5"}),e.createElement("line",{x1:"12",y1:"1",x2:"12",y2:"3"}),e.createElement("line",{x1:"12",y1:"21",x2:"12",y2:"23"}),e.createElement("line",{x1:"4.22",y1:"4.22",x2:"5.64",y2:"5.64"}),e.createElement("line",{x1:"18.36",y1:"18.36",x2:"19.78",y2:"19.78"}),e.createElement("line",{x1:"1",y1:"12",x2:"3",y2:"12"}),e.createElement("line",{x1:"21",y1:"12",x2:"23",y2:"12"}),e.createElement("line",{x1:"4.22",y1:"19.78",x2:"5.64",y2:"18.36"}),e.createElement("line",{x1:"18.36",y1:"5.64",x2:"19.78",y2:"4.22"})),e.createElement("span",null,"Light Theme")),e.createElement("button",{className:"export-dropdown-item",onClick:()=>r("dark")},e.createElement("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"},e.createElement("path",{d:"M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"})),e.createElement("span",null,"Dark Theme"))))}const $=document.getElementById("react-root");$&&window.INSIGHT_DATA&&B?B.createRoot($).render(e.createElement(xe,{data:window.INSIGHT_DATA})):console.error("Failed to mount React app:",{container:!!$,data:!!window.INSIGHT_DATA,ReactDOM:!!B})})(React,ReactDOM);';
var INSIGHT_CSS = '*,:before,:after,::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: #3b82f680;--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border:0 solid #e5e7eb}:before,:after{--tw-content: ""}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";line-height:1.5}body{line-height:inherit;margin:0;background-image:linear-gradient(to bottom right,var(--tw-gradient-stops));--tw-gradient-from: #f8fafc var(--tw-gradient-from-position);--tw-gradient-to: #f1f5f9 var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), #fff var(--tw-gradient-via-position), var(--tw-gradient-to);--tw-text-opacity: 1;min-height:100vh;color:rgb(15 23 42 / var(--tw-text-opacity, 1));-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glass-card{--tw-border-opacity: 1;border-width:1px;border-color:rgb(226 232 240 / var(--tw-border-opacity, 1));--tw-shadow: 0 10px 40px #0f172a14;--tw-shadow-colored: 0 10px 40px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow);--tw-backdrop-blur: blur(8px);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);background-color:#fff9;border-radius:1rem}.col-span-2{grid-column:span 2 / span 2}.mx-auto{margin-left:auto;margin-right:auto}.mb-8{margin-bottom:2rem}.ml-2{margin-left:.5rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.block{display:block}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.h-56{height:14rem}.h-full{height:100%}.min-h-screen{min-height:100vh}.w-full{width:100%}.min-w-\\[720px\\]{min-width:720px}.max-w-6xl{max-width:72rem}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.flex-col{flex-direction:column}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}.divide-slate-200>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:rgb(226 232 240 / var(--tw-divide-opacity, 1))}.overflow-x-auto{overflow-x:auto}.rounded-full{border-radius:9999px}.rounded-xl{border-radius:1.25rem}.border{border-width:1px}.border-slate-100{--tw-border-opacity: 1;border-color:rgb(241 245 249 / var(--tw-border-opacity, 1))}.bg-emerald-50{--tw-bg-opacity: 1;background-color:rgb(236 253 245 / var(--tw-bg-opacity, 1))}.bg-slate-100{--tw-bg-opacity: 1;background-color:rgb(241 245 249 / var(--tw-bg-opacity, 1))}.bg-slate-50{--tw-bg-opacity: 1;background-color:rgb(248 250 252 / var(--tw-bg-opacity, 1))}.bg-slate-900{--tw-bg-opacity: 1;background-color:rgb(15 23 42 / var(--tw-bg-opacity, 1))}.bg-white\\/70{background-color:#ffffff73}.bg-gradient-to-br{background-image:linear-gradient(to bottom right,var(--tw-gradient-stops))}.from-slate-50{--tw-gradient-from: #f8fafc var(--tw-gradient-from-position);--tw-gradient-to: #f8fafc00 var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.via-white{--tw-gradient-to: #ffffff00 var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), #ffffff var(--tw-gradient-via-position), var(--tw-gradient-to)}.to-slate-100{--tw-gradient-to: #f1f5f9 var(--tw-gradient-to-position)}.p-4{padding:1rem}.p-6{padding:1.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.px-8{padding-left:2rem;padding-right:2rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-10{padding-top:2.5rem;padding-bottom:2.5rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.text-left{text-align:left}.text-center{text-align:center}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.tracking-\\[0\\.2em\\]{letter-spacing:.2em}.tracking-tight{letter-spacing:-.025em}.tracking-wide{letter-spacing:.025em}.text-emerald-700{--tw-text-opacity: 1;color:rgb(4 120 87 / var(--tw-text-opacity, 1))}.text-rose-700{--tw-text-opacity: 1;color:rgb(190 18 60 / var(--tw-text-opacity, 1))}.text-slate-200{--tw-text-opacity: 1;color:rgb(226 232 240 / var(--tw-text-opacity, 1))}.text-slate-400{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity, 1))}.text-slate-500{--tw-text-opacity: 1;color:rgb(100 116 139 / var(--tw-text-opacity, 1))}.text-slate-600{--tw-text-opacity: 1;color:rgb(71 85 105 / var(--tw-text-opacity, 1))}.text-slate-700{--tw-text-opacity: 1;color:rgb(51 65 85 / var(--tw-text-opacity, 1))}.text-slate-900{--tw-text-opacity: 1;color:rgb(15 23 42 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.shadow-inner{--tw-shadow: inset 0 2px 4px 0 #0000000d;--tw-shadow-colored: inset 0 2px 4px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-soft{--tw-shadow: 0 10px 40px #0f172a14;--tw-shadow-colored: 0 10px 40px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-slate-100{--tw-shadow-color: #f1f5f9;--tw-shadow: var(--tw-shadow-colored)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.hover\\:-translate-y-\\[1px\\]:hover{--tw-translate-y: -1px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\\:shadow-lg:hover{--tw-shadow: 0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.focus-visible\\:outline:focus-visible{outline-style:solid}.focus-visible\\:outline-2:focus-visible{outline-width:2px}.focus-visible\\:outline-offset-2:focus-visible{outline-offset:2px}.focus-visible\\:outline-slate-400:focus-visible{outline-color:#94a3b8}.active\\:translate-y-\\[1px\\]:active{--tw-translate-y: 1px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.group:hover .group-hover\\:translate-x-0\\.5{--tw-translate-x: .125rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@media (min-width: 768px){.md\\:mt-6{margin-top:1.5rem}.md\\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\\:gap-6{gap:1.5rem}.md\\:py-12{padding-top:3rem;padding-bottom:3rem}.md\\:text-4xl{font-size:2.25rem;line-height:2.5rem}}.heatmap-container{width:100%;overflow-x:auto}.heatmap-svg{min-width:720px}.heatmap-day{cursor:pointer}.heatmap-day:hover{stroke:#00000024;stroke-width:1px}.heatmap-legend{display:flex;align-items:center;gap:4px;font-size:12px;color:#64748b;margin-top:8px}.heatmap-legend-item{width:10px;height:10px;border-radius:2px}.nav-toc{display:flex;flex-wrap:wrap;gap:8px;margin:24px 0 32px;padding:16px;background:#fff;border-radius:8px;border:1px solid #e2e8f0}.nav-toc a{font-size:12px;color:#64748b;text-decoration:none;padding:6px 12px;border-radius:6px;background:#f1f5f9;transition:all .15s}.nav-toc a:hover{background:#e2e8f0;color:#334155}.at-a-glance{background:linear-gradient(135deg,#fef3c7,#fde68a);border:1px solid #f59e0b;border-radius:12px;padding:20px 24px;margin-bottom:32px}.glance-title{font-size:16px;font-weight:700;color:#92400e;margin-bottom:16px}.glance-sections{display:flex;flex-direction:column;gap:12px}.glance-section{font-size:14px;color:#78350f;line-height:1.6}.glance-section strong{color:#92400e;font-weight:700}.see-more{color:#b45309;text-decoration:none;font-size:13px;white-space:nowrap;margin-left:4px}.see-more:hover{text-decoration:underline}.project-areas{display:flex;flex-direction:column;gap:12px;margin-bottom:32px}.project-area{background:#fff;border:1px solid #e2e8f0;border-radius:8px;padding:16px}.area-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:8px}.area-name{font-weight:600;font-size:15px;color:#0f172a}.area-count{font-size:12px;color:#64748b;background:#f1f5f9;padding:2px 8px;border-radius:4px}.area-desc{font-size:14px;color:#475569;line-height:1.5}.narrative{background:#fff;border:1px solid #e2e8f0;border-radius:8px;padding:20px;margin-bottom:24px}.narrative p{margin-top:0;margin-bottom:12px;font-size:14px;color:#475569;line-height:1.7}.key-insight{background:#f0fdf4;border:1px solid #bbf7d0;border-radius:8px;padding:12px 16px;margin-top:12px;font-size:14px;color:#166534}.section-intro{font-size:14px;color:#64748b;margin-bottom:16px}.big-wins{display:flex;flex-direction:column;gap:12px;margin-bottom:24px}.big-win{background:#f0fdf4;border:1px solid #bbf7d0;border-radius:8px;padding:16px}.big-win-title{font-weight:600;font-size:15px;color:#166534;margin-bottom:8px}.big-win-desc{font-size:14px;color:#15803d;line-height:1.5}.friction-categories{display:flex;flex-direction:column;gap:16px;margin-bottom:24px}.friction-category{background:#fef2f2;border:1px solid #fca5a5;border-radius:8px;padding:16px}.friction-title{font-weight:600;font-size:15px;color:#991b1b;margin-bottom:6px}.friction-desc{font-size:13px;color:#7f1d1d;margin-bottom:10px}.friction-examples{margin:0 0 0 10px;padding:0;font-size:13px;color:#334155;list-style-type:disc}.friction-examples li{margin-bottom:4px}.qwen-md-section{background:#eff6ff;border:1px solid #bfdbfe;border-radius:8px;padding:12px;margin-bottom:20px}.qwen-md-section h3{font-size:13px;font-weight:600;color:#1e40af;margin:0 0 8px}.qwen-md-actions{margin-bottom:8px;padding-bottom:8px;border-bottom:1px solid #dbeafe}.copy-all-btn{background:#2563eb;color:#fff;border:none;border-radius:4px;padding:4px 10px;font-size:11px;cursor:pointer;font-weight:500;transition:all .2s}.copy-all-btn:hover{background:#1d4ed8}.copy-all-btn.copied{background:#16a34a}.qwen-md-item{display:flex;flex-wrap:wrap;align-items:flex-start;gap:8px;padding:8px 0;border-bottom:1px solid #dbeafe}.qwen-md-item:last-child{border-bottom:none}.cmd-checkbox{margin-top:2px}.cmd-code{background:#fff;padding:6px 10px;border-radius:4px;font-size:11px;color:#1e40af;border:1px solid #bfdbfe;font-family:monospace;display:block;white-space:pre-wrap;word-break:break-word;flex:1}.cmd-why{font-size:11px;color:#64748b;width:100%;padding-left:20px;margin-top:4px}.features-section,.patterns-section{display:flex;flex-direction:column;gap:12px;margin:16px 0}.feature-card{background:#f0fdf4;border:1px solid #86efac;border-radius:8px;padding:16px}.pattern-card{background:#f0f9ff;border:1px solid #7dd3fc;border-radius:8px;padding:16px}.feature-title,.pattern-title{font-weight:600;font-size:15px;color:#0f172a;margin-bottom:6px}.feature-oneliner,.pattern-summary{font-size:14px;color:#475569;margin-bottom:8px}.feature-why,.pattern-detail{font-size:13px;color:#334155;line-height:1.5}.feature-examples{margin-top:12px}.feature-example{padding:8px 0;border-top:1px solid #d1fae5}.feature-example:first-child{border-top:none}.example-code-row,.copyable-prompt-row{display:flex;align-items:flex-start;gap:8px}.example-code{flex:1;background:#f1f5f9;padding:8px 12px;border-radius:4px;font-family:monospace;font-size:12px;color:#334155;overflow-x:auto;white-space:pre-wrap}.copyable-prompt-section{margin-top:12px;padding-top:12px;border-top:1px solid #e2e8f0}.copyable-prompt{flex:1;background:#f8fafc;padding:10px 12px;border-radius:4px;font-family:monospace;font-size:12px;color:#334155;border:1px solid #e2e8f0;white-space:pre-wrap;line-height:1.5}.prompt-label{font-size:11px;font-weight:600;text-transform:uppercase;color:#64748b;margin-bottom:6px}.copy-btn{background:#e2e8f0;border:none;border-radius:4px;padding:4px 8px;font-size:11px;cursor:pointer;color:#475569;flex-shrink:0;transition:all .2s}.copy-btn:hover{background:#cbd5e1}.horizon-section{display:flex;flex-direction:column;gap:16px}.horizon-card{background:linear-gradient(135deg,#faf5ff,#f5f3ff);border:1px solid #c4b5fd;border-radius:8px;padding:16px}.horizon-title{font-weight:600;font-size:15px;color:#5b21b6;margin-bottom:8px}.horizon-possible{font-size:14px;color:#334155;margin-bottom:10px;line-height:1.5}.horizon-tip{font-size:13px;color:#6b21a8;background:#fff9;padding:8px 12px;border-radius:4px}.pattern-prompt{background:#f8fafc;padding:12px;border-radius:6px;margin-top:12px;border:1px solid #e2e8f0;display:flex;flex-direction:column;gap:8px}.pattern-prompt code{font-family:monospace;font-size:12px;color:#334155;display:block;white-space:pre-wrap}.fun-ending{background:linear-gradient(135deg,#fef3c7,#fde68a);border:1px solid #fbbf24;border-radius:12px;padding:24px;margin-top:40px;text-align:center}.fun-headline{font-size:18px;font-weight:600;color:#78350f;margin-bottom:8px}.fun-detail{font-size:14px;color:#92400e}.stats-row{display:flex;gap:24px;margin-bottom:40px;padding:20px 0;border-top:1px solid #e2e8f0;border-bottom:1px solid #e2e8f0;flex-wrap:wrap}.stat{text-align:center}.stat-value{font-size:24px;font-weight:700;color:#0f172a}.stat-label{font-size:11px;color:#64748b;text-transform:uppercase}@media (max-width: 640px){.stats-row{justify-content:center}}.header-with-action{position:relative}.insights-header{margin-bottom:2rem;padding:1.5rem 0;border-bottom:1px solid #e2e8f0}.header-content{display:flex;justify-content:space-between;align-items:center;gap:1.5rem;flex-wrap:wrap}.header-title-section{flex:1;min-width:0}.header-title{font-size:1.75rem;font-weight:700;color:#0f172a;letter-spacing:-.02em;margin:0 0 .375rem;line-height:1.2}.header-subtitle{font-size:.875rem;color:#64748b;margin:0;font-weight:400}.export-dropdown-wrapper{position:relative}.export-card-btn{display:inline-flex;align-items:center;gap:.5rem;height:36px;padding:0 .875rem;border:1px solid #e2e8f0;border-radius:8px;background:#fff;color:#334155;font-size:.8125rem;font-weight:500;cursor:pointer;transition:all .15s ease}.export-card-btn:hover{background:#f8fafc;border-color:#cbd5e1}.export-card-btn:active{background:#f1f5f9}.export-chevron{transition:transform .15s ease;opacity:.5}.export-chevron.open{transform:rotate(180deg)}.export-dropdown{position:absolute;top:calc(100% + 4px);right:0;min-width:160px;background:#fff;border:1px solid #e2e8f0;border-radius:8px;box-shadow:0 4px 16px #00000014;padding:4px;z-index:50}.export-dropdown-item{display:flex;align-items:center;gap:.5rem;width:100%;padding:.5rem .75rem;border:none;border-radius:6px;background:none;color:#334155;font-size:.8125rem;font-weight:400;cursor:pointer;transition:background .1s ease}.export-dropdown-item:hover{background:#f1f5f9}.export-dropdown-item:active{background:#e2e8f0}@media (max-width: 640px){.header-content{flex-direction:column;align-items:flex-start;gap:1rem}.header-title{font-size:1.5rem}}';

// packages/web-templates/src/generated/exportHtmlTemplate.ts
init_esbuild_shims();
var HTML_TEMPLATE = '<!doctype html>\n<html lang="en" class="dark">\n  <head>\n    <meta charset="UTF-8" />\n    <meta name="viewport" content="width=device-width, initial-scale=1.0" />\n    <link\n      rel="icon"\n      type="image/svg+xml"\n      href="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20141.38%20140%22%3E%0A%20%20%3Cpath%0A%20%20%20%20fill%3D%22%23000000%22%0A%20%20%20%20d%3D%22m140.93%2085-16.35-28.33-1.93-3.34%208.66-15a3.323%203.323%200%200%200%200-3.34l-9.62-16.67c-.3-.51-.72-.93-1.22-1.22s-1.07-.45-1.67-.45H82.23l-8.66-15a3.33%203.33%200%200%200-2.89-1.67H51.43c-.59%200-1.17.16-1.66.45-.5.29-.92.71-1.22%201.22L32.19%2029.98l-1.92%203.33H12.96c-.59%200-1.17.16-1.66.45-.5.29-.93.71-1.22%201.22L.45%2051.66a3.323%203.323%200%200%200%200%203.34l18.28%2031.67-8.66%2015a3.32%203.32%200%200%200%200%203.34l9.62%2016.67c.3.51.72.93%201.22%201.22s1.07.45%201.67.45h36.56l8.66%2015a3.35%203.35%200%200%200%202.89%201.67h19.25a3.34%203.34%200%200%200%202.89-1.67l18.28-31.67h17.32c.6%200%201.17-.16%201.67-.45s.92-.71%201.22-1.22l9.62-16.67a3.323%203.323%200%200%200%200-3.34ZM51.44%203.33%2061.07%2020l-9.63%2016.66h76.98l-9.62%2016.66H45.67l-11.54-20zM57.21%20120H22.58l9.63-16.67h19.25l-38.5-66.67h19.25l9.62%2016.67L68.78%20100l-11.55%2020Zm61.59-33.34-9.62-16.67-38.49%2066.67-9.63-16.67%209.63-16.66%2026.94-46.67h23.1l17.32%2030z%22%0A%20%20%2F%3E%0A%3C%2Fsvg%3E"\n    />\n    <script\n      crossorigin\n      src="https://unpkg.com/react@18.2.0/umd/react.production.min.js"\n    ></script>\n    <script\n      crossorigin\n      src="https://unpkg.com/react-dom@18.2.0/umd/react-dom.production.min.js"\n    ></script>\n    <script>\n      const withKey = (props, key) =>\n        key == null ? props : Object.assign({}, props, { key });\n      const jsx = (type, props, key) =>\n        React.createElement(type, withKey(props, key));\n      const jsxRuntime = {\n        Fragment: React.Fragment,\n        jsx,\n        jsxs: jsx,\n        jsxDEV: jsx,\n      };\n      window.ReactJSXRuntime = jsxRuntime;\n      window[\'react/jsx-runtime\'] = jsxRuntime;\n      window[\'react/jsx-dev-runtime\'] = jsxRuntime;\n    </script>\n    <script src="https://unpkg.com/@qwen-code/webui@latest/dist/index.umd.js"></script>\n    <link\n      rel="stylesheet"\n      href="https://unpkg.com/@qwen-code/webui@latest/dist/styles.css"\n    />\n    <title>Qwen Code Chat Export</title>\n    <script>\n      // Pre-hydrate FOUC guard: must run before <style> below applies layout.\n      // The storage key \'qwen-export-theme\' is duplicated here verbatim and\n      // MUST stay in sync with EXPORT_THEME_STORAGE_KEY in\n      // src/components/useExportTheme.ts.\n      (function () {\n        try {\n          var stored = window.localStorage.getItem(\'qwen-export-theme\');\n          var theme = stored === \'light\' || stored === \'dark\' ? stored : \'dark\';\n          var root = document.documentElement;\n          // Toggle-style writes mirror the React hook\'s effect, so the two\n          // code paths converge on identical class state.\n          root.classList.toggle(\'light\', theme === \'light\');\n          root.classList.toggle(\'dark\', theme === \'dark\');\n        } catch (e) {\n          // localStorage may be unavailable (private mode, file:// sandbox);\n          // the static class="dark" attribute on <html> remains the default.\n        }\n      })();\n    </script>\n    <style>\n      @font-face {\n        font-family: "Press Start 2P";\n        font-style: normal;\n        font-weight: 400;\n        font-display: swap;\n        src: url("data:font/woff2;base64,d09GMgABAAAAAALQAAwAAAAABfwAAAKBAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHCgGYABUEQgKgkSCDAsOAAE2AiQDDgQgBYRKByAb4QTIBB76Oev9JKW02x5ClpELSxHm1M0JQ+OBJAtDpAAVUQ7i///V+A/YgLVswlGo/7a+lmW3sfnUvoBFcUKzUFEnKo08S0F2T8TiAAJQieDvSGUVdW3smBv2LuCGjSpG3jQTD/m9OI5lTDomdQG1hkoMkCJu1ZYsmL42dEu7W8q5gUan/J6yyO+FX5NO5qQPxaqGnEINZ2q7kDf0+i4UigAXdiQUNMppoJnOzcxnDMwX5lXzinnJPDtkzhQFwjTx0DGrx1zkoNhIYr5LTKHjclcs+z3Frrh2ue3Kvk6bxzoRJLsIQpWcQhW27bgJwoUHYXNi2WWnVRUWaVNS0XMJ1eIUHlSX0l3l7BZOOos1ySk7NUWl6+eobG3Nfpj96g8EvukB3Qjouo4+O6svG9/0b8ZyKmfoZj9gzBqq8I2MS7Pf2JquL9vZwHJ51djyD01vbVHRDxSslvFBZwMHjQvexMxIvz3oyftul2+k9yBS+xGM+l+d+Pvo/zH5fVXMRvsHhG4u9/dRsgQyF67l9+jYgZuy+Ath2O6EUzU7E6BxF41nQk2cgkN8IIlOPKecMgWccSrE4XdaOECf00oUaeTm34EpvHhZIodEEllllBWmWcJLyQmsPjNHAousMEkijVRQR5OgNc4qq7TiZZg89pJCE/G0MM4kPuYqqIOKrQw3WmQBjVQSSLLm1H1NiGmCN21uwK/JpZRuWignd/klmbWXFEtZZIn1o8cmkaDqX5JIJgWNNqYYR9s0GsRFZhhntKJSjI+KTaFDZ+MoRllkjHWK2ADCxilLQGTkJZo4NAJMDwhAiK0CJD+jjKFRwWBapYFh5rdzfogQC/m1XLplXiEFEwAA") format("woff2");\n      }\n      :root{--bg-primary: #18181b;--bg-secondary: #27272a;--text-primary: #f4f4f5;--text-secondary: #a1a1aa;--border-color: #3f3f46;--accent-color: #3b82f6;--header-bg: rgba(24, 24, 27, .95);--scrollbar-thumb-hover: #52525b}:root.light{--bg-primary: #ffffff;--bg-secondary: #f3f4f6;--text-primary: #1f2937;--text-secondary: #6b7280;--border-color: #e5e7eb;--accent-color: #2563eb;--header-bg: rgba(249, 250, 251, .95);--scrollbar-thumb-hover: #d1d5db;--app-primary-foreground: #1f2937;--app-secondary-foreground: #6b7280;--app-background: #ffffff;--app-primary-background: #ffffff;--app-background-secondary: #f3f4f6;--app-background-tertiary: #e5e7eb;--app-foreground: #1f2937;--app-foreground-secondary: #6b7280;--app-foreground-muted: #9ca3af;--app-border: #e5e7eb;--app-primary-border-color: #e5e7eb;--app-input-background: #ffffff;--app-input-border: #d1d5db;--app-input-placeholder-foreground: #9ca3af;--app-ghost-button-hover-background: rgba(0, 0, 0, .05);--app-header-background: #f9fafb;--app-list-hover-background: rgba(0, 0, 0, .05);--app-list-active-background: #3b82f6;--app-menu-background: #ffffff;--app-menu-border: #e5e7eb;--app-menu-foreground: #1f2937;--app-tool-background: #ffffff;--app-code-background: #f3f4f6;--app-secondary-background: #f3f4f6;--app-input-secondary-background: #f3f4f6;--app-input-foreground: #1f2937;--app-button-background: #e5e7eb;--app-button-secondary-background: #f3f4f6;--app-button-foreground: #1f2937;--app-transparent-inner-border: rgba(0, 0, 0, .1);--app-warning-foreground: #b45309}body{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;margin:0;padding:0;background-color:var(--bg-primary);color:var(--text-primary);line-height:1.6;-webkit-font-smoothing:antialiased}.page-wrapper{min-height:100vh;display:flex;flex-direction:column;align-items:center}.header{width:100%;padding:16px 24px;border-bottom:1px solid var(--border-color);background-color:var(--header-bg);backdrop-filter:blur(8px);position:sticky;top:0;z-index:100;display:flex;justify-content:space-between;align-items:center;box-sizing:border-box}.header-left{display:flex;align-items:center;gap:12px}.header-right{display:flex;align-items:center;gap:8px}.theme-toggle{display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;padding:0;background:transparent;border:1px solid var(--border-color);border-radius:999px;color:var(--text-secondary);cursor:pointer;transition:background-color .15s ease,color .15s ease,border-color .15s ease}.theme-toggle:hover{background-color:var(--bg-secondary);color:var(--text-primary)}.theme-toggle:focus-visible{outline:2px solid var(--accent-color);outline-offset:2px}.theme-toggle:active{transform:scale(.95)}.logo-icon{width:24px;height:24px;flex-shrink:0;display:flex;align-items:center;justify-content:center}.logo-icon svg{width:100%;height:100%}.logo{display:flex;flex-direction:column;line-height:1}.logo-text{font-family:"Press Start 2P",cursive;font-weight:400;font-size:24px;letter-spacing:-.05em;position:relative;color:#fff}.logo-text-inner{background:linear-gradient(to right,#60a5fa,#a855f7);-webkit-background-clip:text;-webkit-text-fill-color:transparent;position:relative;z-index:2}.logo-text:before,.logo-text:after{content:attr(data-text);position:absolute;top:0;left:0;width:100%;height:100%;z-index:1;background:none;-webkit-text-fill-color:transparent;-webkit-text-stroke:1px rgba(96,165,250,.3)}.logo-text:before{transform:translate(2px,2px);-webkit-text-stroke:1px rgba(168,85,247,.3)}.logo-text:after{transform:translate(4px,4px);opacity:.4}.logo-sub{font-size:11px;font-weight:600;color:var(--text-secondary);letter-spacing:.05em;text-transform:uppercase;margin-top:4px}.badge{font-size:11px;padding:2px 8px;border-radius:999px;background-color:var(--bg-secondary);color:var(--text-secondary);border:1px solid var(--border-color);font-weight:500}.meta{display:flex;gap:24px;font-size:13px;color:var(--text-secondary)}.meta-item{display:flex;align-items:center;gap:8px}.meta-label{color:var(--text-secondary)}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-track{background:var(--bg-primary)}::-webkit-scrollbar-thumb{background:var(--bg-secondary);border-radius:5px;border:2px solid var(--bg-primary)}::-webkit-scrollbar-thumb:hover{background:var(--scrollbar-thumb-hover)}@media (max-width: 768px){.chat-container{max-width:100%;padding:20px 16px}.header{padding:12px 16px}.meta{width:100%;flex-direction:column;gap:6px}}@media (max-width: 480px){.chat-container{padding:16px 12px}}.content-wrapper{display:flex;width:100%;max-width:1600px;height:calc(100vh - 73px)}.chat-container{flex:1;min-width:0;overflow-y:auto;padding:24px;box-sizing:border-box}.metadata-sidebar{width:320px;min-width:320px;padding:12px;border-right:1px solid var(--border-color);background-color:var(--bg-secondary);display:flex;flex-direction:column;gap:12px;overflow-y:auto;height:100%;box-sizing:border-box}.metadata-section{display:flex;flex-direction:column;gap:8px}.metadata-section-title{font-size:10px;font-weight:600;color:var(--text-secondary);text-transform:uppercase;letter-spacing:.05em;margin:0;padding-bottom:4px;border-bottom:1px solid var(--border-color)}.metadata-section-small{margin-top:auto;padding-top:12px;border-top:1px solid var(--border-color)}.metadata-item{display:flex;flex-direction:column;gap:2px}.metadata-item-empty{font-size:12px;color:var(--text-secondary);margin:0;padding:4px 0}.metadata-content{display:flex;flex-direction:column;gap:2px;min-width:0}.metadata-content .metadata-label{font-size:10px;color:var(--text-secondary)}.metadata-content .metadata-value{font-size:12px;color:var(--text-primary);word-break:break-all;line-height:1.3;cursor:pointer}.metadata-content .metadata-value.multiline{white-space:pre-wrap}.metadata-content .metadata-value.text-green{color:#22c55e}.metadata-content .metadata-value.text-red{color:#ef4444}.metadata-value-with-copy{display:flex;align-items:center;gap:8px}.metadata-value-with-copy .metadata-value{flex:1;min-width:0}.copy-button{display:inline-flex;align-items:center;justify-content:center;padding:4px;background:transparent;border:1px solid var(--border-color, #3f3f46);border-radius:4px;color:var(--text-secondary, #a1a1aa);cursor:pointer;transition:all .15s ease;flex-shrink:0}.copy-button:hover{background:var(--bg-hover, #27272a);color:var(--text-primary, #f4f4f5);border-color:var(--border-hover, #52525b)}.copy-button:active{transform:scale(.95)}@media (max-width: 1024px){.metadata-sidebar{width:320px;min-width:320px;padding:10px}}@media (max-width: 768px){.content-wrapper{flex-direction:column;height:auto}.chat-container{height:auto;min-height:50vh}.metadata-sidebar{width:100%;min-width:100%;height:auto;max-height:none;border-right:none;border-top:1px solid var(--border-color);padding:12px;gap:12px}.metadata-section{flex-direction:row;flex-wrap:wrap;gap:12px}.metadata-section-title{width:100%;border-bottom:none;padding-bottom:0}.metadata-item{flex:1;min-width:140px}.metadata-section-small{margin-top:0;padding-top:0;border-top:none}}.modal-overlay{position:fixed;inset:0;z-index:1000;background-color:#0009;display:flex;align-items:center;justify-content:center;padding:24px}.modal-container{background-color:var(--bg-secondary);border:1px solid var(--border-color);border-radius:12px;width:100%;max-width:800px;max-height:80vh;display:flex;flex-direction:column;box-shadow:0 25px 50px -12px #00000080}.modal-header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--border-color);flex-shrink:0}.modal-title{font-size:13px;color:var(--text-secondary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.modal-close{background:none;border:none;color:var(--text-secondary);cursor:pointer;font-size:16px;padding:4px 8px;border-radius:6px;line-height:1;transition:background-color .15s,color .15s}.modal-close:hover{background-color:var(--border-color);color:var(--text-primary)}.modal-content{margin:0;padding:16px;overflow:auto;font-size:13px;line-height:1.6;color:var(--text-primary);white-space:pre-wrap;word-break:break-word}\n    </style>\n  </head>\n  <body>\n    <div id="app"></div>\n\n    <script id="chat-data" type="application/json"></script>\n    <script>\n      (()=>{var f=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 141.38 140">\n  <path\n    fill="#000000"\n    d="m140.93 85-16.35-28.33-1.93-3.34 8.66-15a3.323 3.323 0 0 0 0-3.34l-9.62-16.67c-.3-.51-.72-.93-1.22-1.22s-1.07-.45-1.67-.45H82.23l-8.66-15a3.33 3.33 0 0 0-2.89-1.67H51.43c-.59 0-1.17.16-1.66.45-.5.29-.92.71-1.22 1.22L32.19 29.98l-1.92 3.33H12.96c-.59 0-1.17.16-1.66.45-.5.29-.93.71-1.22 1.22L.45 51.66a3.323 3.323 0 0 0 0 3.34l18.28 31.67-8.66 15a3.32 3.32 0 0 0 0 3.34l9.62 16.67c.3.51.72.93 1.22 1.22s1.07.45 1.67.45h36.56l8.66 15a3.35 3.35 0 0 0 2.89 1.67h19.25a3.34 3.34 0 0 0 2.89-1.67l18.28-31.67h17.32c.6 0 1.17-.16 1.67-.45s.92-.71 1.22-1.22l9.62-16.67a3.323 3.323 0 0 0 0-3.34ZM51.44 3.33 61.07 20l-9.63 16.66h76.98l-9.62 16.66H45.67l-11.54-20zM57.21 120H22.58l9.63-16.67h19.25l-38.5-66.67h19.25l9.62 16.67L68.78 100l-11.55 20Zm61.59-33.34-9.62-16.67-38.49 66.67-9.63-16.67 9.63-16.66 26.94-46.67h23.1l17.32 30z"\n  />\n</svg>\n`;var l=window.React,h=({state:e,onClose:t})=>(l.useEffect(()=>{if(e.visible){let o=document.body.style.overflow;return document.body.style.overflow="hidden",()=>{document.body.style.overflow=o}}},[e.visible]),e.visible?l.createElement("div",{className:"modal-overlay",onClick:t},l.createElement("div",{className:"modal-container",onClick:o=>o.stopPropagation()},l.createElement("div",{className:"modal-header"},l.createElement("span",{className:"modal-title font-mono"},e.fileName),l.createElement("button",{className:"modal-close",onClick:t,"aria-label":"Close"},"\\u2715")),l.createElement("pre",{className:"modal-content"},e.content))):null),x=()=>{let[e,t]=l.useState({visible:!1,content:"",fileName:""}),o=l.useCallback((n,p="temp")=>{t({visible:!0,content:n,fileName:p})},[]),i=l.useCallback(()=>{t(n=>({...n,visible:!1}))},[]);return{modalState:e,openModal:o,closeModal:i}};var z=window.React,b=()=>{let{modalState:e,openModal:t,closeModal:o}=x();return{platformContext:z.useMemo(()=>({platform:"web",postMessage:n=>{console.log("Posted message:",n)},onMessage:n=>(window.addEventListener("message",n),()=>window.removeEventListener("message",n)),openFile:n=>{console.log("Opening file:",n)},openTempFile:t,getResourceUrl:()=>{},features:{canOpenFile:!1,canOpenTempFile:!0,canCopy:!0}}),[t]),modalState:e,closeModal:o}};var a=({label:e,value:t,valueClass:o})=>t==null||t===""?null:React.createElement("div",{className:"metadata-item"},React.createElement("div",{className:"metadata-content"},React.createElement("span",{className:"metadata-label"},e),React.createElement("span",{className:`metadata-value ${o||""}`,title:typeof t=="string"?t:void 0},t)));var v=e=>!!e&&typeof e=="object",w=()=>{let e=document.getElementById("chat-data");if(!(e!=null&&e.textContent))return{};try{let t=JSON.parse(e.textContent);return t&&typeof t=="object"?t:{}}catch(t){return console.error("Failed to parse chat data.",t),{}}};var y=e=>{if(!e)return"-";try{return new Date(e).toLocaleString("en-US",{year:"numeric",month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}catch(t){return e}},k=e=>{if(!e)return"-";try{let o=new Date(e).getTime();if(Number.isNaN(o))return"-";let n=Math.max(0,new Date().getTime()-o),p=Math.floor(n/1e3),c=Math.floor(p/60),d=Math.floor(c/60),s=Math.floor(d/24),m=Math.floor(s/7),g=Math.floor(s/30),u=Math.floor(s/365);return p<60?"just now":c<60?`${c} minute${c===1?"":"s"} ago`:d<24?`${d} hour${d===1?"":"s"} ago`:s<7?`${s} day${s===1?"":"s"} ago`:m<4?`${m} week${m===1?"":"s"} ago`:g<12?`${g} month${g===1?"":"s"} ago`:`${u} year${u===1?"":"s"} ago`}catch(t){return"-"}};var M=e=>{if(e!=null)return e>=1e6?`${(e/1e6).toFixed(e%1e6===0?0:1)}m`:e>=1e3?`${(e/1e3).toFixed(e%1e3===0?0:1)}k`:e.toString()};var T=({metadata:e})=>React.createElement("aside",{className:"metadata-sidebar"},React.createElement("div",{className:"metadata-section"},React.createElement("h3",{className:"metadata-section-title"},"Session Info"),React.createElement(a,{label:"Session created",value:k(e.startTime)}),React.createElement(a,{label:"Project",value:e.cwd,valueClass:"multiline"}),e.gitRepo&&React.createElement(a,{label:"Repository",value:e.gitRepo}),e.gitBranch&&React.createElement(a,{label:"Branch",value:e.gitBranch}),e.model&&React.createElement(a,{label:"Model",value:e.model}),e.channel&&React.createElement(a,{label:"Channel",value:e.channel})),React.createElement("div",{className:"metadata-section"},React.createElement("h3",{className:"metadata-section-title"},"Statistics"),React.createElement(a,{label:"Prompts",value:e.promptCount}),e.contextUsagePercent!==void 0&&e.contextWindowSize!==void 0&&React.createElement(a,{label:"Context",value:`${e.contextUsagePercent>100?">100":e.contextUsagePercent}% of ${M(e.contextWindowSize)}`,valueClass:e.contextUsagePercent>100?"text-red":void 0}),e.totalTokens!==void 0&&React.createElement(a,{label:"Tokens",value:e.totalTokens.toLocaleString()})),React.createElement("div",{className:"metadata-section"},React.createElement("h3",{className:"metadata-section-title"},"File Operations"),e.filesWritten!==void 0&&e.filesWritten>0&&React.createElement(a,{label:"Files modified",value:e.filesWritten}),e.linesAdded!==void 0&&e.linesAdded>0&&React.createElement(a,{label:"Added",value:`+${e.linesAdded}`,valueClass:"text-green"}),e.linesRemoved!==void 0&&e.linesRemoved>0&&React.createElement(a,{label:"Removed",value:`-${e.linesRemoved}`,valueClass:"text-red"}),(e.filesWritten===void 0||e.filesWritten===0)&&(e.linesAdded===void 0||e.linesAdded===0)&&(e.linesRemoved===void 0||e.linesRemoved===0)&&React.createElement("p",{className:"metadata-item metadata-item-empty"},"No file changes")),React.createElement("div",{className:"metadata-section metadata-section-small"},React.createElement(a,{label:"Session ID",value:e.sessionId,valueClass:"font-mono"}),React.createElement(a,{label:"Export Time",value:y(e.exportTime)})));var $=()=>React.createElement("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true"},React.createElement("circle",{cx:"12",cy:"12",r:"4"}),React.createElement("path",{d:"M12 2v2"}),React.createElement("path",{d:"M12 20v2"}),React.createElement("path",{d:"m4.93 4.93 1.41 1.41"}),React.createElement("path",{d:"m17.66 17.66 1.41 1.41"}),React.createElement("path",{d:"M2 12h2"}),React.createElement("path",{d:"M20 12h2"}),React.createElement("path",{d:"m6.34 17.66-1.41 1.41"}),React.createElement("path",{d:"m19.07 4.93-1.41 1.41"})),D=()=>React.createElement("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true"},React.createElement("path",{d:"M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"})),C=({theme:e,onToggle:t})=>{let o=e==="light",i=o?"Switch to dark theme":"Switch to light theme";return React.createElement("button",{type:"button",className:"theme-toggle","aria-label":i,"aria-pressed":o,title:i,onClick:t},React.createElement(o?D:$,null))};var L=window.React,{useCallback:j,useEffect:I,useState:W}=L,N="qwen-export-theme",R=e=>e==="light"||e==="dark",F=()=>{try{let e=window.localStorage.getItem(N);if(R(e))return e}catch(e){}return"dark"},O=e=>{let t=document.documentElement;t.classList.toggle("light",e==="light"),t.classList.toggle("dark",e==="dark")},S=()=>{let[e,t]=W(F);I(()=>{O(e);try{window.localStorage.setItem(N,e)}catch(i){}},[e]);let o=j(()=>{t(i=>i==="light"?"dark":"light")},[]);return{theme:e,toggleTheme:o}};var A=window.ReactDOM,r=window.React,{ChatViewer:U,PlatformProvider:V}=QwenCodeWebUI,B=f?f.replace(/<svg([^>]*)>/,\'<svg$1><defs><linearGradient id="qwen-logo-gradient" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stop-color="#60a5fa" /><stop offset="100%" stop-color="#a855f7" /></linearGradient></defs>\').replace(/fill="[^"]*"/,\'fill="url(#qwen-logo-gradient)"\'):f,H=()=>{let e=w(),o=(Array.isArray(e.messages)?e.messages:[]).filter(v).filter(m=>m.type!=="system"),i=e.metadata,{platformContext:n,modalState:p,closeModal:c}=b(),{theme:d,toggleTheme:s}=S();return r.createElement("div",{className:"page-wrapper"},r.createElement("header",{className:"header"},r.createElement("div",{className:"header-left"},r.createElement("div",{className:"logo-icon","aria-hidden":"true",dangerouslySetInnerHTML:{__html:B}}),r.createElement("div",{className:"logo"},r.createElement("div",{className:"logo-text","data-text":"QWEN"},r.createElement("span",{className:"logo-text-inner"},"QWEN")))),r.createElement("div",{className:"header-right"},r.createElement(C,{theme:d,onToggle:s}))),r.createElement("div",{className:"content-wrapper"},r.createElement("div",{className:"chat-container"},r.createElement(V,{value:n},r.createElement(U,{messages:o,autoScroll:!1,theme:d}))),i&&r.createElement(T,{metadata:i})),r.createElement(h,{state:p,onClose:c}))},E=document.getElementById("app");E?A.createRoot(E).render(r.createElement(H,null)):console.error("App container not found.");})();;\n    </script>\n  </body>\n</html>\n';

// packages/cli/src/ui/utils/export/formatters/html.ts
function escapeJsonForHtml(json) {
  return json.replace(/<\/script/gi, "<\\/script").replace(/&/g, "\\u0026").replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
}
__name(escapeJsonForHtml, "escapeJsonForHtml");
function loadHtmlTemplate() {
  return HTML_TEMPLATE;
}
__name(loadHtmlTemplate, "loadHtmlTemplate");
function injectDataIntoHtmlTemplate(template, data) {
  const jsonData = JSON.stringify(data, null, 2);
  const escapedJsonData = escapeJsonForHtml(jsonData);
  const idAttribute = 'id="chat-data"';
  const idIndex = template.indexOf(idAttribute);
  if (idIndex === -1) {
    return template;
  }
  const openTagStart = template.lastIndexOf("<script", idIndex);
  if (openTagStart === -1) {
    return template;
  }
  const openTagEnd = template.indexOf(">", idIndex);
  if (openTagEnd === -1) {
    return template;
  }
  const closeTagStart = template.indexOf("</script>", openTagEnd);
  if (closeTagStart === -1) {
    return template;
  }
  const lineStart = template.lastIndexOf("\n", openTagStart);
  const lineIndent = lineStart === -1 ? "" : template.slice(lineStart + 1, openTagStart);
  const indentedJson = escapedJsonData.split("\n").map((line) => `${lineIndent}${line}`).join("\n");
  const before = template.slice(0, openTagEnd + 1);
  const after = template.slice(closeTagStart);
  return `${before}
${indentedJson}
${after}`;
}
__name(injectDataIntoHtmlTemplate, "injectDataIntoHtmlTemplate");
function toHtml(sessionData) {
  const template = loadHtmlTemplate();
  return injectDataIntoHtmlTemplate(template, sessionData);
}
__name(toHtml, "toHtml");

// packages/cli/src/ui/utils/export/formatters/json.ts
init_esbuild_shims();
function toJson(sessionData) {
  return JSON.stringify(sessionData, null, 2);
}
__name(toJson, "toJson");

// packages/cli/src/ui/utils/export/formatters/jsonl.ts
init_esbuild_shims();
function toJsonl(sessionData) {
  const lines = [];
  const sourceMetadata = sessionData.metadata;
  const metadata = {
    type: "session_metadata",
    sessionId: sessionData.sessionId,
    startTime: sessionData.startTime
  };
  if (sourceMetadata?.exportTime) {
    metadata["exportTime"] = sourceMetadata.exportTime;
  }
  if (sourceMetadata?.cwd) {
    metadata["cwd"] = sourceMetadata.cwd;
  }
  if (sourceMetadata?.gitRepo) {
    metadata["gitRepo"] = sourceMetadata.gitRepo;
  }
  if (sourceMetadata?.gitBranch) {
    metadata["gitBranch"] = sourceMetadata.gitBranch;
  }
  if (sourceMetadata?.model) {
    metadata["model"] = sourceMetadata.model;
  }
  if (sourceMetadata?.channel) {
    metadata["channel"] = sourceMetadata.channel;
  }
  if (sourceMetadata?.promptCount !== void 0) {
    metadata["promptCount"] = sourceMetadata.promptCount;
  }
  if (sourceMetadata?.contextUsagePercent !== void 0) {
    metadata["contextUsagePercent"] = sourceMetadata.contextUsagePercent;
  }
  if (sourceMetadata?.contextWindowSize !== void 0) {
    metadata["contextWindowSize"] = sourceMetadata.contextWindowSize;
  }
  if (sourceMetadata?.totalTokens !== void 0) {
    metadata["totalTokens"] = sourceMetadata.totalTokens;
  }
  if (sourceMetadata?.filesWritten !== void 0) {
    metadata["filesWritten"] = sourceMetadata.filesWritten;
  }
  if (sourceMetadata?.linesAdded !== void 0) {
    metadata["linesAdded"] = sourceMetadata.linesAdded;
  }
  if (sourceMetadata?.linesRemoved !== void 0) {
    metadata["linesRemoved"] = sourceMetadata.linesRemoved;
  }
  if (sourceMetadata?.uniqueFiles && sourceMetadata.uniqueFiles.length > 0) {
    metadata["uniqueFiles"] = sourceMetadata.uniqueFiles;
  }
  lines.push(JSON.stringify(metadata));
  for (const message of sessionData.messages) {
    lines.push(JSON.stringify(message));
  }
  return lines.join("\n");
}
__name(toJsonl, "toJsonl");

// packages/cli/src/ui/utils/export/utils.ts
init_esbuild_shims();
function generateExportFilename(extension) {
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
  return `qwen-code-export-${timestamp}.${extension}`;
}
__name(generateExportFilename, "generateExportFilename");

// packages/cli/src/ui/commands/exportCommand.ts
var EXPORT_DIR_OUT_OF_CWD = "Export directory must be within the project working directory.";
var debugLogger8 = createDebugLogger("EXPORT_COMMAND");
function formatExportTargetContext(target) {
  return `target: "${target.outputDir}", cwd: "${target.resolvedCwd}"`;
}
__name(formatExportTargetContext, "formatExportTargetContext");
function formatMissingCwdError(resolvedCwd) {
  return `Cannot resolve any existing ancestor within cwd: ${resolvedCwd}. This usually means the project working directory has been deleted or is on an unmounted filesystem.`;
}
__name(formatMissingCwdError, "formatMissingCwdError");
function resolveExportTarget(cwd, args, extension) {
  const filename = generateExportFilename(extension);
  const outputDirArg = args.trim();
  const resolvedCwd = path7.resolve(cwd);
  const outputDir = outputDirArg ? path7.resolve(resolvedCwd, outputDirArg) : resolvedCwd;
  const filepath = path7.join(outputDir, filename);
  const isDefaultOutputDir = outputDir === resolvedCwd;
  const isInsideCwd = isSubpath(resolvedCwd, outputDir);
  const outputDirKind = outputDirArg && !isDefaultOutputDir ? "custom" : "default";
  return {
    filepath,
    outputDir,
    displayPath: isDefaultOutputDir ? filename : path7.join(outputDirArg, filename),
    resolvedCwd,
    outputDirKind,
    isInsideCwd
  };
}
__name(resolveExportTarget, "resolveExportTarget");
async function validateExportTargetWithinCwd(target) {
  debugLogger8.debug(
    "Validating export target realpath:",
    formatExportTargetContext(target)
  );
  let realCwd;
  let realOutputDir;
  try {
    [realCwd, realOutputDir] = await Promise.all([
      fs7.realpath(target.resolvedCwd),
      fs7.realpath(target.outputDir)
    ]);
  } catch (error) {
    if (error.code === "ENOENT") {
      debugLogger8.debug(
        "Export target realpath validation failed: missing path",
        formatExportTargetContext(target)
      );
      return {
        type: "message",
        messageType: "error",
        content: `Export target directory is not accessible (path does not exist; ${formatExportTargetContext(
          target
        )}).`
      };
    }
    throw error;
  }
  if (!isSubpath(realCwd, realOutputDir)) {
    debugLogger8.debug("Export target realpath escaped cwd:", {
      realCwd,
      realOutputDir,
      target
    });
    return {
      type: "message",
      messageType: "error",
      content: `${EXPORT_DIR_OUT_OF_CWD} (target path resolves outside cwd via symlink; ${formatExportTargetContext(
        target
      )})`
    };
  }
  return void 0;
}
__name(validateExportTargetWithinCwd, "validateExportTargetWithinCwd");
async function realpathNearestExisting(outputDir, resolvedCwd) {
  let currentPath = outputDir;
  debugLogger8.debug("Resolving nearest existing export parent:", {
    outputDir,
    resolvedCwd
  });
  while (isSubpath(resolvedCwd, currentPath)) {
    try {
      const realCurrentPath = await fs7.realpath(currentPath);
      debugLogger8.debug("Resolved nearest existing export parent:", {
        currentPath,
        realCurrentPath
      });
      return realCurrentPath;
    } catch (error) {
      if (error.code !== "ENOENT") {
        debugLogger8.debug("Failed to resolve existing export parent:", error);
        throw error;
      }
      const parentPath = path7.dirname(currentPath);
      if (parentPath === currentPath) {
        break;
      }
      currentPath = parentPath;
    }
  }
  throw new Error(formatMissingCwdError(resolvedCwd));
}
__name(realpathNearestExisting, "realpathNearestExisting");
async function validateExistingExportParentWithinCwd(target) {
  debugLogger8.debug(
    "Validating existing export parent realpath:",
    formatExportTargetContext(target)
  );
  let realCwd;
  try {
    realCwd = await fs7.realpath(target.resolvedCwd);
  } catch (error) {
    if (error.code === "ENOENT") {
      throw new Error(formatMissingCwdError(target.resolvedCwd));
    }
    throw error;
  }
  const realExistingParent = await realpathNearestExisting(
    target.outputDir,
    target.resolvedCwd
  );
  if (!isSubpath(realCwd, realExistingParent)) {
    debugLogger8.debug("Existing export parent escaped cwd:", {
      realCwd,
      realExistingParent,
      target
    });
    return {
      type: "message",
      messageType: "error",
      content: `${EXPORT_DIR_OUT_OF_CWD} (parent path resolves outside cwd via symlink; ${formatExportTargetContext(
        target
      )})`
    };
  }
  return void 0;
}
__name(validateExistingExportParentWithinCwd, "validateExistingExportParentWithinCwd");
async function exportSessionAction(context, args, exportFormat) {
  const { services } = context;
  const { config } = services;
  if (!config) {
    return {
      type: "message",
      messageType: "error",
      content: "Configuration not available."
    };
  }
  const cwd = config.getWorkingDir() || config.getProjectRoot();
  if (!cwd) {
    return {
      type: "message",
      messageType: "error",
      content: "Could not determine current working directory."
    };
  }
  const target = resolveExportTarget(cwd, args, exportFormat.extension);
  const targetFilepath = target.filepath;
  debugLogger8.debug("Resolved export target:", {
    format: exportFormat.displayName,
    cwd,
    outputDirArg: args.trim(),
    outputDir: target.outputDir,
    outputDirKind: target.outputDirKind,
    filepath: target.filepath
  });
  if (!target.isInsideCwd) {
    debugLogger8.debug(
      "Export target rejected before realpath validation:",
      formatExportTargetContext(target)
    );
    return {
      type: "message",
      messageType: "error",
      content: `${EXPORT_DIR_OUT_OF_CWD} (target path is outside cwd; ${formatExportTargetContext(
        target
      )})`
    };
  }
  try {
    const initialValidationError = target.outputDirKind === "custom" ? await validateExistingExportParentWithinCwd(target) : await validateExportTargetWithinCwd(target);
    if (initialValidationError) {
      return initialValidationError;
    }
    debugLogger8.debug("Export target validation passed:", {
      format: exportFormat.displayName,
      outputDir: target.outputDir,
      outputDirKind: target.outputDirKind
    });
    const sessionService = new SessionService(cwd);
    const sessionId = config.getSessionId();
    debugLogger8.debug("Loading session for export:", { sessionId, cwd });
    const sessionData = await sessionService.loadSession(sessionId);
    if (!sessionData) {
      debugLogger8.debug("No active session found for export:", {
        sessionId,
        cwd
      });
      return {
        type: "message",
        messageType: "error",
        content: "No active session found to export."
      };
    }
    const { conversation } = sessionData;
    const exportData = await collectSessionData(conversation, config);
    const normalizedData = normalizeSessionData(
      exportData,
      conversation.messages,
      config
    );
    const content = exportFormat.format(normalizedData);
    if (target.outputDirKind === "custom") {
      try {
        debugLogger8.debug("Creating export directory:", {
          outputDir: target.outputDir
        });
        await fs7.mkdir(target.outputDir, { recursive: true, mode: 448 });
      } catch (error) {
        debugLogger8.debug("Failed to create export directory:", error);
        return {
          type: "message",
          messageType: "error",
          content: `Failed to create export directory "${target.outputDir}": ${error instanceof Error ? error.message : String(error)}`
        };
      }
    }
    try {
      const writeValidationError = await validateExportTargetWithinCwd(target);
      if (writeValidationError) {
        return writeValidationError;
      }
    } catch (error) {
      debugLogger8.debug("Export path validation failed before write:", error);
      return {
        type: "message",
        messageType: "error",
        content: `Export path validation failed: ${error instanceof Error ? error.message : String(error)} (${exportFormat.displayName} target: "${targetFilepath}")`
      };
    }
    try {
      debugLogger8.debug("Writing export file:", {
        format: exportFormat.displayName,
        filepath: target.filepath
      });
      await fs7.writeFile(target.filepath, content, {
        encoding: "utf-8",
        mode: 384
      });
      await fs7.chmod(target.filepath, 384).catch((error) => {
        debugLogger8.debug("Failed to tighten export file permissions:", error);
      });
    } catch (error) {
      debugLogger8.debug("Failed to write export file:", error);
      return {
        type: "message",
        messageType: "error",
        content: `Failed to export session: ${error instanceof Error ? error.message : String(error)} (${exportFormat.displayName} target: "${targetFilepath}")`
      };
    }
    debugLogger8.debug("Session export completed:", {
      format: exportFormat.displayName,
      filepath: target.filepath
    });
    return {
      type: "message",
      messageType: "info",
      content: `Session exported to ${exportFormat.displayName}: ${target.displayPath}`
    };
  } catch (error) {
    debugLogger8.debug("Session export failed:", {
      format: exportFormat.displayName,
      target,
      error
    });
    return {
      type: "message",
      messageType: "error",
      content: `Failed to export session: ${error instanceof Error ? error.message : String(error)} (${exportFormat.displayName})`
    };
  }
}
__name(exportSessionAction, "exportSessionAction");
async function exportMarkdownAction(context, args) {
  return exportSessionAction(context, args, {
    extension: "md",
    displayName: "markdown",
    format: toMarkdown
  });
}
__name(exportMarkdownAction, "exportMarkdownAction");
async function exportHtmlAction(context, args) {
  return exportSessionAction(context, args, {
    extension: "html",
    displayName: "HTML",
    format: toHtml
  });
}
__name(exportHtmlAction, "exportHtmlAction");
async function exportJsonAction(context, args) {
  return exportSessionAction(context, args, {
    extension: "json",
    displayName: "JSON",
    format: toJson
  });
}
__name(exportJsonAction, "exportJsonAction");
async function exportJsonlAction(context, args) {
  return exportSessionAction(context, args, {
    extension: "jsonl",
    displayName: "JSONL",
    format: toJsonl
  });
}
__name(exportJsonlAction, "exportJsonlAction");
var exportCommand = {
  name: "export",
  get description() {
    return t("Export current session message history to a file");
  },
  argumentHint: "[md|html|json|jsonl] [path]",
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive", "non_interactive", "acp"],
  action: exportHtmlAction,
  subCommands: [
    {
      name: "html",
      get description() {
        return t("Export session to HTML format");
      },
      kind: "built-in" /* BUILT_IN */,
      supportedModes: ["interactive", "non_interactive", "acp"],
      action: exportHtmlAction
    },
    {
      name: "md",
      get description() {
        return t("Export session to markdown format");
      },
      kind: "built-in" /* BUILT_IN */,
      supportedModes: ["interactive", "non_interactive", "acp"],
      action: exportMarkdownAction
    },
    {
      name: "json",
      get description() {
        return t("Export session to JSON format");
      },
      kind: "built-in" /* BUILT_IN */,
      supportedModes: ["interactive", "non_interactive", "acp"],
      action: exportJsonAction
    },
    {
      name: "jsonl",
      get description() {
        return t("Export session to JSONL format (one message per line)");
      },
      kind: "built-in" /* BUILT_IN */,
      supportedModes: ["interactive", "non_interactive", "acp"],
      action: exportJsonlAction
    }
  ]
};

// packages/cli/src/ui/commands/forkCommand.ts
init_esbuild_shims();
var debugLogger9 = createDebugLogger("FORK_COMMAND");
function deriveForkDescription(directive) {
  const oneLine = directive.replace(/\s+/g, " ").trim();
  return oneLine.length > 60 ? `${oneLine.slice(0, 57)}\u2026` : oneLine;
}
__name(deriveForkDescription, "deriveForkDescription");
function hasFailedDisplayStatus(display) {
  return display !== null && typeof display === "object" && "status" in display && display.status === "failed";
}
__name(hasFailedDisplayStatus, "hasFailedDisplayStatus");
var forkCommand = {
  name: "fork",
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive"],
  argumentHint: "<directive>",
  get description() {
    return t("Spawn a background agent that inherits the full conversation");
  },
  action: /* @__PURE__ */ __name(async (context, args) => {
    const directive = args.trim();
    if (!directive) {
      return {
        type: "message",
        messageType: "error",
        content: t("Please provide a directive. Usage: /fork <directive>")
      };
    }
    const { config } = context.services;
    const { ui } = context;
    if (!config) {
      return {
        type: "message",
        messageType: "error",
        content: t("Config is not available.")
      };
    }
    if (ui.isIdleRef?.current === false) {
      return {
        type: "message",
        messageType: "error",
        content: t(
          "Cannot fork while a response or tool call is in progress. Wait for it to finish or resolve the pending tool call."
        )
      };
    }
    if (!config.getModel()) {
      return {
        type: "message",
        messageType: "error",
        content: t("No model configured.")
      };
    }
    let hasHistory = false;
    try {
      hasHistory = (config.getGeminiClient().getHistoryShallow() ?? []).length > 0;
    } catch (error) {
      debugLogger9.debug("Failed to read history before /fork:", error);
      hasHistory = false;
    }
    if (!hasHistory) {
      return {
        type: "message",
        messageType: "error",
        content: t("Cannot fork before the first conversation turn.")
      };
    }
    const agentTool = config.getToolRegistry().getTool(ToolNames.AGENT);
    if (!agentTool) {
      return {
        type: "message",
        messageType: "error",
        content: t("The agent tool is unavailable; cannot fork.")
      };
    }
    const params = {
      description: deriveForkDescription(directive),
      prompt: directive,
      subagent_type: FORK_SUBAGENT_TYPE,
      run_in_background: true
    };
    let result;
    try {
      result = await agentTool.build(params).execute(new AbortController().signal);
    } catch (error) {
      return {
        type: "message",
        messageType: "error",
        content: t("Failed to launch fork: {{error}}", {
          error: error instanceof Error ? error.message : String(error)
        })
      };
    }
    const display = result?.returnDisplay;
    if (hasFailedDisplayStatus(display)) {
      const reason = typeof result.llmContent === "string" && result.llmContent.trim() ? result.llmContent.trim() : t("the background agent could not be started.");
      return {
        type: "message",
        messageType: "error",
        content: t("Failed to launch fork: {{error}}", { error: reason })
      };
    }
    try {
      config.getGeminiClient().addHistory({
        role: "user",
        parts: [
          {
            text: t(
              "User launched a background fork via /fork: {{directive}}",
              {
                directive
              }
            )
          }
        ]
      });
    } catch (error) {
      debugLogger9.debug("Failed to record fork event in history:", error);
    }
    return {
      type: "message",
      messageType: "info",
      content: t(
        "Forked into a background agent. It inherits this conversation and runs without blocking \u2014 track it in the background tasks panel; it reports back when done."
      )
    };
  }, "action")
};

// packages/cli/src/ui/commands/extensionsCommand.ts
init_esbuild_shims();
var debugLogger10 = createDebugLogger("EXTENSIONS_COMMAND");
var EXTENSION_EXPLORE_URL = {
  Gemini: "https://geminicli.com/extensions/",
  ClaudeCode: "https://claudemarketplaces.com/"
};
async function exploreAction(context, args) {
  const mode = context.executionMode ?? "interactive";
  if (mode !== "interactive") {
    return {
      type: "message",
      messageType: "error",
      content: t("/extensions explore is only available in interactive mode.")
    };
  }
  const source = args.trim();
  const extensionsUrl = source ? EXTENSION_EXPLORE_URL[source] : "";
  if (!extensionsUrl) {
    context.ui.addItem(
      {
        type: "error" /* ERROR */,
        text: t("Unknown extensions source: {{source}}.", { source })
      },
      Date.now()
    );
    return;
  }
  if (false) {
    context.ui.addItem(
      {
        type: "info" /* INFO */,
        text: t(
          "Would open extensions page in your browser: {{url}} (skipped in test environment)",
          { url: extensionsUrl }
        )
      },
      Date.now()
    );
  } else if (process.env["SANDBOX"] && process.env["SANDBOX"] !== "sandbox-exec") {
    context.ui.addItem(
      {
        type: "info" /* INFO */,
        text: t("View available extensions at {{url}}", { url: extensionsUrl })
      },
      Date.now()
    );
  } else {
    context.ui.addItem(
      {
        type: "info" /* INFO */,
        text: t("Opening extensions page in your browser: {{url}}", {
          url: extensionsUrl
        })
      },
      Date.now()
    );
    try {
      await openBrowserSecurely(extensionsUrl);
    } catch (_error) {
      context.ui.addItem(
        {
          type: "error" /* ERROR */,
          text: t(
            "Failed to open browser. Check out the extensions gallery at {{url}}",
            { url: extensionsUrl }
          )
        },
        Date.now()
      );
    }
  }
  return void 0;
}
__name(exploreAction, "exploreAction");
async function listAction(context, args) {
  const mode = context.executionMode ?? "interactive";
  if (mode !== "interactive") {
    return listTextAction(context, args);
  }
  return {
    type: "dialog",
    dialog: "extensions_manage"
  };
}
__name(listAction, "listAction");
async function listTextAction(context, _args) {
  const config = context.services.config;
  if (!config) {
    return {
      type: "message",
      messageType: "error",
      content: t("Config not loaded.")
    };
  }
  let extensions;
  try {
    extensions = config.getExtensions();
  } catch (error) {
    return {
      type: "message",
      messageType: "error",
      content: t("Failed to read extensions: {{error}}", {
        error: error instanceof Error ? error.message : String(error)
      })
    };
  }
  if (extensions.length === 0) {
    return {
      type: "message",
      messageType: "info",
      content: t("No extensions installed.")
    };
  }
  const active = extensions.filter((e) => e.isActive);
  let output = t("**Installed Extensions ({{total}} total, {{active}} active)**", {
    total: String(extensions.length),
    active: String(active.length)
  }) + "\n\n";
  const locale = getCurrentLanguage();
  for (const ext of extensions) {
    const status = ext.isActive ? "\u2713" : "\u2717";
    const displayLabel = getExtensionDisplayName(ext, locale);
    const description = getExtensionDescription(ext, locale);
    const caps = [];
    const mcpCount = ext.mcpServers ? Object.keys(ext.mcpServers).length : 0;
    if (mcpCount > 0) {
      caps.push(t("{{count}} MCP servers", { count: String(mcpCount) }));
    }
    if (ext.skills && ext.skills.length > 0) {
      caps.push(t("{{count}} skills", { count: String(ext.skills.length) }));
    }
    if (ext.commands && ext.commands.length > 0) {
      caps.push(
        t("{{count}} commands", { count: String(ext.commands.length) })
      );
    }
    const capsStr = caps.length > 0 ? ` [${caps.join(", ")}]` : "";
    output += `- [${status}] **${displayLabel}**${capsStr}
`;
    if (description) {
      const maxLen = 80;
      const truncated = description.length > maxLen ? description.slice(0, maxLen - 1) + "\u2026" : description;
      output += `  ${truncated}
`;
    }
  }
  return {
    type: "message",
    messageType: "info",
    content: output
  };
}
__name(listTextAction, "listTextAction");
async function installAction(context, args) {
  const mode = context.executionMode ?? "interactive";
  if (mode !== "interactive") {
    return {
      type: "message",
      messageType: "error",
      content: t("/extensions install is only available in interactive mode.")
    };
  }
  const extensionManager = context.services.config?.getExtensionManager();
  if (!(extensionManager instanceof ExtensionManager)) {
    debugLogger10.error(
      `Cannot ${context.invocation?.name} extensions in this environment`
    );
    return;
  }
  const source = args.trim();
  if (!source) {
    context.ui.addItem(
      {
        type: "error" /* ERROR */,
        text: t("Usage: /extensions install <source>")
      },
      Date.now()
    );
    return;
  }
  try {
    const installMetadata = await parseInstallSource(source);
    const redactedSource = redactUrlCredentials(source);
    context.ui.addItem(
      {
        type: "info" /* INFO */,
        text: t('Installing extension from "{{source}}"...', {
          source: redactedSource
        })
      },
      Date.now()
    );
    const extension = await extensionManager.installExtension(installMetadata);
    context.ui.addItem(
      {
        type: "info" /* INFO */,
        text: t('Extension "{{name}}" installed successfully.', {
          name: extension.name
        })
      },
      Date.now()
    );
    context.ui.reloadCommands();
  } catch (error) {
    context.ui.addItem(
      {
        type: "error" /* ERROR */,
        text: t('Failed to install extension from "{{source}}": {{error}}', {
          source: redactUrlCredentials(source),
          error: redactUrlCredentials(getErrorMessage2(error))
        })
      },
      Date.now()
    );
    return;
  }
  return void 0;
}
__name(installAction, "installAction");
async function completeExtensionsExplore(context, partialArg) {
  const suggestions = Object.keys(EXTENSION_EXPLORE_URL).filter(
    (name) => name.startsWith(partialArg)
  );
  return suggestions;
}
__name(completeExtensionsExplore, "completeExtensionsExplore");
var exploreExtensionsCommand = {
  name: "explore",
  get description() {
    return t("Open extensions page in your browser");
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive"],
  action: exploreAction,
  completion: completeExtensionsExplore
};
var manageExtensionsCommand = {
  name: "manage",
  get description() {
    return t("Manage installed extensions");
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive"],
  action: listAction
};
var listExtensionsCommand = {
  name: "list",
  get description() {
    return t("List installed extensions");
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive", "non_interactive", "acp"],
  action: listTextAction
};
var installCommand = {
  name: "install",
  get description() {
    return t("Install an extension from a git repo or local path");
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive"],
  action: installAction
};
var extensionsCommand = {
  name: "extensions",
  get description() {
    return t("Manage extensions");
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive", "non_interactive", "acp"],
  subCommands: [
    listExtensionsCommand,
    manageExtensionsCommand,
    installCommand,
    exploreExtensionsCommand
  ],
  action: /* @__PURE__ */ __name(async (context, args) => {
    const executionMode = context.executionMode ?? "interactive";
    if (executionMode === "interactive") {
      return manageExtensionsCommand.action(context, args);
    }
    return listTextAction(context, args);
  }, "action")
};

// packages/cli/src/ui/commands/goalCommand.ts
init_esbuild_shims();

// packages/cli/src/ui/utils/restoreGoal.ts
init_esbuild_shims();
function findGoalToRestore(history) {
  for (let i = history.length - 1; i >= 0; i--) {
    const item = history[i];
    if (item?.type !== "goal_status" /* GOAL_STATUS */) continue;
    const goal = item;
    if (goal.kind === "set" || goal.kind === "checking") {
      return { condition: goal.condition, iterations: goal.iterations ?? 0 };
    }
    return null;
  }
  return null;
}
__name(findGoalToRestore, "findGoalToRestore");
function findLastTerminalGoal(history) {
  for (let i = history.length - 1; i >= 0; i--) {
    const item = history[i];
    if (item?.type !== "goal_status" /* GOAL_STATUS */) continue;
    const goal = item;
    if (!isTerminalGoalStatusKind(goal.kind)) continue;
    return {
      kind: goal.kind,
      condition: goal.condition,
      iterations: goal.iterations ?? 0,
      durationMs: goal.durationMs ?? 0,
      lastReason: goal.lastReason
    };
  }
  return null;
}
__name(findLastTerminalGoal, "findLastTerminalGoal");
function goalTerminalEventToHistoryItem(event) {
  return {
    type: "goal_status" /* GOAL_STATUS */,
    kind: event.kind,
    condition: event.condition,
    iterations: event.iterations,
    durationMs: event.durationMs,
    lastReason: event.lastReason ?? event.systemMessage
  };
}
__name(goalTerminalEventToHistoryItem, "goalTerminalEventToHistoryItem");
function recordGoalStatusItem(config, item, rawCommand = "/goal") {
  try {
    config.getChatRecordingService?.()?.recordSlashCommand({
      phase: "result",
      rawCommand,
      outputHistoryItems: [{ ...item }]
    });
  } catch {
  }
}
__name(recordGoalStatusItem, "recordGoalStatusItem");
function installGoalTerminalObserver(args) {
  const { sessionId, config, addItem } = args;
  setGoalTerminalObserver(sessionId, (event) => {
    const item = goalTerminalEventToHistoryItem(event);
    addItem(item, Date.now());
    recordGoalStatusItem(config, item);
  });
}
__name(installGoalTerminalObserver, "installGoalTerminalObserver");
function restoreGoalFromHistory(history, config, addItem) {
  const sessionId = config.getSessionId();
  const lastTerminal = findLastTerminalGoal(history);
  setLastGoalTerminal(sessionId, lastTerminal ?? void 0);
  const restorable = findGoalToRestore(history);
  if (restorable === null) {
    unregisterGoalHook(config, sessionId);
    return { restored: false };
  }
  if (!config.isTrustedFolder() || config.getDisableAllHooks()) {
    unregisterGoalHook(config, sessionId);
    return { restored: false };
  }
  if (!config.getHookSystem()) {
    unregisterGoalHook(config, sessionId);
    return { restored: false };
  }
  registerGoalHook({
    config,
    sessionId,
    condition: restorable.condition,
    tokensAtStart: 0,
    // Resume the iteration count so MAX_GOAL_ITERATIONS is a cross-resume cap,
    // not a per-resume one.
    initialIterations: restorable.iterations
  });
  if (addItem) {
    installGoalTerminalObserver({ sessionId, config, addItem });
  }
  return { restored: true, condition: restorable.condition };
}
__name(restoreGoalFromHistory, "restoreGoalFromHistory");

// packages/cli/src/ui/commands/goalCommand.ts
var CLEAR_KEYWORDS = /* @__PURE__ */ new Set([
  "clear",
  "stop",
  "off",
  "reset",
  "none",
  "cancel"
]);
var MAX_GOAL_LENGTH = 4e3;
function sanitizeConditionForPrompt(condition) {
  return condition.replace(/[\r\n]+/g, " ").replace(/"/g, "'");
}
__name(sanitizeConditionForPrompt, "sanitizeConditionForPrompt");
var goalInstructionPrompt = /* @__PURE__ */ __name((condition) => `A session-scoped Stop hook is now active with condition: "${sanitizeConditionForPrompt(condition)}". Briefly acknowledge the goal, then immediately start (or continue) working toward it \u2014 treat the condition itself as your directive and do not pause to ask the user what to do. The hook will block stopping until the condition holds. It auto-clears once the condition is met \u2014 do not tell the user to run \`/goal clear\` after success; that's only for clearing a goal early.`, "goalInstructionPrompt");
var formatTurns = /* @__PURE__ */ __name((n) => `${n} ${n === 1 ? "turn" : "turns"}`, "formatTurns");
function assertNeverGoalKind(kind) {
  throw new Error(`Unexpected terminal goal kind: ${kind}`);
}
__name(assertNeverGoalKind, "assertNeverGoalKind");
function terminalGoalTitle(kind) {
  switch (kind) {
    case "achieved":
      return "Goal achieved";
    case "failed":
      return "Goal could not be achieved";
    case "aborted":
      return "Goal aborted";
    default:
      return assertNeverGoalKind(kind);
  }
}
__name(terminalGoalTitle, "terminalGoalTitle");
function formatTerminalSummary(event) {
  const title = terminalGoalTitle(event.kind);
  const stats = [];
  if (event.iterations > 0) stats.push(formatTurns(event.iterations));
  if (typeof event.durationMs === "number")
    stats.push(formatDuration(event.durationMs, { hideTrailingZeros: true }));
  const subtitle = stats.length > 0 ? ` \xB7 ${stats.join(" \xB7 ")}` : "";
  const reason = event.lastReason?.trim();
  const reasonLine = reason ? `
Last check: ${reason}` : "";
  return `${title}${subtitle}
Goal: ${event.condition}${reasonLine}`;
}
__name(formatTerminalSummary, "formatTerminalSummary");
function infoMessage(content) {
  return { type: "message", messageType: "info", content };
}
__name(infoMessage, "infoMessage");
function errorMessage(content) {
  return { type: "message", messageType: "error", content };
}
__name(errorMessage, "errorMessage");
var goalCommand = {
  name: "goal",
  get description() {
    return t("Set a goal \u2014 keep working until the condition is met");
  },
  argumentHint: "[<condition> | clear]",
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive", "non_interactive", "acp"],
  action: /* @__PURE__ */ __name(async (context, args) => {
    const { config } = context.services;
    if (!config) {
      return errorMessage("Configuration is not available.");
    }
    const sessionId = config.getSessionId();
    const q = args.trim();
    if (q === "") {
      const active = getActiveGoal(sessionId);
      if (active) {
        const turns = active.iterations === 0 ? "not yet evaluated" : formatTurns(active.iterations);
        const lastReason = active.lastReason ? `
Last check: ${active.lastReason}` : "";
        return infoMessage(
          `Goal active: ${active.condition} (${turns})${lastReason}`
        );
      }
      const last = getLastGoalTerminal(sessionId);
      if (last) {
        return infoMessage(formatTerminalSummary(last));
      }
      return infoMessage(
        "No goal set. Usage: `/goal <condition>` (or `/goal clear`)."
      );
    }
    if (CLEAR_KEYWORDS.has(q.toLowerCase())) {
      const cleared = unregisterGoalHook(config, sessionId);
      if (!cleared) {
        return infoMessage("No goal set.");
      }
      const clearedItem = {
        type: "goal_status" /* GOAL_STATUS */,
        kind: "cleared",
        condition: cleared.condition,
        iterations: cleared.iterations,
        durationMs: Date.now() - cleared.setAt
      };
      context.ui.addItem(clearedItem, Date.now());
      if (context.executionMode !== "interactive") {
        return infoMessage(`Goal cleared: ${cleared.condition}`);
      }
      return;
    }
    if (q.length > MAX_GOAL_LENGTH) {
      return errorMessage(
        `Goal condition is limited to ${MAX_GOAL_LENGTH} characters (got ${q.length}).`
      );
    }
    if (!config.isTrustedFolder()) {
      return errorMessage(
        "/goal is only available in trusted workspaces. Trust this folder via `/trust` and try again."
      );
    }
    if (config.getDisableAllHooks()) {
      return errorMessage(
        "/goal is disabled because hooks are turned off in this session (`disableAllHooks` or bare mode)."
      );
    }
    if (!config.getHookSystem()) {
      return errorMessage(
        "Hook system is not initialized; cannot set a /goal in this session."
      );
    }
    let registered;
    try {
      registered = registerGoalHook({
        config,
        sessionId,
        condition: q,
        tokensAtStart: 0
      });
    } catch (err) {
      return errorMessage(
        `Failed to set goal: ${err instanceof Error ? err.message : String(err)}`
      );
    }
    const setItem = {
      type: "goal_status" /* GOAL_STATUS */,
      kind: "set",
      condition: registered.condition,
      setAt: registered.setAt
    };
    context.ui.addItem(setItem, Date.now());
    installGoalTerminalObserver({
      sessionId,
      config,
      addItem: context.ui.addItem
    });
    const result = {
      type: "submit_prompt",
      content: [{ text: goalInstructionPrompt(q) }]
    };
    return result;
  }, "action")
};

// packages/cli/src/ui/commands/helpCommand.ts
init_esbuild_shims();
var helpCommand = {
  name: "help",
  altNames: ["?"],
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive"],
  get description() {
    return t("for help on Qwen Code");
  },
  action: /* @__PURE__ */ __name(async () => ({
    type: "dialog",
    dialog: "help"
  }), "action")
};

// packages/cli/src/ui/commands/historyCommand.ts
init_esbuild_shims();
var collapseOnResumeCommand = {
  name: "collapse-on-resume",
  get description() {
    return t("Set history to collapse by default when resuming a session");
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive"],
  action: /* @__PURE__ */ __name((context) => {
    const { settings } = context.services;
    settings.setValue("User" /* User */, "ui.history.collapseOnResume", true);
    return {
      type: "message",
      messageType: "info",
      content: t(
        "History will be collapsed by default for future resumed sessions."
      )
    };
  }, "action")
};
var expandOnResumeCommand = {
  name: "expand-on-resume",
  get description() {
    return t("Set history to expand by default when resuming a session");
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive"],
  action: /* @__PURE__ */ __name((context) => {
    const { settings } = context.services;
    settings.setValue("User" /* User */, "ui.history.collapseOnResume", false);
    return {
      type: "message",
      messageType: "info",
      content: t(
        "History will be expanded by default for future resumed sessions."
      )
    };
  }, "action")
};
var expandNowCommand = {
  name: "expand-now",
  get description() {
    return t("Expand the currently collapsed history transcript");
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive"],
  action: /* @__PURE__ */ __name((context) => {
    const { history, loadHistory, refreshStatic } = context.ui;
    const hasSuppressed = history.some(
      (item) => item.display?.suppressOnRestore
    );
    if (!hasSuppressed) {
      return {
        type: "message",
        messageType: "info",
        content: t("History is already expanded in this session.")
      };
    }
    const updated = expandCollapsedHistory(history);
    loadHistory(updated);
    refreshStatic();
  }, "action")
};
var historyCommand = {
  name: "history",
  get description() {
    return t("Control history display preferences and visibility");
  },
  argumentHint: "collapse-on-resume|expand-on-resume|expand-now",
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive"],
  subCommands: [
    collapseOnResumeCommand,
    expandOnResumeCommand,
    expandNowCommand
  ],
  action: /* @__PURE__ */ __name(async () => ({
    type: "message",
    messageType: "error",
    content: t(
      "Usage: /history collapse-on-resume|expand-on-resume|expand-now"
    )
  }), "action")
};

// packages/cli/src/ui/commands/hooksCommand.ts
init_esbuild_shims();

// packages/cli/src/ui/components/hooks/constants.ts
init_esbuild_shims();
function getHookExitCodes(eventName) {
  const exitCodesMap = {
    ["Stop" /* Stop */]: [
      { code: 0, description: t("stdout/stderr not shown") },
      {
        code: 2,
        description: t("show stderr to model and continue conversation")
      },
      { code: "Other", description: t("show stderr to user only") }
    ],
    ["PreToolUse" /* PreToolUse */]: [
      { code: 0, description: t("stdout/stderr not shown") },
      { code: 2, description: t("show stderr to model and block tool call") },
      {
        code: "Other",
        description: t("show stderr to user only but continue with tool call")
      }
    ],
    ["PostToolUse" /* PostToolUse */]: [
      { code: 0, description: t("stdout shown in transcript mode (ctrl+o)") },
      { code: 2, description: t("show stderr to model immediately") },
      { code: "Other", description: t("show stderr to user only") }
    ],
    ["PostToolUseFailure" /* PostToolUseFailure */]: [
      { code: 0, description: t("stdout shown in transcript mode (ctrl+o)") },
      { code: 2, description: t("show stderr to model immediately") },
      { code: "Other", description: t("show stderr to user only") }
    ],
    ["PostToolBatch" /* PostToolBatch */]: [
      { code: 0, description: t("stdout shown in transcript mode (ctrl+o)") },
      { code: 2, description: t("show stderr to model immediately") },
      { code: "Other", description: t("show stderr to user only") }
    ],
    ["Notification" /* Notification */]: [
      { code: 0, description: t("stdout/stderr not shown") },
      { code: "Other", description: t("show stderr to user only") }
    ],
    ["InstructionsLoaded" /* InstructionsLoaded */]: [
      { code: 0, description: t("stdout/stderr not shown") },
      { code: "Other", description: t("show stderr to user only") }
    ],
    ["UserPromptSubmit" /* UserPromptSubmit */]: [
      { code: 0, description: t("stdout shown to Qwen") },
      {
        code: 2,
        description: t(
          "block processing, erase original prompt, and show stderr to user only"
        )
      },
      { code: "Other", description: t("show stderr to user only") }
    ],
    ["UserPromptExpansion" /* UserPromptExpansion */]: [
      { code: 0, description: t("stdout shown to Qwen") },
      {
        code: 2,
        description: t(
          "block expanded prompt submission and show stderr to user only"
        )
      },
      { code: "Other", description: t("show stderr to user only") }
    ],
    ["SessionStart" /* SessionStart */]: [
      { code: 0, description: t("stdout shown to Qwen") },
      {
        code: "Other",
        description: t("show stderr to user only (blocking errors ignored)")
      }
    ],
    ["SessionEnd" /* SessionEnd */]: [
      { code: 0, description: t("command completes successfully") },
      { code: "Other", description: t("show stderr to user only") }
    ],
    ["SubagentStart" /* SubagentStart */]: [
      { code: 0, description: t("stdout shown to subagent") },
      {
        code: "Other",
        description: t("show stderr to user only (blocking errors ignored)")
      }
    ],
    ["SubagentStop" /* SubagentStop */]: [
      { code: 0, description: t("stdout/stderr not shown") },
      {
        code: 2,
        description: t("show stderr to subagent and continue having it run")
      },
      { code: "Other", description: t("show stderr to user only") }
    ],
    ["PreCompact" /* PreCompact */]: [
      {
        code: 0,
        description: t("stdout appended as custom compact instructions")
      },
      { code: 2, description: t("block compaction") },
      {
        code: "Other",
        description: t("show stderr to user only but continue with compaction")
      }
    ],
    ["PostCompact" /* PostCompact */]: [
      { code: 0, description: t("stdout/stderr not shown") },
      { code: "Other", description: t("show stderr to user only") }
    ],
    ["StopFailure" /* StopFailure */]: [
      {
        code: 0,
        description: t("fire-and-forget; exit status is ignored")
      },
      {
        code: "Other",
        description: t("fire-and-forget; exit status is ignored")
      }
    ],
    ["PermissionRequest" /* PermissionRequest */]: [
      { code: 0, description: t("use hook decision if provided") },
      { code: "Other", description: t("show stderr to user only") }
    ],
    ["PermissionDenied" /* PermissionDenied */]: [
      { code: 0, description: t("stdout/stderr not shown") },
      { code: "Other", description: t("show stderr to user only") }
    ],
    ["TodoCreated" /* TodoCreated */]: [
      { code: 0, description: t("allow todo creation") },
      {
        code: 2,
        description: t("block todo creation and show reason to model")
      },
      { code: "Other", description: t("show stderr to user only") }
    ],
    ["TodoCompleted" /* TodoCompleted */]: [
      { code: 0, description: t("allow todo completion") },
      {
        code: 2,
        description: t("block todo completion and show reason to model")
      },
      { code: "Other", description: t("show stderr to user only") }
    ]
  };
  return exitCodesMap[eventName] || [];
}
__name(getHookExitCodes, "getHookExitCodes");
function getHookShortDescription(eventName) {
  const descriptions = {
    ["PreToolUse" /* PreToolUse */]: t("Before tool execution"),
    ["PostToolUse" /* PostToolUse */]: t("After tool execution"),
    ["PostToolUseFailure" /* PostToolUseFailure */]: t("After tool execution fails"),
    ["PostToolBatch" /* PostToolBatch */]: t("After all tool calls in a batch resolve"),
    ["Notification" /* Notification */]: t("When notifications are sent"),
    ["InstructionsLoaded" /* InstructionsLoaded */]: t("When instruction files are loaded"),
    ["UserPromptSubmit" /* UserPromptSubmit */]: t("When the user submits a prompt"),
    ["UserPromptExpansion" /* UserPromptExpansion */]: t(
      "When a slash command expands into a prompt"
    ),
    ["SessionStart" /* SessionStart */]: t("When a new session is started"),
    ["Stop" /* Stop */]: t("Right before Qwen Code concludes its response"),
    ["SubagentStart" /* SubagentStart */]: t(
      "When a subagent (Agent tool call) is started"
    ),
    ["SubagentStop" /* SubagentStop */]: t(
      "Right before a subagent concludes its response"
    ),
    ["PreCompact" /* PreCompact */]: t("Before conversation compaction"),
    ["PostCompact" /* PostCompact */]: t("After conversation compaction"),
    ["StopFailure" /* StopFailure */]: t(
      "When the turn ends due to an API error (fires instead of Stop)"
    ),
    ["SessionEnd" /* SessionEnd */]: t("When a session is ending"),
    ["PermissionRequest" /* PermissionRequest */]: t(
      "When a permission dialog is displayed"
    ),
    ["PermissionDenied" /* PermissionDenied */]: t(
      "When a tool call is denied before a permission dialog is displayed"
    ),
    ["TodoCreated" /* TodoCreated */]: t("When a new todo item is created"),
    ["TodoCompleted" /* TodoCompleted */]: t("When a todo item is marked as completed")
  };
  return descriptions[eventName] || "";
}
__name(getHookShortDescription, "getHookShortDescription");
function getHookDescription(eventName) {
  const descriptions = {
    ["Stop" /* Stop */]: "",
    ["PreToolUse" /* PreToolUse */]: t(
      "Input to command is JSON of tool call arguments."
    ),
    ["PostToolUse" /* PostToolUse */]: t(
      'Input to command is JSON with fields "inputs" (tool call arguments) and "response" (tool call response).'
    ),
    ["PostToolUseFailure" /* PostToolUseFailure */]: t(
      "Input to command is JSON with tool_name, tool_input, tool_use_id, error, error_type, is_interrupt, and is_timeout."
    ),
    ["PostToolBatch" /* PostToolBatch */]: t(
      "Input to command is JSON with tool_calls, an array of resolved tool calls containing tool_name, tool_input, tool_use_id, and tool_response."
    ),
    ["Notification" /* Notification */]: t(
      "Input to command is JSON with notification message and type."
    ),
    ["InstructionsLoaded" /* InstructionsLoaded */]: t(
      "Input to command is JSON with file_path, memory_type, load_reason, and optional trigger_file_path and parent_file_path."
    ),
    ["UserPromptSubmit" /* UserPromptSubmit */]: t(
      "Input to command is JSON with original user prompt text."
    ),
    ["UserPromptExpansion" /* UserPromptExpansion */]: t(
      "Input to command is JSON with command_name, command_args, and expanded prompt text."
    ),
    ["SessionStart" /* SessionStart */]: t(
      "Input to command is JSON with session start source."
    ),
    ["SessionEnd" /* SessionEnd */]: t(
      "Input to command is JSON with session end reason."
    ),
    ["SubagentStart" /* SubagentStart */]: t(
      "Input to command is JSON with agent_id and agent_type."
    ),
    ["SubagentStop" /* SubagentStop */]: t(
      "Input to command is JSON with agent_id, agent_type, and agent_transcript_path."
    ),
    ["PreCompact" /* PreCompact */]: t(
      "Input to command is JSON with compaction details."
    ),
    ["PostCompact" /* PostCompact */]: t(
      "Input to command is JSON with trigger (manual/auto) and compact_summary. Output is ignored for control purposes."
    ),
    ["StopFailure" /* StopFailure */]: t(
      "Input to command is JSON with error (rate_limit, authentication_failed, billing_error, invalid_request, server_error, max_output_tokens, unknown) and optional error_details. Fire-and-forget: output and exit status are ignored."
    ),
    ["PermissionRequest" /* PermissionRequest */]: t(
      "Input to command is JSON with tool_name, tool_input, and tool_use_id. Output JSON with hookSpecificOutput containing decision to allow or deny."
    ),
    ["PermissionDenied" /* PermissionDenied */]: t(
      "Input to command is JSON with tool_name, tool_input, tool_use_id, and reason."
    ),
    ["TodoCreated" /* TodoCreated */]: t(
      "Input to command is JSON with todo_id, todo_content, todo_status, all_todos, and phase. In validation, output JSON with decision (allow/block/deny) and reason. In postWrite, block/deny is ignored."
    ),
    ["TodoCompleted" /* TodoCompleted */]: t(
      "Input to command is JSON with todo_id, todo_content, previous_status, all_todos, and phase. In validation, output JSON with decision (allow/block/deny) and reason. In postWrite, block/deny is ignored."
    )
  };
  return descriptions[eventName] || "";
}
__name(getHookDescription, "getHookDescription");
function getTranslatedSourceDisplayMap() {
  return {
    ["project" /* Project */]: t("Local Settings"),
    ["user" /* User */]: t("User Settings"),
    ["system" /* System */]: t("System Settings"),
    ["extensions" /* Extensions */]: t("Extensions"),
    ["session" /* Session */]: t("Session (temporary)")
  };
}
__name(getTranslatedSourceDisplayMap, "getTranslatedSourceDisplayMap");
var DISPLAY_HOOK_EVENTS = Object.values(HookEventName);
function supportsMatchers(eventName) {
  return hookEventSupportsMatcher(eventName);
}
__name(supportsMatchers, "supportsMatchers");
function createEmptyHookEventInfo(eventName) {
  return {
    event: eventName,
    shortDescription: getHookShortDescription(eventName),
    description: getHookDescription(eventName),
    exitCodes: getHookExitCodes(eventName),
    matcherGroups: []
  };
}
__name(createEmptyHookEventInfo, "createEmptyHookEventInfo");

// packages/cli/src/ui/components/hooks/matcherGrouping.ts
init_esbuild_shims();
function normalizeMatcher(matcher) {
  const trimmed = matcher?.trim();
  return trimmed ? trimmed : "*";
}
__name(normalizeMatcher, "normalizeMatcher");
function addConfigToMatcherGroup(hookInfo, matcher, sequential, configInfo, groupByMatcher = true) {
  const normalizedMatcher = groupByMatcher ? normalizeMatcher(matcher) : "*";
  const normalizedSequential = sequential ?? false;
  const normalizedConfig = {
    ...configInfo,
    matcher: normalizedMatcher,
    sequential: normalizedSequential
  };
  let group = hookInfo.matcherGroups.find(
    (candidate) => candidate.matcher === normalizedMatcher
  );
  if (!group) {
    group = {
      matcher: normalizedMatcher,
      sequential: normalizedSequential,
      configs: []
    };
    hookInfo.matcherGroups.push(group);
  } else if (normalizedSequential) {
    group.sequential = true;
  }
  group.configs.push(normalizedConfig);
}
__name(addConfigToMatcherGroup, "addConfigToMatcherGroup");
function getAllConfigs(hookInfo) {
  return hookInfo.matcherGroups.flatMap((group) => group.configs);
}
__name(getAllConfigs, "getAllConfigs");

// packages/cli/src/ui/commands/hooksCommand.ts
function formatHookSource(source) {
  switch (source) {
    case "project":
      return t("Project");
    case "user":
      return t("User");
    case "system":
      return t("System");
    case "extensions":
      return t("Extension");
    case "session":
      return t("Session (temporary)");
    default:
      return source;
  }
}
__name(formatHookSource, "formatHookSource");
var listCommand = {
  name: "list",
  get description() {
    return t("List all configured hooks");
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive", "non_interactive", "acp"],
  action: /* @__PURE__ */ __name(async (context, _args) => {
    const { config } = context.services;
    if (!config) {
      return {
        type: "message",
        messageType: "error",
        content: t("Config not loaded.")
      };
    }
    const hookSystem = config.getHookSystem();
    if (!hookSystem) {
      return {
        type: "message",
        messageType: "info",
        content: t(
          "Hooks are not enabled. Enable hooks in settings to use this feature."
        )
      };
    }
    const registry = hookSystem.getRegistry();
    const configHooks = registry.getAllHooks();
    const sessionId = config.getSessionId();
    const sessionHooksManager = hookSystem.getSessionHooksManager();
    const sessionHooks = sessionId ? sessionHooksManager.getAllSessionHooks(sessionId) : [];
    const totalHooks = configHooks.length + sessionHooks.length;
    if (totalHooks === 0) {
      return {
        type: "message",
        messageType: "info",
        content: t(
          "No hooks configured. Add hooks in your settings.json file or invoke a skill with hooks."
        )
      };
    }
    const hooksByEvent = /* @__PURE__ */ new Map();
    const addHook = /* @__PURE__ */ __name((eventName, matcher, hook) => {
      const matcherKey = supportsMatchers(eventName) ? matcher : "*";
      let matcherMap = hooksByEvent.get(eventName);
      if (!matcherMap) {
        matcherMap = /* @__PURE__ */ new Map();
        hooksByEvent.set(eventName, matcherMap);
      }
      let bucket = matcherMap.get(matcherKey);
      if (!bucket) {
        bucket = [];
        matcherMap.set(matcherKey, bucket);
      }
      bucket.push(hook);
    }, "addHook");
    const extractName = /* @__PURE__ */ __name((config2) => config2.name || (config2.type === "command" ? config2.command : void 0) || (config2.type === "http" ? config2.url : void 0) || "unnamed", "extractName");
    for (const hook of configHooks) {
      const configHook = hook;
      const config2 = configHook.config;
      addHook(configHook.eventName, normalizeMatcher(configHook.matcher), {
        name: extractName(config2),
        source: formatHookSource(configHook.source)
      });
    }
    for (const hook of sessionHooks) {
      const sessionHook = hook;
      const config2 = sessionHook.config;
      addHook(sessionHook.eventName, normalizeMatcher(sessionHook.matcher), {
        name: extractName(config2),
        source: formatHookSource("session")
      });
    }
    let output = `**Configured Hooks (${totalHooks} total)**

`;
    for (const [eventName, matcherMap] of hooksByEvent) {
      output += `### ${eventName}

`;
      const useMatchers = supportsMatchers(eventName);
      if (useMatchers) {
        for (const [matcher, hookList] of matcherMap) {
          output += `#### ${t("Matcher:")} ${matcher}
`;
          for (const hook of hookList) {
            output += `- **${hook.name}** [${hook.source}]
`;
          }
          output += "\n";
        }
      } else {
        for (const hookList of matcherMap.values()) {
          for (const hook of hookList) {
            output += `- **${hook.name}** [${hook.source}]
`;
          }
        }
        output += "\n";
      }
    }
    return {
      type: "message",
      messageType: "info",
      content: output
    };
  }, "action")
};
var hooksCommand = {
  name: "hooks",
  get description() {
    return t("Manage Qwen Code hooks");
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive", "non_interactive", "acp"],
  action: /* @__PURE__ */ __name(async (context, args) => {
    const executionMode = context.executionMode ?? "interactive";
    if (executionMode === "interactive") {
      return {
        type: "dialog",
        dialog: "hooks"
      };
    }
    const result = await listCommand.action?.(context, args);
    return result ?? { type: "message", messageType: "info", content: "" };
  }, "action")
};

// packages/cli/src/ui/commands/ideCommand.ts
init_esbuild_shims();
import path8 from "node:path";
function getIdeStatusMessage(ideClient) {
  const connection = ideClient.getConnectionStatus();
  switch (connection.status) {
    case "connected" /* Connected */:
      return {
        messageType: "info",
        content: `\u2713 Connected to ${ideClient.getDetectedIdeDisplayName()}`
      };
    case "connecting" /* Connecting */:
      return {
        messageType: "info",
        content: `\u25D0 Connecting...`
      };
    default: {
      let content = `\u2717 Disconnected`;
      if (connection?.details) {
        content += `: ${connection.details}`;
      }
      return {
        messageType: "error",
        content
      };
    }
  }
}
__name(getIdeStatusMessage, "getIdeStatusMessage");
function formatFileList(openFiles) {
  const basenameCounts = /* @__PURE__ */ new Map();
  for (const file of openFiles) {
    const basename3 = path8.basename(file.path);
    basenameCounts.set(basename3, (basenameCounts.get(basename3) || 0) + 1);
  }
  const fileList = openFiles.map((file) => {
    const basename3 = path8.basename(file.path);
    const isDuplicate = (basenameCounts.get(basename3) || 0) > 1;
    const parentDir = path8.basename(path8.dirname(file.path));
    const displayName = isDuplicate ? `${basename3} (/${parentDir})` : basename3;
    return `  - ${displayName}${file.isActive ? " (active)" : ""}`;
  }).join("\n");
  const infoMessage2 = `
(Note: The file list is limited to a number of recently accessed files within your workspace and only includes local files on disk)`;
  return `

Open files:
${fileList}
${infoMessage2}`;
}
__name(formatFileList, "formatFileList");
async function getIdeStatusMessageWithFiles(ideClient) {
  const connection = ideClient.getConnectionStatus();
  switch (connection.status) {
    case "connected" /* Connected */: {
      let content = `\u2713 Connected to ${ideClient.getDetectedIdeDisplayName()}`;
      const context = ideContextStore.get();
      const openFiles = context?.workspaceState?.openFiles;
      if (openFiles && openFiles.length > 0) {
        content += formatFileList(openFiles);
      }
      return {
        messageType: "info",
        content
      };
    }
    case "connecting" /* Connecting */:
      return {
        messageType: "info",
        content: `\u25D0 Connecting...`
      };
    default: {
      let content = `\u2717 Disconnected`;
      if (connection?.details) {
        content += `: ${connection.details}`;
      }
      return {
        messageType: "error",
        content
      };
    }
  }
}
__name(getIdeStatusMessageWithFiles, "getIdeStatusMessageWithFiles");
async function setIdeModeAndSyncConnection(config, value) {
  config.setIdeMode(value);
  const ideClient = await IdeClient.getInstance();
  if (value) {
    await ideClient.connect();
    logIdeConnection(config, new IdeConnectionEvent("session" /* SESSION */));
  } else {
    await ideClient.disconnect();
  }
}
__name(setIdeModeAndSyncConnection, "setIdeModeAndSyncConnection");
var ideCommand = /* @__PURE__ */ __name(async () => {
  const ideClient = await IdeClient.getInstance();
  const currentIDE = ideClient.getCurrentIde();
  if (!currentIDE) {
    return {
      name: "ide",
      get description() {
        return t("manage IDE integration");
      },
      kind: "built-in" /* BUILT_IN */,
      supportedModes: ["interactive"],
      action: /* @__PURE__ */ __name(() => ({
        type: "message",
        messageType: "error",
        content: t(
          "IDE integration is not supported in your current environment. To use this feature, run Qwen Code in one of these supported IDEs: VS Code or VS Code forks."
        )
      }), "action")
    };
  }
  const ideSlashCommand = {
    name: "ide",
    get description() {
      return t("manage IDE integration");
    },
    kind: "built-in" /* BUILT_IN */,
    supportedModes: ["interactive"],
    subCommands: []
  };
  const statusCommand = {
    name: "status",
    get description() {
      return t("check status of IDE integration");
    },
    kind: "built-in" /* BUILT_IN */,
    supportedModes: ["interactive"],
    action: /* @__PURE__ */ __name(async () => {
      const { messageType, content } = await getIdeStatusMessageWithFiles(ideClient);
      return {
        type: "message",
        messageType,
        content
      };
    }, "action")
  };
  const installCommand2 = {
    name: "install",
    get description() {
      const ideName = ideClient.getDetectedIdeDisplayName() ?? "IDE";
      return t("install required IDE companion for {{ideName}}", {
        ideName
      });
    },
    kind: "built-in" /* BUILT_IN */,
    supportedModes: ["interactive"],
    action: /* @__PURE__ */ __name(async (context) => {
      const installer = getIdeInstaller(currentIDE);
      const isSandBox = !!process.env["SANDBOX"];
      if (isSandBox) {
        context.ui.addItem(
          {
            type: "info",
            text: `IDE integration needs to be installed on the host. If you have already installed it, you can directly connect the ide`
          },
          Date.now()
        );
        return;
      }
      if (!installer) {
        const ideName = ideClient.getDetectedIdeDisplayName();
        context.ui.addItem(
          {
            type: "error",
            text: `Automatic installation is not supported for ${ideName}. Please install the '${QWEN_CODE_COMPANION_EXTENSION_NAME}' extension manually from the marketplace.`
          },
          Date.now()
        );
        return;
      }
      context.ui.addItem(
        {
          type: "info",
          text: `Installing IDE companion...`
        },
        Date.now()
      );
      const result = await installer.install();
      context.ui.addItem(
        {
          type: result.success ? "info" : "error",
          text: result.message
        },
        Date.now()
      );
      if (result.success) {
        context.services.settings.setValue(
          "User" /* User */,
          "ide.enabled",
          true
        );
        for (let i = 0; i < 10; i++) {
          await setIdeModeAndSyncConnection(context.services.config, true);
          if (ideClient.getConnectionStatus().status === "connected" /* Connected */) {
            break;
          }
          await new Promise((resolve5) => setTimeout(resolve5, 500));
        }
        const { messageType, content } = getIdeStatusMessage(ideClient);
        if (messageType === "error") {
          context.ui.addItem(
            {
              type: messageType,
              text: `Failed to automatically enable IDE integration. To fix this, run the CLI in a new terminal window.`
            },
            Date.now()
          );
        } else {
          context.ui.addItem(
            {
              type: messageType,
              text: content
            },
            Date.now()
          );
        }
      }
    }, "action")
  };
  const enableCommand = {
    name: "enable",
    get description() {
      return t("enable IDE integration");
    },
    kind: "built-in" /* BUILT_IN */,
    supportedModes: ["interactive"],
    action: /* @__PURE__ */ __name(async (context) => {
      context.services.settings.setValue(
        "User" /* User */,
        "ide.enabled",
        true
      );
      await setIdeModeAndSyncConnection(context.services.config, true);
      const { messageType, content } = getIdeStatusMessage(ideClient);
      context.ui.addItem(
        {
          type: messageType,
          text: content
        },
        Date.now()
      );
    }, "action")
  };
  const disableCommand = {
    name: "disable",
    get description() {
      return t("disable IDE integration");
    },
    kind: "built-in" /* BUILT_IN */,
    supportedModes: ["interactive"],
    action: /* @__PURE__ */ __name(async (context) => {
      context.services.settings.setValue(
        "User" /* User */,
        "ide.enabled",
        false
      );
      await setIdeModeAndSyncConnection(context.services.config, false);
      const { messageType, content } = getIdeStatusMessage(ideClient);
      context.ui.addItem(
        {
          type: messageType,
          text: content
        },
        Date.now()
      );
    }, "action")
  };
  const { status } = ideClient.getConnectionStatus();
  const isConnected = status === "connected" /* Connected */;
  if (isConnected) {
    ideSlashCommand.subCommands = [statusCommand, disableCommand];
  } else {
    ideSlashCommand.subCommands = [
      enableCommand,
      statusCommand,
      installCommand2
    ];
  }
  return ideSlashCommand;
}, "ideCommand");

// packages/cli/src/ui/commands/importConfigCommand.ts
init_esbuild_shims();

// packages/cli/src/config/claudeMcpImport.ts
init_esbuild_shims();
import * as fs8 from "node:fs";
import * as os4 from "node:os";
import * as path9 from "node:path";
var import_strip_json_comments = __toESM(require_strip_json_comments(), 1);
function isRecord(value) {
  return !!value && typeof value === "object" && !Array.isArray(value);
}
__name(isRecord, "isRecord");
function isReadableConfigError(error) {
  return !!error && typeof error === "object" && "code" in error;
}
__name(isReadableConfigError, "isReadableConfigError");
function isReservedServerName(name) {
  return name === "__proto__" || name === "constructor" || name === "prototype";
}
__name(isReservedServerName, "isReservedServerName");
function emptyServerRecord() {
  return /* @__PURE__ */ Object.create(null);
}
__name(emptyServerRecord, "emptyServerRecord");
function readJsonObject(filePath) {
  let raw;
  try {
    raw = fs8.readFileSync(filePath, "utf-8");
  } catch (error) {
    if (isReadableConfigError(error) && (error.code === "ENOENT" || error.code === "ENOTDIR")) {
      return { found: false };
    }
    return {
      found: true,
      error: `Failed to read ${filePath}: ${error instanceof Error ? error.message : String(error)}`
    };
  }
  if (!raw.trim()) {
    return { found: false };
  }
  let parsed;
  try {
    parsed = JSON.parse((0, import_strip_json_comments.default)(raw));
  } catch (error) {
    return {
      found: true,
      error: `Failed to parse ${filePath}: ${error instanceof Error ? error.message : String(error)}`
    };
  }
  if (!isRecord(parsed)) {
    return {
      found: true,
      error: `${filePath} must contain a JSON object`
    };
  }
  return { found: true, data: parsed };
}
__name(readJsonObject, "readJsonObject");
function copyMcpServers(value, sourcePath, servers, errors) {
  if (value === void 0) {
    return;
  }
  if (!isRecord(value)) {
    errors.push(`${sourcePath} has no "mcpServers" object`);
    return;
  }
  for (const [name, serverConfig] of Object.entries(value)) {
    if (!isRecord(serverConfig)) {
      errors.push(`${sourcePath}: server "${name}" is not an object - skipped`);
      continue;
    }
    servers[name] = normalizeClaudeMcpServer(serverConfig);
  }
}
__name(copyMcpServers, "copyMcpServers");
function normalizeProjectPath(projectPath) {
  return path9.resolve(projectPath);
}
__name(normalizeProjectPath, "normalizeProjectPath");
function getClaudeProjectSettings(projects, cwd) {
  if (!isRecord(projects)) {
    return void 0;
  }
  const normalizedCwd = normalizeProjectPath(cwd);
  for (const [projectPath, projectSettings] of Object.entries(projects)) {
    if (normalizeProjectPath(projectPath) === normalizedCwd && isRecord(projectSettings)) {
      return projectSettings;
    }
  }
  return void 0;
}
__name(getClaudeProjectSettings, "getClaudeProjectSettings");
function getClaudeCodeConfigPath(homeDir = os4.homedir()) {
  return path9.join(homeDir, ".claude.json");
}
__name(getClaudeCodeConfigPath, "getClaudeCodeConfigPath");
function getClaudeDesktopConfigPath(homeDir = os4.homedir(), platform3 = process.platform, env = process.env) {
  if (platform3 === "win32") {
    const appData = env["APPDATA"] ?? path9.win32.join(homeDir, "AppData", "Roaming");
    return path9.win32.join(appData, "Claude", "claude_desktop_config.json");
  }
  if (platform3 === "darwin") {
    return path9.join(
      homeDir,
      "Library",
      "Application Support",
      "Claude",
      "claude_desktop_config.json"
    );
  }
  return path9.join(homeDir, ".config", "Claude", "claude_desktop_config.json");
}
__name(getClaudeDesktopConfigPath, "getClaudeDesktopConfigPath");
function loadMcpServersFromSettingsFile(filePath, label, source) {
  const errors = [];
  const servers = emptyServerRecord();
  const parsed = readJsonObject(filePath);
  if (!parsed.found) {
    return {
      source,
      label,
      path: filePath,
      servers,
      errors,
      found: false
    };
  }
  if (!parsed.data) {
    return {
      source,
      label,
      path: filePath,
      servers,
      errors: parsed.error ? [parsed.error] : errors,
      found: true
    };
  }
  copyMcpServers(parsed.data["mcpServers"], filePath, servers, errors);
  return {
    source,
    label,
    path: filePath,
    servers,
    errors,
    found: true
  };
}
__name(loadMcpServersFromSettingsFile, "loadMcpServersFromSettingsFile");
function loadClaudeCodeJsonMcpServers(homeDir, cwd, scope) {
  const filePath = getClaudeCodeConfigPath(homeDir);
  const errors = [];
  const servers = emptyServerRecord();
  const parsed = readJsonObject(filePath);
  if (!parsed.found) {
    return {
      source: "claude-code",
      label: "Claude Code",
      path: filePath,
      servers,
      errors,
      found: false
    };
  }
  if (!parsed.data) {
    return {
      source: "claude-code",
      label: "Claude Code",
      path: filePath,
      servers,
      errors: parsed.error ? [parsed.error] : errors,
      found: true
    };
  }
  if (scope === "user") {
    copyMcpServers(parsed.data["mcpServers"], filePath, servers, errors);
  } else {
    const projectSettings = getClaudeProjectSettings(
      parsed.data["projects"],
      cwd
    );
    if (projectSettings) {
      copyMcpServers(
        projectSettings["mcpServers"],
        `${filePath} projects["${normalizeProjectPath(cwd)}"]`,
        servers,
        errors
      );
    }
  }
  return {
    source: "claude-code",
    label: "Claude Code",
    path: filePath,
    servers,
    errors,
    found: true
  };
}
__name(loadClaudeCodeJsonMcpServers, "loadClaudeCodeJsonMcpServers");
function loadClaudeCodeMcpSources(homeDir, cwd, scope) {
  const candidates = scope === "project" ? [
    loadMcpServersFromSettingsFile(
      path9.join(cwd, ".claude", "settings.json"),
      "Claude Code project settings",
      "claude-code"
    ),
    loadClaudeCodeJsonMcpServers(homeDir, cwd, scope)
  ] : [
    loadClaudeCodeJsonMcpServers(homeDir, cwd, scope),
    loadMcpServersFromSettingsFile(
      path9.join(homeDir, ".claude", "settings.json"),
      "Claude Code global settings",
      "claude-code"
    )
  ];
  const seen = /* @__PURE__ */ new Set();
  return candidates.filter((candidate) => {
    if (seen.has(candidate.path)) {
      return false;
    }
    seen.add(candidate.path);
    return true;
  });
}
__name(loadClaudeCodeMcpSources, "loadClaudeCodeMcpSources");
function loadClaudeDesktopMcpServers(homeDir, platform3, env) {
  const filePath = getClaudeDesktopConfigPath(homeDir, platform3, env);
  const errors = [];
  const servers = emptyServerRecord();
  const parsed = readJsonObject(filePath);
  if (!parsed.found) {
    return {
      source: "claude-desktop",
      label: "Claude Desktop",
      path: filePath,
      servers,
      errors,
      found: false
    };
  }
  if (!parsed.data) {
    return {
      source: "claude-desktop",
      label: "Claude Desktop",
      path: filePath,
      servers,
      errors: parsed.error ? [parsed.error] : errors,
      found: true
    };
  }
  copyMcpServers(parsed.data["mcpServers"], filePath, servers, errors);
  return {
    source: "claude-desktop",
    label: "Claude Desktop",
    path: filePath,
    servers,
    errors,
    found: true
  };
}
__name(loadClaudeDesktopMcpServers, "loadClaudeDesktopMcpServers");
function loadClaudeMcpSources(options) {
  const homeDir = options.homeDir ?? os4.homedir();
  const cwd = options.cwd ?? process.cwd();
  const platform3 = options.platform ?? process.platform;
  const env = options.env ?? process.env;
  const scope = options.scope ?? "user";
  const sources = options.source === "all" ? ["claude-code", "claude-desktop"] : [options.source];
  return sources.flatMap(
    (source) => source === "claude-code" ? loadClaudeCodeMcpSources(homeDir, cwd, scope) : [loadClaudeDesktopMcpServers(homeDir, platform3, env)]
  );
}
__name(loadClaudeMcpSources, "loadClaudeMcpSources");
function getSettingScope(settings, scope) {
  if (scope === "user") {
    return "User" /* User */;
  }
  if (settings.workspace.path === settings.user.path) {
    throw new Error(
      "Please use --scope user to edit settings in the home directory."
    );
  }
  return "Workspace" /* Workspace */;
}
__name(getSettingScope, "getSettingScope");
function addServerNamesFromRecord(value, names) {
  if (!isRecord(value)) {
    return;
  }
  for (const name of Object.keys(value)) {
    names.add(name);
  }
}
__name(addServerNamesFromRecord, "addServerNamesFromRecord");
function copyExistingServers(settings, settingScope) {
  const existingServers = settings.forScope(settingScope).settings.mcpServers;
  const existingNames = /* @__PURE__ */ new Set();
  if (existingServers === void 0) {
    addServerNamesFromRecord(settings.merged?.mcpServers, existingNames);
    return { nextServers: emptyServerRecord(), existingNames };
  }
  if (!isRecord(existingServers)) {
    throw new Error("Existing mcpServers setting must be an object.");
  }
  const copy = emptyServerRecord();
  for (const [name, serverConfig] of Object.entries(existingServers)) {
    copy[name] = serverConfig;
    existingNames.add(name);
  }
  addServerNamesFromRecord(settings.merged?.mcpServers, existingNames);
  return { nextServers: copy, existingNames };
}
__name(copyExistingServers, "copyExistingServers");
function importClaudeMcpServers(options) {
  const settingScope = getSettingScope(options.settings, options.scope);
  const { nextServers, existingNames } = copyExistingServers(
    options.settings,
    settingScope
  );
  const scanned = loadClaudeMcpSources(options);
  const imported = [];
  const skipped = [];
  const errors = scanned.flatMap((source) => source.errors);
  for (const source of scanned) {
    for (const [name, serverConfig] of Object.entries(source.servers)) {
      if (isReservedServerName(name)) {
        skipped.push({ name, source: source.label, reason: "reserved-name" });
        continue;
      }
      if (existingNames.has(name)) {
        skipped.push({ name, source: source.label, reason: "already-exists" });
        continue;
      }
      nextServers[name] = serverConfig;
      existingNames.add(name);
      imported.push({ name, source: source.label });
    }
  }
  if (imported.length > 0) {
    options.settings.setValue(settingScope, "mcpServers", nextServers);
  }
  return {
    scope: options.scope,
    settingScope,
    scanned,
    imported,
    skipped,
    errors
  };
}
__name(importClaudeMcpServers, "importClaudeMcpServers");

// packages/cli/src/ui/commands/importConfigCommand.ts
var SOURCE_ALIASES = {
  all: "all",
  claude: "claude-code",
  "claude-code": "claude-code",
  code: "claude-code",
  desktop: "claude-desktop",
  "claude-desktop": "claude-desktop"
};
function parseSource(value) {
  return SOURCE_ALIASES[value.toLowerCase()];
}
__name(parseSource, "parseSource");
function parseScope(value) {
  if (value === "user" || value === "project") {
    return value;
  }
  return void 0;
}
__name(parseScope, "parseScope");
function parseImportConfigArgs(args) {
  const tokens = args.trim().split(/\s+/).filter(Boolean);
  let source = "all";
  let sourceWasSet = false;
  let scope = "user";
  for (let i = 0; i < tokens.length; i++) {
    const token = tokens[i];
    if (token === "--help" || token === "-h" || token === "help") {
      return { source, sourceExplicit: sourceWasSet, scope, help: true };
    }
    if (token === "--from") {
      const value = tokens[++i];
      if (!value) {
        return {
          source,
          sourceExplicit: sourceWasSet,
          scope,
          help: false,
          error: t("Missing value for --from.")
        };
      }
      const parsed2 = parseSource(value);
      if (!parsed2) {
        return {
          source,
          sourceExplicit: sourceWasSet,
          scope,
          help: false,
          error: t("Unknown import source: {{source}}", { source: value })
        };
      }
      source = parsed2;
      sourceWasSet = true;
      continue;
    }
    if (token.startsWith("--from=")) {
      const value = token.slice("--from=".length);
      const parsed2 = parseSource(value);
      if (!parsed2) {
        return {
          source,
          sourceExplicit: sourceWasSet,
          scope,
          help: false,
          error: t("Unknown import source: {{source}}", { source: value })
        };
      }
      source = parsed2;
      sourceWasSet = true;
      continue;
    }
    if (token === "--scope" || token === "-s") {
      const value = tokens[++i];
      const parsed2 = value ? parseScope(value) : void 0;
      if (!parsed2) {
        return {
          source,
          sourceExplicit: sourceWasSet,
          scope,
          help: false,
          error: t('Expected --scope to be "user" or "project".')
        };
      }
      scope = parsed2;
      continue;
    }
    if (token.startsWith("--scope=")) {
      const value = token.slice("--scope=".length);
      const parsed2 = parseScope(value);
      if (!parsed2) {
        return {
          source,
          sourceExplicit: sourceWasSet,
          scope,
          help: false,
          error: t('Expected --scope to be "user" or "project".')
        };
      }
      scope = parsed2;
      continue;
    }
    const parsed = parseSource(token);
    if (parsed && !sourceWasSet) {
      source = parsed;
      sourceWasSet = true;
      continue;
    }
    return {
      source,
      sourceExplicit: sourceWasSet,
      scope,
      help: false,
      error: t("Unknown argument: {{arg}}", { arg: token })
    };
  }
  return { source, sourceExplicit: sourceWasSet, scope, help: false };
}
__name(parseImportConfigArgs, "parseImportConfigArgs");
function resolveImportSourceForScope(source, scope, sourceExplicit) {
  if (scope === "project" && source === "all" && !sourceExplicit) {
    return "claude-code";
  }
  return source;
}
__name(resolveImportSourceForScope, "resolveImportSourceForScope");
function usage() {
  return [
    t("Import MCP servers from Claude configs."),
    "",
    t(
      "Usage: /import-config [all|claude-code|claude-desktop] [--scope user|project]"
    ),
    "",
    t("Examples:"),
    "  /import-config",
    "  /import-config claude-code",
    "  /import-config claude-desktop --scope user",
    "  /import-config --scope project"
  ].join("\n");
}
__name(usage, "usage");
function formatNameList(names) {
  if (names.length <= 6) {
    return names.join(", ");
  }
  return `${names.slice(0, 6).join(", ")} +${names.length - 6} more`;
}
__name(formatNameList, "formatNameList");
function formatClaudeMcpImportResult(result) {
  const target = result.scope === "user" ? "user" : "project";
  const importedNames = result.imported.map((entry) => entry.name);
  const skippedExisting = result.skipped.filter((entry) => entry.reason === "already-exists").map((entry) => entry.name);
  const skippedReserved = result.skipped.filter((entry) => entry.reason === "reserved-name").map((entry) => entry.name);
  const checkedPaths = result.scanned.map((entry) => entry.path);
  const lines = [];
  if (result.imported.length > 0) {
    lines.push(
      t("Imported {{count}} MCP server(s) to {{scope}} settings: {{names}}", {
        count: String(result.imported.length),
        scope: target,
        names: formatNameList(importedNames)
      })
    );
  } else {
    lines.push(
      t("No new Claude MCP servers imported into {{scope}} settings.", {
        scope: target
      })
    );
  }
  if (skippedExisting.length > 0) {
    lines.push(
      t("Skipped existing server(s): {{names}}", {
        names: formatNameList([...new Set(skippedExisting)])
      })
    );
  }
  if (skippedReserved.length > 0) {
    lines.push(
      t("Skipped unsupported server name(s): {{names}}", {
        names: formatNameList([...new Set(skippedReserved)])
      })
    );
  }
  if (result.errors.length > 0) {
    lines.push("", t("Warnings:"));
    lines.push(...result.errors.map((error) => `  - ${error}`));
  }
  if (result.imported.length === 0 && result.skipped.length === 0 && result.errors.length === 0) {
    lines.push("", t("Checked:"));
    lines.push(...checkedPaths.map((filePath) => `  - ${filePath}`));
  }
  const messageType = result.errors.length > 0 || result.skipped.length > 0 ? "warning" : "info";
  return {
    type: "message",
    messageType,
    content: lines.join("\n")
  };
}
__name(formatClaudeMcpImportResult, "formatClaudeMcpImportResult");
var importConfigCommand = {
  name: "import-config",
  get description() {
    return t("Import MCP servers from Claude configs");
  },
  argumentHint: "[all|claude-code|claude-desktop] [--scope user|project]",
  examples: [
    "/import-config",
    "/import-config claude-code",
    "/import-config claude-desktop --scope user",
    "/import-config --scope project"
  ],
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive", "non_interactive", "acp"],
  action: /* @__PURE__ */ __name(async (context, args) => {
    const parsed = parseImportConfigArgs(args);
    if (parsed.help) {
      return {
        type: "message",
        messageType: "info",
        content: usage()
      };
    }
    if (parsed.error) {
      return {
        type: "message",
        messageType: "error",
        content: `${parsed.error}

${usage()}`
      };
    }
    try {
      const importSource = resolveImportSourceForScope(
        parsed.source,
        parsed.scope,
        parsed.sourceExplicit
      );
      const result = importClaudeMcpServers({
        source: importSource,
        scope: parsed.scope,
        settings: context.services.settings,
        cwd: context.services.config?.getTargetDir() ?? process.cwd()
      });
      return formatClaudeMcpImportResult(result);
    } catch (error) {
      return {
        type: "message",
        messageType: "error",
        content: error instanceof Error ? error.message : t("Import failed: {{error}}", {
          error: String(error)
        })
      };
    }
  }, "action"),
  completion: /* @__PURE__ */ __name(async (_context, partialArg) => {
    const current = partialArg.trimStart();
    const candidates = [
      "all",
      "claude-code",
      "claude-desktop",
      "--scope user",
      "--scope project"
    ];
    return candidates.filter((candidate) => candidate.startsWith(current));
  }, "completion")
};

// packages/cli/src/ui/commands/initCommand.ts
init_esbuild_shims();
import * as fs9 from "node:fs";
import * as path10 from "node:path";
var import_react2 = __toESM(require_react(), 1);
var initCommand = {
  name: "init",
  get description() {
    return t("Analyzes the project and creates a tailored QWEN.md file.");
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive", "non_interactive", "acp"],
  action: /* @__PURE__ */ __name(async (context, _args) => {
    if (!context.services.config) {
      return {
        type: "message",
        messageType: "error",
        content: t("Configuration not available.")
      };
    }
    const targetDir = context.services.config.getTargetDir();
    const contextFileName = getCurrentGeminiMdFilename();
    const contextFilePath = path10.join(targetDir, contextFileName);
    try {
      if (fs9.existsSync(contextFilePath)) {
        try {
          const existing = fs9.readFileSync(contextFilePath, "utf8");
          if (existing && existing.trim().length > 0) {
            if (!context.overwriteConfirmed) {
              return {
                type: "confirm_action",
                // TODO: Move to .tsx file to use JSX syntax instead of React.createElement
                // For now, using React.createElement to maintain .ts compatibility for PR review
                prompt: import_react2.default.createElement(
                  Text,
                  null,
                  `A ${contextFileName} file already exists in this directory. Do you want to regenerate it?`
                ),
                originalInvocation: {
                  raw: context.invocation?.raw || "/init"
                }
              };
            }
          }
        } catch {
        }
      }
      try {
        fs9.writeFileSync(contextFilePath, "", "utf8");
        context.ui.addItem(
          {
            type: "info",
            text: `Empty ${contextFileName} created. Now analyzing the project to populate it.`
          },
          Date.now()
        );
      } catch (err) {
        return {
          type: "message",
          messageType: "error",
          content: `Failed to create ${contextFileName}: ${err instanceof Error ? err.message : String(err)}`
        };
      }
    } catch (error) {
      return {
        type: "message",
        messageType: "error",
        content: `Unexpected error preparing ${contextFileName}: ${error instanceof Error ? error.message : String(error)}`
      };
    }
    return {
      type: "submit_prompt",
      content: `
You are Qwen Code, an interactive CLI agent. Analyze the current directory and generate a comprehensive ${contextFileName} file to be used as instructional context for future interactions.

**Analysis Process:**

1.  **Initial Exploration:**
    *   Start by listing the files and directories to get a high-level overview of the structure.
    *   Read the README file (e.g., \`README.md\`, \`README.txt\`) if it exists. This is often the best place to start.

2.  **Iterative Deep Dive (up to 10 files):**
    *   Based on your initial findings, select a few files that seem most important (e.g., configuration files, main source files, documentation).
    *   Read them. As you learn more, refine your understanding and decide which files to read next. You don't need to decide all 10 files at once. Let your discoveries guide your exploration.

3.  **Identify Project Type:**
    *   **Code Project:** Look for clues like \`package.json\`, \`requirements.txt\`, \`pom.xml\`, \`go.mod\`, \`Cargo.toml\`, \`build.gradle\`, or a \`src\` directory. If you find them, this is likely a software project.
    *   **Non-Code Project:** If you don't find code-related files, this might be a directory for documentation, research papers, notes, or something else.

**${contextFileName} Content Generation:**

**For a Code Project:**

*   **Project Overview:** Write a clear and concise summary of the project's purpose, main technologies, and architecture.
*   **Building and Running:** Document the key commands for building, running, and testing the project. Infer these from the files you've read (e.g., \`scripts\` in \`package.json\`, \`Makefile\`, etc.). If you can't find explicit commands, provide a placeholder with a TODO.
*   **Development Conventions:** Describe any coding styles, testing practices, or contribution guidelines you can infer from the codebase.

**For a Non-Code Project:**

*   **Directory Overview:** Describe the purpose and contents of the directory. What is it for? What kind of information does it hold?
*   **Key Files:** List the most important files and briefly explain what they contain.
*   **Usage:** Explain how the contents of this directory are intended to be used.

**Final Output:**

Write the complete content to the \`${contextFileName}\` file. The output must be well-formatted Markdown.
`
    };
  }, "action")
};

// packages/cli/src/ui/commands/languageCommand.ts
init_esbuild_shims();
var debugLogger11 = createDebugLogger("LANGUAGE_COMMAND");
function getCurrentOutputLanguage(context) {
  const settingValue = context?.services?.settings?.merged?.general?.outputLanguage || OUTPUT_LANGUAGE_AUTO;
  const resolved = resolveOutputLanguage(settingValue);
  return { setting: settingValue, resolved };
}
__name(getCurrentOutputLanguage, "getCurrentOutputLanguage");
function parseUiLanguageArg(input) {
  return resolveSupportedLanguage(input) ?? null;
}
__name(parseUiLanguageArg, "parseUiLanguageArg");
function formatUiLanguageDisplay(lang) {
  const option = SUPPORTED_LANGUAGES.find((o) => o.code === lang);
  if (!option) return lang;
  return option.nativeName && option.nativeName !== option.fullName ? `${option.nativeName} (${option.fullName}) [${option.id}]` : `${option.fullName} [${option.id}]`;
}
__name(formatUiLanguageDisplay, "formatUiLanguageDisplay");
async function setUiLanguage(context, lang) {
  const { services } = context;
  if (!services.config) {
    return {
      type: "message",
      messageType: "error",
      content: t("Configuration not available.")
    };
  }
  await setLanguageAsync(lang);
  if (services.settings?.setValue) {
    try {
      services.settings.setValue("User" /* User */, "general.language", lang);
    } catch (error) {
      debugLogger11.warn("Failed to save language setting:", error);
    }
  }
  context.ui.reloadCommands();
  return {
    type: "message",
    messageType: "info",
    content: t("UI language changed to {{lang}}", {
      lang: formatUiLanguageDisplay(lang)
    })
  };
}
__name(setUiLanguage, "setUiLanguage");
async function setOutputLanguage(context, language) {
  try {
    const isAuto = isAutoLanguage(language);
    const resolved = resolveOutputLanguage(language);
    const settingValue = isAuto ? OUTPUT_LANGUAGE_AUTO : resolved;
    writeOutputLanguageAndRegisterPath(settingValue, context.services.config);
    if (context.services.settings?.setValue) {
      try {
        context.services.settings.setValue(
          "User" /* User */,
          "general.outputLanguage",
          settingValue
        );
      } catch (error) {
        debugLogger11.warn("Failed to save output language setting:", error);
      }
    }
    const config = context.services.config;
    if (config) {
      try {
        await config.refreshHierarchicalMemory();
        await config.getGeminiClient().refreshSystemInstruction();
      } catch (error) {
        debugLogger11.warn(
          "Failed to apply output language to running session:",
          error
        );
      }
    }
    const displayLang = isAuto ? `${t("Auto (detect from system)")} \u2192 ${resolved}` : resolved;
    return {
      type: "message",
      messageType: "info",
      content: t("LLM output language set to {{lang}}", { lang: displayLang })
    };
  } catch (error) {
    return {
      type: "message",
      messageType: "error",
      content: t(
        "Failed to generate LLM output language rule file: {{error}}",
        {
          error: error instanceof Error ? error.message : String(error)
        }
      )
    };
  }
}
__name(setOutputLanguage, "setOutputLanguage");
var languageCommand = {
  name: "language",
  get description() {
    return t("View or change the language setting");
  },
  argumentHint: "ui|output <language>",
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive", "non_interactive", "acp"],
  action: /* @__PURE__ */ __name(async (context, args) => {
    if (!context.services.config) {
      return {
        type: "message",
        messageType: "error",
        content: t("Configuration not available.")
      };
    }
    const trimmedArgs = args.trim();
    if (trimmedArgs) {
      const [firstArg, ...rest] = trimmedArgs.split(/\s+/);
      const subCommandName = firstArg.toLowerCase();
      const subArgs = rest.join(" ");
      if (subCommandName === "ui" || subCommandName === "output") {
        const subCommand = languageCommand.subCommands?.find(
          (s) => s.name === subCommandName
        );
        if (subCommand?.action) {
          return subCommand.action(
            context,
            subArgs
          );
        }
      }
      const targetLang = parseUiLanguageArg(trimmedArgs);
      if (targetLang) {
        return setUiLanguage(context, targetLang);
      }
      return {
        type: "message",
        messageType: "error",
        content: [
          t("Invalid command. Available subcommands:"),
          `  - /language ui [${getSupportedLanguageIds()}] - ${t("Set UI language")}`,
          `  - /language output <language> - ${t("Set LLM output language")}`
        ].join("\n")
      };
    }
    const currentUiLang = getCurrentLanguage();
    const { setting: outputSetting, resolved: outputResolved } = getCurrentOutputLanguage(context);
    const outputLangDisplay = isAutoLanguage(outputSetting) ? `${t("Auto (detect from system)")} \u2192 ${outputResolved}` : outputResolved;
    return {
      type: "message",
      messageType: "info",
      content: [
        t("Current UI language: {{lang}}", {
          lang: formatUiLanguageDisplay(currentUiLang)
        }),
        t("Current LLM output language: {{lang}}", { lang: outputLangDisplay }),
        "",
        t("Available subcommands:"),
        `  /language ui [${getSupportedLanguageIds()}] - ${t("Set UI language")}`,
        `  /language output <language> - ${t("Set LLM output language")}`
      ].join("\n")
    };
  }, "action"),
  subCommands: [
    // /language ui subcommand
    {
      name: "ui",
      get description() {
        return t("Set UI language");
      },
      kind: "built-in" /* BUILT_IN */,
      supportedModes: ["interactive", "non_interactive", "acp"],
      action: /* @__PURE__ */ __name(async (context, args) => {
        const trimmedArgs = args.trim();
        if (!trimmedArgs) {
          return {
            type: "message",
            messageType: "info",
            content: [
              t("Set UI language"),
              "",
              t("Usage: /language ui [{{options}}]", {
                options: getSupportedLanguageIds()
              }),
              "",
              t("Available options:"),
              ...SUPPORTED_LANGUAGES.map(
                (o) => `  - ${o.id}: ${o.nativeName || o.fullName}`
              ),
              "",
              t(
                "To request additional UI language packs, please open an issue on GitHub."
              )
            ].join("\n")
          };
        }
        const targetLang = parseUiLanguageArg(trimmedArgs);
        if (!targetLang) {
          return {
            type: "message",
            messageType: "error",
            content: t("Invalid language. Available: {{options}}", {
              options: getSupportedLanguageIds(",")
            })
          };
        }
        return setUiLanguage(context, targetLang);
      }, "action"),
      // Nested subcommands for each supported language (e.g., /language ui zh-CN)
      subCommands: SUPPORTED_LANGUAGES.map(
        (lang) => ({
          name: lang.id,
          get description() {
            return t("Set UI language to {{name}}", {
              name: lang.nativeName || lang.fullName
            });
          },
          kind: "built-in" /* BUILT_IN */,
          supportedModes: ["interactive", "non_interactive", "acp"],
          action: /* @__PURE__ */ __name(async (context, args) => {
            if (args.trim()) {
              return {
                type: "message",
                messageType: "error",
                content: t(
                  "Language subcommands do not accept additional arguments."
                )
              };
            }
            return setUiLanguage(context, lang.code);
          }, "action")
        })
      )
    },
    // /language output subcommand
    {
      name: "output",
      get description() {
        return t("Set LLM output language");
      },
      kind: "built-in" /* BUILT_IN */,
      supportedModes: ["interactive", "non_interactive", "acp"],
      action: /* @__PURE__ */ __name(async (context, args) => {
        const trimmedArgs = args.trim();
        if (!trimmedArgs) {
          return {
            type: "message",
            messageType: "info",
            content: [
              t("Set LLM output language"),
              "",
              t("Usage: /language output <language>"),
              `  ${t("Example: /language output \u4E2D\u6587")}`,
              `  ${t("Example: /language output English")}`,
              `  ${t("Example: /language output \u65E5\u672C\u8A9E")}`
            ].join("\n")
          };
        }
        return setOutputLanguage(context, trimmedArgs);
      }, "action")
    }
  ]
};

// packages/cli/src/ui/commands/mcpCommand.ts
init_esbuild_shims();
var mcpCommand = {
  name: "mcp",
  get description() {
    return t("Open MCP management dialog");
  },
  argumentHint: "desc|nodesc|schema",
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive"],
  action: /* @__PURE__ */ __name(async (_context, args = "") => {
    const [subcommand, serverName] = args.trim().split(/\s+/);
    if (subcommand === "auth" || subcommand === "noauth") {
      return {
        type: "message",
        messageType: "warning",
        content: serverName ? t(
          "MCP OAuth is now managed in the /mcp dialog. Open /mcp, select '{{serverName}}', then use the Auth actions there.",
          { serverName }
        ) : t(
          "MCP OAuth is now managed in the /mcp dialog. Open /mcp, select a server, then use the Auth actions there."
        )
      };
    }
    return {
      type: "dialog",
      dialog: "mcp"
    };
  }, "action")
};

// packages/cli/src/ui/commands/dreamCommand.ts
init_esbuild_shims();
import * as path11 from "node:path";
var dreamCommand = {
  name: "dream",
  get description() {
    return t("Consolidate managed auto-memory topic files.");
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive", "acp"],
  action: /* @__PURE__ */ __name(async (context) => {
    const config = context.services.config;
    if (!config) {
      return {
        type: "message",
        messageType: "error",
        content: t("Config not loaded.")
      };
    }
    try {
      const projectRoot = config.getProjectRoot();
      const memoryRoot = getAutoMemoryRoot(projectRoot);
      const transcriptDir = path11.join(
        new Storage(projectRoot).getProjectDir(),
        "chats"
      );
      const prompt = config.getMemoryManager().buildConsolidationPrompt(memoryRoot, transcriptDir);
      const recordDream = /* @__PURE__ */ __name(async () => config.getMemoryManager().writeDreamManualRun(projectRoot, config.getSessionId()), "recordDream");
      if (context.executionMode === "acp") {
        recordDream().catch(() => {
        });
        return { type: "submit_prompt", content: prompt };
      }
      return {
        type: "submit_prompt",
        content: prompt,
        onComplete: recordDream
      };
    } catch (error) {
      return {
        type: "message",
        messageType: "error",
        content: t("Failed to process /dream: {{message}}", {
          message: error instanceof Error ? error.message : String(error)
        })
      };
    }
  }, "action")
};

// packages/cli/src/ui/commands/forgetCommand.ts
init_esbuild_shims();
var forgetCommand = {
  name: "forget",
  get description() {
    return t("Remove matching entries from managed auto-memory.");
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive", "acp"],
  argumentHint: "<memory text to remove>",
  action: /* @__PURE__ */ __name(async (context, args) => {
    const query = args.trim();
    if (!query) {
      return {
        type: "message",
        messageType: "error",
        content: t("Usage: /forget <memory text to remove>")
      };
    }
    const config = context.services.config;
    if (!config) {
      return {
        type: "message",
        messageType: "error",
        content: t("Config not loaded.")
      };
    }
    try {
      const selection = await config.getMemoryManager().selectForgetCandidates(config.getProjectRoot(), query, { config });
      const result = await config.getMemoryManager().forgetMatches(config.getProjectRoot(), selection.matches);
      return {
        type: "message",
        messageType: "info",
        content: result.systemMessage ?? t("No managed auto-memory entries matched: {{query}}", { query })
      };
    } catch (error) {
      return {
        type: "message",
        messageType: "error",
        content: t("Failed to process /forget: {{message}}", {
          message: error instanceof Error ? error.message : String(error)
        })
      };
    }
  }, "action")
};

// packages/cli/src/ui/commands/memoryCommand.ts
init_esbuild_shims();
var memoryCommand = {
  name: "memory",
  get description() {
    return t("Open the memory manager.");
  },
  argumentHint: "show|add|refresh",
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive"],
  action: /* @__PURE__ */ __name(async () => ({
    type: "dialog",
    dialog: "memory"
  }), "action")
};

// packages/cli/src/ui/commands/modelCommand.ts
init_esbuild_shims();

// packages/cli/src/ui/voice/voice-model.ts
init_esbuild_shims();

// packages/cli/src/ui/commands/modelCommand.ts
var MAIN_MODEL_CONFIGURATION_HINT = "Configure models in settings.modelProviders and ensure the required environment variables are set. In interactive mode, run /auth to configure or switch providers, or run /model without arguments to choose from configured models.";
var FAST_MODEL_CONFIGURATION_HINT = "Configure models in settings.modelProviders and ensure the required environment variables are set. In interactive mode, run /auth to configure or switch providers, or run /model --fast without a model to choose from configured models.";
var VISION_MODEL_CONFIGURATION_HINT = "Configure an image-capable model in settings.modelProviders and ensure the required environment variables are set. Run /model --vision <model-id> to set it, or leave it unset to auto-pick a same-provider vision model.";
function formatVisionModelSettingForDisplay(setting) {
  const parsed = parseVisionModelSetting(setting);
  if (!parsed) return setting.replace(/\0/g, "\\0");
  return parsed.baseUrl ? `${parsed.selector} (${parsed.baseUrl})` : parsed.selector;
}
__name(formatVisionModelSettingForDisplay, "formatVisionModelSettingForDisplay");
function persistSetting(settings, path20, value) {
  settings.setValue(getPersistScopeForModelSelection(settings), path20, value);
}
__name(persistSetting, "persistSetting");
async function switchMainModel(config, settings, currentAuthType, modelArg) {
  const parsed = parseAcpModelOption(modelArg);
  if (parsed.authType) {
    await config.switchModel(
      parsed.authType,
      parsed.modelId,
      parsed.authType !== currentAuthType && parsed.authType === "qwen-oauth" /* QWEN_OAUTH */ ? { requireCachedCredentials: true } : void 0
    );
    persistSetting(settings, "security.auth.selectedType", parsed.authType);
    persistSetting(settings, "model.name", parsed.modelId);
    persistSetting(settings, "model.baseUrl", "");
    return parsed.modelId;
  }
  await config.switchModel(currentAuthType, modelArg, void 0);
  persistSetting(settings, "model.name", modelArg);
  persistSetting(settings, "model.baseUrl", "");
  return modelArg;
}
__name(switchMainModel, "switchMainModel");
function formatUnavailableModelMessage(kind, modelName, authType, availableModels) {
  const availableModelIds = Array.from(
    new Set(availableModels.map((model) => model.id))
  );
  const availableModelsLine = availableModelIds.length === 0 ? `No models are configured for auth type '${authType}'.` : `Available models for '${authType}': ${availableModelIds.join(", ")}.`;
  const hint = kind === "Fast model" ? FAST_MODEL_CONFIGURATION_HINT : kind === "Vision model" ? VISION_MODEL_CONFIGURATION_HINT : MAIN_MODEL_CONFIGURATION_HINT;
  return `${kind} '${modelName}' is not available for auth type '${authType}'.
${availableModelsLine}
` + hint;
}
__name(formatUnavailableModelMessage, "formatUnavailableModelMessage");
function formatUnavailableAuxModelMessage(label, modelName, availableModels, hint) {
  const availableModelIds = Array.from(
    new Set(availableModels.map((model) => model.id))
  );
  const availableModelsLine = availableModelIds.length === 0 ? "No models are configured." : `Configured models: ${availableModelIds.join(", ")}.`;
  return `${label} '${modelName}' is not configured for any auth type.
${availableModelsLine}
` + hint;
}
__name(formatUnavailableAuxModelMessage, "formatUnavailableAuxModelMessage");
function formatUnavailableFastModelMessage(modelName, availableModels) {
  return formatUnavailableAuxModelMessage(
    "Fast model",
    modelName,
    availableModels,
    FAST_MODEL_CONFIGURATION_HINT
  );
}
__name(formatUnavailableFastModelMessage, "formatUnavailableFastModelMessage");
function formatUnavailableVisionModelMessage(modelName, availableModels) {
  return formatUnavailableAuxModelMessage(
    "Vision model",
    modelName,
    availableModels,
    VISION_MODEL_CONFIGURATION_HINT
  );
}
__name(formatUnavailableVisionModelMessage, "formatUnavailableVisionModelMessage");
function formatAmbiguousVisionModelMessage(modelName, matchingModels) {
  const endpoints = matchingModels.map((model) => model.baseUrl ?? "(default endpoint)").join(", ");
  const qualifiedSelectors = Array.from(
    new Set(
      matchingModels.map(
        (model) => model.authType ? `${model.authType}:${model.id}` : void 0
      ).filter((selector) => selector !== void 0)
    )
  );
  const scriptedHint = qualifiedSelectors.length > 1 ? `
${t(
    "For scripts, pass an auth-qualified selector such as {{selector}}.",
    {
      selector: qualifiedSelectors[0]
    }
  )}` : "";
  return t("Vision model '{{modelName}}' matches multiple configured endpoints.", {
    modelName
  }) + "\n" + t("Matching endpoints: {{endpoints}}.", { endpoints }) + "\n" + t(
    "Run /model --vision without an argument and choose the exact endpoint."
  ) + scriptedHint;
}
__name(formatAmbiguousVisionModelMessage, "formatAmbiguousVisionModelMessage");
function formatNonVisionModelWarning(modelName) {
  return t(
    "\u26A0 '{{model}}' is not a known image-capable model; the vision bridge may fail on images.",
    { model: modelName }
  );
}
__name(formatNonVisionModelWarning, "formatNonVisionModelWarning");
function formatUnavailableVoiceModelMessage(modelName, availableModels) {
  const availableModelIds = Array.from(
    new Set(availableModels.map((model) => model.id))
  );
  const availableModelsLine = availableModelIds.length === 0 ? t("No models are configured.") : t("Configured models: {{models}}.", {
    models: availableModelIds.join(", ")
  });
  return t("Voice model '{{modelName}}' is not configured.", { modelName }) + `
${availableModelsLine}
` + t(
    "Configure a unique model id in settings.modelProviders or run /model --voice to select an available model."
  );
}
__name(formatUnavailableVoiceModelMessage, "formatUnavailableVoiceModelMessage");
function getAvailableModelIds(context, mode = "main") {
  const { services } = context;
  const { config } = services;
  if (!config) {
    return [];
  }
  const availableModels = config.getAvailableModels().filter((m) => {
    if (mode === "fast") return !m.voiceOnly;
    if (mode === "voice") return !m.fastOnly;
    return !m.fastOnly && !m.voiceOnly;
  });
  return availableModels.map((model) => model.id);
}
__name(getAvailableModelIds, "getAvailableModelIds");
var modelCommand = {
  name: "model",
  completionPriority: 100,
  get description() {
    return t(
      "Switch the model for this session (--fast for suggestion model, --voice for voice transcription model, --vision for the vision bridge model, [model-id] to switch immediately, or [model-id] [prompt] to run a one-off prompt on another model; the inline prompt is sent verbatim without @file expansion)."
    );
  },
  argumentHint: "[--fast|--voice|--vision] [<model-id>] | <model-id> <prompt>",
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive", "non_interactive", "acp"],
  completion: /* @__PURE__ */ __name(async (context, partialArg) => {
    if (partialArg) {
      const flagCompletions = [
        {
          value: "--fast",
          description: t(
            "Set a lighter model for prompt suggestions and speculative execution"
          )
        },
        {
          value: "--voice",
          description: t("Set the model for voice transcription")
        },
        {
          value: "--vision",
          description: t(
            "Set the image-capable model used to transcribe images for a text-only main model"
          )
        }
      ].filter((item) => item.value.startsWith(partialArg));
      if (flagCompletions.length > 0) {
        return flagCompletions;
      }
      const trimmed = partialArg.trim();
      if (trimmed) {
        let mode = "main";
        let modelPrefix = trimmed;
        if (trimmed.startsWith("--fast ")) {
          mode = "fast";
          modelPrefix = trimmed.slice("--fast ".length);
        } else if (trimmed.startsWith("--voice ")) {
          mode = "voice";
          modelPrefix = trimmed.slice("--voice ".length);
        } else if (trimmed.startsWith("--vision ")) {
          mode = "vision";
          modelPrefix = trimmed.slice("--vision ".length);
        }
        return getAvailableModelIds(context, mode).filter(
          (id) => id.startsWith(modelPrefix)
        );
      }
      return null;
    } else {
      return null;
    }
  }, "completion"),
  action: /* @__PURE__ */ __name(async (context, actionArgs) => {
    const { services } = context;
    const { config, settings } = services;
    if (!config) {
      return {
        type: "message",
        messageType: "error",
        content: t("Configuration not available.")
      };
    }
    const args = context.invocation?.args?.trim() || actionArgs.trim();
    const isVoiceModelCommand = args === "--voice" || args.startsWith("--voice ");
    if (isVoiceModelCommand) {
      const modelName2 = args.replace("--voice", "").trim();
      if (!modelName2) {
        if (context.executionMode !== "interactive") {
          const voiceModel = context.services.settings?.merged?.voiceModel?.trim() || t("not set");
          return {
            type: "message",
            messageType: "info",
            content: t(
              'Current voice model: {{voiceModel}}\nUse "/model --voice <model-id>" to set voice model.',
              { voiceModel }
            )
          };
        }
        return {
          type: "dialog",
          dialog: "voice-model"
        };
      }
      if (!settings) {
        return {
          type: "message",
          messageType: "error",
          content: t("Settings service not available.")
        };
      }
      const availableModels = config.getAllConfiguredModels().filter((m) => !m.fastOnly);
      const matches = availableModels.filter((model) => model.id === modelName2);
      if (matches.length === 0) {
        return {
          type: "message",
          messageType: "error",
          content: formatUnavailableVoiceModelMessage(
            modelName2,
            availableModels
          )
        };
      }
      if (matches.length > 1) {
        return {
          type: "message",
          messageType: "error",
          content: t(
            "Voice model '{{modelName}}' is ambiguous. Configure a unique model id before using /model --voice.",
            { modelName: modelName2 }
          )
        };
      }
      if (!isSelectableVoiceModel(matches[0])) {
        return {
          type: "message",
          messageType: "error",
          content: formatUnsupportedVoiceModelMessage(modelName2)
        };
      }
      persistSetting(settings, "voiceModel", modelName2);
      return {
        type: "message",
        messageType: "info",
        content: t("Voice Model") + ": " + modelName2
      };
    }
    const isFastModelCommand = args === "--fast" || args.startsWith("--fast ");
    if (isFastModelCommand) {
      const modelName2 = args.replace("--fast", "").trim();
      if (!modelName2) {
        if (context.executionMode !== "interactive") {
          const fastModel = context.services.settings?.merged?.fastModel ?? "not set";
          return {
            type: "message",
            messageType: "info",
            content: `Current fast model: ${fastModel}
Use "/model --fast <model-id>" to set fast model.`
          };
        }
        return {
          type: "dialog",
          dialog: "fast-model"
        };
      }
      if (!settings) {
        return {
          type: "message",
          messageType: "error",
          content: t("Settings service not available.")
        };
      }
      const contentGeneratorConfig2 = config.getContentGeneratorConfig();
      const authType2 = contentGeneratorConfig2?.authType;
      if (!authType2) {
        return {
          type: "message",
          messageType: "error",
          content: t("Authentication type not available.")
        };
      }
      const selector = (() => {
        try {
          return resolveModelId(modelName2);
        } catch {
          return void 0;
        }
      })();
      if (!selector) {
        return {
          type: "message",
          messageType: "error",
          content: formatUnavailableFastModelMessage(modelName2, [])
        };
      }
      const availableModels = (selector.authType ? config.getAvailableModelsForAuthType(selector.authType) : config.getAllConfiguredModels()).filter((m) => !m.voiceOnly);
      if (!availableModels.some((model) => model.id === selector.modelId)) {
        return {
          type: "message",
          messageType: "error",
          content: selector.authType ? formatUnavailableModelMessage(
            "Fast model",
            selector.modelId,
            selector.authType,
            availableModels
          ) : formatUnavailableFastModelMessage(modelName2, availableModels)
        };
      }
      persistSetting(settings, "fastModel", modelName2);
      config.setFastModel(modelName2);
      return {
        type: "message",
        messageType: "info",
        content: t("Fast Model") + ": " + modelName2
      };
    }
    const isVisionModelCommand = args === "--vision" || args.startsWith("--vision ");
    if (isVisionModelCommand) {
      const modelName2 = args.replace("--vision", "").trim();
      if (!modelName2) {
        if (context.executionMode !== "interactive") {
          const visionModel2 = context.services.settings?.merged?.visionModel?.trim();
          return {
            type: "message",
            messageType: "info",
            content: t(
              'Current vision model: {{visionModel}}\nUse "/model --vision <model-id>" to set the vision bridge model.',
              {
                visionModel: visionModel2 ? formatVisionModelSettingForDisplay(visionModel2) : t("not set")
              }
            )
          };
        }
        return {
          type: "dialog",
          dialog: "vision-model"
        };
      }
      if (!settings) {
        return {
          type: "message",
          messageType: "error",
          content: t("Settings service not available.")
        };
      }
      const selector = (() => {
        try {
          return resolveModelId(modelName2);
        } catch {
          return void 0;
        }
      })();
      if (!selector) {
        return {
          type: "message",
          messageType: "error",
          content: formatUnavailableVisionModelMessage(modelName2, [])
        };
      }
      const availableModels = (selector.authType ? config.getAvailableModelsForAuthType(selector.authType) : config.getAllConfiguredModels()).filter((m) => !m.fastOnly && !m.voiceOnly);
      const matchingModels = availableModels.filter(
        (model) => model.id === selector.modelId
      );
      if (matchingModels.length > 1) {
        return {
          type: "message",
          messageType: "error",
          content: formatAmbiguousVisionModelMessage(modelName2, matchingModels)
        };
      }
      const matched = matchingModels[0];
      if (!matched) {
        return {
          type: "message",
          messageType: "error",
          content: selector.authType ? formatUnavailableModelMessage(
            "Vision model",
            selector.modelId,
            selector.authType,
            availableModels
          ) : formatUnavailableVisionModelMessage(modelName2, availableModels)
        };
      }
      if (config.isCurrentPrimaryModel(matched)) {
        return {
          type: "message",
          messageType: "error",
          content: t(
            "'{{model}}' is the current primary model and cannot be used as the vision bridge. Choose a different image-capable model.",
            { model: modelName2 }
          )
        };
      }
      const qualifiedModelName = `${selector.authType ?? matched.authType}:${selector.modelId}`;
      const visionModel = matched.baseUrl ? `${qualifiedModelName}\0${matched.baseUrl}` : qualifiedModelName;
      persistSetting(settings, "visionModel", visionModel);
      config.setVisionModel(visionModel);
      const visionWarning = isImageCapable(matched) ? "" : `
${formatNonVisionModelWarning(modelName2)}`;
      return {
        type: "message",
        messageType: "info",
        content: t("Vision Model") + ": " + modelName2 + visionWarning
      };
    }
    const contentGeneratorConfig = config.getContentGeneratorConfig();
    if (!contentGeneratorConfig) {
      return {
        type: "message",
        messageType: "error",
        content: t("Content generator configuration not available.")
      };
    }
    const authType = contentGeneratorConfig.authType;
    if (!authType) {
      return {
        type: "message",
        messageType: "error",
        content: t("Authentication type not available.")
      };
    }
    const trimmedArgs = args.trim();
    const firstSpace = trimmedArgs.search(/\s/);
    const modelName = firstSpace === -1 ? trimmedArgs : trimmedArgs.slice(0, firstSpace);
    const inlinePrompt = firstSpace === -1 ? "" : trimmedArgs.slice(firstSpace + 1).trim();
    if (modelName) {
      const parsed = parseAcpModelOption(modelName);
      const targetAuthType = parsed.authType ?? authType;
      const availableModels = config.getAvailableModelsForAuthType(targetAuthType).filter((m) => !m.fastOnly && !m.voiceOnly);
      if (!availableModels.some((model) => model.id === parsed.modelId)) {
        return {
          type: "message",
          messageType: "error",
          content: formatUnavailableModelMessage(
            "Model",
            parsed.modelId,
            targetAuthType,
            availableModels
          )
        };
      }
      if (inlinePrompt) {
        if (context.executionMode === "acp") {
          return {
            type: "message",
            messageType: "error",
            content: t(
              "Inline one-shot override isn't supported in this mode \u2014 run '/model {{model}}' first, then send your prompt.",
              { model: modelName }
            )
          };
        }
        const sameAuthType = targetAuthType === authType;
        if (!sameAuthType || !isInlineModelOverrideAllowed(config, parsed.modelId)) {
          return {
            type: "message",
            messageType: "error",
            content: t(
              "Inline one-shot override can't switch providers. '{{model}}' belongs to a different provider \u2014 run '/model {{model}}' first, then send your prompt.",
              { model: modelName }
            )
          };
        }
        return {
          type: "submit_prompt",
          content: inlinePrompt,
          modelOverride: parsed.modelId
        };
      }
      if (!settings) {
        return {
          type: "message",
          messageType: "error",
          content: t("Settings service not available.")
        };
      }
      const effectiveModelName = await switchMainModel(
        config,
        settings,
        authType,
        modelName
      );
      return {
        type: "message",
        messageType: "info",
        content: t("Model") + ": " + effectiveModelName
      };
    }
    if (context.executionMode !== "interactive") {
      const currentModel = config.getModel() ?? "unknown";
      return {
        type: "message",
        messageType: "info",
        content: `Current model: ${currentModel}
Use "/model <model-id>" to switch models or "/model --fast <model-id>" to set the fast model.`
      };
    }
    return {
      type: "dialog",
      dialog: "model"
    };
  }, "action")
};

// packages/cli/src/ui/commands/rememberCommand.ts
init_esbuild_shims();
var rememberCommand = {
  name: "remember",
  get description() {
    return t("Save a durable memory to the memory system.");
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive", "acp"],
  argumentHint: "<text to remember>",
  action: /* @__PURE__ */ __name((context, args) => {
    const fact = args.trim();
    if (!fact) {
      return {
        type: "message",
        messageType: "error",
        content: t("Usage: /remember <text to remember>")
      };
    }
    const config = context.services.config;
    if (!config) {
      return {
        type: "message",
        messageType: "error",
        content: t("Config not loaded.")
      };
    }
    const useManagedMemory = config?.isManagedMemoryAvailable() ?? false;
    if (useManagedMemory) {
      return {
        type: "submit_prompt",
        content: buildManagedRememberPrompt(fact, config.getProjectRoot())
      };
    }
    return {
      type: "submit_prompt",
      content: buildBareRememberPrompt(fact)
    };
  }, "action")
};

// packages/cli/src/ui/commands/planCommand.ts
init_esbuild_shims();
var planCommand = {
  name: "plan",
  get description() {
    return t("Switch to plan mode or exit plan mode");
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive"],
  action: /* @__PURE__ */ __name(async (context, args) => {
    const { config } = context.services;
    if (!config) {
      return {
        type: "message",
        messageType: "error",
        content: t("Configuration is not available.")
      };
    }
    const trimmedArgs = args.trim();
    const currentMode = config.getApprovalMode();
    if (trimmedArgs === "exit") {
      if (currentMode !== "plan" /* PLAN */) {
        return {
          type: "message",
          messageType: "error",
          content: t('Not in plan mode. Use "/plan" to enter plan mode first.')
        };
      }
      try {
        config.setApprovalMode(config.getPrePlanMode());
      } catch (e) {
        return {
          type: "message",
          messageType: "error",
          content: e.message
        };
      }
      return {
        type: "message",
        messageType: "info",
        content: t("Exited plan mode. Previous approval mode restored.")
      };
    }
    if (currentMode !== "plan" /* PLAN */) {
      try {
        config.setApprovalMode("plan" /* PLAN */);
      } catch (e) {
        return {
          type: "message",
          messageType: "error",
          content: e.message
        };
      }
      if (trimmedArgs) {
        return {
          type: "submit_prompt",
          content: [{ text: trimmedArgs }]
        };
      }
      return {
        type: "message",
        messageType: "info",
        content: t(
          "Enabled plan mode. The agent will analyze and plan without executing tools."
        )
      };
    }
    if (trimmedArgs) {
      return {
        type: "submit_prompt",
        content: [{ text: trimmedArgs }]
      };
    }
    return {
      type: "message",
      messageType: "info",
      content: t('Already in plan mode. Use "/plan exit" to exit plan mode.')
    };
  }, "action")
};

// packages/cli/src/ui/commands/permissionsCommand.ts
init_esbuild_shims();
var permissionsCommand = {
  name: "permissions",
  get description() {
    return t("Manage permission rules");
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive"],
  action: /* @__PURE__ */ __name(() => ({
    type: "dialog",
    dialog: "permissions"
  }), "action")
};

// packages/cli/src/ui/commands/trustCommand.ts
init_esbuild_shims();
var trustCommand = {
  name: "trust",
  get description() {
    return t("Manage folder trust settings");
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive"],
  action: /* @__PURE__ */ __name(() => ({
    type: "dialog",
    dialog: "trust"
  }), "action")
};

// packages/cli/src/ui/commands/quitCommand.ts
init_esbuild_shims();
var quitCommand = {
  name: "quit",
  altNames: ["exit"],
  get description() {
    return t("exit the cli");
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive"],
  action: /* @__PURE__ */ __name((context) => {
    const now = Date.now();
    const { sessionStartTime } = context.session.stats;
    const wallDuration = now - sessionStartTime.getTime();
    return {
      type: "quit",
      messages: [
        {
          type: "user",
          text: `/quit`,
          // Keep it consistent, even if /exit was used
          id: now - 1
        },
        {
          type: "quit",
          duration: formatDuration(wallDuration),
          id: now
        }
      ]
    };
  }, "action")
};

// packages/cli/src/ui/commands/recapCommand.ts
init_esbuild_shims();
var recapCommand = {
  name: "recap",
  kind: "built-in" /* BUILT_IN */,
  get description() {
    return t("Generate a one-line session recap now");
  },
  action: /* @__PURE__ */ __name(async (context) => {
    const { config } = context.services;
    const abortSignal = context.abortSignal ?? new AbortController().signal;
    if (!config) {
      return {
        type: "message",
        messageType: "error",
        content: t("Config not loaded.")
      };
    }
    if (context.executionMode === "interactive") {
      const turnInFlight = !context.ui.isIdleRef.current || context.ui.pendingItem !== null;
      if (turnInFlight) {
        return {
          type: "message",
          messageType: "error",
          content: t(
            "Cannot run /recap while another operation is in progress."
          )
        };
      }
    }
    const recap = await generateSessionRecap(config, abortSignal);
    if (abortSignal.aborted) return;
    if (!recap) {
      return {
        type: "message",
        messageType: "info",
        content: t("Not enough conversation context for a recap yet.")
      };
    }
    if (context.executionMode === "interactive") {
      const item = {
        type: "away_recap",
        text: recap
      };
      context.ui.addItem(item, Date.now());
      return;
    }
    return { type: "message", messageType: "info", content: recap };
  }, "action")
};

// packages/cli/src/ui/commands/renameCommand.ts
init_esbuild_shims();
var MAX_TITLE_LENGTH = SESSION_TITLE_MAX_LENGTH;
function titleFailureMessage(reason) {
  switch (reason) {
    case "no_fast_model":
      return t(
        "Auto-generating a title requires a fast model. Configure one with `/model --fast <model>`, or pass a name: `/rename <name>`."
      );
    case "empty_history":
      return t(
        "No conversation to title yet \u2014 send at least one message first."
      );
    case "empty_result":
      return t(
        "The fast model returned no usable title. Try `/rename <name>` to set one yourself."
      );
    case "aborted":
      return t("Title generation was cancelled.");
    case "model_error":
      return t(
        "The fast model could not generate a title (rate limit, auth, network error, or unexpected response format). Check debug log or try again."
      );
    case "no_client":
      return t("Session is still initializing \u2014 try again in a moment.");
    default:
      return t("Could not generate a title.");
  }
}
__name(titleFailureMessage, "titleFailureMessage");
function parseArgs(raw) {
  const trimmed = raw.trim().replace(/[\r\n]+/g, " ");
  if (!trimmed) return { auto: false, positional: "" };
  const parts = trimmed.split(/\s+/);
  let auto = false;
  let unknownFlag;
  let flagsDone = false;
  const rest = [];
  for (const p of parts) {
    if (!flagsDone && p === "--") {
      flagsDone = true;
      continue;
    }
    if (!flagsDone && p.startsWith("--")) {
      if (p.toLowerCase() === "--auto") {
        auto = true;
        continue;
      }
      if (!unknownFlag) unknownFlag = p;
      continue;
    }
    rest.push(p);
  }
  return { auto, positional: rest.join(" "), unknownFlag };
}
__name(parseArgs, "parseArgs");
var renameCommand = {
  name: "rename",
  altNames: ["tag"],
  kind: "built-in" /* BUILT_IN */,
  get description() {
    return t(
      "Rename the current conversation. --auto lets the fast model pick a title."
    );
  },
  argumentHint: "[--auto] [<name>]",
  completion: /* @__PURE__ */ __name(async (_context, partialArg) => {
    const trimmed = partialArg.trim();
    if (trimmed && "--auto".startsWith(trimmed)) {
      return [
        {
          value: "--auto",
          description: t(
            "Let the fast model generate a sentence-case title from the conversation so far."
          )
        }
      ];
    }
    return null;
  }, "completion"),
  action: /* @__PURE__ */ __name(async (context, args) => {
    const { config } = context.services;
    if (!config) {
      return {
        type: "message",
        messageType: "error",
        content: t("Config is not available.")
      };
    }
    const { auto, positional, unknownFlag } = parseArgs(args);
    if (unknownFlag) {
      return {
        type: "message",
        messageType: "error",
        content: t(
          'Unknown flag "{{flag}}". Supported: --auto. To use this as a literal name, run `/rename -- {{flag}}`.',
          { flag: unknownFlag }
        )
      };
    }
    let name = positional;
    const titleSource = name ? "manual" : "auto";
    if (auto && positional) {
      return {
        type: "message",
        messageType: "error",
        content: t(
          "/rename --auto does not take a name. Use `/rename <name>` to set a name yourself."
        )
      };
    }
    if (!name) {
      const dots = [".", "..", "..."];
      let dotIndex = 0;
      const baseText = t("Generating session title");
      context.ui.setPendingItem({
        type: "info",
        text: baseText + dots[dotIndex]
      });
      const timer = setInterval(() => {
        dotIndex = (dotIndex + 1) % dots.length;
        context.ui.setPendingItem({
          type: "info",
          text: baseText + dots[dotIndex]
        });
      }, 500);
      let outcome;
      try {
        outcome = await tryGenerateSessionTitle(
          config,
          context.abortSignal ?? new AbortController().signal
        );
      } finally {
        clearInterval(timer);
        context.ui.setPendingItem(null);
      }
      if (!outcome.ok) {
        return {
          type: "message",
          messageType: "error",
          content: titleFailureMessage(outcome.reason)
        };
      }
      name = outcome.title;
    }
    if (name.length > MAX_TITLE_LENGTH) {
      return {
        type: "message",
        messageType: "error",
        content: t("Name is too long. Maximum {{max}} characters.", {
          max: String(MAX_TITLE_LENGTH)
        })
      };
    }
    const chatRecordingService = config.getChatRecordingService();
    if (chatRecordingService) {
      const ok = chatRecordingService.recordCustomTitle(name, titleSource);
      if (!ok) {
        return {
          type: "message",
          messageType: "error",
          content: t("Failed to rename session.")
        };
      }
    } else {
      const sessionId = config.getSessionId();
      const sessionService = config.getSessionService();
      const success = await sessionService.renameSession(
        sessionId,
        name,
        titleSource
      );
      if (!success) {
        return {
          type: "message",
          messageType: "error",
          content: t("Failed to rename session.")
        };
      }
    }
    context.ui.setSessionName(name);
    return {
      type: "message",
      messageType: "info",
      content: t('Session renamed to "{{name}}"', { name })
    };
  }, "action")
};

// packages/cli/src/ui/commands/restoreCommand.ts
init_esbuild_shims();
import * as fs10 from "node:fs/promises";
import path12 from "node:path";
async function restoreAction(context, args) {
  const { services, ui } = context;
  const { config } = services;
  const { addItem, loadHistory } = ui;
  const checkpointDir = config?.storage.getProjectTempCheckpointsDir();
  if (!checkpointDir) {
    return {
      type: "message",
      messageType: "error",
      content: "Could not determine the .qwen directory path."
    };
  }
  try {
    await fs10.mkdir(checkpointDir, { recursive: true });
    const files = await fs10.readdir(checkpointDir);
    const jsonFiles = files.filter((file) => file.endsWith(".json"));
    if (!args) {
      if (jsonFiles.length === 0) {
        return {
          type: "message",
          messageType: "info",
          content: "No restorable tool calls found."
        };
      }
      const truncatedFiles = jsonFiles.map((file) => {
        const components = file.split(".");
        if (components.length <= 1) {
          return file;
        }
        components.pop();
        return components.join(".");
      });
      const fileList = truncatedFiles.join("\n");
      return {
        type: "message",
        messageType: "info",
        content: `Available tool calls to restore:

${fileList}`
      };
    }
    const selectedFile = args.endsWith(".json") ? args : `${args}.json`;
    if (!jsonFiles.includes(selectedFile)) {
      return {
        type: "message",
        messageType: "error",
        content: `File not found: ${selectedFile}`
      };
    }
    const filePath = path12.join(checkpointDir, selectedFile);
    const data = await fs10.readFile(filePath, "utf-8");
    const toolCallData = JSON.parse(data);
    if (toolCallData.commitHash && !toolCallData.promptId) {
      return {
        type: "message",
        messageType: "error",
        content: "This checkpoint uses a legacy format that is no longer supported. Please create a new checkpoint."
      };
    }
    const toolCall = toolCallData.toolCall;
    if (!toolCall || typeof toolCall !== "object" || typeof toolCall.name !== "string") {
      throw new Error("Checkpoint is missing a valid toolCall.");
    }
    if (toolCallData.promptId) {
      if (!config) {
        return {
          type: "message",
          messageType: "error",
          content: "Configuration is not available."
        };
      }
      try {
        const result = await config.getFileHistoryService().rewind(toolCallData.promptId, true);
        if (result.filesFailed.length > 0) {
          addItem(
            {
              type: "warning",
              text: `Partially restored: ${result.filesChanged.length} file(s) reverted, ${result.filesFailed.length} file(s) failed. Aborting tool replay.`
            },
            Date.now()
          );
          return;
        }
        addItem(
          {
            type: "info",
            text: "Restored project to the state at the start of this turn."
          },
          Date.now()
        );
      } catch (error) {
        addItem(
          {
            type: "warning",
            text: `Could not restore files: ${error instanceof Error ? error.message : String(error)}`
          },
          Date.now()
        );
        return;
      }
    }
    if (toolCallData.history) {
      if (!loadHistory) {
        return {
          type: "message",
          messageType: "error",
          content: "loadHistory function is not available."
        };
      }
      loadHistory(toolCallData.history);
    }
    if (toolCallData.clientHistory) {
      await config?.getGeminiClient()?.setHistory(toolCallData.clientHistory);
    }
    return {
      type: "tool",
      toolName: toolCall.name,
      toolArgs: toolCall.args
    };
  } catch (error) {
    return {
      type: "message",
      messageType: "error",
      content: `Could not read restorable tool calls. This is the error: ${error}`
    };
  }
}
__name(restoreAction, "restoreAction");
async function completion(context, _partialArg) {
  const { services } = context;
  const { config } = services;
  const checkpointDir = config?.storage.getProjectTempCheckpointsDir();
  if (!checkpointDir) {
    return [];
  }
  try {
    const files = await fs10.readdir(checkpointDir);
    return files.filter((file) => file.endsWith(".json")).map((file) => file.replace(".json", ""));
  } catch (_err) {
    return [];
  }
}
__name(completion, "completion");
var restoreCommand = /* @__PURE__ */ __name((config) => {
  if (!config?.getFileCheckpointingEnabled()) {
    return null;
  }
  return {
    name: "restore",
    get description() {
      return t(
        "Restore a tool call. This will reset the conversation and file history to the state it was in when the tool call was suggested"
      );
    },
    kind: "built-in" /* BUILT_IN */,
    supportedModes: ["interactive"],
    action: restoreAction,
    completion
  };
}, "restoreCommand");

// packages/cli/src/ui/commands/resumeCommand.ts
init_esbuild_shims();
var resumeCommand = {
  name: "resume",
  altNames: ["continue"],
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive"],
  get description() {
    return t("Resume a previous session");
  },
  action: /* @__PURE__ */ __name(async (context, args) => {
    const arg = args.trim();
    if (!arg) {
      return { type: "dialog", dialog: "resume" };
    }
    const { config } = context.services;
    if (!config) {
      return {
        type: "message",
        messageType: "error",
        content: t("Config is not available.")
      };
    }
    if (isValidSessionId(arg)) {
      const sessionService2 = config.getSessionService();
      const exists = await sessionService2.sessionExists(arg);
      if (exists) {
        return { type: "dialog", dialog: "resume", sessionId: arg };
      }
      return {
        type: "message",
        messageType: "error",
        content: t('No session found with ID "{{id}}".', { id: arg })
      };
    }
    const sessionService = config.getSessionService();
    const matches = await sessionService.findSessionsByTitle(arg);
    if (matches.length === 1) {
      return {
        type: "dialog",
        dialog: "resume",
        sessionId: matches[0].sessionId
      };
    }
    if (matches.length > 1) {
      return { type: "dialog", dialog: "resume", matchedSessions: matches };
    }
    return {
      type: "message",
      messageType: "error",
      content: t('No session found with title "{{title}}".', { title: arg })
    };
  }, "action")
};

// packages/cli/src/ui/commands/rewindCommand.ts
init_esbuild_shims();
var rewindCommand = {
  name: "rewind",
  altNames: ["rollback"],
  get description() {
    return t("Rewind conversation to a previous turn");
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive"],
  action: /* @__PURE__ */ __name(async () => ({
    type: "dialog",
    dialog: "rewind"
  }), "action")
};

// packages/cli/src/ui/commands/settingsCommand.ts
init_esbuild_shims();
var settingsCommand = {
  name: "settings",
  get description() {
    return t("View and edit Qwen Code settings");
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive"],
  action: /* @__PURE__ */ __name((_context, _args) => ({
    type: "dialog",
    dialog: "settings"
  }), "action")
};

// packages/cli/src/ui/commands/skillsCommand.ts
init_esbuild_shims();
var skillsCommand = {
  name: "skills",
  get description() {
    return t("Open the skills panel (browse, search, toggle, pick).");
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive", "acp"],
  // Accepting `/skills` from the auto-completion popup (e.g. typing
  // `/skil<Enter>`) submits immediately rather than inserting `/skills `
  // and forcing a second Enter — `/skills` has no required arg, the bare
  // action just opens the dialog. See `SlashCommand.submitOnAccept`.
  submitOnAccept: true,
  action: /* @__PURE__ */ __name(async (context) => {
    const skillManager = context.services.config?.getSkillManager();
    if (!skillManager) {
      if (context.executionMode === "interactive") {
        context.ui.addItem(
          {
            type: "error" /* ERROR */,
            text: t("Could not retrieve skill manager.")
          },
          Date.now()
        );
        return;
      }
      return {
        type: "message",
        messageType: "error",
        content: t("Could not retrieve skill manager.")
      };
    }
    if (context.executionMode === "interactive") {
      return { type: "dialog", dialog: "skills_manage" };
    }
    const skills = await skillManager.listSkills();
    const disabled = context.services.config?.getDisabledSkillNames() ?? /* @__PURE__ */ new Set();
    const userInvocableSkills = skills.filter(
      (skill) => skill.userInvocable !== false
    );
    const visibleSkills = userInvocableSkills.filter(
      (s) => !disabled.has(s.name.toLowerCase())
    );
    if (visibleSkills.length === 0) {
      const content = skills.length > 0 && userInvocableSkills.length === 0 ? t("All skills are marked as non-user-invocable.") : userInvocableSkills.length === 0 ? t("No skills are currently available.") : t(
        "All available skills are disabled. Edit ~/.qwen/settings.json or .qwen/settings.json (skills.disabled) to re-enable."
      );
      return {
        type: "message",
        messageType: "info",
        content
      };
    }
    const sortedSkills = [...visibleSkills].sort(
      (a, b) => normalizeSkillPriority(b.priority) - normalizeSkillPriority(a.priority) || a.name.localeCompare(b.name)
    );
    const sanitize = /* @__PURE__ */ __name((text, max) => {
      const oneLine = text.replace(/[\r\n]+/g, " ").trim();
      return oneLine.length <= max ? oneLine : `${oneLine.slice(0, Math.max(0, max - 1))}\u2026`;
    }, "sanitize");
    const lines = sortedSkills.map(
      (s) => `  - ${s.name}${s.description ? `  ${sanitize(s.description, 80)}` : ""}${s.level ? `  (${levelLabel(s.level)})` : ""}`
    );
    return {
      type: "message",
      messageType: "info",
      content: `${t("Available skills:")}

${lines.join("\n")}`
    };
  }, "action")
};

// packages/cli/src/ui/commands/statsCommand.ts
init_esbuild_shims();
import * as fs11 from "node:fs/promises";
import { randomUUID as randomUUID2 } from "node:crypto";
import path13 from "node:path";
var VALID_EXPORT_FORMATS = /* @__PURE__ */ new Set(["csv", "json"]);
var EMPTY_SKILL_METRICS = {
  totalCalls: 0,
  totalSuccess: 0,
  totalFail: 0,
  byName: {}
};
function formatInteger(value) {
  return new Intl.NumberFormat(getCurrentLanguage()).format(value);
}
__name(formatInteger, "formatInteger");
function formatGroupLines(titleKey, groups) {
  if (groups.length === 0) {
    return [t(titleKey), `  ${t("No usage data.")}`];
  }
  return [
    t(titleKey),
    ...groups.map((group) => {
      const label = group.model && group.authType ? `${group.model} (${group.authType})` : group.model || group.authType || group.source || group.key;
      return `  ${t("{{label}}: {{tokens}} tokens ({{requests}} requests)", {
        label,
        tokens: formatInteger(group.totalTokens),
        requests: formatInteger(group.requests)
      })}`;
    })
  ];
}
__name(formatGroupLines, "formatGroupLines");
function formatSkillStats(skills) {
  const skillNames = Object.keys(skills.byName).sort((a, b) => {
    const countDelta = skills.byName[b].count - skills.byName[a].count;
    return countDelta !== 0 ? countDelta : a.localeCompare(b);
  });
  if (skillNames.length === 0) {
    return t("No skill usage data yet.");
  }
  return [
    t("Skill calls: {{total}} ({{success}} ok, {{fail}} fail)", {
      total: String(skills.totalCalls),
      success: String(skills.totalSuccess),
      fail: String(skills.totalFail)
    }),
    ...skillNames.map((name) => {
      const stats = skills.byName[name];
      return t("  {{name}}: {{count}} ({{success}} ok, {{fail}} fail)", {
        name,
        count: String(stats.count),
        success: String(stats.success),
        fail: String(stats.fail)
      });
    })
  ].join("\n");
}
__name(formatSkillStats, "formatSkillStats");
function formatTokenUsageSummary(summary) {
  const label = summary.period === "day" ? t("Daily token usage for {{value}}", { value: summary.value }) : t("Monthly token usage for {{value}}", { value: summary.value });
  return [
    label,
    t("Total: {{tokens}} tokens", {
      tokens: formatInteger(summary.totals.totalTokens)
    }),
    t("Requests: {{requests}}", {
      requests: formatInteger(summary.totals.requests)
    }),
    "",
    t("Breakdown:"),
    `  ${t("Input: {{tokens}}", {
      tokens: formatInteger(summary.totals.inputTokens)
    })}`,
    `  ${t("Output: {{tokens}}", {
      tokens: formatInteger(summary.totals.outputTokens)
    })}`,
    `  ${t("Cached (included in Input): {{tokens}}", {
      tokens: formatInteger(summary.totals.cachedTokens)
    })}`,
    `  ${t("Thoughts: {{tokens}}", {
      tokens: formatInteger(summary.totals.thoughtsTokens)
    })}`,
    "",
    ...formatGroupLines("By model:", summary.byModel),
    "",
    ...formatGroupLines("By auth type:", summary.byAuthType),
    "",
    ...formatGroupLines("By model/auth type:", summary.byModelAndAuthType),
    "",
    ...formatGroupLines("By source:", summary.bySource),
    "",
    t("Note: generation timing (TTFT/TPS) belongs to generation metrics.")
  ].join("\n");
}
__name(formatTokenUsageSummary, "formatTokenUsageSummary");
function asMessage(content, messageType = "info") {
  return {
    type: "message",
    messageType,
    content
  };
}
__name(asMessage, "asMessage");
function addInteractiveMessage(context, content, type = "info" /* INFO */) {
  context.ui.addItem(
    {
      type,
      text: content
    },
    Date.now()
  );
}
__name(addInteractiveMessage, "addInteractiveMessage");
async function showTokenUsageStats(context, period, args) {
  try {
    const value = args.trim() || void 0;
    const summary = await queryTokenUsage({ period, value });
    const content = formatTokenUsageSummary(summary);
    if (context.executionMode !== "interactive") {
      return asMessage(content);
    }
    addInteractiveMessage(context, content);
  } catch (error) {
    const content = t("Failed to load token usage stats: {{error}}", {
      error: error instanceof Error ? error.message : String(error)
    });
    if (context.executionMode !== "interactive") {
      return asMessage(content, "error");
    }
    addInteractiveMessage(context, content, "error" /* ERROR */);
  }
}
__name(showTokenUsageStats, "showTokenUsageStats");
function tokenizeArgs(args) {
  const tokens = [];
  let current = "";
  let quote;
  for (let index = 0; index < args.length; index++) {
    const char = args[index];
    if (quote) {
      if (char === "\\") {
        if (args[index + 1] === quote) {
          current += quote;
          index++;
        } else {
          current += char;
        }
        continue;
      }
      if (char === quote) {
        quote = void 0;
      } else {
        current += char;
      }
      continue;
    }
    if (char === '"' || char === "'") {
      quote = char;
      continue;
    }
    if (/\s/.test(char)) {
      if (current.length > 0) {
        tokens.push(current);
        current = "";
      }
      continue;
    }
    current += char;
  }
  if (quote !== void 0) {
    throw new Error(t("Unclosed quote in arguments."));
  }
  if (current.length > 0) {
    tokens.push(current);
  }
  return tokens;
}
__name(tokenizeArgs, "tokenizeArgs");
function isNotFoundError(error) {
  return error.code === "ENOENT";
}
__name(isNotFoundError, "isNotFoundError");
function statsExportPathError() {
  return asMessage(
    t("Token usage export path must be within the project working directory."),
    "error"
  );
}
__name(statsExportPathError, "statsExportPathError");
function statsExportTargetMissingError(targetPath) {
  return asMessage(
    t("Export target does not exist: {{path}}", { path: targetPath }),
    "error"
  );
}
__name(statsExportTargetMissingError, "statsExportTargetMissingError");
async function realpathNearestExisting2(targetDirectory, cwd) {
  let currentDirectory = targetDirectory;
  while (isSubpath(cwd, currentDirectory)) {
    try {
      return await fs11.realpath(currentDirectory);
    } catch (error) {
      if (!isNotFoundError(error)) {
        throw error;
      }
      const parentDirectory = path13.dirname(currentDirectory);
      if (parentDirectory === currentDirectory) {
        break;
      }
      currentDirectory = parentDirectory;
    }
  }
  throw new Error(
    t("Cannot resolve export path within the working directory.")
  );
}
__name(realpathNearestExisting2, "realpathNearestExisting");
async function validateStatsExportExistingParent(cwd, outputDirectory) {
  const [realCwd, realExistingParent] = await Promise.all([
    fs11.realpath(cwd),
    realpathNearestExisting2(outputDirectory, cwd)
  ]);
  if (!isSubpath(realCwd, realExistingParent)) {
    return statsExportPathError();
  }
  return void 0;
}
__name(validateStatsExportExistingParent, "validateStatsExportExistingParent");
async function validateStatsExportDirectory(cwd, outputDirectory) {
  const [realCwd, realOutputDirectory] = await Promise.all([
    fs11.realpath(cwd),
    fs11.realpath(outputDirectory)
  ]);
  if (!isSubpath(realCwd, realOutputDirectory)) {
    return statsExportPathError();
  }
  return void 0;
}
__name(validateStatsExportDirectory, "validateStatsExportDirectory");
function validateStatsExportPathShape(targetPath) {
  if (process.platform === "win32" && path13.basename(targetPath).includes(":")) {
    return statsExportPathError();
  }
  return void 0;
}
__name(validateStatsExportPathShape, "validateStatsExportPathShape");
async function validateStatsExportFileTarget(targetPath) {
  try {
    const stats = await fs11.lstat(targetPath);
    if (stats.isSymbolicLink() || !stats.isFile()) {
      return statsExportPathError();
    }
  } catch (error) {
    if (isNotFoundError(error)) {
      return void 0;
    }
    throw error;
  }
  return void 0;
}
__name(validateStatsExportFileTarget, "validateStatsExportFileTarget");
async function validateStatsExportFinalFile(cwd, targetPath) {
  let stats;
  try {
    stats = await fs11.lstat(targetPath);
  } catch (error) {
    if (isNotFoundError(error)) {
      return statsExportTargetMissingError(targetPath);
    }
    throw error;
  }
  if (stats.isSymbolicLink() || !stats.isFile()) {
    return statsExportPathError();
  }
  const [realCwd, realTargetPath] = await Promise.all([
    fs11.realpath(cwd),
    fs11.realpath(targetPath)
  ]);
  if (!isSubpath(realCwd, realTargetPath)) {
    return statsExportPathError();
  }
  return void 0;
}
__name(validateStatsExportFinalFile, "validateStatsExportFinalFile");
function createTemporaryExportPath(outputDirectory, targetPath) {
  return path13.join(
    outputDirectory,
    `.${path13.basename(targetPath)}.${process.pid}.${Date.now()}.${randomUUID2()}.tmp`
  );
}
__name(createTemporaryExportPath, "createTemporaryExportPath");
function isSamePath(leftPath, rightPath) {
  return isSubpath(leftPath, rightPath) && isSubpath(rightPath, leftPath);
}
__name(isSamePath, "isSamePath");
async function validateStatsExportDirectoryIdentity(cwd, outputDirectory, expectedRealOutputDirectory) {
  const [realCwd, realOutputDirectory] = await Promise.all([
    fs11.realpath(cwd),
    fs11.realpath(outputDirectory)
  ]);
  if (!isSubpath(realCwd, realOutputDirectory) || !isSamePath(expectedRealOutputDirectory, realOutputDirectory)) {
    return statsExportPathError();
  }
  return void 0;
}
__name(validateStatsExportDirectoryIdentity, "validateStatsExportDirectoryIdentity");
async function writeStatsExportFileAtomically(cwd, outputDirectory, targetPath, content) {
  const initialDirectoryError = await validateStatsExportDirectory(
    cwd,
    outputDirectory
  );
  if (initialDirectoryError) {
    return initialDirectoryError;
  }
  const [realCwd, realOutputDirectory] = await Promise.all([
    fs11.realpath(cwd),
    fs11.realpath(outputDirectory)
  ]);
  const realTargetPath = path13.join(
    realOutputDirectory,
    path13.basename(targetPath)
  );
  if (!isSubpath(realCwd, realTargetPath)) {
    return statsExportPathError();
  }
  for (let attempt = 0; attempt < 10; attempt++) {
    let tempPath = createTemporaryExportPath(
      realOutputDirectory,
      targetPath
    );
    try {
      if (!isSubpath(realCwd, tempPath)) {
        return statsExportPathError();
      }
      const preTempDirectoryError = await validateStatsExportDirectoryIdentity(
        cwd,
        outputDirectory,
        realOutputDirectory
      );
      if (preTempDirectoryError) {
        return preTempDirectoryError;
      }
      const preTempFileError = await validateStatsExportFileTarget(realTargetPath);
      if (preTempFileError) {
        return preTempFileError;
      }
      const file = await fs11.open(tempPath, "wx", 384);
      try {
        await file.writeFile(content, { encoding: "utf-8" });
      } finally {
        await file.close();
      }
      const tempFileError = await validateStatsExportFinalFile(cwd, tempPath);
      if (tempFileError) {
        return tempFileError;
      }
      const preRenameDirectoryError = await validateStatsExportDirectoryIdentity(
        cwd,
        outputDirectory,
        realOutputDirectory
      );
      if (preRenameDirectoryError) {
        return preRenameDirectoryError;
      }
      const preRenameFileError = await validateStatsExportFileTarget(realTargetPath);
      if (preRenameFileError) {
        return preRenameFileError;
      }
      await fs11.rename(tempPath, realTargetPath);
      tempPath = void 0;
      return validateStatsExportFinalFile(cwd, realTargetPath);
    } catch (error) {
      if (error.code === "EEXIST") {
        continue;
      }
      throw error;
    } finally {
      if (tempPath) {
        await fs11.rm(tempPath, { force: true }).catch(() => void 0);
      }
    }
  }
  throw new Error(t("Could not create a temporary export file."));
}
__name(writeStatsExportFileAtomically, "writeStatsExportFileAtomically");
function parseStatsExportArgs(args) {
  const tokens = tokenizeArgs(args);
  let period;
  let value;
  let format = "csv";
  let outputPath;
  for (let index = 0; index < tokens.length; index++) {
    const token = tokens[index];
    if (token === "--format" || token === "-f") {
      const next = tokens[++index];
      if (!next || !VALID_EXPORT_FORMATS.has(next)) {
        throw new Error(t("Expected --format csv or --format json."));
      }
      format = next;
      continue;
    }
    if (token.startsWith("--format=")) {
      const next = token.slice("--format=".length);
      if (!VALID_EXPORT_FORMATS.has(next)) {
        throw new Error(t("Expected --format csv or --format json."));
      }
      format = next;
      continue;
    }
    if (token === "--output" || token === "-o") {
      const next = tokens[++index];
      if (!next) {
        throw new Error(t("Expected a file path after --output."));
      }
      outputPath = next;
      continue;
    }
    if (token.startsWith("--output=")) {
      outputPath = token.slice("--output=".length);
      continue;
    }
    if (!period && (token === "daily" || token === "day")) {
      period = "day";
      continue;
    }
    if (!period && (token === "monthly" || token === "month")) {
      period = "month";
      continue;
    }
    if (!value) {
      value = token;
      continue;
    }
    if (!outputPath) {
      outputPath = token;
      continue;
    }
    throw new Error(
      t("Unexpected argument: {{argument}}", { argument: token })
    );
  }
  if (!period) {
    throw new Error(
      t(
        "Usage: /stats export <daily|monthly> [YYYY-MM-DD|YYYY-MM] [--format csv|json] [--output path]"
      )
    );
  }
  return {
    period,
    value,
    format,
    outputPath
  };
}
__name(parseStatsExportArgs, "parseStatsExportArgs");
function getConfigCwd(context) {
  const config = context.services.config;
  return config?.getWorkingDir() || config?.getProjectRoot() || process.cwd();
}
__name(getConfigCwd, "getConfigCwd");
async function writeStatsExport(context, args) {
  try {
    const parsed = parseStatsExportArgs(args);
    const summary = await queryTokenUsage({
      period: parsed.period,
      value: parsed.value
    });
    const content = parsed.format === "json" ? formatTokenUsageSummaryAsJson(summary) : `${formatTokenUsageSummaryAsCsv(summary)}
`;
    const cwd = path13.resolve(getConfigCwd(context));
    const defaultFilename = `qwen-token-usage-${summary.period}-${summary.value}.${parsed.format}`;
    const targetPath = path13.resolve(cwd, parsed.outputPath || defaultFilename);
    const outputDirectory = path13.dirname(targetPath);
    if (!isSubpath(cwd, targetPath) || !isSubpath(cwd, outputDirectory)) {
      return statsExportPathError();
    }
    const pathShapeError = validateStatsExportPathShape(targetPath);
    if (pathShapeError) {
      return pathShapeError;
    }
    const parentError = await validateStatsExportExistingParent(
      cwd,
      outputDirectory
    );
    if (parentError) {
      return parentError;
    }
    await fs11.mkdir(outputDirectory, { recursive: true });
    const postMkdirError = await validateStatsExportDirectory(
      cwd,
      outputDirectory
    );
    if (postMkdirError) {
      return postMkdirError;
    }
    const preWriteFileError = await validateStatsExportFileTarget(targetPath);
    if (preWriteFileError) {
      return preWriteFileError;
    }
    const writeError = await writeStatsExportFileAtomically(
      cwd,
      outputDirectory,
      targetPath,
      content
    );
    if (writeError) {
      return writeError;
    }
    return asMessage(
      t("Token usage exported to {{format}}: {{path}}", {
        format: parsed.format.toUpperCase(),
        path: path13.relative(cwd, targetPath)
      })
    );
  } catch (error) {
    return asMessage(
      t("Failed to export token usage stats: {{error}}", {
        error: error instanceof Error ? error.message : String(error)
      }),
      "error"
    );
  }
}
__name(writeStatsExport, "writeStatsExport");
var statsCommand = {
  name: "stats",
  altNames: ["usage"],
  get description() {
    return t("Show usage statistics dashboard.");
  },
  argumentHint: "[model|tools|skills|daily|monthly|export]",
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive", "non_interactive", "acp"],
  action: /* @__PURE__ */ __name((context) => {
    if (context.executionMode !== "interactive") {
      const now = /* @__PURE__ */ new Date();
      const { sessionStartTime, promptCount, metrics } = context.session.stats;
      const wallDuration = sessionStartTime ? now.getTime() - sessionStartTime.getTime() : 0;
      let totalPromptTokens = 0;
      let totalCandidateTokens = 0;
      let totalRequests = 0;
      for (const modelMetrics of Object.values(metrics.models)) {
        totalPromptTokens += modelMetrics.tokens.prompt;
        totalCandidateTokens += modelMetrics.tokens.candidates;
        totalRequests += modelMetrics.api.totalRequests;
      }
      return {
        type: "message",
        messageType: "info",
        content: [
          t("Session duration: {{duration}}", {
            duration: formatDuration(wallDuration)
          }),
          t("Prompts: {{count}}", { count: String(promptCount) }),
          t("API requests: {{count}}", { count: String(totalRequests) }),
          t("Tokens \u2014 prompt: {{prompt}}, output: {{output}}", {
            prompt: String(totalPromptTokens),
            output: String(totalCandidateTokens)
          }),
          t("Tool calls: {{total}} ({{success}} ok, {{fail}} fail)", {
            total: String(metrics.tools.totalCalls),
            success: String(metrics.tools.totalSuccess),
            fail: String(metrics.tools.totalFail)
          }),
          t("Files: +{{added}} / -{{removed}} lines", {
            added: String(metrics.files.totalLinesAdded),
            removed: String(metrics.files.totalLinesRemoved)
          })
        ].join("\n")
      };
    }
    return { type: "dialog", dialog: "stats" };
  }, "action"),
  subCommands: [
    {
      name: "model",
      get description() {
        return t("Show model-specific usage statistics.");
      },
      kind: "built-in" /* BUILT_IN */,
      supportedModes: ["interactive", "non_interactive", "acp"],
      action: /* @__PURE__ */ __name((context) => {
        if (context.executionMode !== "interactive") {
          const { metrics } = context.session.stats;
          const pricing = context.services.settings.merged.modelPricing;
          const lines = [];
          for (const [modelName, modelMetrics] of Object.entries(
            metrics.models
          )) {
            lines.push(
              `${modelName}: ${t("prompt")}=${modelMetrics.tokens.prompt}, ${t("output")}=${modelMetrics.tokens.candidates}, ${t("cached")}=${modelMetrics.tokens.cached}`
            );
            const cost = calculateCost({
              inputTokens: modelMetrics.tokens.prompt,
              outputTokens: modelMetrics.tokens.candidates + modelMetrics.tokens.thoughts,
              pricing: pricing?.[modelName]
            });
            if (cost != null) {
              lines.push(
                `  ${t("Estimated cost: ${{cost}}", { cost: cost.toFixed(4) })}`
              );
            }
          }
          if (lines.length === 0) {
            lines.push(t("No model usage data yet."));
          }
          return {
            type: "message",
            messageType: "info",
            content: lines.join("\n")
          };
        }
        context.ui.addItem(
          {
            type: "model_stats" /* MODEL_STATS */
          },
          Date.now()
        );
      }, "action")
    },
    {
      name: "tools",
      get description() {
        return t("Show tool-specific usage statistics.");
      },
      kind: "built-in" /* BUILT_IN */,
      supportedModes: ["interactive", "non_interactive", "acp"],
      action: /* @__PURE__ */ __name((context) => {
        if (context.executionMode !== "interactive") {
          const { metrics } = context.session.stats;
          const { tools } = metrics;
          const toolNames = Object.keys(tools.byName);
          const content = toolNames.length > 0 ? [
            t("Tool calls: {{total}} ({{success}} ok, {{fail}} fail)", {
              total: String(tools.totalCalls),
              success: String(tools.totalSuccess),
              fail: String(tools.totalFail)
            }),
            ...toolNames.map((name) => `  ${name}`)
          ].join("\n") : t("No tool usage data yet.");
          return { type: "message", messageType: "info", content };
        }
        context.ui.addItem(
          {
            type: "tool_stats" /* TOOL_STATS */
          },
          Date.now()
        );
      }, "action")
    },
    {
      name: "skills",
      get description() {
        return t("Show skill-specific usage statistics.");
      },
      kind: "built-in" /* BUILT_IN */,
      supportedModes: ["interactive", "non_interactive", "acp"],
      action: /* @__PURE__ */ __name((context) => {
        if (context.executionMode !== "interactive") {
          const skills = context.session.stats.metrics.skills ?? EMPTY_SKILL_METRICS;
          return {
            type: "message",
            messageType: "info",
            content: formatSkillStats(skills)
          };
        }
        context.ui.addItem(
          {
            type: "skill_stats" /* SKILL_STATS */
          },
          Date.now()
        );
      }, "action")
    },
    {
      name: "daily",
      altNames: ["day"],
      get description() {
        return t("Show daily token usage statistics.");
      },
      argumentHint: "[YYYY-MM-DD]",
      kind: "built-in" /* BUILT_IN */,
      supportedModes: ["interactive", "non_interactive", "acp"],
      action: /* @__PURE__ */ __name((context, args) => showTokenUsageStats(context, "day", args), "action")
    },
    {
      name: "monthly",
      altNames: ["month"],
      get description() {
        return t("Show monthly token usage statistics.");
      },
      argumentHint: "[YYYY-MM]",
      kind: "built-in" /* BUILT_IN */,
      supportedModes: ["interactive", "non_interactive", "acp"],
      action: /* @__PURE__ */ __name((context, args) => showTokenUsageStats(context, "month", args), "action")
    },
    {
      name: "export",
      get description() {
        return t("Export token usage statistics to CSV or JSON.");
      },
      argumentHint: "<daily|monthly> [date|month] [--format csv|json] [--output path]",
      kind: "built-in" /* BUILT_IN */,
      supportedModes: ["interactive", "non_interactive", "acp"],
      action: /* @__PURE__ */ __name(async (context, args) => {
        const result = await writeStatsExport(context, args);
        if (context.executionMode !== "interactive") {
          return result;
        }
        addInteractiveMessage(
          context,
          result.content,
          result.messageType === "error" ? "error" /* ERROR */ : "info" /* INFO */
        );
      }, "action")
    }
  ]
};

// packages/cli/src/ui/commands/summaryCommand.ts
init_esbuild_shims();
import * as fsPromises from "fs/promises";
import path14 from "path";
var summaryCommand = {
  name: "summary",
  get description() {
    return t(
      "Generate a project summary and save it to .qwen/PROJECT_SUMMARY.md"
    );
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive", "non_interactive", "acp"],
  action: /* @__PURE__ */ __name(async (context) => {
    const { config } = context.services;
    const { ui } = context;
    const executionMode = context.executionMode ?? "interactive";
    const abortSignal = context.abortSignal;
    if (!config) {
      return {
        type: "message",
        messageType: "error",
        content: t("Config not loaded.")
      };
    }
    const geminiClient = config.getGeminiClient();
    if (!geminiClient) {
      return {
        type: "message",
        messageType: "error",
        content: t("No chat client available to generate summary.")
      };
    }
    if (executionMode === "interactive" && ui.pendingItem) {
      ui.addItem(
        {
          type: "error",
          text: t(
            "Already generating summary, wait for previous request to complete"
          )
        },
        Date.now()
      );
      return {
        type: "message",
        messageType: "error",
        content: t(
          "Already generating summary, wait for previous request to complete"
        )
      };
    }
    const getChatHistory = /* @__PURE__ */ __name(() => {
      const chat = geminiClient.getChat();
      return chat.getHistoryShallow();
    }, "getChatHistory");
    const validateChatHistory = /* @__PURE__ */ __name((history2) => {
      if (history2.length <= 2) {
        throw new Error(t("No conversation found to summarize."));
      }
    }, "validateChatHistory");
    const generateSummaryMarkdown = /* @__PURE__ */ __name(async (history2) => {
      const conversationContext = history2.map((message) => ({
        role: message.role,
        parts: message.parts
      }));
      const rawSystemInstruction = geminiClient.getChat().getGenerationConfig().systemInstruction;
      const chatSystemInstruction = typeof rawSystemInstruction === "string" ? rawSystemInstruction : void 0;
      const result = await runSideQuery(config, {
        purpose: "project-summary",
        skipOutputLanguagePreference: true,
        model: config.getModel(),
        systemInstruction: chatSystemInstruction,
        contents: [
          ...conversationContext,
          {
            role: "user",
            parts: [
              {
                text: getProjectSummaryPrompt()
              }
            ]
          }
        ],
        abortSignal: abortSignal ?? new AbortController().signal
      });
      if (!result.text) {
        throw new Error(
          t(
            "Failed to generate summary - no text content received from LLM response"
          )
        );
      }
      return result.text;
    }, "generateSummaryMarkdown");
    const saveSummaryToDisk = /* @__PURE__ */ __name(async (markdownSummary) => {
      const projectRoot = config.getProjectRoot();
      const qwenDir = path14.join(projectRoot, ".qwen");
      try {
        await fsPromises.mkdir(qwenDir, { recursive: true });
      } catch (_err) {
      }
      const summaryPath = path14.join(qwenDir, "PROJECT_SUMMARY.md");
      const summaryContent = `${markdownSummary}

---

## Summary Metadata
**Update time**: ${(/* @__PURE__ */ new Date()).toISOString()} 
`;
      await fsPromises.writeFile(summaryPath, summaryContent, "utf8");
      return {
        filePathForDisplay: ".qwen/PROJECT_SUMMARY.md",
        fullPath: summaryPath
      };
    }, "saveSummaryToDisk");
    const emitInteractivePending = /* @__PURE__ */ __name((stage) => {
      if (executionMode !== "interactive") {
        return;
      }
      const pendingMessage = {
        type: "summary",
        summary: {
          isPending: true,
          stage
        }
      };
      ui.setPendingItem(pendingMessage);
    }, "emitInteractivePending");
    const completeInteractive = /* @__PURE__ */ __name((filePathForDisplay) => {
      if (executionMode !== "interactive") {
        return;
      }
      ui.setPendingItem(null);
      const completedSummaryItem = {
        type: "summary",
        summary: {
          isPending: false,
          stage: "completed",
          filePath: filePathForDisplay
        }
      };
      ui.addItem(completedSummaryItem, Date.now());
    }, "completeInteractive");
    const formatErrorMessage3 = /* @__PURE__ */ __name((error) => t("Failed to generate project context summary: {{error}}", {
      error: error instanceof Error ? error.message : String(error)
    }), "formatErrorMessage");
    const failInteractive = /* @__PURE__ */ __name((error) => {
      if (executionMode !== "interactive") {
        return;
      }
      if (abortSignal?.aborted) {
        return;
      }
      ui.setPendingItem(null);
      ui.addItem(
        {
          type: "error",
          text: `\u2717 ${formatErrorMessage3(error)}`
        },
        Date.now()
      );
    }, "failInteractive");
    const formatSuccessMessage = /* @__PURE__ */ __name((filePathForDisplay) => t("Saved project summary to {{filePathForDisplay}}.", {
      filePathForDisplay
    }), "formatSuccessMessage");
    const returnNoConversationMessage = /* @__PURE__ */ __name(() => {
      const msg = t("No conversation found to summarize.");
      if (executionMode === "acp") {
        const messages = /* @__PURE__ */ __name(async function* () {
          yield {
            messageType: "info",
            content: msg
          };
        }, "messages");
        return {
          type: "stream_messages",
          messages: messages()
        };
      }
      return {
        type: "message",
        messageType: "info",
        content: msg
      };
    }, "returnNoConversationMessage");
    const executeSummaryGeneration = /* @__PURE__ */ __name(async (history2) => {
      emitInteractivePending("generating");
      const markdownSummary = await generateSummaryMarkdown(history2);
      if (abortSignal?.aborted) {
        throw new DOMException("Summary generation cancelled.", "AbortError");
      }
      emitInteractivePending("saving");
      const { filePathForDisplay } = await saveSummaryToDisk(markdownSummary);
      completeInteractive(filePathForDisplay);
      return { markdownSummary, filePathForDisplay };
    }, "executeSummaryGeneration");
    const history = getChatHistory();
    try {
      validateChatHistory(history);
    } catch (_error) {
      return returnNoConversationMessage();
    }
    if (executionMode === "acp") {
      const messages = /* @__PURE__ */ __name(async function* () {
        try {
          yield {
            messageType: "info",
            content: t("Generating project summary...")
          };
          const { filePathForDisplay } = await executeSummaryGeneration(history);
          yield {
            messageType: "info",
            content: formatSuccessMessage(filePathForDisplay)
          };
        } catch (error) {
          failInteractive(error);
          yield {
            messageType: "error",
            content: formatErrorMessage3(error)
          };
        }
      }, "messages");
      return {
        type: "stream_messages",
        messages: messages()
      };
    }
    try {
      const { filePathForDisplay } = await executeSummaryGeneration(history);
      if (executionMode === "non_interactive") {
        return {
          type: "message",
          messageType: "info",
          content: formatSuccessMessage(filePathForDisplay)
        };
      }
      return {
        type: "message",
        messageType: "info",
        content: ""
      };
    } catch (error) {
      failInteractive(error);
      return {
        type: "message",
        messageType: "error",
        content: formatErrorMessage3(error)
      };
    }
  }, "action")
};

// packages/cli/src/ui/commands/terminalSetupCommand.ts
init_esbuild_shims();

// packages/cli/src/ui/utils/terminalSetup.ts
init_esbuild_shims();
import { promises as fs12 } from "node:fs";
import * as os5 from "node:os";
import * as path15 from "node:path";
import { exec } from "node:child_process";
import { promisify } from "node:util";
var debugLogger12 = createDebugLogger("TERMINAL_SETUP");
var execAsync = promisify(exec);
function stripJsonComments2(content) {
  return content.replace(/^\s*\/\/.*$/gm, "");
}
__name(stripJsonComments2, "stripJsonComments");
async function detectTerminal() {
  const termProgram = process.env["TERM_PROGRAM"];
  if (process.env["CURSOR_TRACE_ID"] || process.env["VSCODE_GIT_ASKPASS_MAIN"]?.toLowerCase().includes("cursor")) {
    return "cursor";
  }
  if (process.env["VSCODE_GIT_ASKPASS_MAIN"]?.toLowerCase().includes("windsurf")) {
    return "windsurf";
  }
  if (process.env["TERM_PRODUCT"]?.toLowerCase().includes("trae")) {
    return "trae";
  }
  if (termProgram === "vscode" || process.env["VSCODE_GIT_IPC_HANDLE"]) {
    return "vscode";
  }
  if (os5.platform() !== "win32") {
    try {
      const { stdout } = await execAsync("ps -o comm= -p $PPID");
      const parentName = stdout.trim();
      if (parentName.includes("windsurf") || parentName.includes("Windsurf"))
        return "windsurf";
      if (parentName.includes("cursor") || parentName.includes("Cursor"))
        return "cursor";
      if (parentName.includes("code") || parentName.includes("Code"))
        return "vscode";
      if (parentName.includes("trae") || parentName.includes("Trae"))
        return "trae";
    } catch (error) {
      debugLogger12.debug("Parent process detection failed:", error);
    }
  }
  return null;
}
__name(detectTerminal, "detectTerminal");
async function backupFile(filePath) {
  try {
    const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
    const backupPath = `${filePath}.backup.${timestamp}`;
    await fs12.copyFile(filePath, backupPath);
  } catch (error) {
    debugLogger12.warn(`Failed to create backup of ${filePath}:`, error);
  }
}
__name(backupFile, "backupFile");
function getVSCodeStyleConfigDir(appName) {
  const platform3 = os5.platform();
  if (platform3 === "darwin") {
    return path15.join(
      os5.homedir(),
      "Library",
      "Application Support",
      appName,
      "User"
    );
  } else if (platform3 === "win32") {
    if (!process.env["APPDATA"]) {
      return null;
    }
    return path15.join(process.env["APPDATA"], appName, "User");
  } else {
    return path15.join(os5.homedir(), ".config", appName, "User");
  }
}
__name(getVSCodeStyleConfigDir, "getVSCodeStyleConfigDir");
async function configureVSCodeStyle(terminalName, appName) {
  const configDir = getVSCodeStyleConfigDir(appName);
  if (!configDir) {
    return {
      success: false,
      message: t(
        "Could not determine {{terminalName}} config path on Windows: APPDATA environment variable is not set.",
        { terminalName }
      )
    };
  }
  const keybindingsFile = path15.join(configDir, "keybindings.json");
  try {
    await fs12.mkdir(configDir, { recursive: true });
    let keybindings = [];
    try {
      const content = await fs12.readFile(keybindingsFile, "utf8");
      await backupFile(keybindingsFile);
      try {
        const cleanContent = stripJsonComments2(content);
        const parsedContent = JSON.parse(cleanContent);
        if (!Array.isArray(parsedContent)) {
          return {
            success: false,
            message: t(
              "{{terminalName}} keybindings.json exists but is not a valid JSON array. Please fix the file manually or delete it to allow automatic configuration.",
              { terminalName }
            ) + "\n" + t("File: {{file}}", { file: keybindingsFile })
          };
        }
        keybindings = parsedContent;
      } catch (parseError) {
        return {
          success: false,
          message: t(
            "Failed to parse {{terminalName}} keybindings.json. The file contains invalid JSON. Please fix the file manually or delete it to allow automatic configuration.",
            { terminalName }
          ) + "\n" + t("File: {{file}}", { file: keybindingsFile }) + "\n" + t("Error: {{error}}", { error: String(parseError) })
        };
      }
    } catch {
    }
    const shiftEnterBinding = {
      key: "shift+enter",
      command: "workbench.action.terminal.sendSequence",
      when: "terminalFocus",
      args: { text: VSCODE_SHIFT_ENTER_SEQUENCE }
    };
    const ctrlEnterBinding = {
      key: "ctrl+enter",
      command: "workbench.action.terminal.sendSequence",
      when: "terminalFocus",
      args: { text: VSCODE_SHIFT_ENTER_SEQUENCE }
    };
    const existingShiftEnter = keybindings.find((kb) => {
      const binding = kb;
      return binding.key === "shift+enter";
    });
    const existingCtrlEnter = keybindings.find((kb) => {
      const binding = kb;
      return binding.key === "ctrl+enter";
    });
    if (existingShiftEnter || existingCtrlEnter) {
      const messages = [];
      if (existingShiftEnter) {
        messages.push("- " + t("Shift+Enter binding already exists"));
      }
      if (existingCtrlEnter) {
        messages.push("- " + t("Ctrl+Enter binding already exists"));
      }
      return {
        success: false,
        message: t(
          "Existing keybindings detected. Will not modify to avoid conflicts."
        ) + "\n" + messages.join("\n") + "\n" + t("Please check and modify manually if needed: {{file}}", {
          file: keybindingsFile
        })
      };
    }
    const hasOurShiftEnter = keybindings.some((kb) => {
      const binding = kb;
      return binding.key === "shift+enter" && binding.command === "workbench.action.terminal.sendSequence" && binding.args?.text === "\\\r\n";
    });
    const hasOurCtrlEnter = keybindings.some((kb) => {
      const binding = kb;
      return binding.key === "ctrl+enter" && binding.command === "workbench.action.terminal.sendSequence" && binding.args?.text === "\\\r\n";
    });
    if (!hasOurShiftEnter || !hasOurCtrlEnter) {
      if (!hasOurShiftEnter) keybindings.unshift(shiftEnterBinding);
      if (!hasOurCtrlEnter) keybindings.unshift(ctrlEnterBinding);
      await fs12.writeFile(keybindingsFile, JSON.stringify(keybindings, null, 4));
      return {
        success: true,
        message: t(
          "Added Shift+Enter and Ctrl+Enter keybindings to {{terminalName}}.",
          {
            terminalName
          }
        ) + "\n" + t("Modified: {{file}}", { file: keybindingsFile }),
        requiresRestart: true
      };
    } else {
      return {
        success: true,
        message: t("{{terminalName}} keybindings already configured.", {
          terminalName
        })
      };
    }
  } catch (error) {
    return {
      success: false,
      message: t("Failed to configure {{terminalName}}.", { terminalName }) + "\n" + t("File: {{file}}", { file: keybindingsFile }) + "\n" + t("Error: {{error}}", { error: String(error) })
    };
  }
}
__name(configureVSCodeStyle, "configureVSCodeStyle");
async function configureVSCode() {
  return configureVSCodeStyle("VS Code", "Code");
}
__name(configureVSCode, "configureVSCode");
async function configureCursor() {
  return configureVSCodeStyle("Cursor", "Cursor");
}
__name(configureCursor, "configureCursor");
async function configureWindsurf() {
  return configureVSCodeStyle("Windsurf", "Windsurf");
}
__name(configureWindsurf, "configureWindsurf");
async function configureTrae() {
  return configureVSCodeStyle("Trae", "Trae");
}
__name(configureTrae, "configureTrae");
async function terminalSetup() {
  if (isKittyProtocolEnabled()) {
    return {
      success: true,
      message: t(
        "Your terminal is already configured for an optimal experience with multiline input (Shift+Enter and Ctrl+Enter)."
      )
    };
  }
  const terminal = await detectTerminal();
  if (!terminal) {
    return {
      success: false,
      message: t(
        "Could not detect terminal type. Supported terminals: VS Code, Cursor, Windsurf, and Trae."
      )
    };
  }
  switch (terminal) {
    case "vscode":
      return configureVSCode();
    case "cursor":
      return configureCursor();
    case "windsurf":
      return configureWindsurf();
    case "trae":
      return configureTrae();
    default:
      return {
        success: false,
        message: t('Terminal "{{terminal}}" is not supported yet.', {
          terminal
        })
      };
  }
}
__name(terminalSetup, "terminalSetup");

// packages/cli/src/ui/commands/terminalSetupCommand.ts
var terminalSetupCommand = {
  name: "terminal-setup",
  get description() {
    return t(
      "Configure terminal keybindings for multiline input (VS Code, Cursor, Windsurf, Trae)"
    );
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive"],
  action: /* @__PURE__ */ __name(async () => {
    try {
      const result = await terminalSetup();
      let content = result.message;
      if (result.requiresRestart) {
        content += "\n\n" + t("Please restart your terminal for the changes to take effect.");
      }
      return {
        type: "message",
        content,
        messageType: result.success ? "info" : "error"
      };
    } catch (error) {
      return {
        type: "message",
        content: t("Failed to configure terminal: {{error}}", {
          error: String(error)
        }),
        messageType: "error"
      };
    }
  }, "action")
};

// packages/cli/src/ui/commands/themeCommand.ts
init_esbuild_shims();
var themeCommand = {
  name: "theme",
  get description() {
    return t("change the theme");
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive"],
  action: /* @__PURE__ */ __name((_context, _args) => ({
    type: "dialog",
    dialog: "theme"
  }), "action")
};

// packages/cli/src/ui/commands/toolsCommand.ts
init_esbuild_shims();
var toolsCommand = {
  name: "tools",
  get description() {
    return t("List available Qwen Code tools. Usage: /tools [desc]");
  },
  kind: "built-in" /* BUILT_IN */,
  action: /* @__PURE__ */ __name(async (context, args) => {
    const subCommand = args?.trim();
    let useShowDescriptions = false;
    if (subCommand === "desc" || subCommand === "descriptions") {
      useShowDescriptions = true;
    }
    const toolRegistry = context.services.config?.getToolRegistry();
    if (!toolRegistry) {
      context.ui.addItem(
        {
          type: "error" /* ERROR */,
          text: t("Could not retrieve tool registry.")
        },
        Date.now()
      );
      return;
    }
    const tools = toolRegistry.getAllTools();
    const geminiTools = tools.filter((tool) => !("serverName" in tool));
    const toolsListItem = {
      type: "tools_list" /* TOOLS_LIST */,
      tools: geminiTools.map((tool) => ({
        name: tool.name,
        displayName: tool.displayName,
        description: tool.description
      })),
      showDescriptions: useShowDescriptions
    };
    context.ui.addItem(toolsListItem, Date.now());
  }, "action")
};

// packages/cli/src/ui/commands/vimCommand.ts
init_esbuild_shims();
var vimCommand = {
  name: "vim",
  get description() {
    return t("toggle vim mode on/off");
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive"],
  action: /* @__PURE__ */ __name(async (context, _args) => {
    const newVimState = await context.ui.toggleVimEnabled();
    const message = newVimState ? "Entered Vim mode. Run /vim again to exit." : "Exited Vim mode.";
    return {
      type: "message",
      messageType: "info",
      content: message
    };
  }, "action")
};

// packages/cli/src/ui/commands/voice-command.ts
init_esbuild_shims();

// packages/cli/src/ui/voice/voice-availability.ts
init_esbuild_shims();
import { existsSync as existsSync4 } from "node:fs";
import process5 from "node:process";
var SUPPORTED_PLATFORMS = [
  "darwin",
  "linux",
  "win32"
];
function isWsl(env) {
  return Boolean(env["WSL_DISTRO_NAME"] || env["WSL_INTEROP"]);
}
__name(isWsl, "isWsl");
function getVoiceUnavailableReason(environment = {
  platform: process5.platform,
  env: process5.env
}) {
  const { platform: platform3, env } = environment;
  const fileExists = environment.fileExists ?? existsSync4;
  if (!SUPPORTED_PLATFORMS.includes(platform3)) {
    return t("Voice dictation is not supported on {{platform}}.", {
      platform: platform3
    });
  }
  if (platform3 === "linux" && isWsl(env) && !env["PULSE_SERVER"] && !fileExists("/mnt/wslg/PulseServer")) {
    return t(
      "Voice dictation needs microphone access, which is unavailable in this WSL session. Use WSLg/PulseAudio, or run Qwen Code on a host with a microphone."
    );
  }
  return void 0;
}
__name(getVoiceUnavailableReason, "getVoiceUnavailableReason");

// packages/cli/src/ui/commands/voice-command.ts
var voiceCommand = {
  name: "voice",
  get description() {
    return t("Toggle voice dictation input");
  },
  argumentHint: "[hold|tap|off|status]",
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive"],
  action: /* @__PURE__ */ __name((context, args) => {
    const settings = context.services.settings;
    const command = args.trim().toLowerCase();
    if (command === "status") {
      const voiceModel2 = readVoiceModel(settings);
      const status = isVoiceEnabled(settings) ? "enabled" : "disabled";
      const modelText = voiceModel2 ? t("model: {{voiceModel}}", { voiceModel: voiceModel2 }) : t("no voice model selected");
      return {
        type: "message",
        messageType: "info",
        content: t(
          "Voice dictation: {{status}} (mode: {{mode}}, {{modelText}}).",
          {
            status,
            mode: readVoiceMode(settings),
            modelText
          }
        )
      };
    }
    if (command === "off") {
      settings.setValue(
        getVoiceSettingsScope(settings),
        "general.voice.enabled",
        false
      );
      return {
        type: "message",
        messageType: "info",
        content: t("Voice dictation disabled.")
      };
    }
    if (command !== "" && command !== "hold" && command !== "tap") {
      return {
        type: "message",
        messageType: "warning",
        content: t("Usage: /voice [hold|tap|off|status]")
      };
    }
    if (command === "" && isVoiceEnabled(settings)) {
      settings.setValue(
        getVoiceSettingsScope(settings),
        "general.voice.enabled",
        false
      );
      return {
        type: "message",
        messageType: "info",
        content: t("Voice dictation disabled.")
      };
    }
    const voiceModel = readVoiceModel(settings);
    if (!voiceModel) {
      return {
        type: "message",
        messageType: "warning",
        content: t(
          "No voice model selected. Run /model --voice to choose one before enabling voice dictation."
        )
      };
    }
    const unavailableReason = getVoiceUnavailableReason();
    if (unavailableReason) {
      return {
        type: "message",
        messageType: "warning",
        content: unavailableReason
      };
    }
    const scope = getVoiceSettingsScope(settings);
    const mode = command === "tap" ? "tap" : command === "hold" ? "hold" : readVoiceMode(settings);
    settings.setValue(scope, "general.voice.mode", mode);
    settings.setValue(scope, "general.voice.enabled", true);
    return {
      type: "message",
      messageType: "info",
      content: mode === "tap" ? t(
        "Voice dictation enabled (tap mode). Tap Space at an empty prompt to start, tap again or pause to stop and submit, using {{voiceModel}}.",
        { voiceModel }
      ) : t(
        "Voice dictation enabled (hold mode). Hold Space at an empty prompt to dictate with {{voiceModel}}.",
        { voiceModel }
      )
    };
  }, "action")
};

// packages/cli/src/ui/commands/setupGithubCommand.ts
init_esbuild_shims();
function getOpenUrlsCommands(readmeUrl, secretsUrl) {
  const openCmd = getUrlOpenCommand();
  const urlsToOpen = [readmeUrl];
  if (secretsUrl) urlsToOpen.push(secretsUrl);
  const commands = urlsToOpen.map((url) => `${openCmd} "${url}"`);
  return commands;
}
__name(getOpenUrlsCommands, "getOpenUrlsCommands");
var setupGithubCommand = {
  name: "setup-github",
  get description() {
    return t("Set up GitHub Actions");
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive"],
  action: /* @__PURE__ */ __name(async (context) => {
    const abortController = new AbortController();
    if (context.abortSignal) {
      context.abortSignal.addEventListener(
        "abort",
        () => abortController.abort(),
        { once: true }
      );
    }
    const proxy = context?.services?.config?.getProxy();
    const result = await setupGithub({
      proxy,
      abortSignal: abortController.signal
    }).finally(() => abortController.abort());
    const commands = [];
    commands.push("set -eEuo pipefail");
    commands.push(
      `echo "Successfully downloaded ${GITHUB_WORKFLOW_PATHS.length} workflows and updated .gitignore. Follow the steps in ${result.readmeUrl} (skipping the /setup-github step) to complete setup."`
    );
    commands.push(...getOpenUrlsCommands(result.readmeUrl, result.secretsUrl));
    const command = `(${commands.join(" && ")})`;
    return {
      type: "tool",
      toolName: "run_shell_command",
      toolArgs: {
        description: "Setting up GitHub Actions to triage issues and review PRs with Qwen.",
        command,
        is_background: false
      }
    };
  }, "action")
};

// packages/cli/src/ui/commands/insightCommand.ts
init_esbuild_shims();
import { join as join9 } from "path";
import { pathToFileURL } from "node:url";

// packages/cli/src/services/insight/generators/StaticInsightGenerator.ts
init_esbuild_shims();
import fs14 from "fs/promises";
import path17 from "path";

// packages/cli/src/services/insight/generators/DataProcessor.ts
init_esbuild_shims();
import fs13 from "fs/promises";
import path16 from "path";

// packages/cli/node_modules/p-limit/index.js
init_esbuild_shims();

// packages/cli/node_modules/yocto-queue/index.js
init_esbuild_shims();
var Node = class {
  static {
    __name(this, "Node");
  }
  value;
  next;
  constructor(value) {
    this.value = value;
  }
};
var Queue = class {
  static {
    __name(this, "Queue");
  }
  #head;
  #tail;
  #size;
  constructor() {
    this.clear();
  }
  enqueue(value) {
    const node = new Node(value);
    if (this.#head) {
      this.#tail.next = node;
      this.#tail = node;
    } else {
      this.#head = node;
      this.#tail = node;
    }
    this.#size++;
  }
  dequeue() {
    const current = this.#head;
    if (!current) {
      return;
    }
    this.#head = this.#head.next;
    this.#size--;
    if (!this.#head) {
      this.#tail = void 0;
    }
    return current.value;
  }
  peek() {
    if (!this.#head) {
      return;
    }
    return this.#head.value;
  }
  clear() {
    this.#head = void 0;
    this.#tail = void 0;
    this.#size = 0;
  }
  get size() {
    return this.#size;
  }
  *[Symbol.iterator]() {
    let current = this.#head;
    while (current) {
      yield current.value;
      current = current.next;
    }
  }
  *drain() {
    while (this.#head) {
      yield this.dequeue();
    }
  }
};

// packages/cli/node_modules/p-limit/index.js
function pLimit(concurrency) {
  let rejectOnClear = false;
  if (typeof concurrency === "object") {
    ({ concurrency, rejectOnClear = false } = concurrency);
  }
  validateConcurrency(concurrency);
  if (typeof rejectOnClear !== "boolean") {
    throw new TypeError("Expected `rejectOnClear` to be a boolean");
  }
  const queue = new Queue();
  let activeCount = 0;
  const resumeNext = /* @__PURE__ */ __name(() => {
    if (activeCount < concurrency && queue.size > 0) {
      activeCount++;
      queue.dequeue().run();
    }
  }, "resumeNext");
  const next = /* @__PURE__ */ __name(() => {
    activeCount--;
    resumeNext();
  }, "next");
  const run = /* @__PURE__ */ __name(async (function_, resolve5, arguments_) => {
    const result = (async () => function_(...arguments_))();
    resolve5(result);
    try {
      await result;
    } catch {
    }
    next();
  }, "run");
  const enqueue = /* @__PURE__ */ __name((function_, resolve5, reject, arguments_) => {
    const queueItem = { reject };
    new Promise((internalResolve) => {
      queueItem.run = internalResolve;
      queue.enqueue(queueItem);
    }).then(run.bind(void 0, function_, resolve5, arguments_));
    if (activeCount < concurrency) {
      resumeNext();
    }
  }, "enqueue");
  const generator = /* @__PURE__ */ __name((function_, ...arguments_) => new Promise((resolve5, reject) => {
    enqueue(function_, resolve5, reject, arguments_);
  }), "generator");
  Object.defineProperties(generator, {
    activeCount: {
      get: /* @__PURE__ */ __name(() => activeCount, "get")
    },
    pendingCount: {
      get: /* @__PURE__ */ __name(() => queue.size, "get")
    },
    clearQueue: {
      value() {
        if (!rejectOnClear) {
          queue.clear();
          return;
        }
        const abortError = AbortSignal.abort().reason;
        while (queue.size > 0) {
          queue.dequeue().reject(abortError);
        }
      }
    },
    concurrency: {
      get: /* @__PURE__ */ __name(() => concurrency, "get"),
      set(newConcurrency) {
        validateConcurrency(newConcurrency);
        concurrency = newConcurrency;
        queueMicrotask(() => {
          while (activeCount < concurrency && queue.size > 0) {
            resumeNext();
          }
        });
      }
    },
    map: {
      async value(iterable, function_) {
        const promises = Array.from(iterable, (value, index) => this(function_, value, index));
        return Promise.all(promises);
      }
    }
  });
  return generator;
}
__name(pLimit, "pLimit");
function validateConcurrency(concurrency) {
  if (!((Number.isInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency > 0)) {
    throw new TypeError("Expected `concurrency` to be a number from 1 and up");
  }
}
__name(validateConcurrency, "validateConcurrency");

// packages/cli/src/services/insight/generators/DataProcessor.ts
var logger = createDebugLogger("DataProcessor");
var CONCURRENCY_LIMIT = 4;
var SESSION_OUTCOMES = [
  "fully_achieved",
  "mostly_achieved",
  "partially_achieved",
  "not_achieved",
  "unclear_from_transcript"
];
var OUTCOME_FALLBACK = "unclear_from_transcript";
var QWEN_HELPFULNESS_LEVELS = [
  "unhelpful",
  "slightly_helpful",
  "moderately_helpful",
  "very_helpful",
  "essential"
];
var SESSION_TYPES = [
  "single_task",
  "multi_task",
  "iterative_refinement",
  "exploration",
  "quick_question"
];
var PRIMARY_SUCCESS_VALUES = [
  "none",
  "fast_accurate_search",
  "correct_code_edits",
  "good_explanations",
  "proactive_help",
  "multi_file_changes",
  "good_debugging"
];
var PRIMARY_SUCCESS_FALLBACK = "none";
function hasMeaningfulInsightValue(value) {
  if (typeof value === "string") {
    return value.trim().length > 0;
  }
  if (typeof value === "number") {
    return Number.isFinite(value) && value !== 0;
  }
  if (typeof value === "boolean") {
    return value;
  }
  if (Array.isArray(value)) {
    return value.some((item) => hasMeaningfulInsightValue(item));
  }
  if (value && typeof value === "object") {
    return Object.values(value).some((item) => hasMeaningfulInsightValue(item));
  }
  return false;
}
__name(hasMeaningfulInsightValue, "hasMeaningfulInsightValue");
function normalizeInsightText(value) {
  return typeof value === "string" ? value.trim() : "";
}
__name(normalizeInsightText, "normalizeInsightText");
function normalizeInsightCountRecord(value) {
  if (!value || typeof value !== "object" || Array.isArray(value)) {
    return {};
  }
  return Object.entries(value).reduce(
    (acc, [key, count]) => {
      if (typeof count === "number" && Number.isFinite(count) && count > 0) {
        acc[key] = count;
      }
      return acc;
    },
    {}
  );
}
__name(normalizeInsightCountRecord, "normalizeInsightCountRecord");
function getInsightCountEntries(value) {
  return Object.entries(normalizeInsightCountRecord(value));
}
__name(getInsightCountEntries, "getInsightCountEntries");
function normalizeInsightEnum(value, allowed, fallback) {
  const trimmed = typeof value === "string" ? value.trim() : "";
  if (trimmed) {
    const match = allowed.find(
      (item) => String(item).toLowerCase() === trimmed.toLowerCase()
    );
    if (match) return match;
  }
  logger.debug(
    `Normalized unknown insight enum value "${String(value)}" to fallback "${fallback}"`
  );
  return fallback;
}
__name(normalizeInsightEnum, "normalizeInsightEnum");
function normalizeSessionFacet(facet, sessionId) {
  if (!facet || typeof facet !== "object" || Array.isArray(facet)) {
    return null;
  }
  const rawFacet = facet;
  const normalizedFacet = {
    session_id: sessionId,
    underlying_goal: normalizeInsightText(rawFacet["underlying_goal"]),
    goal_categories: normalizeInsightCountRecord(rawFacet["goal_categories"]),
    outcome: normalizeInsightEnum(
      rawFacet["outcome"],
      SESSION_OUTCOMES,
      OUTCOME_FALLBACK
    ),
    user_satisfaction_counts: normalizeInsightCountRecord(
      rawFacet["user_satisfaction_counts"]
    ),
    Qwen_helpfulness: normalizeInsightEnum(
      rawFacet["Qwen_helpfulness"],
      QWEN_HELPFULNESS_LEVELS,
      "moderately_helpful"
    ),
    session_type: normalizeInsightEnum(
      rawFacet["session_type"],
      SESSION_TYPES,
      "single_task"
    ),
    friction_counts: normalizeInsightCountRecord(rawFacet["friction_counts"]),
    friction_detail: normalizeInsightText(rawFacet["friction_detail"]),
    primary_success: normalizeInsightEnum(
      rawFacet["primary_success"],
      PRIMARY_SUCCESS_VALUES,
      PRIMARY_SUCCESS_FALLBACK
    ),
    brief_summary: normalizeInsightText(rawFacet["brief_summary"])
  };
  const meaningfulContent = {
    underlying_goal: normalizedFacet.underlying_goal,
    goal_categories: normalizedFacet.goal_categories,
    outcome: normalizedFacet.outcome === OUTCOME_FALLBACK ? "" : normalizedFacet.outcome,
    user_satisfaction_counts: normalizedFacet.user_satisfaction_counts,
    friction_counts: normalizedFacet.friction_counts,
    friction_detail: normalizedFacet.friction_detail,
    primary_success: normalizedFacet.primary_success === PRIMARY_SUCCESS_FALLBACK ? "" : normalizedFacet.primary_success,
    brief_summary: normalizedFacet.brief_summary
  };
  return hasMeaningfulInsightValue(meaningfulContent) ? normalizedFacet : null;
}
__name(normalizeSessionFacet, "normalizeSessionFacet");
var DataProcessor = class {
  constructor(config) {
    this.config = config;
  }
  static {
    __name(this, "DataProcessor");
  }
  // Helper function to format date as YYYY-MM-DD
  formatDate(date) {
    return date.toISOString().split("T")[0];
  }
  // Format chat records for LLM analysis
  formatRecordsForAnalysis(records) {
    let output = "";
    const sessionStart = records.length > 0 ? new Date(records[0].timestamp) : /* @__PURE__ */ new Date();
    output += `Session: ${records[0]?.sessionId || "unknown"}
`;
    output += `Date: ${sessionStart.toISOString()}
`;
    output += `Duration: ${records.length} turns

`;
    for (const record of records) {
      if (record.type === "user") {
        const text = record.message?.parts?.map((p) => "text" in p ? p.text : "").join("") || "";
        output += `[User]: ${text}
`;
      } else if (record.type === "assistant") {
        if (record.message?.parts) {
          for (const part of record.message.parts) {
            if ("text" in part && part.text) {
              output += `[Assistant]: ${part.text}
`;
            } else if ("functionCall" in part) {
              const call = part.functionCall;
              if (call) {
                output += `[Tool: ${call.name}]
`;
              }
            }
          }
        }
      }
    }
    return output;
  }
  // Only analyze conversational sessions for facets (skip system-only logs).
  hasUserAndAssistantRecords(records) {
    let hasUser = false;
    let hasAssistant = false;
    for (const record of records) {
      if (record.type === "user") {
        hasUser = true;
      } else if (record.type === "assistant") {
        hasAssistant = true;
      }
      if (hasUser && hasAssistant) {
        return true;
      }
    }
    return false;
  }
  // Analyze a single session using LLM
  async analyzeSession(records) {
    if (records.length === 0) return null;
    const INSIGHT_SCHEMA = {
      type: "object",
      properties: {
        underlying_goal: {
          type: "string",
          description: "What the user fundamentally wanted to achieve"
        },
        goal_categories: {
          type: "object",
          additionalProperties: { type: "number" }
        },
        outcome: {
          type: "string",
          enum: [
            "fully_achieved",
            "mostly_achieved",
            "partially_achieved",
            "not_achieved",
            "unclear_from_transcript"
          ]
        },
        user_satisfaction_counts: {
          type: "object",
          additionalProperties: { type: "number" }
        },
        Qwen_helpfulness: {
          type: "string",
          enum: [
            "unhelpful",
            "slightly_helpful",
            "moderately_helpful",
            "very_helpful",
            "essential"
          ]
        },
        session_type: {
          type: "string",
          enum: [
            "single_task",
            "multi_task",
            "iterative_refinement",
            "exploration",
            "quick_question"
          ]
        },
        friction_counts: {
          type: "object",
          additionalProperties: { type: "number" }
        },
        friction_detail: {
          type: "string",
          description: "One sentence describing friction or empty"
        },
        primary_success: {
          type: "string",
          enum: [
            "none",
            "fast_accurate_search",
            "correct_code_edits",
            "good_explanations",
            "proactive_help",
            "multi_file_changes",
            "good_debugging"
          ]
        },
        brief_summary: {
          type: "string",
          description: "One sentence: what user wanted and whether they got it"
        }
      },
      required: [
        "underlying_goal",
        "goal_categories",
        "outcome",
        "user_satisfaction_counts",
        "Qwen_helpfulness",
        "session_type",
        "friction_counts",
        "friction_detail",
        "primary_success",
        "brief_summary"
      ]
    };
    const sessionText = this.formatRecordsForAnalysis(records);
    const prompt = `${getInsightPrompt("analysis")}

SESSION:
${sessionText}`;
    try {
      const result = await runSideQuery(this.config, {
        purpose: "insight-session-analysis",
        // Quality is the entire point — keep main model + reasoning on.
        model: this.config.getModel(),
        contents: [{ role: "user", parts: [{ text: prompt }] }],
        schema: INSIGHT_SCHEMA,
        config: {
          thinkingConfig: { includeThoughts: true }
        },
        abortSignal: AbortSignal.timeout(6e5)
        // 10 minute timeout per session
      });
      if (!result || Object.keys(result).length === 0) {
        return null;
      }
      const sessionId = records[0].sessionId;
      const normalizedFacet = normalizeSessionFacet(result, sessionId);
      if (!normalizedFacet) {
        logger.warn(
          `Ignoring malformed insight facet for session ${sessionId}`
        );
        return null;
      }
      return normalizedFacet;
    } catch (error) {
      logger.error(
        `Failed to analyze session ${records[0]?.sessionId}:`,
        error
      );
      return null;
    }
  }
  // Calculate streaks from activity dates
  calculateStreaks(dates) {
    if (dates.length === 0) {
      return { currentStreak: 0, longestStreak: 0, dates: [] };
    }
    const dateObjects = dates.map((dateStr) => new Date(dateStr));
    dateObjects.sort((a, b) => a.getTime() - b.getTime());
    let currentStreak = 1;
    let maxStreak = 1;
    let currentDate = new Date(dateObjects[0]);
    currentDate.setHours(0, 0, 0, 0);
    for (let i = 1; i < dateObjects.length; i++) {
      const nextDate = new Date(dateObjects[i]);
      nextDate.setHours(0, 0, 0, 0);
      const diffDays = Math.floor(
        (nextDate.getTime() - currentDate.getTime()) / (1e3 * 60 * 60 * 24)
      );
      if (diffDays === 1) {
        currentStreak++;
        maxStreak = Math.max(maxStreak, currentStreak);
      } else if (diffDays > 1) {
        currentStreak = 1;
      }
      currentDate = nextDate;
    }
    const today = /* @__PURE__ */ new Date();
    today.setHours(0, 0, 0, 0);
    const yesterday = new Date(today);
    yesterday.setDate(yesterday.getDate() - 1);
    if (currentDate.getTime() === today.getTime() || currentDate.getTime() === yesterday.getTime()) {
    }
    return {
      currentStreak,
      longestStreak: maxStreak,
      dates
    };
  }
  // Process chat files from all projects in the base directory and generate insights
  async generateInsights(baseDir, facetsOutputDir, onProgress) {
    if (onProgress) onProgress("Scanning chat history...", 0);
    const allChatFiles = await this.scanChatFiles(baseDir);
    if (onProgress) onProgress("Crunching the numbers", 10);
    const metrics = await this.generateMetrics(allChatFiles, onProgress);
    if (onProgress) onProgress("Preparing sessions...", 20);
    const facets = await this.generateFacets(
      allChatFiles,
      facetsOutputDir,
      onProgress
    );
    if (onProgress) onProgress("Generating personalized insights...", 80);
    const qualitative = await this.generateQualitativeInsights(metrics, facets);
    const {
      satisfactionAgg,
      frictionAgg,
      primarySuccessAgg,
      outcomesAgg,
      goalsAgg
    } = this.aggregateFacetsData(facets);
    if (onProgress) onProgress("Assembling report...", 100);
    return {
      ...metrics,
      qualitative,
      satisfaction: satisfactionAgg,
      friction: frictionAgg,
      primarySuccess: primarySuccessAgg,
      outcomes: outcomesAgg,
      topGoals: goalsAgg
    };
  }
  // Aggregate satisfaction and friction data from facets
  aggregateFacetsData(facets) {
    const satisfactionAgg = {};
    const frictionAgg = {};
    const primarySuccessAgg = {};
    const outcomesAgg = {};
    const goalsAgg = {};
    facets.forEach((facet) => {
      getInsightCountEntries(facet.user_satisfaction_counts).forEach(
        ([sat, count]) => {
          satisfactionAgg[sat] = (satisfactionAgg[sat] || 0) + count;
        }
      );
      getInsightCountEntries(facet.friction_counts).forEach(([fric, count]) => {
        frictionAgg[fric] = (frictionAgg[fric] || 0) + count;
      });
      const primarySuccess = normalizeInsightEnum(
        facet.primary_success,
        PRIMARY_SUCCESS_VALUES,
        PRIMARY_SUCCESS_FALLBACK
      );
      if (primarySuccess !== PRIMARY_SUCCESS_FALLBACK) {
        primarySuccessAgg[primarySuccess] = (primarySuccessAgg[primarySuccess] || 0) + 1;
      }
      const outcome = normalizeInsightEnum(
        facet.outcome,
        SESSION_OUTCOMES,
        OUTCOME_FALLBACK
      );
      outcomesAgg[outcome] = (outcomesAgg[outcome] || 0) + 1;
      getInsightCountEntries(facet.goal_categories).forEach(([goal, count]) => {
        goalsAgg[goal] = (goalsAgg[goal] || 0) + count;
      });
    });
    return {
      satisfactionAgg,
      frictionAgg,
      primarySuccessAgg,
      outcomesAgg,
      goalsAgg
    };
  }
  async generateQualitativeInsights(metrics, facets) {
    if (facets.length === 0) {
      return void 0;
    }
    logger.info("Generating qualitative insights...");
    const commonData = this.prepareCommonPromptData(metrics, facets);
    const generate = /* @__PURE__ */ __name(async (promptTemplate, schema) => {
      const prompt = `${promptTemplate}

${commonData}`;
      try {
        const result = await runSideQuery(
          this.config,
          {
            purpose: "insight-qualitative-generate",
            model: this.config.getModel(),
            contents: [{ role: "user", parts: [{ text: prompt }] }],
            schema,
            config: {
              thinkingConfig: { includeThoughts: true }
            },
            abortSignal: AbortSignal.timeout(6e5)
          }
        );
        return result;
      } catch (error) {
        logger.error("Failed to generate insight:", error);
        return void 0;
      }
    }, "generate");
    const schemaImpressiveWorkflows = {
      type: "object",
      properties: {
        intro: { type: "string" },
        impressive_workflows: {
          type: "array",
          items: {
            type: "object",
            properties: {
              title: { type: "string" },
              description: { type: "string" }
            },
            required: ["title", "description"]
          }
        }
      },
      required: ["intro", "impressive_workflows"]
    };
    const schemaProjectAreas = {
      type: "object",
      properties: {
        areas: {
          type: "array",
          items: {
            type: "object",
            properties: {
              name: { type: "string" },
              session_count: { type: "number" },
              description: { type: "string" }
            },
            required: ["name", "session_count", "description"]
          }
        }
      },
      required: ["areas"]
    };
    const schemaFutureOpportunities = {
      type: "object",
      properties: {
        intro: { type: "string" },
        opportunities: {
          type: "array",
          items: {
            type: "object",
            properties: {
              title: { type: "string" },
              whats_possible: { type: "string" },
              how_to_try: { type: "string" },
              copyable_prompt: { type: "string" }
            },
            required: [
              "title",
              "whats_possible",
              "how_to_try",
              "copyable_prompt"
            ]
          }
        }
      },
      required: ["intro", "opportunities"]
    };
    const schemaFrictionPoints = {
      type: "object",
      properties: {
        intro: { type: "string" },
        categories: {
          type: "array",
          items: {
            type: "object",
            properties: {
              category: { type: "string" },
              description: { type: "string" },
              examples: { type: "array", items: { type: "string" } }
            },
            required: ["category", "description", "examples"]
          }
        }
      },
      required: ["intro", "categories"]
    };
    const schemaMemorableMoment = {
      type: "object",
      properties: {
        headline: { type: "string" },
        detail: { type: "string" }
      },
      required: ["headline", "detail"]
    };
    const schemaImprovements = {
      type: "object",
      properties: {
        Qwen_md_additions: {
          type: "array",
          items: {
            type: "object",
            properties: {
              addition: { type: "string" },
              why: { type: "string" },
              prompt_scaffold: { type: "string" }
            },
            required: ["addition", "why", "prompt_scaffold"]
          }
        },
        features_to_try: {
          type: "array",
          items: {
            type: "object",
            properties: {
              feature: { type: "string" },
              one_liner: { type: "string" },
              why_for_you: { type: "string" },
              example_code: { type: "string" }
            },
            required: ["feature", "one_liner", "why_for_you", "example_code"]
          }
        },
        usage_patterns: {
          type: "array",
          items: {
            type: "object",
            properties: {
              title: { type: "string" },
              suggestion: { type: "string" },
              detail: { type: "string" },
              copyable_prompt: { type: "string" }
            },
            required: ["title", "suggestion", "detail", "copyable_prompt"]
          }
        }
      },
      required: ["Qwen_md_additions", "features_to_try", "usage_patterns"]
    };
    const schemaInteractionStyle = {
      type: "object",
      properties: {
        narrative: { type: "string" },
        key_pattern: { type: "string" }
      },
      required: ["narrative", "key_pattern"]
    };
    const schemaAtAGlance = {
      type: "object",
      properties: {
        whats_working: { type: "string" },
        whats_hindering: { type: "string" },
        quick_wins: { type: "string" },
        ambitious_workflows: { type: "string" }
      },
      required: [
        "whats_working",
        "whats_hindering",
        "quick_wins",
        "ambitious_workflows"
      ]
    };
    const limit = pLimit(CONCURRENCY_LIMIT);
    try {
      const [
        impressiveWorkflows,
        projectAreas,
        futureOpportunities,
        frictionPoints,
        memorableMoment,
        improvements,
        interactionStyle,
        atAGlance
      ] = await Promise.all([
        limit(
          () => generate(
            getInsightPrompt("impressive_workflows"),
            schemaImpressiveWorkflows
          )
        ),
        limit(
          () => generate(
            getInsightPrompt("project_areas"),
            schemaProjectAreas
          )
        ),
        limit(
          () => generate(
            getInsightPrompt("future_opportunities"),
            schemaFutureOpportunities
          )
        ),
        limit(
          () => generate(
            getInsightPrompt("friction_points"),
            schemaFrictionPoints
          )
        ),
        limit(
          () => generate(
            getInsightPrompt("memorable_moment"),
            schemaMemorableMoment
          )
        ),
        limit(
          () => generate(
            getInsightPrompt("improvements"),
            schemaImprovements
          )
        ),
        limit(
          () => generate(
            getInsightPrompt("interaction_style"),
            schemaInteractionStyle
          )
        ),
        limit(
          () => generate(
            getInsightPrompt("at_a_glance"),
            schemaAtAGlance
          )
        )
      ]);
      logger.debug(
        JSON.stringify(
          {
            impressiveWorkflows,
            projectAreas,
            futureOpportunities,
            frictionPoints,
            memorableMoment,
            improvements,
            interactionStyle,
            atAGlance
          },
          null,
          2
        )
      );
      const qualitative = {
        impressiveWorkflows,
        projectAreas,
        futureOpportunities,
        frictionPoints,
        memorableMoment,
        improvements,
        interactionStyle,
        atAGlance
      };
      return hasMeaningfulInsightValue(qualitative) ? qualitative : void 0;
    } catch (e) {
      logger.error("Error generating qualitative insights:", e);
      return void 0;
    }
  }
  prepareCommonPromptData(metrics, facets) {
    const goalsAgg = {};
    const outcomesAgg = {};
    const satisfactionAgg = {};
    const frictionAgg = {};
    const successAgg = {};
    facets.forEach((facet) => {
      getInsightCountEntries(facet.goal_categories).forEach(([goal, count]) => {
        goalsAgg[goal] = (goalsAgg[goal] || 0) + count;
      });
      const outcome = normalizeInsightEnum(
        facet.outcome,
        SESSION_OUTCOMES,
        OUTCOME_FALLBACK
      );
      outcomesAgg[outcome] = (outcomesAgg[outcome] || 0) + 1;
      getInsightCountEntries(facet.user_satisfaction_counts).forEach(
        ([sat, count]) => {
          satisfactionAgg[sat] = (satisfactionAgg[sat] || 0) + count;
        }
      );
      getInsightCountEntries(facet.friction_counts).forEach(([fric, count]) => {
        frictionAgg[fric] = (frictionAgg[fric] || 0) + count;
      });
      const primarySuccess = normalizeInsightEnum(
        facet.primary_success,
        PRIMARY_SUCCESS_VALUES,
        PRIMARY_SUCCESS_FALLBACK
      );
      if (primarySuccess !== PRIMARY_SUCCESS_FALLBACK) {
        successAgg[primarySuccess] = (successAgg[primarySuccess] || 0) + 1;
      }
    });
    const topGoals = Object.entries(goalsAgg).sort((a, b) => b[1] - a[1]).slice(0, 8);
    const dataObj = {
      sessions: metrics.totalSessions || facets.length,
      analyzed: facets.length,
      date_range: {
        start: Object.keys(metrics.heatmap).sort()[0] || "N/A",
        end: Object.keys(metrics.heatmap).sort().pop() || "N/A"
      },
      messages: metrics.totalMessages || 0,
      hours: metrics.totalHours || 0,
      commits: 0,
      // Not tracked yet
      top_tools: metrics.topTools || [],
      top_goals: topGoals,
      outcomes: outcomesAgg,
      satisfaction: satisfactionAgg,
      friction: frictionAgg,
      success: successAgg
    };
    const sessionSummaries = facets.map((f) => normalizeInsightText(f.brief_summary)).filter((summary) => summary.length > 0).map((summary) => `- ${summary}`).join("\n");
    const frictionDetails = facets.map((f) => normalizeInsightText(f.friction_detail)).filter((detail) => detail.length > 0).map((detail) => `- ${detail}`).join("\n");
    return `DATA:
${JSON.stringify(dataObj, null, 2)}

SESSION SUMMARIES:
${sessionSummaries}

FRICTION DETAILS:
${frictionDetails}

USER INSTRUCTIONS TO Qwen:
None captured`;
  }
  async scanChatFiles(baseDir) {
    const allChatFiles = [];
    try {
      const projectDirs = await fs13.readdir(baseDir);
      for (const projectDir of projectDirs) {
        const projectPath = path16.join(baseDir, projectDir);
        const stats = await fs13.stat(projectPath);
        if (stats.isDirectory()) {
          const chatsDir = path16.join(projectPath, "chats");
          try {
            const files = await fs13.readdir(chatsDir);
            const chatFiles = files.filter((file) => file.endsWith(".jsonl"));
            for (const file of chatFiles) {
              const filePath = path16.join(chatsDir, file);
              try {
                const fileStats = await fs13.stat(filePath);
                allChatFiles.push({ path: filePath, mtime: fileStats.mtimeMs });
              } catch (e) {
                logger.error(`Failed to stat file ${filePath}:`, e);
              }
            }
          } catch (error) {
            if (error.code !== "ENOENT") {
              logger.error(
                `Error reading chats directory for project ${projectDir}: ${error}`
              );
            }
            continue;
          }
        }
      }
    } catch (error) {
      if (error.code === "ENOENT") {
        logger.info(`Base directory does not exist: ${baseDir}`);
      } else {
        logger.error(`Error reading base directory: ${error}`);
      }
    }
    return allChatFiles;
  }
  async generateMetrics(files, onProgress) {
    const heatmap = {};
    const activeHours = {};
    const sessionStartTimes = {};
    const sessionEndTimes = {};
    let totalMessages = 0;
    let totalLinesAdded = 0;
    let totalLinesRemoved = 0;
    const uniqueFiles = /* @__PURE__ */ new Set();
    const toolUsage = {};
    const BATCH_SIZE = 50;
    const totalFiles = files.length;
    for (let i = 0; i < totalFiles; i += BATCH_SIZE) {
      const batchEnd = Math.min(i + BATCH_SIZE, totalFiles);
      const batch = files.slice(i, batchEnd);
      for (const fileInfo of batch) {
        try {
          const records = await read(fileInfo.path);
          for (const record of records) {
            const timestamp = new Date(record.timestamp);
            const dateKey = this.formatDate(timestamp);
            const hour = timestamp.getHours();
            const isUserMessage = record.type === "user";
            const isSlashCommand2 = record.type === "system" && record.subtype === "slash_command";
            if (isUserMessage || isSlashCommand2) {
              totalMessages++;
              heatmap[dateKey] = (heatmap[dateKey] || 0) + 1;
              activeHours[hour] = (activeHours[hour] || 0) + 1;
            }
            if (!sessionStartTimes[record.sessionId]) {
              sessionStartTimes[record.sessionId] = timestamp;
            }
            sessionEndTimes[record.sessionId] = timestamp;
            if (record.type === "assistant" && record.message?.parts) {
              for (const part of record.message.parts) {
                if ("functionCall" in part) {
                  const name = part.functionCall.name;
                  toolUsage[name] = (toolUsage[name] || 0) + 1;
                }
              }
            }
            if (record.type === "tool_result" && record.toolCallResult?.resultDisplay) {
              const display = record.toolCallResult.resultDisplay;
              if (typeof display === "object" && display !== null && "fileName" in display) {
                const diff = display;
                if (typeof diff.fileName === "string") {
                  uniqueFiles.add(diff.fileName);
                }
                if (diff.diffStat) {
                  totalLinesAdded += diff.diffStat.model_added_lines || 0;
                  totalLinesRemoved += diff.diffStat.model_removed_lines || 0;
                }
              }
            }
          }
        } catch (error) {
          logger.error(
            `Failed to process metrics for file ${fileInfo.path}:`,
            error
          );
        }
      }
      if (onProgress) {
        const percentComplete = batchEnd / totalFiles;
        const overallProgress = 10 + Math.round(percentComplete * 10);
        onProgress(
          `Crunching the numbers (${batchEnd}/${totalFiles})`,
          overallProgress
        );
      }
      await new Promise((resolve5) => setTimeout(resolve5, 0));
    }
    const streakData = this.calculateStreaks(Object.keys(heatmap));
    let longestWorkDuration = 0;
    let longestWorkDate = null;
    let totalDurationMs = 0;
    const sessionIds = Object.keys(sessionStartTimes);
    const totalSessions = sessionIds.length;
    for (const sessionId of sessionIds) {
      const start = sessionStartTimes[sessionId];
      const end = sessionEndTimes[sessionId];
      const durationMs = end.getTime() - start.getTime();
      const durationMinutes = Math.round(durationMs / (1e3 * 60));
      totalDurationMs += durationMs;
      if (durationMinutes > longestWorkDuration) {
        longestWorkDuration = durationMinutes;
        longestWorkDate = this.formatDate(start);
      }
    }
    const totalHours = Math.round(totalDurationMs / (1e3 * 60 * 60));
    let latestActiveTime = null;
    let latestTimestamp = /* @__PURE__ */ new Date(0);
    for (const dateStr in heatmap) {
      const date = new Date(dateStr);
      if (date > latestTimestamp) {
        latestTimestamp = date;
        latestActiveTime = date.toLocaleTimeString([], {
          hour: "2-digit",
          minute: "2-digit"
        });
      }
    }
    const topTools = Object.entries(toolUsage).sort((a, b) => b[1] - a[1]).slice(0, 10);
    return {
      heatmap,
      currentStreak: streakData.currentStreak,
      longestStreak: streakData.longestStreak,
      longestWorkDate,
      longestWorkDuration,
      activeHours,
      latestActiveTime,
      totalSessions,
      totalMessages,
      totalHours,
      topTools,
      totalLinesAdded,
      totalLinesRemoved,
      totalFiles: uniqueFiles.size
    };
  }
  async generateFacets(allFiles, facetsOutputDir, onProgress) {
    const MAX_ELIGIBLE_SESSIONS = 50;
    const sortedFiles = [...allFiles].sort((a, b) => b.mtime - a.mtime);
    const eligibleSessions = [];
    for (const fileInfo of sortedFiles) {
      if (eligibleSessions.length >= MAX_ELIGIBLE_SESSIONS) {
        break;
      }
      try {
        const records = await read(fileInfo.path);
        if (!this.hasUserAndAssistantRecords(records)) {
          continue;
        }
        eligibleSessions.push({ fileInfo, records });
      } catch (e) {
        logger.error(
          `Error reading session file ${fileInfo.path} for facet eligibility:`,
          e
        );
      }
    }
    logger.info(
      `Analyzing ${eligibleSessions.length} eligible recent sessions with LLM...`
    );
    const limit = pLimit(CONCURRENCY_LIMIT);
    let completed = 0;
    const total = eligibleSessions.length;
    const analysisPromises = eligibleSessions.map(
      ({ fileInfo, records }) => limit(async () => {
        try {
          if (records.length > 0 && facetsOutputDir) {
            const sessionId = records[0].sessionId;
            if (sessionId) {
              const existingFacetPath = path16.join(
                facetsOutputDir,
                `${sessionId}.json`
              );
              try {
                const existingData = await fs13.readFile(
                  existingFacetPath,
                  "utf-8"
                );
                const existingFacet = JSON.parse(existingData);
                const normalizedFacet = normalizeSessionFacet(
                  existingFacet,
                  sessionId
                );
                if (!normalizedFacet) {
                  logger.warn(
                    `Cached insight facet for ${sessionId} is malformed, regenerating.`
                  );
                  throw new Error("Malformed cached insight facet");
                }
                const normalizedData = JSON.stringify(normalizedFacet, null, 2);
                if (existingData !== normalizedData) {
                  try {
                    await fs13.writeFile(
                      existingFacetPath,
                      normalizedData,
                      "utf-8"
                    );
                  } catch (writeError) {
                    logger.warn(
                      `Failed to write back normalized facet for ${sessionId}:`,
                      writeError
                    );
                  }
                }
                completed++;
                if (onProgress) {
                  const percent = 20 + Math.round(completed / total * 60);
                  onProgress(
                    "Analyzing sessions",
                    percent,
                    `${completed}/${total}`
                  );
                }
                return normalizedFacet;
              } catch (readError) {
                if (readError.code !== "ENOENT") {
                  logger.warn(
                    `Failed to read existing facet for ${sessionId}, regenerating:`,
                    readError
                  );
                }
              }
            }
          }
          const facet = await this.analyzeSession(records);
          if (facet && facetsOutputDir) {
            try {
              const facetPath = path16.join(
                facetsOutputDir,
                `${facet.session_id}.json`
              );
              await fs13.writeFile(
                facetPath,
                JSON.stringify(facet, null, 2),
                "utf-8"
              );
            } catch (writeError) {
              logger.error(
                `Failed to write facet file for session ${facet.session_id}:`,
                writeError
              );
            }
          }
          completed++;
          if (onProgress) {
            const percent = 20 + Math.round(completed / total * 60);
            onProgress("Analyzing sessions", percent, `${completed}/${total}`);
          }
          return facet;
        } catch (e) {
          logger.error(`Error analyzing session file ${fileInfo.path}:`, e);
          completed++;
          if (onProgress) {
            const percent = 20 + Math.round(completed / total * 60);
            onProgress("Analyzing sessions", percent, `${completed}/${total}`);
          }
          return null;
        }
      })
    );
    const sessionFacetsWithNulls = await Promise.all(analysisPromises);
    const facets = sessionFacetsWithNulls.filter(
      (f) => f !== null
    );
    return facets;
  }
};

// packages/cli/src/services/insight/generators/TemplateRenderer.ts
init_esbuild_shims();
var TemplateRenderer = class {
  static {
    __name(this, "TemplateRenderer");
  }
  // Render the complete HTML file
  async renderInsightHTML(insights) {
    const html = `<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Qwen Code Insights</title>
    <style>
      ${INSIGHT_CSS}
    </style>
  </head>
  <body>
    <div class="min-h-screen" id="container">
      <div class="mx-auto max-w-6xl px-6 py-10 md:py-12">
        <div id="react-root"></div>
      </div>
    </div>

    <!-- React CDN -->
    <script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>

    <!-- CDN Libraries -->
    <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js"></script>

    <!-- Application Data -->
    <script>
      window.INSIGHT_DATA = ${JSON.stringify(insights)};
    </script>

    <!-- App Script -->
    <script>
      ${INSIGHT_JS}
    </script>
  </body>
</html>`;
    return html;
  }
};

// packages/cli/src/services/insight/generators/StaticInsightGenerator.ts
var StaticInsightGenerator = class {
  static {
    __name(this, "StaticInsightGenerator");
  }
  dataProcessor;
  templateRenderer;
  constructor(config) {
    this.dataProcessor = new DataProcessor(config);
    this.templateRenderer = new TemplateRenderer();
  }
  // Ensure the output directory exists
  async ensureOutputDirectory() {
    const outputDir = path17.join(Storage.getRuntimeBaseDir(), "insights");
    await fs14.mkdir(outputDir, { recursive: true });
    return outputDir;
  }
  // Generate timestamped filename with collision detection
  async generateOutputPath(outputDir) {
    const now = /* @__PURE__ */ new Date();
    const date = now.toISOString().split("T")[0];
    const time = now.toTimeString().slice(0, 8).replace(/:/g, "");
    let outputPath = path17.join(outputDir, `insight-${date}.html`);
    try {
      await fs14.access(outputPath);
      outputPath = path17.join(outputDir, `insight-${date}-${time}.html`);
    } catch {
    }
    return outputPath;
  }
  async updateInsightSymlink(outputDir, targetPath) {
    const latestPath = path17.join(outputDir, "insight.html");
    await updateSymlink(latestPath, targetPath);
  }
  // Generate the static insight HTML file
  async generateStaticInsight(baseDir, onProgress) {
    const outputDir = await this.ensureOutputDirectory();
    const facetsDir = path17.join(outputDir, "facets");
    await fs14.mkdir(facetsDir, { recursive: true });
    const insights = await this.dataProcessor.generateInsights(
      baseDir,
      facetsDir,
      onProgress
    );
    const html = await this.templateRenderer.renderInsightHTML(insights);
    const outputPath = await this.generateOutputPath(outputDir);
    await fs14.writeFile(outputPath, html, "utf-8");
    await this.updateInsightSymlink(outputDir, outputPath);
    return outputPath;
  }
};

// packages/cli/src/ui/commands/insightCommand.ts
var logger2 = createDebugLogger("DataProcessor");
var insightCommand = {
  name: "insight",
  get description() {
    return t(
      "generate personalized programming insights from your chat history"
    );
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive", "non_interactive", "acp"],
  action: /* @__PURE__ */ __name(async (context) => {
    try {
      context.ui.setDebugMessage(t("Generating insights..."));
      const projectsDir = join9(Storage.getRuntimeBaseDir(), "projects");
      if (!context.services.config) {
        if (context.executionMode !== "interactive") {
          return {
            type: "message",
            messageType: "error",
            content: "Config service is not available."
          };
        }
        throw new Error("Config service is not available");
      }
      const insightGenerator = new StaticInsightGenerator(
        context.services.config
      );
      if (context.executionMode === "non_interactive") {
        try {
          const outputPath2 = await insightGenerator.generateStaticInsight(
            projectsDir,
            () => {
            }
          );
          return {
            type: "message",
            messageType: "info",
            content: t("Insight report generated at: {{path}}", {
              path: outputPath2
            })
          };
        } catch (error) {
          return {
            type: "message",
            messageType: "error",
            content: t("Failed to generate insights: {{error}}", {
              error: error.message
            })
          };
        }
      }
      if (context.executionMode === "acp") {
        const pendingMessages = [];
        let isComplete = false;
        let resume = null;
        const flushResume = /* @__PURE__ */ __name(() => {
          const resolve5 = resume;
          if (!resolve5) {
            return;
          }
          resume = null;
          resolve5();
        }, "flushResume");
        const pushMessage = /* @__PURE__ */ __name((message) => {
          pendingMessages.push(message);
          flushResume();
        }, "pushMessage");
        const streamMessages = /* @__PURE__ */ __name(async function* () {
          while (!isComplete || pendingMessages.length > 0) {
            if (pendingMessages.length === 0) {
              await new Promise((resolve5) => {
                resume = resolve5;
              });
            }
            while (pendingMessages.length > 0) {
              const message = pendingMessages.shift();
              if (message) {
                yield message;
              }
            }
          }
        }, "streamMessages");
        void (async () => {
          try {
            pushMessage({
              messageType: "info",
              content: t("This may take a couple minutes. Sit tight!")
            });
            pushMessage({
              messageType: "info",
              content: encodeInsightProgressMessage(
                t("Starting insight generation..."),
                0
              )
            });
            const outputPath2 = await insightGenerator.generateStaticInsight(
              projectsDir,
              (stage, progress, detail) => {
                pushMessage({
                  messageType: "info",
                  content: encodeInsightProgressMessage(
                    stage,
                    progress,
                    detail
                  )
                });
              }
            );
            pushMessage({
              messageType: "info",
              content: encodeInsightReadyMessage(outputPath2)
            });
          } catch (error) {
            const errorText = error.message;
            pushMessage({
              messageType: "info",
              content: encodeInsightErrorMessage(errorText)
            });
            pushMessage({
              messageType: "error",
              content: t("Failed to generate insights: {{error}}", {
                error: errorText
              })
            });
            logger2.error("Insight generation error:", error);
          } finally {
            isComplete = true;
            flushResume();
          }
        })();
        return {
          type: "stream_messages",
          messages: streamMessages()
        };
      }
      const updateProgress = /* @__PURE__ */ __name((stage, progress, detail) => {
        const progressItem = {
          type: "insight_progress" /* INSIGHT_PROGRESS */,
          progress: {
            stage,
            progress,
            detail
          }
        };
        context.ui.setPendingItem(progressItem);
      }, "updateProgress");
      context.ui.addItem(
        {
          type: "info" /* INFO */,
          text: t("This may take a couple minutes. Sit tight!")
        },
        Date.now()
      );
      updateProgress(t("Starting insight generation..."), 0);
      const outputPath = await insightGenerator.generateStaticInsight(
        projectsDir,
        updateProgress
      );
      context.ui.setPendingItem(null);
      context.ui.addItem(
        {
          type: "info" /* INFO */,
          text: t("Insight report generated successfully!")
        },
        Date.now()
      );
      context.ui.addItem(
        {
          type: "info" /* INFO */,
          text: t(
            "Insights generated at: {{path}}. If the browser does not open automatically, open this file manually.",
            {
              path: outputPath
            }
          )
        },
        Date.now()
      );
      try {
        await openBrowserSecurely(pathToFileURL(outputPath).href, {
          allowFile: true,
          allowedFilePaths: [outputPath]
        });
      } catch (browserError) {
        logger2.error("Failed to open browser automatically:", browserError);
      }
      context.ui.setDebugMessage(t("Insights ready."));
      return;
    } catch (error) {
      context.ui.setPendingItem(null);
      if (context.executionMode !== "interactive") {
        return {
          type: "message",
          messageType: "error",
          content: `Failed to generate insights: ${error.message}`
        };
      }
      context.ui.addItem(
        {
          type: "error" /* ERROR */,
          text: t("Failed to generate insights: {{error}}", {
            error: error.message
          })
        },
        Date.now()
      );
      logger2.error("Insight generation error:", error);
      return;
    }
  }, "action")
};

// packages/cli/src/ui/commands/statuslineCommand.ts
init_esbuild_shims();
var statuslineCommand = {
  name: "statusline",
  get description() {
    return t("Set up Qwen Code's status line UI");
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive"],
  action: /* @__PURE__ */ __name((_context, args) => {
    const prompt = args.trim();
    if (!prompt) {
      return {
        type: "dialog",
        dialog: "statusline"
      };
    }
    return {
      type: "submit_prompt",
      content: [
        {
          text: `Use the Agent tool with subagent_type: "statusline-setup" and this prompt:

${prompt}`
        }
      ]
    };
  }, "action")
};

// packages/cli/src/ui/commands/lspCommand.ts
init_esbuild_shims();
function emitMessage(context, messageType, content) {
  if (context.executionMode !== "interactive") {
    return {
      type: "message",
      messageType,
      content
    };
  }
  context.ui.addItem(
    {
      type: messageType === "error" ? "error" /* ERROR */ : "info" /* INFO */,
      text: content
    },
    Date.now()
  );
}
__name(emitMessage, "emitMessage");
var lspCommand = {
  name: "lsp",
  get description() {
    return t("Show LSP server status. Usage: /lsp [status]");
  },
  kind: "built-in" /* BUILT_IN */,
  supportedModes: ["interactive", "non_interactive", "acp"],
  action: /* @__PURE__ */ __name(async (context, _args) => {
    const config = context.services.config;
    if (!config) {
      return emitMessage(context, "error", t("Config not available."));
    }
    if (!config.isLspEnabled()) {
      return emitMessage(
        context,
        "info",
        t(
          "LSP is not enabled. Start Qwen Code with `--experimental-lsp` to enable LSP support."
        )
      );
    }
    const client = config.getLspClient();
    if (!client) {
      return emitMessage(
        context,
        "info",
        t(
          "LSP is enabled but no client is connected. Check debug logs under `${QWEN_RUNTIME_DIR:-~/.qwen}/debug/` or see the LSP troubleshooting docs."
        )
      );
    }
    if (!client.getServerStatus) {
      return emitMessage(
        context,
        "info",
        t("LSP is enabled, but server status is unavailable.")
      );
    }
    const servers = client.getServerStatus();
    if (servers.length === 0) {
      return emitMessage(
        context,
        "info",
        t(
          "No LSP servers configured. Add a `.lsp.json` file to your project root. See `/help` for details."
        )
      );
    }
    const lines = ["**LSP Server Status**", ""];
    lines.push("| Server | Command | Languages | Status |");
    lines.push("|--------|---------|-----------|--------|");
    for (const server of servers) {
      const cmd = server.command ?? "(n/a)";
      const langs = server.languages.join(", ") || "(auto)";
      const statusText = server.error ? `${server.status} - ${server.error}` : server.status;
      lines.push(`| ${server.name} | \`${cmd}\` | ${langs} | ${statusText} |`);
    }
    return emitMessage(context, "info", lines.join("\n"));
  }, "action")
};

// packages/cli/src/services/BuiltinCommandLoader.ts
var builtinDebugLogger = createDebugLogger("BUILTIN_COMMAND_LOADER");
var BuiltinCommandLoader = class {
  constructor(config) {
    this.config = config;
  }
  static {
    __name(this, "BuiltinCommandLoader");
  }
  /**
   * Gathers all raw built-in command definitions, injects dependencies where
   * needed (e.g., config) and filters out any that are not available.
   *
   * @param _signal An AbortSignal (unused for this synchronous loader).
   * @returns A promise that resolves to an array of `SlashCommand` objects.
   */
  async loadCommands(_signal) {
    let resolvedIdeCommand = null;
    try {
      resolvedIdeCommand = await ideCommand();
    } catch (error) {
      builtinDebugLogger.warn(
        "Failed to load IDE command:",
        error instanceof Error ? error.message : String(error)
      );
    }
    const allDefinitions = [
      aboutCommand,
      agentsCommand,
      tasksCommand,
      // Gated behind isWorkflowsEnabled — feature flag honors
      // QWEN_CODE_ENABLE_WORKFLOWS (opt-in) and QWEN_CODE_DISABLE_WORKFLOWS
      // (kill switch). When the flag is off the command vanishes entirely
      // from typeahead and help, matching the established convention for
      // experimental builtins.
      this.config?.isWorkflowsEnabled() ? workflowsCommand : null,
      arenaCommand,
      approvalModeCommand,
      authCommand,
      branchCommand,
      btwCommand,
      forkCommand,
      bugCommand,
      cdCommand,
      clearCommand,
      compressCommand,
      compressFastCommand,
      configCommand,
      contextCommand,
      copyCommand,
      diffCommand,
      deleteCommand,
      docsCommand,
      doctorCommand,
      directoryCommand,
      editorCommand,
      effortCommand,
      exportCommand,
      extensionsCommand,
      helpCommand,
      historyCommand,
      hooksCommand,
      resolvedIdeCommand,
      importConfigCommand,
      initCommand,
      languageCommand,
      mcpCommand,
      ...this.config?.isManagedMemoryAvailable() ? [dreamCommand, forgetCommand] : [],
      goalCommand,
      memoryCommand,
      modelCommand,
      rememberCommand,
      planCommand,
      permissionsCommand,
      ...this.config?.getFolderTrust() ? [trustCommand] : [],
      quitCommand,
      recapCommand,
      renameCommand,
      restoreCommand(this.config),
      resumeCommand,
      rewindCommand,
      skillsCommand,
      statsCommand,
      summaryCommand,
      themeCommand,
      toolsCommand,
      settingsCommand,
      vimCommand,
      voiceCommand,
      setupGithubCommand,
      terminalSetupCommand,
      insightCommand,
      statuslineCommand,
      ...this.config?.isLspEnabled() ? [lspCommand] : []
    ];
    return allDefinitions.filter((cmd) => cmd !== null).map((cmd) => ({
      ...cmd,
      source: "builtin-command",
      sourceLabel: "Built-in",
      modelInvocable: false,
      userInvocable: cmd.userInvocable ?? true
    }));
  }
};

// packages/cli/src/services/BundledSkillLoader.ts
init_esbuild_shims();
import { dirname as dirname4 } from "node:path";
var debugLogger13 = createDebugLogger("BUNDLED_SKILL_LOADER");
var BundledSkillLoader = class {
  constructor(config) {
    this.config = config;
  }
  static {
    __name(this, "BundledSkillLoader");
  }
  async loadCommands(_signal) {
    if (this.config?.getBareMode?.()) {
      debugLogger13.debug("Bare mode enabled, skipping bundled skills");
      return [];
    }
    const skillManager = this.config?.getSkillManager();
    if (!skillManager) {
      debugLogger13.debug("SkillManager not available, skipping bundled skills");
      return [];
    }
    try {
      const allSkills = await skillManager.listSkills({ level: "bundled" });
      const cronEnabled = this.config?.isCronEnabled() ?? false;
      const cronVisible = allSkills.filter((skill) => {
        if (!cronEnabled && skill.allowedTools?.some((t2) => t2.startsWith("cron_"))) {
          debugLogger13.debug(
            `Hiding skill "${skill.name}" because cron is not enabled`
          );
          return false;
        }
        return true;
      });
      const disabled = this.config?.getDisabledSkillNames() ?? /* @__PURE__ */ new Set();
      const skills = cronVisible.filter(
        (skill) => !disabled.has(skill.name.toLowerCase())
      );
      debugLogger13.debug(
        `Loaded ${skills.length} bundled skill(s) as slash commands; ${cronVisible.length - skills.length} hidden by skills.disabled`
      );
      return skills.map((skill) => ({
        name: skill.name,
        description: skill.description,
        modelDescription: skill.description,
        kind: "skill" /* SKILL */,
        source: "bundled-skill",
        sourceLabel: t("Skill"),
        userInvocable: skill.userInvocable ?? true,
        modelInvocable: !skill.disableModelInvocation,
        argumentHint: skill.argumentHint,
        whenToUse: skill.whenToUse,
        skillDetail: {
          name: skill.name,
          description: skill.description,
          body: skill.body,
          level: skill.level
        },
        action: /* @__PURE__ */ __name(async (context, _args) => {
          applySkillAllowedTools(
            this.config?.getPermissionManager(),
            skill.allowedTools
          );
          let body = skill.body;
          const modelId = this.config?.getModel()?.trim() || "";
          if (body.includes("{{model}}") || body.includes("YOUR_MODEL_ID")) {
            body = body.replaceAll("{{model}}", modelId);
            body = body.replaceAll("YOUR_MODEL_ID", modelId);
            if (modelId) {
              body = `YOUR_MODEL_ID="${modelId}"

${body}`;
            }
          }
          const skillPrompt = buildSkillLlmContent(
            dirname4(skill.filePath),
            body
          );
          const content = context.invocation?.args ? appendToLastTextPart(
            [{ text: skillPrompt }],
            context.invocation.raw
          ) : [{ text: skillPrompt }];
          return {
            type: "submit_prompt",
            content
          };
        }, "action")
      }));
    } catch (error) {
      debugLogger13.error("Failed to load bundled skills:", error);
      return [];
    }
  }
};

// packages/cli/src/services/FileCommandLoader.ts
init_esbuild_shims();
var import_toml = __toESM(require_toml(), 1);
import { promises as fs15 } from "node:fs";
import * as fsSync from "node:fs";
import path19 from "node:path";

// packages/cli/src/services/markdown-command-parser.ts
init_esbuild_shims();
var MarkdownCommandDefSchema = external_exports.object({
  frontmatter: external_exports.object({
    description: external_exports.string().optional(),
    "argument-hint": external_exports.string().optional(),
    when_to_use: external_exports.string().optional(),
    "disable-model-invocation": external_exports.boolean().optional()
  }).passthrough().optional(),
  prompt: external_exports.string({
    required_error: "The prompt content is required.",
    invalid_type_error: "The prompt content must be a string."
  })
});
function parseMarkdownCommand(content) {
  const normalizedContent = normalizeContent(content);
  const frontmatterRegex = /^---\n(?:([\s\S]*?)\n)?---(?:\n|$)([\s\S]*)$/;
  const match = normalizedContent.match(frontmatterRegex);
  if (!match) {
    return {
      prompt: normalizedContent.trim()
    };
  }
  const [, frontmatterYaml = "", body] = match;
  let frontmatter;
  if (frontmatterYaml.trim()) {
    try {
      frontmatter = parse(frontmatterYaml);
    } catch (error) {
      throw new Error(
        `Failed to parse YAML frontmatter: ${error instanceof Error ? error.message : String(error)}`
      );
    }
  }
  return {
    frontmatter,
    prompt: body.trim()
  };
}
__name(parseMarkdownCommand, "parseMarkdownCommand");

// packages/cli/src/services/command-factory.ts
init_esbuild_shims();
import path18 from "node:path";

// packages/cli/src/services/prompt-processors/argumentProcessor.ts
init_esbuild_shims();
var DefaultArgumentProcessor = class {
  static {
    __name(this, "DefaultArgumentProcessor");
  }
  async process(prompt, context) {
    if (context.invocation?.args) {
      return appendToLastTextPart(prompt, context.invocation.raw);
    }
    return prompt;
  }
};

// packages/cli/src/services/prompt-processors/types.ts
init_esbuild_shims();
var SHORTHAND_ARGS_PLACEHOLDER = "{{args}}";
var SHELL_INJECTION_TRIGGER = "!{";
var AT_FILE_INJECTION_TRIGGER = "@{";

// packages/cli/src/services/prompt-processors/shellProcessor.ts
init_esbuild_shims();

// packages/cli/src/services/prompt-processors/injectionParser.ts
init_esbuild_shims();
function extractInjections(prompt, trigger, contextName) {
  const injections = [];
  let index = 0;
  while (index < prompt.length) {
    const startIndex = prompt.indexOf(trigger, index);
    if (startIndex === -1) {
      break;
    }
    let currentIndex = startIndex + trigger.length;
    let braceCount = 1;
    let foundEnd = false;
    while (currentIndex < prompt.length) {
      const char = prompt[currentIndex];
      if (char === "{") {
        braceCount++;
      } else if (char === "}") {
        braceCount--;
        if (braceCount === 0) {
          const injectionContent = prompt.substring(
            startIndex + trigger.length,
            currentIndex
          );
          const endIndex = currentIndex + 1;
          injections.push({
            content: injectionContent.trim(),
            startIndex,
            endIndex
          });
          index = endIndex;
          foundEnd = true;
          break;
        }
      }
      currentIndex++;
    }
    if (!foundEnd) {
      const contextInfo = contextName ? ` in command '${contextName}'` : "";
      throw new Error(
        `Invalid syntax${contextInfo}: Unclosed injection starting at index ${startIndex} ('${trigger}'). Ensure braces are balanced. Paths or commands with unbalanced braces are not supported directly.`
      );
    }
  }
  return injections;
}
__name(extractInjections, "extractInjections");

// packages/cli/src/services/prompt-processors/shellProcessor.ts
var ConfirmationRequiredError = class extends Error {
  constructor(message, commandsToConfirm) {
    super(message);
    this.commandsToConfirm = commandsToConfirm;
    this.name = "ConfirmationRequiredError";
  }
  static {
    __name(this, "ConfirmationRequiredError");
  }
};
var ShellProcessor = class {
  constructor(commandName) {
    this.commandName = commandName;
  }
  static {
    __name(this, "ShellProcessor");
  }
  async process(prompt, context) {
    return flatMapTextParts(
      prompt,
      (text) => this.processString(text, context)
    );
  }
  async processString(prompt, context) {
    const userArgsRaw = context.invocation?.args || "";
    if (!prompt.includes(SHELL_INJECTION_TRIGGER)) {
      return [
        { text: prompt.replaceAll(SHORTHAND_ARGS_PLACEHOLDER, userArgsRaw) }
      ];
    }
    const config = context.services.config;
    if (!config) {
      throw new Error(
        `Security configuration not loaded. Cannot verify shell command permissions for '${this.commandName}'. Aborting.`
      );
    }
    const { sessionShellAllowlist } = context.session;
    const injections = extractInjections(
      prompt,
      SHELL_INJECTION_TRIGGER,
      this.commandName
    );
    if (injections.length === 0) {
      return [
        { text: prompt.replaceAll(SHORTHAND_ARGS_PLACEHOLDER, userArgsRaw) }
      ];
    }
    const { shell } = getShellConfiguration();
    const userArgsEscaped = escapeShellArg(userArgsRaw, shell);
    let userArgsForArgumentsPlaceholder = userArgsRaw.replace(
      /^'([\s\S]*?)'$/,
      "$1"
    );
    const argumentSafety = checkArgumentSafety(userArgsForArgumentsPlaceholder);
    if (!argumentSafety.isSafe) {
      userArgsForArgumentsPlaceholder = userArgsEscaped;
    }
    const resolvedInjections = injections.map(
      (injection) => {
        const command = injection.content;
        if (command === "") {
          return { ...injection, resolvedCommand: void 0 };
        }
        const resolvedCommand = command.replaceAll(SHORTHAND_ARGS_PLACEHOLDER, userArgsEscaped).replaceAll("$ARGUMENTS", userArgsForArgumentsPlaceholder);
        return { ...injection, resolvedCommand };
      }
    );
    const commandsToConfirm = /* @__PURE__ */ new Set();
    for (const injection of resolvedInjections) {
      const command = injection.resolvedCommand;
      if (!command) continue;
      const { allAllowed, disallowedCommands, blockReason, isHardDenial } = await checkCommandPermissions(command, config, sessionShellAllowlist);
      const pm = config.getPermissionManager?.();
      const isAllowedBySettings = pm ? await pm.isCommandAllowed(command) === "allow" : false;
      if (!allAllowed) {
        if (isHardDenial) {
          throw new Error(
            `${this.commandName} cannot be run. Blocked command: "${command}". Reason: ${blockReason || "Blocked by configuration."}`
          );
        }
        if (isAllowedBySettings) {
          continue;
        }
        if (config.getApprovalMode() === "yolo" /* YOLO */) {
          continue;
        }
        disallowedCommands.forEach((uc) => commandsToConfirm.add(uc));
      }
    }
    if (commandsToConfirm.size > 0) {
      throw new ConfirmationRequiredError(
        "Shell command confirmation required",
        Array.from(commandsToConfirm)
      );
    }
    let processedPrompt = "";
    let lastIndex = 0;
    for (const injection of resolvedInjections) {
      const segment = prompt.substring(lastIndex, injection.startIndex);
      processedPrompt += segment.replaceAll(
        SHORTHAND_ARGS_PLACEHOLDER,
        userArgsRaw
      );
      if (injection.resolvedCommand) {
        const activeTheme = themeManager.getActiveTheme();
        const shellExecutionConfig = {
          ...config.getShellExecutionConfig(),
          defaultFg: activeTheme.colors.Foreground,
          defaultBg: activeTheme.colors.Background
        };
        const { result } = await ShellExecutionService.execute(
          injection.resolvedCommand,
          config.getTargetDir(),
          () => {
          },
          new AbortController().signal,
          config.getShouldUseNodePtyShell(),
          shellExecutionConfig
        );
        const executionResult = await result;
        if (executionResult.error && !executionResult.aborted) {
          throw new Error(
            `Failed to start shell command in '${this.commandName}': ${executionResult.error.message}. Command: ${injection.resolvedCommand}`
          );
        }
        processedPrompt += executionResult.output;
        if (executionResult.aborted) {
          processedPrompt += `
[Shell command '${injection.resolvedCommand}' aborted]`;
        } else if (executionResult.exitCode !== 0 && executionResult.exitCode !== null) {
          processedPrompt += `
[Shell command '${injection.resolvedCommand}' exited with code ${executionResult.exitCode}]`;
        } else if (executionResult.signal !== null) {
          processedPrompt += `
[Shell command '${injection.resolvedCommand}' terminated by signal ${executionResult.signal}]`;
        }
      }
      lastIndex = injection.endIndex;
    }
    const finalSegment = prompt.substring(lastIndex);
    processedPrompt += finalSegment.replaceAll(
      SHORTHAND_ARGS_PLACEHOLDER,
      userArgsRaw
    );
    return [{ text: processedPrompt }];
  }
};

// packages/cli/src/services/prompt-processors/atFileProcessor.ts
init_esbuild_shims();
var debugLogger14 = createDebugLogger("AT_FILE_PROCESSOR");
var AtFileProcessor = class {
  constructor(commandName) {
    this.commandName = commandName;
  }
  static {
    __name(this, "AtFileProcessor");
  }
  async process(input, context) {
    const config = context.services.config;
    if (!config) {
      return input;
    }
    return flatMapTextParts(input, async (text) => {
      if (!text.includes(AT_FILE_INJECTION_TRIGGER)) {
        return [{ text }];
      }
      const injections = extractInjections(
        text,
        AT_FILE_INJECTION_TRIGGER,
        this.commandName
      );
      if (injections.length === 0) {
        return [{ text }];
      }
      const output = [];
      let lastIndex = 0;
      for (const injection of injections) {
        const prefix = text.substring(lastIndex, injection.startIndex);
        if (prefix) {
          output.push({ text: prefix });
        }
        const pathStr = injection.content;
        try {
          const fileContentParts = await readPathFromWorkspace(pathStr, config);
          if (fileContentParts.length === 0) {
            const uiMessage = `File '@{${pathStr}}' was ignored by .gitignore or configured Qwen ignore files and was not included in the prompt.`;
            context.ui.addItem(
              { type: "info" /* INFO */, text: uiMessage },
              Date.now()
            );
          }
          output.push(...fileContentParts);
        } catch (error) {
          const message = error instanceof Error ? error.message : String(error);
          const uiMessage = `Failed to inject content for '@{${pathStr}}': ${message}`;
          debugLogger14.error(
            `[AtFileProcessor] ${uiMessage}. Leaving placeholder in prompt.`
          );
          context.ui.addItem(
            { type: "error" /* ERROR */, text: uiMessage },
            Date.now()
          );
          const placeholder = text.substring(
            injection.startIndex,
            injection.endIndex
          );
          output.push({ text: placeholder });
        }
        lastIndex = injection.endIndex;
      }
      const suffix = text.substring(lastIndex);
      if (suffix) {
        output.push({ text: suffix });
      }
      return output;
    });
  }
};

// packages/cli/src/services/command-factory.ts
var debugLogger15 = createDebugLogger("COMMAND_FACTORY");
function createSlashCommandFromDefinition(filePath, baseDir, definition, extensionName, fileExtension) {
  const relativePathWithExt = path18.relative(baseDir, filePath);
  const relativePath = relativePathWithExt.substring(
    0,
    relativePathWithExt.length - fileExtension.length
  );
  const baseCommandName = relativePath.split(path18.sep).map((segment) => segment.replaceAll(":", "_")).join(":");
  const defaultDescription = `Custom command from ${path18.basename(filePath)}`;
  let description = definition.description || defaultDescription;
  if (extensionName) {
    description = `[${extensionName}] ${description}`;
  }
  const processors = [];
  const usesArgs = definition.prompt.includes(SHORTHAND_ARGS_PLACEHOLDER);
  const usesShellInjection = definition.prompt.includes(
    SHELL_INJECTION_TRIGGER
  );
  const usesAtFileInjection = definition.prompt.includes(
    AT_FILE_INJECTION_TRIGGER
  );
  if (usesAtFileInjection) {
    processors.push(new AtFileProcessor(baseCommandName));
  }
  if (usesShellInjection || usesArgs) {
    processors.push(new ShellProcessor(baseCommandName));
  }
  if (!usesArgs) {
    processors.push(new DefaultArgumentProcessor());
  }
  return {
    name: baseCommandName,
    description,
    modelDescription: description,
    kind: "file" /* FILE */,
    extensionName,
    source: extensionName ? "plugin-command" : "skill-dir-command",
    sourceLabel: extensionName ? `${t("Extension:")} ${extensionName}` : t("Custom"),
    sourceDetail: extensionName ? "extension" : "custom",
    modelInvocable: definition.disableModelInvocation ? false : !extensionName || !!(definition.description || definition.whenToUse),
    argumentHint: definition.argumentHint,
    whenToUse: definition.whenToUse,
    action: /* @__PURE__ */ __name(async (context, _args) => {
      if (!context.invocation) {
        debugLogger15.error(
          `[FileCommandLoader] Critical error: Command '${baseCommandName}' was executed without invocation context.`
        );
        return {
          type: "submit_prompt",
          content: [{ text: definition.prompt }]
          // Fallback to unprocessed prompt
        };
      }
      try {
        let processedContent = [
          { text: definition.prompt }
        ];
        for (const processor of processors) {
          processedContent = await processor.process(processedContent, context);
        }
        return {
          type: "submit_prompt",
          content: processedContent
        };
      } catch (e) {
        if (e instanceof ConfirmationRequiredError) {
          return {
            type: "confirm_shell_commands",
            commandsToConfirm: e.commandsToConfirm,
            originalInvocation: {
              raw: context.invocation.raw
            }
          };
        }
        throw e;
      }
    }, "action")
  };
}
__name(createSlashCommandFromDefinition, "createSlashCommandFromDefinition");

// packages/cli/src/services/FileCommandLoader.ts
var debugLogger16 = createDebugLogger("FILE_COMMAND_LOADER");
var TomlCommandDefSchema = external_exports.object({
  prompt: external_exports.string({
    required_error: "The 'prompt' field is required.",
    invalid_type_error: "The 'prompt' field must be a string."
  }),
  description: external_exports.string().optional()
});
var FileCommandLoader = class {
  constructor(config) {
    this.config = config;
    this.folderTrustEnabled = !!config?.getFolderTrustFeature();
    this.folderTrust = !!config?.getFolderTrust();
    this.projectRoot = config?.getProjectRoot() || process.cwd();
  }
  static {
    __name(this, "FileCommandLoader");
  }
  projectRoot;
  folderTrustEnabled;
  folderTrust;
  /**
   * Loads all commands from user, project, and extension directories.
   * Returns commands in order: user → project → extensions (alphabetically).
   *
   * Order is important for conflict resolution in CommandService:
   * - User/project commands (without extensionName) use "last wins" strategy
   * - Extension commands (with extensionName) get renamed if conflicts exist
   *
   * @param signal An AbortSignal to cancel the loading process.
   * @returns A promise that resolves to an array of all loaded SlashCommands.
   */
  async loadCommands(signal) {
    if (this.config?.getBareMode?.()) {
      debugLogger16.debug("Bare mode enabled, skipping auto-discovered commands");
      return [];
    }
    const allCommands = [];
    const globOptions = {
      nodir: true,
      dot: true,
      signal,
      follow: true
    };
    const commandDirs = this.getCommandDirectories();
    for (const dirInfo of commandDirs) {
      try {
        const tomlFiles = await glob("**/*.toml", {
          ...globOptions,
          cwd: dirInfo.path
        });
        const mdFiles = await glob("**/*.md", {
          ...globOptions,
          cwd: dirInfo.path
        });
        if (this.folderTrustEnabled && !this.folderTrust) {
          return [];
        }
        const tomlCommandPromises = tomlFiles.map(
          (file) => this.parseAndAdaptTomlFile(
            path19.join(dirInfo.path, file),
            dirInfo.path,
            dirInfo.extensionName
          )
        );
        const mdCommandPromises = mdFiles.map(
          (file) => this.parseAndAdaptMarkdownFile(
            path19.join(dirInfo.path, file),
            dirInfo.path,
            dirInfo.extensionName
          )
        );
        const commands = (await Promise.all([...tomlCommandPromises, ...mdCommandPromises])).filter((cmd) => cmd !== null);
        allCommands.push(...commands);
      } catch (error) {
        const isEnoent = error.code === "ENOENT";
        const isAbortError = error instanceof Error && error.name === "AbortError";
        if (!isEnoent && !isAbortError) {
          debugLogger16.error(
            `[FileCommandLoader] Error loading commands from ${dirInfo.path}:`,
            error
          );
        }
      }
    }
    return allCommands;
  }
  /**
   * Get all command directories in order for loading.
   * User commands → Project commands → Extension commands
   * This order ensures extension commands can detect all conflicts.
   */
  getCommandDirectories() {
    const dirs = [];
    const storage = this.config?.storage ?? new Storage(this.projectRoot);
    dirs.push({ path: Storage.getUserCommandsDir() });
    dirs.push({ path: storage.getProjectCommandsDir() });
    if (this.config) {
      const activeExtensions = this.config.getExtensions().filter((ext) => ext.isActive).sort((a, b) => a.name.localeCompare(b.name));
      for (const ext of activeExtensions) {
        const commandsPaths = this.getExtensionCommandsPaths(ext);
        for (const cmdPath of commandsPaths) {
          dirs.push({
            path: cmdPath,
            extensionName: ext.displayName ?? ext.name
          });
        }
      }
    }
    return dirs;
  }
  /**
   * Get commands paths from an extension.
   * Returns paths from config.commands if specified, otherwise defaults to 'commands' directory.
   */
  getExtensionCommandsPaths(ext) {
    try {
      const configPath = path19.join(ext.path, EXTENSIONS_CONFIG_FILENAME);
      if (fsSync.existsSync(configPath)) {
        const configContent = fsSync.readFileSync(configPath, "utf-8");
        const config = JSON.parse(configContent);
        if (config.commands) {
          const commandsArray = Array.isArray(config.commands) ? config.commands : [config.commands];
          return commandsArray.map(
            (cmdPath) => path19.isAbsolute(cmdPath) ? cmdPath : path19.join(ext.path, cmdPath)
          ).filter((cmdPath) => {
            try {
              return fsSync.existsSync(cmdPath);
            } catch {
              return false;
            }
          });
        }
      }
    } catch (error) {
      debugLogger16.warn(
        `Failed to read extension config for ${ext.name}:`,
        error
      );
    }
    const defaultPath = path19.join(ext.path, "commands");
    try {
      if (fsSync.existsSync(defaultPath)) {
        return [defaultPath];
      }
    } catch {
    }
    return [];
  }
  /**
   * Parses a single .toml file and transforms it into a SlashCommand object.
   * @param filePath The absolute path to the .toml file.
   * @param baseDir The root command directory for name calculation.
   * @param extensionName Optional extension name to prefix commands with.
   * @returns A promise resolving to a SlashCommand, or null if the file is invalid.
   */
  async parseAndAdaptTomlFile(filePath, baseDir, extensionName) {
    let fileContent;
    try {
      fileContent = await fs15.readFile(filePath, "utf-8");
    } catch (error) {
      debugLogger16.error(
        `[FileCommandLoader] Failed to read file ${filePath}:`,
        error instanceof Error ? error.message : String(error)
      );
      return null;
    }
    let parsed;
    try {
      parsed = import_toml.default.parse(fileContent);
    } catch (error) {
      debugLogger16.error(
        `[FileCommandLoader] Failed to parse TOML file ${filePath}:`,
        error instanceof Error ? error.message : String(error)
      );
      return null;
    }
    const validationResult = TomlCommandDefSchema.safeParse(parsed);
    if (!validationResult.success) {
      debugLogger16.error(
        `[FileCommandLoader] Skipping invalid command file: ${filePath}. Validation errors:`,
        validationResult.error.flatten()
      );
      return null;
    }
    const validDef = validationResult.data;
    return createSlashCommandFromDefinition(
      filePath,
      baseDir,
      validDef,
      extensionName,
      ".toml"
    );
  }
  /**
   * Parses a single .md file and transforms it into a SlashCommand object.
   * @param filePath The absolute path to the .md file.
   * @param baseDir The root command directory for name calculation.
   * @param extensionName Optional extension name to prefix commands with.
   * @returns A promise resolving to a SlashCommand, or null if the file is invalid.
   */
  async parseAndAdaptMarkdownFile(filePath, baseDir, extensionName) {
    let fileContent;
    try {
      fileContent = await fs15.readFile(filePath, "utf-8");
    } catch (error) {
      debugLogger16.error(
        `[FileCommandLoader] Failed to read file ${filePath}:`,
        error instanceof Error ? error.message : String(error)
      );
      return null;
    }
    let parsed;
    try {
      parsed = parseMarkdownCommand(fileContent);
    } catch (error) {
      debugLogger16.error(
        `[FileCommandLoader] Failed to parse Markdown file ${filePath}:`,
        error instanceof Error ? error.message : String(error)
      );
      return null;
    }
    const validationResult = MarkdownCommandDefSchema.safeParse(parsed);
    if (!validationResult.success) {
      debugLogger16.error(
        `[FileCommandLoader] Skipping invalid command file: ${filePath}. Validation errors:`,
        validationResult.error.flatten()
      );
      return null;
    }
    const validDef = validationResult.data;
    const definition = {
      prompt: validDef.prompt,
      description: validDef.frontmatter?.description && typeof validDef.frontmatter.description === "string" ? validDef.frontmatter.description : void 0,
      whenToUse: validDef.frontmatter?.when_to_use,
      argumentHint: validDef.frontmatter?.["argument-hint"],
      disableModelInvocation: validDef.frontmatter?.["disable-model-invocation"]
    };
    return createSlashCommandFromDefinition(
      filePath,
      baseDir,
      definition,
      extensionName,
      ".md"
    );
  }
};

// packages/cli/src/services/saved-workflow-loader.ts
init_esbuild_shims();
var debugLogger17 = createDebugLogger("SavedWorkflowLoader");
var SavedWorkflowLoader = class {
  constructor(config) {
    this.config = config;
  }
  static {
    __name(this, "SavedWorkflowLoader");
  }
  async loadCommands(signal) {
    if (!this.config) return [];
    if (!this.config.isWorkflowsEnabled?.()) return [];
    if (this.config.getBareMode?.()) return [];
    const folderTrustEnabled = !!this.config.getFolderTrustFeature?.();
    const folderTrust = !!this.config.getFolderTrust?.();
    if (folderTrustEnabled && !folderTrust) return [];
    let entries;
    try {
      entries = await listSavedWorkflows(this.config);
    } catch (e) {
      debugLogger17.debug(`listSavedWorkflows failed: ${e}`);
      return [];
    }
    if (signal.aborted) return [];
    return entries.map((entry) => this.toCommand(entry));
  }
  toCommand(entry) {
    return {
      name: entry.name,
      description: `Run the "${entry.name}" saved workflow (${entry.source})`,
      // File-derived command (all execution modes via commandUtils fallback);
      // `source` carries the distinct workflow identity for display/telemetry.
      kind: "file" /* FILE */,
      source: "workflow-command",
      sourceLabel: "Workflow",
      sourceDetail: entry.source,
      // 'project' | 'user'
      // Interactive only: the action returns a `{type:'tool'}` dispatch, which
      // the non-interactive command adapter converts to `unsupported`. Listing
      // these in headless / ACP modes would advertise a command that then fails
      // to run, so restrict them until those paths can execute a tool return.
      supportedModes: ["interactive"],
      acceptsInput: true,
      argumentHint: "[json-args]",
      action: /* @__PURE__ */ __name((_context, args) => {
        const toolArgs = {
          // The tool reads the file fresh at execution time (hot reload).
          scriptPath: entry.scriptPath
        };
        const trimmed = (args ?? "").trim();
        if (trimmed.length > 0) {
          toolArgs["args"] = tryParseJson(trimmed);
        }
        return {
          type: "tool",
          toolName: ToolNames.WORKFLOW,
          toolArgs
        };
      }, "action")
    };
  }
};
function tryParseJson(raw) {
  try {
    return JSON.parse(raw);
  } catch {
    return raw;
  }
}
__name(tryParseJson, "tryParseJson");

// packages/cli/src/services/McpPromptLoader.ts
init_esbuild_shims();
var McpPromptLoader = class {
  constructor(config) {
    this.config = config;
  }
  static {
    __name(this, "McpPromptLoader");
  }
  /**
   * Loads all available prompts from all configured MCP servers and adapts
   * them into executable SlashCommand objects.
   *
   * @param _signal An AbortSignal (unused for this synchronous loader).
   * @returns A promise that resolves to an array of loaded SlashCommands.
   */
  loadCommands(_signal) {
    const promptCommands = [];
    if (!this.config) {
      return Promise.resolve([]);
    }
    const mcpServers = this.config.getMcpServers() || {};
    for (const serverName in mcpServers) {
      const prompts = getMCPServerPrompts(this.config, serverName) || [];
      for (const prompt of prompts) {
        const commandName = `${prompt.name}`;
        const description = prompt.description || `Invoke prompt ${prompt.name}`;
        const newPromptCommand = {
          name: commandName,
          description,
          modelDescription: description,
          kind: "mcp-prompt" /* MCP_PROMPT */,
          source: "mcp-prompt",
          sourceLabel: `MCP: ${serverName}`,
          subCommands: [
            {
              name: "help",
              description: "Show help for this prompt",
              modelDescription: "Show help for this prompt",
              kind: "mcp-prompt" /* MCP_PROMPT */,
              source: "mcp-prompt",
              action: /* @__PURE__ */ __name(async () => {
                if (!prompt.arguments || prompt.arguments.length === 0) {
                  return {
                    type: "message",
                    messageType: "info",
                    content: `Prompt "${prompt.name}" has no arguments.`
                  };
                }
                let helpMessage = `Arguments for "${prompt.name}":

`;
                if (prompt.arguments && prompt.arguments.length > 0) {
                  helpMessage += `You can provide arguments by name (e.g., --argName="value") or by position.

`;
                  helpMessage += `e.g., ${prompt.name} ${prompt.arguments?.map((_) => `"foo"`)} is equivalent to ${prompt.name} ${prompt.arguments?.map((arg) => `--${arg.name}="foo"`)}

`;
                }
                for (const arg of prompt.arguments) {
                  helpMessage += `  --${arg.name}
`;
                  if (arg.description) {
                    helpMessage += `    ${arg.description}
`;
                  }
                  helpMessage += `    (required: ${arg.required ? "yes" : "no"})

`;
                }
                return {
                  type: "message",
                  messageType: "info",
                  content: helpMessage
                };
              }, "action")
            }
          ],
          action: /* @__PURE__ */ __name(async (context, args) => {
            if (!this.config) {
              return {
                type: "message",
                messageType: "error",
                content: "Config not loaded."
              };
            }
            const promptInputs = this.parseArgs(args, prompt.arguments);
            if (promptInputs instanceof Error) {
              return {
                type: "message",
                messageType: "error",
                content: promptInputs.message
              };
            }
            try {
              const mcpServers2 = this.config.getMcpServers() || {};
              const mcpServerConfig = mcpServers2[serverName];
              if (!mcpServerConfig) {
                return {
                  type: "message",
                  messageType: "error",
                  content: `MCP server config not found for '${serverName}'.`
                };
              }
              const result = await prompt.invoke(promptInputs);
              if (result["error"]) {
                return {
                  type: "message",
                  messageType: "error",
                  content: `Error invoking prompt: ${result["error"]}`
                };
              }
              const firstMessage = result.messages?.[0];
              const content = firstMessage?.content;
              if (content?.type !== "text") {
                return {
                  type: "message",
                  messageType: "error",
                  content: "Received an empty or invalid prompt response from the server."
                };
              }
              return {
                type: "submit_prompt",
                content: JSON.stringify(content.text)
              };
            } catch (error) {
              return {
                type: "message",
                messageType: "error",
                content: `Error: ${getErrorMessage(error)}`
              };
            }
          }, "action"),
          completion: /* @__PURE__ */ __name(async (commandContext, partialArg) => {
            const invocation = commandContext.invocation;
            if (!prompt || !prompt.arguments || !invocation) {
              return [];
            }
            const indexOfFirstSpace = invocation.raw.indexOf(" ") + 1;
            let promptInputs = indexOfFirstSpace === 0 ? {} : this.parseArgs(
              invocation.raw.substring(indexOfFirstSpace),
              prompt.arguments
            );
            if (promptInputs instanceof Error) {
              promptInputs = {};
            }
            const providedArgNames = Object.keys(promptInputs);
            const unusedArguments = prompt.arguments.filter((arg) => {
              if (!providedArgNames.includes(arg.name)) {
                return true;
              }
              const argValue = promptInputs[arg.name];
              return argValue === partialArg;
            }).map((argument) => `--${argument.name}="`) || [];
            const exactlyMatchingArgumentAtTheEnd = prompt.arguments.map((argument) => `--${argument.name}="`).filter((flagArgument) => {
              const regex = new RegExp(`${flagArgument}[^"]*$`);
              return regex.test(invocation.raw);
            });
            if (exactlyMatchingArgumentAtTheEnd.length === 1) {
              if (exactlyMatchingArgumentAtTheEnd[0] === partialArg) {
                return [`${partialArg}"`];
              }
              if (partialArg.endsWith('"')) {
                return [partialArg];
              }
              return [`${partialArg}"`];
            }
            const matchingArguments = unusedArguments.filter(
              (flagArgument) => flagArgument.startsWith(partialArg)
            );
            return matchingArguments;
          }, "completion")
        };
        promptCommands.push(newPromptCommand);
      }
    }
    return Promise.resolve(promptCommands);
  }
  /**
   * Parses the `userArgs` string representing the prompt arguments (all the text
   * after the command) into a record matching the shape of the `promptArgs`.
   *
   * @param userArgs
   * @param promptArgs
   * @returns A record of the parsed arguments
   * @visibleForTesting
   */
  parseArgs(userArgs, promptArgs) {
    const argValues = {};
    const promptInputs = {};
    const namedArgRegex = /--([^=]+)=(?:"((?:\\.|[^"\\])*)"|([^ ]+))/g;
    let match;
    let lastIndex = 0;
    const positionalParts = [];
    while ((match = namedArgRegex.exec(userArgs)) !== null) {
      const key = match[1];
      const value = (match[2] ?? match[3]).replace(/\\(.)/g, "$1");
      argValues[key] = value;
      if (match.index > lastIndex) {
        positionalParts.push(userArgs.substring(lastIndex, match.index));
      }
      lastIndex = namedArgRegex.lastIndex;
    }
    if (lastIndex < userArgs.length) {
      positionalParts.push(userArgs.substring(lastIndex));
    }
    const positionalArgsString = positionalParts.join("").trim();
    const positionalArgRegex = /(?:"((?:\\.|[^"\\])*)"|([^ ]+))/g;
    const positionalArgs = [];
    while ((match = positionalArgRegex.exec(positionalArgsString)) !== null) {
      positionalArgs.push((match[1] ?? match[2]).replace(/\\(.)/g, "$1"));
    }
    if (!promptArgs) {
      return promptInputs;
    }
    for (const arg of promptArgs) {
      if (Object.hasOwn(argValues, arg.name)) {
        promptInputs[arg.name] = argValues[arg.name];
      }
    }
    const unfilledArgs = promptArgs.filter(
      (arg) => arg.required && !Object.hasOwn(promptInputs, arg.name)
    );
    if (unfilledArgs.length === 1) {
      promptInputs[unfilledArgs[0].name] = positionalArgs.join(" ");
    } else {
      const missingArgs = [];
      for (let i = 0; i < unfilledArgs.length; i++) {
        if (positionalArgs.length > i) {
          promptInputs[unfilledArgs[i].name] = positionalArgs[i];
        } else {
          missingArgs.push(unfilledArgs[i].name);
        }
      }
      if (missingArgs.length > 0) {
        const missingArgNames = missingArgs.map((name) => `--${name}`).join(", ");
        return new Error(`Missing required argument(s): ${missingArgNames}`);
      }
    }
    return promptInputs;
  }
};

// packages/cli/src/services/SkillCommandLoader.ts
init_esbuild_shims();
import { dirname as dirname5 } from "node:path";
var debugLogger18 = createDebugLogger("SKILL_COMMAND_LOADER");
var SkillCommandLoader = class {
  constructor(config) {
    this.config = config;
  }
  static {
    __name(this, "SkillCommandLoader");
  }
  async loadCommands(_signal) {
    if (this.config?.getBareMode?.()) {
      debugLogger18.debug("Bare mode enabled, skipping skill commands");
      return [];
    }
    const skillManager = this.config?.getSkillManager();
    if (!skillManager) {
      debugLogger18.debug("SkillManager not available, skipping skill commands");
      return [];
    }
    try {
      const [userSkills, projectSkills, extensionSkills] = await Promise.all([
        skillManager.listSkills({ level: "user" }),
        skillManager.listSkills({ level: "project" }),
        skillManager.listSkills({ level: "extension" })
      ]);
      const allSkills = [...userSkills, ...projectSkills, ...extensionSkills];
      const disabled = this.config?.getDisabledSkillNames() ?? /* @__PURE__ */ new Set();
      const visibleSkills = allSkills.filter(
        (skill) => !disabled.has(skill.name.toLowerCase())
      );
      const nonUserInvocableCount = visibleSkills.filter(
        (skill) => skill.userInvocable === false
      ).length;
      debugLogger18.debug(
        `Loaded ${userSkills.length} user + ${projectSkills.length} project + ${extensionSkills.length} extension skill(s) as slash commands; ${allSkills.length - visibleSkills.length} hidden by skills.disabled; ${nonUserInvocableCount} marked non-user-invocable`
      );
      return visibleSkills.map((skill) => {
        const isExtension = skill.level === "extension";
        const modelInvocable = skill.disableModelInvocation ? false : isExtension ? !!(skill.description || skill.whenToUse) : true;
        const sourceLabel = isExtension ? `${t("Extension:")} ${skill.extensionName ?? "unknown"}` : skill.level === "project" ? t("Project") : t("User");
        return {
          name: skill.name,
          description: skill.description,
          modelDescription: skill.description,
          kind: "skill" /* SKILL */,
          source: isExtension ? "plugin-command" : "skill-dir-command",
          sourceLabel,
          sourceDetail: isExtension ? "extension" : skill.level === "project" ? "project" : "user",
          userInvocable: skill.userInvocable ?? true,
          modelInvocable,
          argumentHint: skill.argumentHint,
          whenToUse: skill.whenToUse,
          skillDetail: {
            name: skill.name,
            description: skill.description,
            body: skill.body,
            level: skill.level
          },
          action: /* @__PURE__ */ __name(async (context, _args) => {
            applySkillAllowedTools(
              this.config?.getPermissionManager(),
              skill.allowedTools
            );
            const body = buildSkillLlmContent(
              dirname5(skill.filePath),
              skill.body
            );
            const content = context.invocation?.args ? appendToLastTextPart([{ text: body }], context.invocation.raw) : [{ text: body }];
            return {
              type: "submit_prompt",
              content
            };
          }, "action")
        };
      });
    } catch (error) {
      debugLogger18.error("Failed to load skill commands:", error);
      return [];
    }
  }
};

// packages/cli/src/ui/noninteractive/nonInteractiveUi.ts
init_esbuild_shims();
function createNonInteractiveUI() {
  return {
    history: [],
    addItem: /* @__PURE__ */ __name((_item, _timestamp) => 0, "addItem"),
    clear: /* @__PURE__ */ __name(() => {
    }, "clear"),
    setDebugMessage: /* @__PURE__ */ __name((_message) => {
    }, "setDebugMessage"),
    loadHistory: /* @__PURE__ */ __name((_newHistory) => {
    }, "loadHistory"),
    refreshStatic: /* @__PURE__ */ __name(() => {
    }, "refreshStatic"),
    pendingItem: null,
    setPendingItem: /* @__PURE__ */ __name((_item) => {
    }, "setPendingItem"),
    btwItem: null,
    setBtwItem: /* @__PURE__ */ __name((_item) => {
    }, "setBtwItem"),
    cancelBtw: /* @__PURE__ */ __name(() => {
    }, "cancelBtw"),
    btwAbortControllerRef: { current: null },
    isIdleRef: { current: true },
    toggleVimEnabled: /* @__PURE__ */ __name(async () => false, "toggleVimEnabled"),
    setGeminiMdFileCount: /* @__PURE__ */ __name((_count) => {
    }, "setGeminiMdFileCount"),
    reloadCommands: /* @__PURE__ */ __name(() => {
    }, "reloadCommands"),
    setSessionName: /* @__PURE__ */ __name(() => {
    }, "setSessionName"),
    extensionsUpdateState: /* @__PURE__ */ new Map(),
    dispatchExtensionStateUpdate: /* @__PURE__ */ __name((_action) => {
    }, "dispatchExtensionStateUpdate"),
    addConfirmUpdateExtensionRequest: /* @__PURE__ */ __name((_request) => {
    }, "addConfirmUpdateExtensionRequest")
  };
}
__name(createNonInteractiveUI, "createNonInteractiveUI");

// packages/cli/src/utils/userPromptExpansionHook.ts
init_esbuild_shims();
function appendUserPromptExpansionAdditionalContext(content, additionalContext) {
  if (!additionalContext) {
    return content;
  }
  const suffix = `

${additionalContext}`;
  if (typeof content === "string") {
    return `${content}${suffix}`;
  }
  if (Array.isArray(content)) {
    return [...content, { text: suffix }];
  }
  return [content, { text: suffix }];
}
__name(appendUserPromptExpansionAdditionalContext, "appendUserPromptExpansionAdditionalContext");
function serializeUserPromptExpansionPrompt(content) {
  return partToString(content, { verbose: true });
}
__name(serializeUserPromptExpansionPrompt, "serializeUserPromptExpansionPrompt");
function formatUserPromptExpansionBlockedMessage(reason) {
  const sanitizedReason = sanitizeUserPromptExpansionAdditionalContext(reason);
  return `UserPromptExpansion blocked: ${sanitizedReason}`;
}
__name(formatUserPromptExpansionBlockedMessage, "formatUserPromptExpansionBlockedMessage");

// packages/cli/src/nonInteractiveCliCommands.ts
var debugLogger19 = createDebugLogger("NON_INTERACTIVE_COMMANDS");
function getSkillCommandName(command) {
  return command.skillDetail?.name ?? command.name;
}
__name(getSkillCommandName, "getSkillCommandName");
function handleCommandResult(result, outputHistoryItems) {
  switch (result.type) {
    case "submit_prompt":
      return {
        type: "submit_prompt",
        content: result.content,
        ...result.modelOverride ? { modelOverride: result.modelOverride } : {},
        ...outputHistoryItems?.length ? { outputHistoryItems } : {}
      };
    case "message":
      return {
        type: "message",
        messageType: result.messageType,
        content: result.content,
        ...outputHistoryItems?.length ? { outputHistoryItems } : {}
      };
    case "stream_messages":
      return {
        type: "stream_messages",
        messages: result.messages
      };
    /**
     * Currently return types below are never generated due to the
     * whitelist of allowed slash commands in ACP and non-interactive mode.
     * We'll try to add more supported return types in the future.
     */
    case "tool":
      return {
        type: "unsupported",
        reason: "Tool execution from slash commands is not supported in non-interactive mode.",
        originalType: "tool"
      };
    case "quit":
      return {
        type: "unsupported",
        reason: "Quit command is not supported in non-interactive mode. The process will exit naturally after completion.",
        originalType: "quit"
      };
    case "dialog":
      return {
        type: "unsupported",
        reason: `Dialog '${result.dialog}' cannot be opened in non-interactive mode.`,
        originalType: "dialog"
      };
    case "load_history":
      return {
        type: "unsupported",
        reason: "Loading history is not supported in non-interactive mode. Each invocation starts with a fresh context.",
        originalType: "load_history"
      };
    case "confirm_shell_commands":
      return {
        type: "unsupported",
        reason: "Shell command confirmation is not supported in non-interactive mode. Use YOLO mode or pre-approve commands.",
        originalType: "confirm_shell_commands"
      };
    case "confirm_action":
      return {
        type: "unsupported",
        reason: "Action confirmation is not supported in non-interactive mode. Commands requiring confirmation cannot be executed.",
        originalType: "confirm_action"
      };
    default: {
      const _exhaustive = result;
      return {
        type: "unsupported",
        reason: `Unknown command result type: ${_exhaustive.type}`,
        originalType: "unknown"
      };
    }
  }
}
__name(handleCommandResult, "handleCommandResult");
async function fireUserPromptExpansionHook(config, commandName, commandArgs, content, signal) {
  if (config.getDisableAllHooks?.() || !(config.hasHooksForEvent?.("UserPromptExpansion") ?? false)) {
    return { content };
  }
  const hookSystem = config.getHookSystem();
  if (!hookSystem) {
    return { content };
  }
  const output = await hookSystem.fireUserPromptExpansionEvent(
    commandName,
    commandArgs,
    serializeUserPromptExpansionPrompt(content),
    signal
  );
  if (!output) {
    return { content };
  }
  const blockingError = output.getBlockingError();
  if (blockingError.blocked || output.shouldStopExecution()) {
    return {
      blockedResult: {
        type: "message",
        messageType: "error",
        content: formatUserPromptExpansionBlockedMessage(
          blockingError.reason || output.getEffectiveReason()
        )
      },
      content
    };
  }
  return {
    content: appendUserPromptExpansionAdditionalContext(
      content,
      output.getAdditionalContext()
    )
  };
}
__name(fireUserPromptExpansionHook, "fireUserPromptExpansionHook");
async function registerModelInvocableCommands(commandService, config, executionMode, settings) {
  if (!settings) {
    return;
  }
  config.setModelInvocableCommandsProvider(
    () => commandService.getModelInvocableCommands().map((cmd) => ({
      name: cmd.name,
      description: cmd.modelDescription ?? cmd.description
    }))
  );
  config.setModelInvocableCommandsExecutor(
    async (name, args = "") => {
      const commands = commandService.getModelInvocableCommands();
      const cmd = commands.find((c) => c.name === name);
      if (!cmd?.action) return null;
      const minimalContext = {
        executionMode,
        invocation: {
          raw: args ? `/${name} ${args}` : `/${name}`,
          name,
          args
        },
        services: { config, settings, logger: null }
      };
      const result = await cmd.action(minimalContext, args);
      if (!result || result.type !== "submit_prompt") return null;
      const hookSignal = new AbortController().signal;
      const hookResult = await fireUserPromptExpansionHook(
        config,
        name,
        args,
        result.content,
        hookSignal
      );
      if (hookResult.blockedResult) {
        return hookResult.blockedResult.type === "message" ? { error: hookResult.blockedResult.content } : null;
      }
      const content = hookResult.content;
      if (typeof content === "string") return content;
      if (Array.isArray(content)) {
        return content.map(
          (p) => typeof p === "string" ? p : p.text ?? ""
        ).join("");
      }
      return null;
    }
  );
  const skillManager = typeof config.getSkillManager === "function" ? config.getSkillManager() : null;
  await skillManager?.notifyConfigChanged();
}
__name(registerModelInvocableCommands, "registerModelInvocableCommands");
var handleSlashCommand = /* @__PURE__ */ __name(async (rawQuery, abortController, config, settings) => {
  const trimmed = rawQuery.trim();
  if (!trimmed.startsWith("/")) {
    return { type: "no_command" };
  }
  const isAcpMode = config.getExperimentalZedIntegration();
  const isInteractive = config.isInteractive();
  const executionMode = isAcpMode ? "acp" : isInteractive ? "interactive" : "non_interactive";
  const allLoaders = [
    new McpPromptLoader(config),
    new BuiltinCommandLoader(config),
    new BundledSkillLoader(config),
    new SkillCommandLoader(config),
    new SavedWorkflowLoader(config),
    new FileCommandLoader(config)
  ];
  const disabledSlashCommandsRaw = config.getDisabledSlashCommands();
  const disabledNameSet = /* @__PURE__ */ new Set();
  for (const name of disabledSlashCommandsRaw) {
    const trimmed2 = name.trim();
    if (trimmed2) disabledNameSet.add(trimmed2.toLowerCase());
  }
  const isDisabled = /* @__PURE__ */ __name((cmd) => disabledNameSet.has(cmd.name.toLowerCase()) || (cmd.altNames ?? []).some((a) => disabledNameSet.has(a.toLowerCase())), "isDisabled");
  const allCommandService = await CommandService.create(
    allLoaders,
    abortController.signal
  );
  const commandService = disabledNameSet.size > 0 ? await CommandService.create(
    allLoaders,
    abortController.signal,
    disabledNameSet
  ) : allCommandService;
  await registerModelInvocableCommands(
    commandService,
    config,
    executionMode,
    settings
  );
  const allCommands = allCommandService.getCommands();
  const filteredCommands = commandService.getCommandsForMode(executionMode).filter((cmd) => !isDisabled(cmd));
  const { commandToExecute, args } = parseSlashCommand(
    rawQuery,
    filteredCommands
  );
  if (!commandToExecute) {
    const { commandToExecute: knownCommand } = parseSlashCommand(
      rawQuery,
      allCommands
    );
    if (knownCommand) {
      const typedToken = rawQuery.trim().substring(1).trim().split(/\s+/)[0] ?? knownCommand.name;
      if (isDisabled(knownCommand)) {
        return {
          type: "unsupported",
          reason: t(
            'The command "/{{command}}" is disabled by the current configuration.',
            { command: typedToken }
          ),
          originalType: "filtered_command"
        };
      }
      return {
        type: "unsupported",
        reason: t('The command "/{{command}}" is not supported in this mode.', {
          command: typedToken
        }),
        originalType: "filtered_command"
      };
    }
    return { type: "no_command" };
  }
  if (!commandToExecute.action) {
    return { type: "no_command" };
  }
  const sessionStats = {
    sessionId: config?.getSessionId(),
    sessionStartTime: /* @__PURE__ */ new Date(),
    metrics: config ? uiTelemetryService.getMetricsForSession(config.getSessionId()) : uiTelemetryService.getMetrics(),
    lastPromptTokenCount: 0,
    promptCount: 1
  };
  const logger3 = new Logger(config?.getSessionId() || "", config?.storage);
  const outputHistoryItems = [];
  const ui = createNonInteractiveUI();
  ui.addItem = (item) => {
    outputHistoryItems.push(item);
    return 0;
  };
  const context = {
    executionMode,
    services: {
      config,
      settings,
      logger: logger3
    },
    ui,
    session: {
      stats: sessionStats,
      sessionShellAllowlist: /* @__PURE__ */ new Set()
    },
    invocation: {
      raw: trimmed,
      name: commandToExecute.name,
      args
    }
  };
  const isSkillCommand = commandToExecute.kind === "skill" /* SKILL */;
  let skillInvocationRecorded = false;
  const recordSkillCommandInvocation = /* @__PURE__ */ __name((success) => {
    if (!isSkillCommand || skillInvocationRecorded) {
      return;
    }
    recordSkillInvocation(config, {
      skillName: getSkillCommandName(commandToExecute),
      success
    });
    skillInvocationRecorded = true;
  }, "recordSkillCommandInvocation");
  let result;
  try {
    result = await commandToExecute.action(context, args);
  } catch (error) {
    recordSkillCommandInvocation(false);
    throw error;
  }
  if (!result) {
    return {
      type: "message",
      messageType: "info",
      content: "Command executed successfully."
    };
  }
  if (result.type === "submit_prompt") {
    let hookResult;
    try {
      hookResult = await fireUserPromptExpansionHook(
        config,
        commandToExecute.name,
        args,
        result.content,
        abortController.signal
      );
    } catch (error) {
      recordSkillCommandInvocation(false);
      throw error;
    }
    if (hookResult.blockedResult) {
      recordSkillCommandInvocation(false);
      return hookResult.blockedResult;
    }
    recordSkillCommandInvocation(true);
    return handleCommandResult(
      { ...result, content: hookResult.content },
      outputHistoryItems
    );
  }
  return handleCommandResult(result, outputHistoryItems);
}, "handleSlashCommand");
var getAvailableCommands = /* @__PURE__ */ __name(async (config, abortSignal, mode = "acp", settings) => {
  try {
    const loaders = [
      new McpPromptLoader(config),
      new BuiltinCommandLoader(config),
      new BundledSkillLoader(config),
      new SkillCommandLoader(config),
      new SavedWorkflowLoader(config),
      new FileCommandLoader(config)
    ];
    const disabledSlashCommands = config.getDisabledSlashCommands();
    const commandService = await CommandService.create(
      loaders,
      abortSignal,
      disabledSlashCommands.length > 0 ? new Set(disabledSlashCommands) : void 0
    );
    await registerModelInvocableCommands(
      commandService,
      config,
      mode,
      settings
    );
    return commandService.getCommandsForMode(mode);
  } catch (error) {
    debugLogger19.error("Error loading available commands:", error);
    return [];
  }
}, "getAvailableCommands");

// packages/cli/src/utils/nonInteractiveHelpers.ts
init_esbuild_shims();
var debugLogger20 = createDebugLogger("NON_INTERACTIVE");
function normalizePartList(parts) {
  if (!parts) {
    return [];
  }
  if (typeof parts === "string") {
    return [{ text: parts }];
  }
  if (Array.isArray(parts)) {
    return parts.map(
      (part) => typeof part === "string" ? { text: part } : part
    );
  }
  return [parts];
}
__name(normalizePartList, "normalizePartList");
function extractPartsFromUserMessage(message) {
  if (!message) {
    return null;
  }
  const content = message.message?.content;
  if (typeof content === "string") {
    return content;
  }
  if (Array.isArray(content)) {
    const parts = [];
    for (const block of content) {
      if (!block || typeof block !== "object" || !("type" in block)) {
        continue;
      }
      if (block.type === "text" && "text" in block && block.text) {
        parts.push({ text: block.text });
      } else {
        parts.push({ text: JSON.stringify(block) });
      }
    }
    return parts.length > 0 ? parts : null;
  }
  return null;
}
__name(extractPartsFromUserMessage, "extractPartsFromUserMessage");
function computeUsageFromMetrics(metrics) {
  const stats = computeSessionStats(metrics);
  const { models } = metrics;
  const totalOutputTokens = Object.values(models).reduce(
    (acc, model) => acc + model.tokens.candidates,
    0
  );
  const totalTokens = Object.values(models).reduce(
    (acc, model) => acc + model.tokens.total,
    0
  );
  const usage2 = {
    input_tokens: stats.totalPromptTokens,
    output_tokens: totalOutputTokens,
    cache_read_input_tokens: stats.totalCachedTokens
  };
  if (totalTokens > 0) {
    usage2.total_tokens = totalTokens;
  }
  return usage2;
}
__name(computeUsageFromMetrics, "computeUsageFromMetrics");
function buildInitialSystemReminders(config) {
  const reminders = [];
  if (config.getApprovalMode() === "plan" /* PLAN */) {
    reminders.push({ text: getPlanModeSystemReminder(config.getSdkMode?.()) });
  }
  const arenaManager = config.getArenaManager?.();
  if (arenaManager) {
    try {
      const sessionDir = arenaManager.getArenaSessionDir();
      const configPath = `${sessionDir}/config.json`;
      reminders.push({ text: getArenaSystemReminder(configPath) });
    } catch {
    }
  }
  return reminders;
}
__name(buildInitialSystemReminders, "buildInitialSystemReminders");
function insertAfterFunctionResponses(parts, additions) {
  const firstNonFunctionResponse = parts.findIndex(
    (part) => !part.functionResponse
  );
  const insertAt = firstNonFunctionResponse === -1 ? parts.length : firstNonFunctionResponse;
  return [...parts.slice(0, insertAt), ...additions, ...parts.slice(insertAt)];
}
__name(insertAfterFunctionResponses, "insertAfterFunctionResponses");
async function loadSlashCommandNames(config) {
  const controller = new AbortController();
  try {
    const commands = await getAvailableCommands(
      config,
      controller.signal,
      "non_interactive"
    );
    return commands.map((cmd) => cmd.name).sort();
  } catch (error) {
    debugLogger20.error(
      "[buildSystemMessage] Failed to load slash commands:",
      error
    );
    return [];
  } finally {
    controller.abort();
  }
}
__name(loadSlashCommandNames, "loadSlashCommandNames");
async function buildSystemMessage(config, sessionId, permissionMode) {
  const toolRegistry = config.getToolRegistry();
  const tools = toolRegistry ? toolRegistry.getAllToolNames() : [];
  const mcpServers = config.getMcpServers();
  const mcpServerList = mcpServers ? Object.keys(mcpServers).map((name) => ({
    name,
    status: getMCPServerStatus(name)
  })) : [];
  const slashCommands = await loadSlashCommandNames(config);
  let agentNames = [];
  try {
    const subagentManager = config.getSubagentManager();
    const subagents = await subagentManager.listSubagents();
    agentNames = subagents.map((subagent) => subagent.name);
  } catch (error) {
    debugLogger20.error("[buildSystemMessage] Failed to load subagents:", error);
  }
  const systemMessage = {
    type: "system",
    subtype: "init",
    uuid: sessionId,
    session_id: sessionId,
    cwd: config.getTargetDir(),
    tools,
    mcp_servers: mcpServerList,
    model: config.getModel(),
    permission_mode: permissionMode,
    slash_commands: slashCommands,
    qwen_code_version: config.getCliVersion() || "unknown",
    agents: agentNames
  };
  return systemMessage;
}
__name(buildSystemMessage, "buildSystemMessage");
function isMcpToolProgressData(output) {
  return typeof output === "object" && output !== null && "type" in output && output.type === "mcp_tool_progress";
}
__name(isMcpToolProgressData, "isMcpToolProgressData");
function createToolProgressHandler(request, adapter) {
  const handler = /* @__PURE__ */ __name((_callId, output) => {
    if (isMcpToolProgressData(output)) {
      adapter.emitToolProgress(request, output);
    }
  }, "handler");
  return { handler };
}
__name(createToolProgressHandler, "createToolProgressHandler");
function createAgentToolProgressHandler(config, agentToolCallId, adapter) {
  const previousTaskStates = /* @__PURE__ */ new Map();
  const emittedToolUseIds = /* @__PURE__ */ new Set();
  const emittedToolResultIds = /* @__PURE__ */ new Set();
  const buildRequest = /* @__PURE__ */ __name((toolCall) => ({
    callId: toolCall.callId,
    name: toolCall.name,
    args: toolCall.args || {},
    isClientInitiated: true,
    prompt_id: "",
    response_id: void 0
  }), "buildRequest");
  const buildResponse = /* @__PURE__ */ __name((toolCall) => ({
    callId: toolCall.callId,
    error: toolCall.status === "failed" ? new Error(toolCall.error || "Tool execution failed") : void 0,
    errorType: toolCall.status === "failed" ? "execution_failed" /* EXECUTION_FAILED */ : void 0,
    resultDisplay: toolCall.resultDisplay,
    responseParts: toolCall.responseParts || []
  }), "buildResponse");
  const hasResultContent = /* @__PURE__ */ __name((toolCall) => {
    if (typeof toolCall.resultDisplay === "string" && toolCall.resultDisplay.trim().length > 0) {
      return true;
    }
    if (toolCall.responseParts && toolCall.responseParts.length > 0) {
      return true;
    }
    return toolCall.status === "failed";
  }, "hasResultContent");
  const emitToolUseIfNeeded = /* @__PURE__ */ __name((toolCall, fallbackStatus) => {
    if (emittedToolUseIds.has(toolCall.callId)) {
      return;
    }
    const toolCallToEmit = fallbackStatus ? {
      ...toolCall,
      status: fallbackStatus
    } : toolCall;
    if (toolCallToEmit.status === "executing" || toolCallToEmit.status === "awaiting_approval") {
      if (adapter.processSubagentToolCall) {
        adapter.processSubagentToolCall(toolCallToEmit, agentToolCallId);
        emittedToolUseIds.add(toolCall.callId);
      }
    }
  }, "emitToolUseIfNeeded");
  const emitToolResultIfNeeded = /* @__PURE__ */ __name((toolCall) => {
    if (emittedToolResultIds.has(toolCall.callId)) {
      return;
    }
    if (!hasResultContent(toolCall)) {
      return;
    }
    emittedToolResultIds.add(toolCall.callId);
    const request = buildRequest(toolCall);
    const response = buildResponse(toolCall);
    if ("emitToolResult" in adapter && typeof adapter.emitToolResult === "function") {
      adapter.emitToolResult(request, response, agentToolCallId);
    } else {
      adapter.emitToolResult(request, response);
    }
  }, "emitToolResultIfNeeded");
  const processToolCall = /* @__PURE__ */ __name((toolCall, previousCall) => {
    const isCompleted = toolCall.status === "success" || toolCall.status === "failed";
    const isExecuting = toolCall.status === "executing" || toolCall.status === "awaiting_approval";
    const wasExecuting = previousCall && (previousCall.status === "executing" || previousCall.status === "awaiting_approval");
    if (isExecuting) {
      emitToolUseIfNeeded(toolCall);
    } else if (isCompleted && !emittedToolUseIds.has(toolCall.callId)) {
      emitToolUseIfNeeded(toolCall, "executing");
    } else if (wasExecuting && isCompleted) {
      emitToolUseIfNeeded(toolCall, "executing");
    }
    if (isCompleted) {
      emitToolResultIfNeeded(toolCall);
    }
  }, "processToolCall");
  const outputUpdateHandler = /* @__PURE__ */ __name((callId, outputChunk) => {
    if (typeof outputChunk === "object" && outputChunk !== null && "type" in outputChunk && outputChunk.type === "task_execution") {
      const taskDisplay = outputChunk;
      const previous = previousTaskStates.get(callId);
      if (!adapter.processSubagentToolCall || !adapter.emitSubagentErrorResult) {
        previousTaskStates.set(callId, taskDisplay);
        return;
      }
      if (taskDisplay.toolCalls) {
        if (!previous || !previous.toolCalls) {
          for (const toolCall of taskDisplay.toolCalls) {
            processToolCall(toolCall);
          }
        } else {
          for (const toolCall of taskDisplay.toolCalls) {
            const previousCall = previous.toolCalls.find(
              (tc) => tc.callId === toolCall.callId
            );
            processToolCall(toolCall, previousCall);
          }
        }
      }
      if (taskDisplay.status === "failed" || taskDisplay.status === "cancelled") {
        const previousStatus = previous?.status;
        if (previousStatus !== "failed" && previousStatus !== "cancelled" && previousStatus !== void 0) {
          const errorMessage2 = taskDisplay.terminateReason || (taskDisplay.status === "cancelled" ? "Task was cancelled" : "Task execution failed");
          adapter.emitSubagentErrorResult(errorMessage2, 0, agentToolCallId);
        }
      }
      if (!previous && taskDisplay.taskPrompt && !config.isInteractive() && (config.getOutputFormat() === "json" /* JSON */ || config.getOutputFormat() === "stream-json" /* STREAM_JSON */)) {
        adapter.emitUserMessage(
          [{ text: taskDisplay.taskPrompt }],
          agentToolCallId
        );
      }
      previousTaskStates.set(callId, taskDisplay);
    }
  }, "outputUpdateHandler");
  return {
    handler: outputUpdateHandler
  };
}
__name(createAgentToolProgressHandler, "createAgentToolProgressHandler");
function functionResponsePartsToString(parts) {
  return parts.map((part) => {
    if ("functionResponse" in part) {
      const content = part.functionResponse?.response?.["output"] ?? "";
      return content;
    }
    return JSON.stringify(part);
  }).join("");
}
__name(functionResponsePartsToString, "functionResponsePartsToString");

export {
  parseSlashCommand,
  CommandService,
  useAutoAcceptIndicator,
  formatApprovalModeName,
  formatApprovalModeDescription,
  hasBlockingBackgroundWork,
  resetBackgroundStateForSessionSwitch,
  isAtCommand,
  hasSlashCommandPathSeparator,
  isSlashCommand,
  isBtwCommand,
  isMidInputCompletableCommand,
  findMidInputSlashCommand,
  getBestSlashCommandMatch,
  findSlashCommandTokens,
  performStandaloneUpdate,
  getInstallationInfo,
  MessageEmitter,
  PlanEmitter,
  ToolCallEmitter,
  HistoryReplayer,
  recordGoalStatusItem,
  restoreGoalFromHistory,
  getTranslatedSourceDisplayMap,
  DISPLAY_HOOK_EVENTS,
  supportsMatchers,
  createEmptyHookEventInfo,
  addConfigToMatcherGroup,
  getAllConfigs,
  BuiltinCommandLoader,
  BundledSkillLoader,
  FileCommandLoader,
  SavedWorkflowLoader,
  McpPromptLoader,
  SkillCommandLoader,
  appendUserPromptExpansionAdditionalContext,
  serializeUserPromptExpansionPrompt,
  formatUserPromptExpansionBlockedMessage,
  handleSlashCommand,
  getAvailableCommands,
  normalizePartList,
  extractPartsFromUserMessage,
  computeUsageFromMetrics,
  buildInitialSystemReminders,
  insertAfterFunctionResponses,
  buildSystemMessage,
  createToolProgressHandler,
  createAgentToolProgressHandler,
  functionResponsePartsToString
};
/**
 * @license
 * Copyright 2025 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
/**
 * @license
 * Copyright 2025 Qwen
 * SPDX-License-Identifier: Apache-2.0
 */
/**
 * @license
 * Copyright 2025 Qwen Team
 * SPDX-License-Identifier: Apache-2.0
 */
/**
 * @license
 * Copyright 2026 Qwen Team
 * SPDX-License-Identifier: Apache-2.0
 */
/**
 * @license
 * Copyright 2025 Qwen Code
 * SPDX-License-Identifier: Apache-2.0
 */
/**
 * @license
 * Copyright 2026 Qwen
 * SPDX-License-Identifier: Apache-2.0
 */
/**
 * @license
 * Copyright 2025 Qwen Team
 * SPDX-License-Identifier: Apache-2.0
 *
 * This file is code-generated; do not edit manually.
 */
/**
 * @license
 * Copyright 2025 Qwen Team
 * SPDX-License-Identifier: Apache-2.0
 *
 * This HTML template is code-generated; do not edit manually.
 */
/**
 * @license
 * Copyright 2025 Qwen team
 * SPDX-License-Identifier: Apache-2.0
 */
