// Force strict mode and setup for ESM
"use strict";
import {
  Colors,
  RowMouseController
} from "./chunk-6OOS3TNP.js";
import {
  theme
} from "./chunk-VXGPYF7U.js";
import {
  Box_default,
  Text,
  require_jsx_runtime
} from "./chunk-4FRUXVSE.js";
import {
  require_react
} from "./chunk-KYMBIKIW.js";
import {
  t
} from "./chunk-RYT2ET4O.js";
import {
  readManyFiles,
  shouldRunVisionBridge,
  stripTerminalControlSequences
} from "./chunk-IQ7FOOIH.js";
import {
  emptyMcpResourceText,
  formatMcpResourceContents,
  summarizeMcpResource
} from "./chunk-LQ7TMOCE.js";
import {
  Storage,
  getErrorMessage,
  isNodeError,
  isSubpath,
  unescapePath
} from "./chunk-AVQDCKNF.js";
import {
  init_esbuild_shims
} from "./chunk-A4BMJM77.js";
import {
  __name,
  __toESM
} from "./chunk-J2S4EL5Y.js";

// packages/cli/src/ui/hooks/atCommandProcessor.ts
init_esbuild_shims();
import * as fs2 from "node:fs/promises";
import * as path from "node:path";

// packages/cli/src/ui/hooks/mcpResourceRef.ts
init_esbuild_shims();
function matchMcpServerPrefix(input, serverNames) {
  let serverName = null;
  for (const name of serverNames) {
    if (input.startsWith(`${name}:`) && (serverName === null || name.length > serverName.length)) {
      serverName = name;
    }
  }
  if (serverName === null) return null;
  return { serverName, rest: input.slice(serverName.length + 1) };
}
__name(matchMcpServerPrefix, "matchMcpServerPrefix");
function buildMcpResourceRef(serverName, uri) {
  return `${serverName}:${uri}`;
}
__name(buildMcpResourceRef, "buildMcpResourceRef");

// packages/cli/src/ui/hooks/extension-mention-ref.ts
init_esbuild_shims();

// packages/cli/src/ui/components/SuggestionsDisplay.tsx
init_esbuild_shims();
var import_react2 = __toESM(require_react(), 1);

// packages/cli/src/ui/components/PrepareLabel.tsx
init_esbuild_shims();
var import_react = __toESM(require_react(), 1);
var import_jsx_runtime = __toESM(require_jsx_runtime(), 1);
var MAX_WIDTH = 150;
var _PrepareLabel = /* @__PURE__ */ __name(({
  label,
  matchedIndex,
  userInput,
  textColor,
  isExpanded = false
}) => {
  const hasMatch = matchedIndex !== void 0 && matchedIndex >= 0 && matchedIndex < label.length && userInput.length > 0;
  if (!hasMatch) {
    const display = isExpanded ? label : label.length > MAX_WIDTH ? label.slice(0, MAX_WIDTH) + "..." : label;
    return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { wrap: "wrap", color: textColor, children: display });
  }
  const matchLength = userInput.length;
  let before = "";
  let match = "";
  let after = "";
  if (isExpanded || label.length <= MAX_WIDTH) {
    before = label.slice(0, matchedIndex);
    match = label.slice(matchedIndex, matchedIndex + matchLength);
    after = label.slice(matchedIndex + matchLength);
  } else if (matchLength >= MAX_WIDTH) {
    match = label.slice(matchedIndex, matchedIndex + MAX_WIDTH - 1) + "...";
  } else {
    const contextSpace = MAX_WIDTH - matchLength;
    const beforeSpace = Math.floor(contextSpace / 2);
    const afterSpace = Math.ceil(contextSpace / 2);
    let start = matchedIndex - beforeSpace;
    let end = matchedIndex + matchLength + afterSpace;
    if (start < 0) {
      end += -start;
      start = 0;
    }
    if (end > label.length) {
      start -= end - label.length;
      end = label.length;
    }
    start = Math.max(0, start);
    const finalMatchIndex = matchedIndex - start;
    const slicedLabel = label.slice(start, end);
    before = slicedLabel.slice(0, finalMatchIndex);
    match = slicedLabel.slice(finalMatchIndex, finalMatchIndex + matchLength);
    after = slicedLabel.slice(finalMatchIndex + matchLength);
    if (start > 0) {
      before = before.length >= 3 ? "..." + before.slice(3) : "...";
    }
    if (end < label.length) {
      after = after.length >= 3 ? after.slice(0, -3) + "..." : "...";
    }
  }
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { color: textColor, wrap: "wrap", children: [
    before,
    match ? match.split(/(\s+)/).map((part, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
      Text,
      {
        color: theme.background.primary,
        backgroundColor: theme.text.primary,
        children: part
      },
      `match-${index}`
    )) : null,
    after
  ] });
}, "_PrepareLabel");
var PrepareLabel = import_react.default.memo(_PrepareLabel);

// packages/cli/src/ui/components/SuggestionsDisplay.tsx
var import_jsx_runtime2 = __toESM(require_jsx_runtime(), 1);
var MAX_SUGGESTIONS_TO_SHOW = 8;
var MIN_DESCRIPTION_WIDTH = 12;
var ACTIVE_MARKER_WIDTH = 2;
function normalizeDescription(description) {
  return description.replace(/\s+/g, " ").trim();
}
__name(normalizeDescription, "normalizeDescription");
function SuggestionsDisplay({
  suggestions,
  activeIndex,
  isLoading,
  width,
  scrollOffset,
  userInput,
  mode,
  expandedIndex,
  onHoverIndex,
  onSelectIndex,
  mouseEnabled
}) {
  const containerRef = (0, import_react2.useRef)(null);
  const itemRefs = (0, import_react2.useRef)([]);
  if (isLoading) {
    return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box_default, { width, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { color: "gray", children: t("Loading suggestions...") }) });
  }
  if (suggestions.length === 0) {
    return null;
  }
  const startIndex = scrollOffset;
  const endIndex = Math.min(
    scrollOffset + MAX_SUGGESTIONS_TO_SHOW,
    suggestions.length
  );
  const visibleSuggestions = suggestions.slice(startIndex, endIndex);
  const getFullLabel = /* @__PURE__ */ __name((s) => [s.label, s.argumentHint, s.sourceBadge].filter(Boolean).join(" "), "getFullLabel");
  const maxLabelLength = Math.max(
    ...suggestions.map((s) => getFullLabel(s).length)
  );
  const describedLabelLengths = suggestions.filter((s) => s.description).map((s) => getFullLabel(s).length);
  const contentWidth = Math.max(width - ACTIVE_MARKER_WIDTH, 1);
  const labelColumnWidth = mode === "slash" ? Math.min(maxLabelLength, Math.floor(contentWidth * 0.5)) : describedLabelLengths.length > 0 ? Math.min(
    Math.max(...describedLabelLengths),
    Math.max(contentWidth - MIN_DESCRIPTION_WIDTH - 2, 1)
  ) : 0;
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box_default, { flexDirection: "column", width, ref: containerRef, children: [
    mouseEnabled && onHoverIndex && onSelectIndex && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
      RowMouseController,
      {
        containerRef,
        itemRefs,
        scrollOffset: startIndex,
        onHoverIndex,
        onSelectIndex
      }
    ),
    scrollOffset > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { color: theme.text.primary, children: "\u25B2" }),
    visibleSuggestions.map((suggestion, index) => {
      const originalIndex = startIndex + index;
      const isActive = originalIndex === activeIndex;
      const isExpanded = originalIndex === expandedIndex;
      const textColor = isActive ? theme.text.accent : theme.text.secondary;
      const displayLabel = suggestion.label ?? suggestion.value;
      const isLong = displayLabel.length >= MAX_WIDTH;
      const expansionIndicatorWidth = isActive && isLong ? 3 : 0;
      const descriptionColumnWidth = Math.max(
        contentWidth - labelColumnWidth - 2 - expansionIndicatorWidth,
        1
      );
      const labelElement = /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
        PrepareLabel,
        {
          label: displayLabel,
          matchedIndex: suggestion.matchedIndex,
          userInput,
          textColor,
          isExpanded
        }
      );
      return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
        Box_default,
        {
          flexDirection: "row",
          ref: (node) => {
            itemRefs.current[index] = node;
          },
          children: [
            /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box_default, { width: ACTIVE_MARKER_WIDTH, flexShrink: 0, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { color: textColor, children: isActive ? "> " : "  " }) }),
            /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
              Box_default,
              {
                ...mode === "slash" || suggestion.description ? { width: labelColumnWidth, flexShrink: 0 } : { flexShrink: 1 },
                children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box_default, { children: [
                  labelElement,
                  suggestion.argumentHint && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Text, { color: theme.text.secondary, children: [
                    " ",
                    suggestion.argumentHint
                  ] }),
                  suggestion.sourceBadge && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Text, { color: textColor, children: [
                    " ",
                    suggestion.sourceBadge
                  ] })
                ] })
              }
            ),
            suggestion.description && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
              Box_default,
              {
                width: descriptionColumnWidth,
                flexGrow: 1,
                flexShrink: 1,
                paddingLeft: 2,
                children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { color: textColor, wrap: "truncate-end", children: normalizeDescription(suggestion.description) })
              }
            ),
            isActive && isLong && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box_default, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { color: Colors.Gray, children: isExpanded ? " \u2190 " : " \u2192 " }) })
          ]
        },
        `${suggestion.value}-${originalIndex}`
      );
    }),
    endIndex < suggestions.length && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { color: "gray", children: "\u25BC" }),
    suggestions.length > MAX_SUGGESTIONS_TO_SHOW && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Text, { color: "gray", children: [
      "(",
      activeIndex + 1,
      "/",
      suggestions.length,
      ")"
    ] })
  ] });
}
__name(SuggestionsDisplay, "SuggestionsDisplay");

// packages/cli/src/utils/extension-mention.ts
init_esbuild_shims();
import * as fs from "node:fs/promises";
var EXTENSION_REF_PREFIX = "ext:";
var EXTENSION_CONTEXT_BUDGET = 2e5;
var EXTENSION_CONTEXT_FILE_CAP = 5e4;
function parseExtensionRef(pathName) {
  if (!pathName.startsWith(EXTENSION_REF_PREFIX)) return null;
  const name = pathName.slice(EXTENSION_REF_PREFIX.length);
  if (!name) return null;
  return { name };
}
__name(parseExtensionRef, "parseExtensionRef");
function buildExtensionRef(extensionName) {
  return `${EXTENSION_REF_PREFIX}${extensionName}`;
}
__name(buildExtensionRef, "buildExtensionRef");
function matchExtensionByRef(name, extensions) {
  const lower = name.toLowerCase();
  return extensions.find(
    (ext) => ext.name.toLowerCase() === lower || ext.config.name.toLowerCase() === lower
  );
}
__name(matchExtensionByRef, "matchExtensionByRef");
var BIDI_CONTROL_RE = /[‎‏؜⁦⁧⁨⁩‪‫‬‭‮]/g;
function sanitizeDisplayText(raw) {
  const stripped = stripTerminalControlSequences(raw).replace(BIDI_CONTROL_RE, "").replace(/\s+/g, " ").trim();
  return stripped.length > 0 ? stripped : null;
}
__name(sanitizeDisplayText, "sanitizeDisplayText");
function getExtensionDisplayName(extension) {
  return sanitizeDisplayText(extension.displayName || extension.name) || extension.name;
}
__name(getExtensionDisplayName, "getExtensionDisplayName");
function buildExtensionContextText(extension) {
  const displayName = getExtensionDisplayName(extension);
  const lines = [];
  lines.push(
    `--- Extension: ${displayName} (untrusted third-party content) ---`
  );
  if (extension.config.description) {
    const desc = sanitizeDisplayText(extension.config.description);
    if (desc) {
      lines.push(desc);
      lines.push("");
    }
  }
  const capabilities = [];
  if (extension.skills && extension.skills.length > 0) {
    const skillNames = extension.skills.map((s) => sanitizeDisplayText(s.name) || s.name).join(", ");
    capabilities.push(`- Skills: ${skillNames} (invoke via /<skill-name>)`);
  }
  if (extension.mcpServers && Object.keys(extension.mcpServers).length > 0) {
    const serverNames = Object.keys(extension.mcpServers).map((n) => sanitizeDisplayText(n) || n).join(", ");
    capabilities.push(`- MCP Servers: ${serverNames}`);
  }
  if (extension.agents && extension.agents.length > 0) {
    const agentNames = extension.agents.map((a) => sanitizeDisplayText(a.name) || a.name).join(", ");
    capabilities.push(`- Agents: ${agentNames}`);
  }
  if (capabilities.length > 0) {
    lines.push("Available capabilities from this extension:");
    lines.push(...capabilities);
    lines.push("");
  }
  lines.push(`--- End Extension: ${displayName} ---`);
  return lines.join("\n");
}
__name(buildExtensionContextText, "buildExtensionContextText");
async function buildExtensionMentionContext(extension, options) {
  let contextText = buildExtensionContextText(extension);
  let remainingBudget = options.remainingBudget;
  if (extension.contextFiles.length === 0) {
    return { text: contextText, remainingBudget };
  }
  const fileReads = await Promise.allSettled(
    extension.contextFiles.map(async (contextFilePath) => {
      let realPath;
      let realExtPath;
      try {
        realPath = await fs.realpath(contextFilePath);
        realExtPath = await fs.realpath(extension.path);
      } catch {
        options.onDebugMessage?.(
          `Skipping unreadable context file: ${contextFilePath}`
        );
        return null;
      }
      if (!isSubpath(realExtPath, realPath)) {
        options.onDebugMessage?.(
          `Skipping context file outside extension directory: ${contextFilePath}`
        );
        return null;
      }
      return fs.readFile(realPath, {
        encoding: "utf-8",
        signal: options.signal
      });
    })
  );
  for (let i = 0; i < fileReads.length; i++) {
    const outcome = fileReads[i];
    if (outcome.status === "rejected") {
      options.onDebugMessage?.(
        `Failed to read extension context file ${extension.contextFiles[i]}: ${getErrorMessage(outcome.reason)}`
      );
      continue;
    }
    const content = outcome.value;
    if (!content || !content.trim()) continue;
    if (remainingBudget <= 0) {
      options.onDebugMessage?.(
        "Extension context budget exhausted, skipping remaining files."
      );
      break;
    }
    const cap = Math.min(EXTENSION_CONTEXT_FILE_CAP, remainingBudget);
    const cappedContent = content.length > cap ? content.slice(0, cap) + "\n... (truncated)" : content;
    contextText += `

${cappedContent}`;
    remainingBudget -= cappedContent.length;
  }
  return { text: contextText, remainingBudget };
}
__name(buildExtensionMentionContext, "buildExtensionMentionContext");

// packages/cli/src/ui/hooks/extension-mention-ref.ts
function getExtensionSuggestions(config, pattern) {
  if (!config) return [];
  if (config.isTrustedFolder?.() === false) return [];
  const extensions = config.getActiveExtensions?.() ?? [];
  if (extensions.length === 0) return [];
  const query = pattern.toLowerCase();
  return extensions.map((ext) => ({
    ext,
    safeLabel: sanitizeDisplayText(ext.displayName || ext.name) || ext.name
  })).filter(({ safeLabel, ext }) => {
    const label = safeLabel.toLowerCase();
    const name = ext.name.toLowerCase();
    return label.includes(query) || name.includes(query);
  }).sort((a, b) => {
    const aName = a.safeLabel.toLowerCase();
    const bName = b.safeLabel.toLowerCase();
    const aPrefix = aName.startsWith(query) ? 0 : 1;
    const bPrefix = bName.startsWith(query) ? 0 : 1;
    if (aPrefix !== bPrefix) return aPrefix - bPrefix;
    return aName.localeCompare(bName);
  }).slice(0, MAX_SUGGESTIONS_TO_SHOW).map(({ ext, safeLabel }) => ({
    label: safeLabel,
    value: buildExtensionRef(ext.name),
    description: ext.config.description ? sanitizeDisplayText(ext.config.description) ?? void 0 : void 0,
    sourceBadge: t("Extension"),
    isDirectory: false
  }));
}
__name(getExtensionSuggestions, "getExtensionSuggestions");

// packages/cli/src/ui/hooks/atCommandProcessor.ts
function parseAllAtCommands(query) {
  const parts = [];
  let currentIndex = 0;
  while (currentIndex < query.length) {
    let atIndex = -1;
    let nextSearchIndex = currentIndex;
    while (nextSearchIndex < query.length) {
      if (query[nextSearchIndex] === "@" && (nextSearchIndex === 0 || query[nextSearchIndex - 1] !== "\\")) {
        atIndex = nextSearchIndex;
        break;
      }
      nextSearchIndex++;
    }
    if (atIndex === -1) {
      if (currentIndex < query.length) {
        parts.push({ type: "text", content: query.substring(currentIndex) });
      }
      break;
    }
    if (atIndex > currentIndex) {
      parts.push({
        type: "text",
        content: query.substring(currentIndex, atIndex)
      });
    }
    let pathEndIndex = atIndex + 1;
    let inEscape = false;
    while (pathEndIndex < query.length) {
      const char = query[pathEndIndex];
      if (inEscape) {
        inEscape = false;
      } else if (char === "\\") {
        inEscape = true;
      } else if (/[,\s;!?()[\]{}]/.test(char)) {
        break;
      } else if (char === ".") {
        const nextChar = pathEndIndex + 1 < query.length ? query[pathEndIndex + 1] : "";
        if (nextChar === "" || /\s/.test(nextChar)) {
          break;
        }
      }
      pathEndIndex++;
    }
    const rawAtPath = query.substring(atIndex, pathEndIndex);
    const atPath = unescapePath(rawAtPath);
    parts.push({ type: "atPath", content: atPath });
    currentIndex = pathEndIndex;
  }
  return parts.filter(
    (part) => !(part.type === "text" && part.content.trim() === "")
  );
}
__name(parseAllAtCommands, "parseAllAtCommands");
function parseMcpResourceRef(pathName, mcpServerNames) {
  const match = matchMcpServerPrefix(pathName, mcpServerNames);
  if (!match || !match.rest) return null;
  return { serverName: match.serverName, uri: match.rest };
}
__name(parseMcpResourceRef, "parseMcpResourceRef");
async function resolveAtCommandQuery({
  query,
  config,
  onDebugMessage,
  messageId: userMessageTimestamp,
  signal
}) {
  const commandParts = parseAllAtCommands(query);
  const atPathCommandParts = commandParts.filter(
    (part) => part.type === "atPath"
  );
  if (atPathCommandParts.length === 0) {
    return { processedQuery: [{ text: query }], shouldProceed: true };
  }
  const fileDiscovery = config.getFileService();
  const respectFileIgnore = config.getFileFilteringOptions();
  const pathSpecsToRead = [];
  const atPathToResolvedSpecMap = /* @__PURE__ */ new Map();
  const contentLabelsForDisplay = [];
  const ignoredByReason = {
    git: [],
    qwen: [],
    both: []
  };
  const mcpServerNames = new Set(Object.keys(config.getMcpServers() || {}));
  const mcpResourceRefs = [];
  const activeExtensions = config.getActiveExtensions?.() ?? [];
  const extensionMentions = [];
  for (const atPathPart of atPathCommandParts) {
    const originalAtPath = atPathPart.content;
    if (originalAtPath === "@") {
      onDebugMessage(
        "Lone @ detected, will be treated as text in the modified query."
      );
      continue;
    }
    const pathName = originalAtPath.substring(1);
    const extRef = parseExtensionRef(pathName);
    if (extRef) {
      const extension = matchExtensionByRef(extRef.name, activeExtensions);
      if (extension) {
        if (!extensionMentions.some((m) => m.extension.name === extension.name)) {
          extensionMentions.push({ originalAtPath, extension });
        }
        atPathToResolvedSpecMap.set(originalAtPath, pathName);
        continue;
      }
      onDebugMessage(
        `Extension "${extRef.name}" not found among active extensions. Available: ${activeExtensions.map((e) => e.name).join(", ") || "(none)"}`
      );
      continue;
    }
    const resourceRef = parseMcpResourceRef(pathName, mcpServerNames);
    if (resourceRef) {
      mcpResourceRefs.push({ originalAtPath, ...resourceRef });
      atPathToResolvedSpecMap.set(originalAtPath, pathName);
      continue;
    }
    const workspaceContext = config.getWorkspaceContext();
    const projectTempDir = Storage.getGlobalTempDir();
    const absolutePathName = path.isAbsolute(pathName) ? pathName : path.resolve(workspaceContext.getDirectories()[0] || "", pathName);
    if (!isSubpath(projectTempDir, absolutePathName) && !workspaceContext.isPathWithinWorkspace(pathName)) {
      onDebugMessage(
        `Path ${pathName} is not in the workspace and will be skipped.`
      );
      continue;
    }
    const gitIgnored = respectFileIgnore.respectGitIgnore && fileDiscovery.shouldIgnoreFile(pathName, {
      respectGitIgnore: true,
      respectQwenIgnore: false
    });
    const qwenIgnored = respectFileIgnore.respectQwenIgnore && fileDiscovery.shouldIgnoreFile(pathName, {
      respectGitIgnore: false,
      respectQwenIgnore: true
    });
    if (gitIgnored || qwenIgnored) {
      const reason = gitIgnored && qwenIgnored ? "both" : gitIgnored ? "git" : "qwen";
      ignoredByReason[reason].push(pathName);
      const reasonText = reason === "both" ? "ignored by both git and qwen" : reason === "git" ? "git-ignored" : "qwen-ignored";
      onDebugMessage(`Path ${pathName} is ${reasonText} and will be skipped.`);
      continue;
    }
    let resolvedSuccessfully = false;
    let sawNotFound = false;
    for (const dir of config.getWorkspaceContext().getDirectories()) {
      let currentPathSpec = pathName;
      try {
        const absolutePath = path.resolve(dir, pathName);
        const stats = await fs2.stat(absolutePath);
        if (stats.isDirectory()) {
          currentPathSpec = pathName;
          onDebugMessage(`Path ${pathName} resolved to directory.`);
        } else {
          onDebugMessage(`Path ${pathName} resolved to file: ${absolutePath}`);
        }
        resolvedSuccessfully = true;
      } catch (error) {
        if (isNodeError(error) && error.code === "ENOENT") {
          sawNotFound = true;
          continue;
        } else {
          onDebugMessage(
            `Error stating path ${pathName}: ${getErrorMessage(error)}. Path ${pathName} will be skipped.`
          );
        }
      }
      if (resolvedSuccessfully) {
        pathSpecsToRead.push(currentPathSpec);
        atPathToResolvedSpecMap.set(originalAtPath, currentPathSpec);
        contentLabelsForDisplay.push(pathName);
        break;
      }
    }
    if (!resolvedSuccessfully && sawNotFound) {
      onDebugMessage(
        `Path ${pathName} not found. Path ${pathName} will be skipped.`
      );
    }
  }
  let initialQueryText = "";
  for (let i = 0; i < commandParts.length; i++) {
    const part = commandParts[i];
    if (part.type === "text") {
      initialQueryText += part.content;
    } else {
      const resolvedSpec = atPathToResolvedSpecMap.get(part.content);
      if (i > 0 && initialQueryText.length > 0 && !initialQueryText.endsWith(" ")) {
        const prevPart = commandParts[i - 1];
        if (prevPart.type === "text" || prevPart.type === "atPath" && atPathToResolvedSpecMap.has(prevPart.content)) {
          initialQueryText += " ";
        }
      }
      if (resolvedSpec) {
        initialQueryText += `@${resolvedSpec}`;
      } else {
        if (i > 0 && initialQueryText.length > 0 && !initialQueryText.endsWith(" ") && !part.content.startsWith(" ")) {
          initialQueryText += " ";
        }
        initialQueryText += part.content;
      }
    }
  }
  initialQueryText = initialQueryText.trim();
  const totalIgnored = ignoredByReason["git"].length + ignoredByReason["qwen"].length + ignoredByReason["both"].length;
  if (totalIgnored > 0) {
    const messages = [];
    if (ignoredByReason["git"].length) {
      messages.push(`Git-ignored: ${ignoredByReason["git"].join(", ")}`);
    }
    if (ignoredByReason["qwen"].length) {
      messages.push(`Qwen-ignored: ${ignoredByReason["qwen"].join(", ")}`);
    }
    if (ignoredByReason["both"].length) {
      messages.push(`Ignored by both: ${ignoredByReason["both"].join(", ")}`);
    }
    const message = `Ignored ${totalIgnored} files:
${messages.join("\n")}`;
    onDebugMessage(message);
  }
  const resourceReads = await Promise.allSettled(
    mcpResourceRefs.map(
      (ref) => config.getToolRegistry().readMcpResource(ref.serverName, ref.uri, { signal })
    )
  );
  const resourceParts = [];
  const resourceDisplays = [];
  const resourceLabels = [];
  for (let i = 0; i < mcpResourceRefs.length; i++) {
    const ref = mcpResourceRefs[i];
    const label = `${ref.serverName}:${ref.uri}`;
    const callId = `client-mcp-resource-${userMessageTimestamp}-${i}`;
    const outcome = resourceReads[i];
    if (outcome.status === "rejected") {
      onDebugMessage(
        `Failed to read MCP resource ${label}: ${getErrorMessage(outcome.reason)}`
      );
      resourceDisplays.push({
        callId,
        name: "Read MCP Resource",
        description: `Read resource ${label}`,
        status: "Error" /* Error */,
        resultDisplay: `Failed to read resource ${label}: ${getErrorMessage(outcome.reason)}`,
        confirmationDetails: void 0
      });
      continue;
    }
    const formatted = formatMcpResourceContents(outcome.value, label);
    if (formatted.parts.length > 0) {
      resourceParts.push(...formatted.parts);
    } else {
      resourceParts.push({ text: emptyMcpResourceText(formatted, label) });
    }
    resourceLabels.push(label);
    resourceDisplays.push({
      callId,
      name: "Read MCP Resource",
      description: `Read resource ${label}`,
      status: "Success" /* Success */,
      resultDisplay: summarizeMcpResource(formatted),
      confirmationDetails: void 0
    });
  }
  if (pathSpecsToRead.length === 0 && mcpResourceRefs.length === 0 && extensionMentions.length === 0) {
    onDebugMessage("No valid file paths found in @ commands to read.");
    if (initialQueryText === "@" && query.trim() === "@") {
      return { processedQuery: [{ text: query }], shouldProceed: true };
    } else if (!initialQueryText && query) {
      return { processedQuery: [{ text: query }], shouldProceed: true };
    }
    return {
      processedQuery: [{ text: initialQueryText || query }],
      shouldProceed: true
    };
  }
  let extensionContextBudgetRemaining = EXTENSION_CONTEXT_BUDGET;
  const extensionParts = [];
  const extensionDisplays = [];
  const extensionLabels = [];
  for (let i = 0; i < extensionMentions.length; i++) {
    const { extension } = extensionMentions[i];
    const displayName = getExtensionDisplayName(extension);
    const callId = `client-extension-${userMessageTimestamp}-${i}`;
    const context = await buildExtensionMentionContext(extension, {
      remainingBudget: extensionContextBudgetRemaining,
      signal,
      onDebugMessage
    });
    extensionContextBudgetRemaining = context.remainingBudget;
    extensionParts.push({ text: context.text });
    extensionLabels.push(buildExtensionRef(extension.name));
    extensionDisplays.push({
      callId,
      name: "Activate Extension",
      description: `Activated extension ${displayName}`,
      status: "Success" /* Success */,
      resultDisplay: void 0,
      confirmationDetails: void 0
    });
  }
  const fileParts = [];
  let fileDisplays = [];
  if (pathSpecsToRead.length > 0) {
    try {
      const result = await readManyFiles(config, {
        paths: pathSpecsToRead,
        signal,
        preserveUnsupportedImageForBridge: shouldRunVisionBridge(config)
      });
      const parts = Array.isArray(result.contentParts) ? result.contentParts : [result.contentParts];
      fileDisplays = result.files.map((file, index) => ({
        callId: `client-read-${userMessageTimestamp}-${index}`,
        name: file.isDirectory ? "Read Directory" : "Read File",
        description: file.isDirectory ? `Read directory ${path.basename(file.filePath)}` : `Read file ${path.basename(file.filePath)}`,
        status: file.error ? "Error" /* Error */ : "Success" /* Success */,
        resultDisplay: file.error ? `Failed to read ${path.basename(file.filePath)}: ${file.error}` : void 0,
        confirmationDetails: void 0
      }));
      if (parts.length > 0 && !result.error) {
        for (const part of parts) {
          fileParts.push(typeof part === "string" ? { text: part } : part);
        }
      } else {
        onDebugMessage("readManyFiles returned no content or empty content.");
      }
    } catch (error) {
      const errorToolCallDisplay = {
        callId: `client-read-${userMessageTimestamp}`,
        name: "Read File(s)",
        description: "Error attempting to read files",
        status: "Error" /* Error */,
        resultDisplay: `Error reading files (${contentLabelsForDisplay.join(", ")}): ${getErrorMessage(error)}`,
        confirmationDetails: void 0
      };
      const errorMessage = typeof errorToolCallDisplay.resultDisplay === "string" ? errorToolCallDisplay.resultDisplay : void 0;
      const labelsOnError = [
        ...extensionLabels,
        ...contentLabelsForDisplay,
        ...resourceLabels
      ];
      return {
        processedQuery: null,
        shouldProceed: false,
        toolDisplays: [
          ...extensionDisplays,
          ...resourceDisplays,
          errorToolCallDisplay
        ],
        filesRead: labelsOnError,
        recording: {
          filesRead: labelsOnError,
          status: "error",
          message: errorMessage
        }
      };
    }
  }
  const processedQueryParts = [
    { text: initialQueryText },
    ...extensionParts,
    ...fileParts,
    ...resourceParts
  ];
  const allLabels = [
    ...extensionLabels,
    ...contentLabelsForDisplay,
    ...resourceLabels
  ];
  return {
    processedQuery: processedQueryParts,
    shouldProceed: true,
    toolDisplays: [...extensionDisplays, ...fileDisplays, ...resourceDisplays],
    filesRead: allLabels,
    recording: {
      filesRead: allLabels,
      status: "success"
    }
  };
}
__name(resolveAtCommandQuery, "resolveAtCommandQuery");
async function handleAtCommand(params) {
  const result = await resolveAtCommandQuery(params);
  if (result.recording) {
    const chatRecorder = params.config.getChatRecordingService?.();
    chatRecorder?.recordAtCommand({
      filesRead: result.recording.filesRead,
      status: result.recording.status,
      ...result.recording.message ? { message: result.recording.message } : {},
      userText: params.query
    });
  }
  if (params.addItem && result.toolDisplays && result.toolDisplays.length > 0) {
    const toolGroupItem = {
      type: "tool_group",
      tools: result.toolDisplays
    };
    params.addItem(toolGroupItem, params.messageId);
  }
  return {
    processedQuery: result.processedQuery,
    shouldProceed: result.shouldProceed,
    toolDisplays: result.toolDisplays,
    filesRead: result.filesRead
  };
}
__name(handleAtCommand, "handleAtCommand");

export {
  matchMcpServerPrefix,
  buildMcpResourceRef,
  MAX_WIDTH,
  MAX_SUGGESTIONS_TO_SHOW,
  SuggestionsDisplay,
  EXTENSION_CONTEXT_BUDGET,
  parseExtensionRef,
  matchExtensionByRef,
  buildExtensionMentionContext,
  getExtensionSuggestions,
  resolveAtCommandQuery,
  handleAtCommand
};
/**
 * @license
 * Copyright 2025 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
/**
 * @license
 * Copyright 2025 Qwen
 * SPDX-License-Identifier: Apache-2.0
 */
