"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// tools/warp_grep/providers/local.ts
var local_exports = {};
__export(local_exports, {
  LocalRipgrepProvider: () => LocalRipgrepProvider
});
module.exports = __toCommonJS(local_exports);
var import_promises2 = __toESM(require("fs/promises"), 1);
var import_path2 = __toESM(require("path"), 1);

// tools/warp_grep/utils/ripgrep.ts
var import_child_process = require("child_process");
var import_ripgrep = require("@vscode/ripgrep");
var resolvedRgPath = null;
var rgPathChecked = false;
function spawnRg(rgBinary, args, opts) {
  return new Promise((resolve) => {
    const child = (0, import_child_process.spawn)(rgBinary, args, {
      cwd: opts?.cwd,
      env: { ...process.env, ...opts?.env || {} },
      stdio: ["ignore", "pipe", "pipe"]
    });
    let stdout = "";
    let stderr = "";
    child.stdout.on("data", (d) => stdout += d.toString());
    child.stderr.on("data", (d) => stderr += d.toString());
    child.on("close", (code) => {
      resolve({ stdout, stderr, exitCode: typeof code === "number" ? code : -1 });
    });
    child.on("error", () => {
      resolve({ stdout: "", stderr: "Failed to spawn ripgrep.", exitCode: -1 });
    });
  });
}
function isBinaryFailure(result) {
  if (result.exitCode === -1) return true;
  if (result.stderr.includes("jemalloc") || result.stderr.includes("Unsupported system page size")) return true;
  if (result.exitCode === 134) return true;
  return false;
}
async function runRipgrep(args, opts) {
  if (rgPathChecked && resolvedRgPath) {
    return spawnRg(resolvedRgPath, args, opts);
  }
  if (!rgPathChecked) {
    const result = await spawnRg(import_ripgrep.rgPath, args, opts);
    if (!isBinaryFailure(result)) {
      resolvedRgPath = import_ripgrep.rgPath;
      rgPathChecked = true;
      return result;
    }
    const fallbackResult = await spawnRg("rg", args, opts);
    if (!isBinaryFailure(fallbackResult)) {
      resolvedRgPath = "rg";
      rgPathChecked = true;
      return fallbackResult;
    }
    rgPathChecked = true;
    return {
      stdout: "",
      stderr: "Failed to spawn ripgrep. Neither bundled nor system rg is available.",
      exitCode: -1
    };
  }
  return {
    stdout: "",
    stderr: "Failed to spawn ripgrep. Neither bundled nor system rg is available.",
    exitCode: -1
  };
}

// tools/warp_grep/utils/paths.ts
var import_fs = __toESM(require("fs"), 1);
var import_path = __toESM(require("path"), 1);
function resolveUnderRepo(repoRoot, targetPath) {
  const absRoot = import_path.default.resolve(repoRoot);
  const resolved = import_path.default.resolve(absRoot, targetPath);
  ensureWithinRepo(absRoot, resolved);
  return resolved;
}
function ensureWithinRepo(repoRoot, absTarget) {
  const rel = import_path.default.relative(import_path.default.resolve(repoRoot), import_path.default.resolve(absTarget));
  if (rel.startsWith("..") || import_path.default.isAbsolute(rel)) {
    throw new Error(`Path outside repository root: ${absTarget}`);
  }
}
function toRepoRelative(repoRoot, absPath) {
  return import_path.default.relative(import_path.default.resolve(repoRoot), import_path.default.resolve(absPath));
}
function isSymlink(p) {
  try {
    const st = import_fs.default.lstatSync(p);
    return st.isSymbolicLink();
  } catch {
    return false;
  }
}
function fixPathRepetition(fullPath) {
  const segments = fullPath.split(import_path.default.sep).filter(Boolean);
  if (segments.length < 2) return null;
  for (let len = Math.floor(segments.length / 2); len >= 1; len--) {
    for (let i = 0; i <= segments.length - 2 * len; i++) {
      const first = segments.slice(i, i + len);
      const second = segments.slice(i + len, i + 2 * len);
      if (first.every((seg, idx) => seg === second[idx])) {
        const fixed = [...segments.slice(0, i), ...segments.slice(i + len)];
        return import_path.default.sep + fixed.join(import_path.default.sep);
      }
    }
  }
  return null;
}
function isTextualFile(filePath, maxBytes = 2e6) {
  try {
    const st = import_fs.default.statSync(filePath);
    if (!st.isFile()) return false;
    if (st.size > maxBytes) return false;
    const fd = import_fs.default.openSync(filePath, "r");
    const buf = Buffer.alloc(512);
    const read = import_fs.default.readSync(fd, buf, 0, buf.length, 0);
    import_fs.default.closeSync(fd);
    for (let i = 0; i < read; i++) {
      const c = buf[i];
      if (c === 0) return false;
    }
    return true;
  } catch {
    return false;
  }
}

// tools/warp_grep/utils/files.ts
var import_promises = __toESM(require("fs/promises"), 1);
async function readAllLines(filePath) {
  const content = await import_promises.default.readFile(filePath, "utf8");
  return content.split(/\r?\n/);
}

// tools/warp_grep/agent/config.ts
var parseEnvTimeout = (envValue, defaultMs) => {
  if (!envValue) return defaultMs;
  const parsed = parseInt(envValue, 10);
  return isNaN(parsed) || parsed <= 0 ? defaultMs : parsed;
};
var AGENT_CONFIG = {
  MAX_TURNS: 4,
  /** Default timeout for model calls. Can be overridden via MORPH_WARP_GREP_TIMEOUT env var (in ms) */
  TIMEOUT_MS: parseEnvTimeout(process.env.MORPH_WARP_GREP_TIMEOUT, 3e4),
  MAX_CONTEXT_CHARS: 54e4,
  MAX_OUTPUT_LINES: 200,
  MAX_READ_LINES: 800,
  MAX_LIST_DEPTH: 3,
  LIST_TIMEOUT_MS: 2e3
};
var BUILTIN_EXCLUDES = [
  // Version control
  ".git",
  ".svn",
  ".hg",
  ".bzr",
  // Dependencies
  "node_modules",
  "bower_components",
  ".pnpm",
  ".yarn",
  "vendor",
  "packages",
  "Pods",
  ".bundle",
  // Python
  "__pycache__",
  ".pytest_cache",
  ".mypy_cache",
  ".ruff_cache",
  ".venv",
  "venv",
  ".tox",
  ".nox",
  ".eggs",
  "*.egg-info",
  // Build outputs
  "dist",
  "build",
  "out",
  "output",
  "target",
  "_build",
  ".next",
  ".nuxt",
  ".output",
  ".vercel",
  ".netlify",
  // Cache directories
  ".cache",
  ".parcel-cache",
  ".turbo",
  ".nx",
  ".gradle",
  // IDE/Editor
  ".idea",
  ".vscode",
  ".vs",
  // Coverage
  "coverage",
  ".coverage",
  "htmlcov",
  ".nyc_output",
  // Temporary
  "tmp",
  "temp",
  ".tmp",
  ".temp",
  // Lock files
  "package-lock.json",
  "yarn.lock",
  "pnpm-lock.yaml",
  "bun.lockb",
  "Cargo.lock",
  "Gemfile.lock",
  "poetry.lock",
  // Binary/minified
  "*.min.js",
  "*.min.css",
  "*.bundle.js",
  "*.wasm",
  "*.so",
  "*.dll",
  "*.pyc",
  "*.map",
  "*.js.map",
  // Hidden directories catch-all
  ".*"
];
var DEFAULT_EXCLUDES = (process.env.MORPH_WARP_GREP_EXCLUDE || "").split(",").map((s) => s.trim()).filter(Boolean).concat(BUILTIN_EXCLUDES);

// tools/warp_grep/providers/local.ts
var SKIP_NAMES = /* @__PURE__ */ new Set([
  // Version control
  ".git",
  ".svn",
  ".hg",
  ".bzr",
  // Dependencies
  "node_modules",
  "bower_components",
  ".pnpm",
  ".yarn",
  "vendor",
  "Pods",
  ".bundle",
  // Python
  "__pycache__",
  ".pytest_cache",
  ".mypy_cache",
  ".ruff_cache",
  ".venv",
  "venv",
  ".tox",
  ".nox",
  ".eggs",
  // Build outputs
  "dist",
  "build",
  "out",
  "output",
  "target",
  "_build",
  ".next",
  ".nuxt",
  ".output",
  ".vercel",
  ".netlify",
  // Cache
  ".cache",
  ".parcel-cache",
  ".turbo",
  ".nx",
  ".gradle",
  // IDE
  ".idea",
  ".vscode",
  ".vs",
  // Coverage
  "coverage",
  ".coverage",
  "htmlcov",
  ".nyc_output",
  // Temp
  "tmp",
  "temp",
  ".tmp",
  ".temp",
  // Lock files
  "package-lock.json",
  "yarn.lock",
  "pnpm-lock.yaml",
  "bun.lockb",
  "Cargo.lock",
  "Gemfile.lock",
  "poetry.lock"
]);
var SKIP_EXTENSIONS = /* @__PURE__ */ new Set([
  ".min.js",
  ".min.css",
  ".bundle.js",
  ".wasm",
  ".so",
  ".dll",
  ".pyc",
  ".map",
  ".js.map"
]);
function shouldSkip(name) {
  if (SKIP_NAMES.has(name)) return true;
  if (name.startsWith(".")) return true;
  for (const ext of SKIP_EXTENSIONS) {
    if (name.endsWith(ext)) return true;
  }
  return false;
}
var LocalRipgrepProvider = class {
  constructor(repoRoot, excludes = DEFAULT_EXCLUDES) {
    this.repoRoot = repoRoot;
    this.excludes = excludes;
  }
  async grep(params) {
    let abs;
    try {
      abs = resolveUnderRepo(this.repoRoot, params.path);
    } catch (err) {
      return {
        lines: [],
        error: `[PATH ERROR] ${err instanceof Error ? err.message : String(err)}`
      };
    }
    const stat = await import_promises2.default.stat(abs).catch(() => null);
    if (!stat) return { lines: [] };
    const targetArg = abs === import_path2.default.resolve(this.repoRoot) ? "." : toRepoRelative(this.repoRoot, abs);
    const args = [
      "--no-config",
      "--no-heading",
      "--with-filename",
      "--line-number",
      "--color=never",
      "--trim",
      "--max-columns=400",
      "-C",
      "1",
      ...params.glob ? ["--glob", params.glob] : [],
      ...this.excludes.flatMap((e) => ["-g", `!${e}`]),
      params.pattern,
      targetArg || "."
    ];
    const res = await runRipgrep(args, { cwd: this.repoRoot });
    if (res.exitCode === -1) {
      return {
        lines: [],
        error: `[RIPGREP NOT AVAILABLE] ripgrep (rg) is required but failed to execute. Please install it:
  \u2022 macOS: brew install ripgrep
  \u2022 Ubuntu/Debian: apt install ripgrep
  \u2022 Windows: choco install ripgrep
  \u2022 Or visit: https://github.com/BurntSushi/ripgrep#installation
Exit code: ${res.exitCode}${res.stderr ? `
Details: ${res.stderr}` : ""}`
      };
    }
    if (res.exitCode !== 0 && res.exitCode !== 1) {
      return {
        lines: [],
        error: `[RIPGREP ERROR] grep failed with exit code ${res.exitCode}${res.stderr ? `: ${res.stderr}` : ""}`
      };
    }
    const lines = (res.stdout || "").trim().split(/\r?\n/).filter((l) => l.length > 0);
    if (lines.length > AGENT_CONFIG.MAX_OUTPUT_LINES) {
      return {
        lines: [],
        error: "query not specific enough, tool tried to return too much context and failed"
      };
    }
    return { lines };
  }
  async read(params) {
    let abs;
    try {
      abs = resolveUnderRepo(this.repoRoot, params.path);
    } catch (err) {
      return {
        lines: [],
        error: `[PATH ERROR] ${err instanceof Error ? err.message : String(err)}`
      };
    }
    let stat = await import_promises2.default.stat(abs).catch(() => null);
    if (!stat || !stat.isFile()) {
      const fixedPath = fixPathRepetition(abs);
      if (fixedPath) {
        const fixedStat = await import_promises2.default.stat(fixedPath).catch(() => null);
        if (fixedStat?.isFile()) {
          abs = fixedPath;
          stat = fixedStat;
        }
      }
    }
    if (!stat || !stat.isFile()) {
      return {
        lines: [],
        error: `[FILE NOT FOUND] You tried to read "${params.path}" but there is no file at this path. Double-check the path exists and is spelled correctly.`
      };
    }
    if (isSymlink(abs)) {
      return {
        lines: [],
        error: `[SYMLINK] You tried to read "${params.path}" but this is a symlink. Try reading the actual file it points to instead.`
      };
    }
    if (!isTextualFile(abs)) {
      return {
        lines: [],
        error: `[UNREADABLE FILE] You tried to read "${params.path}" but this file is either too large or not a text file, so it cannot be read. Try a different file.`
      };
    }
    let lines;
    try {
      lines = await readAllLines(abs);
    } catch (err) {
      return {
        lines: [],
        error: `[READ ERROR] Failed to read "${params.path}": ${err instanceof Error ? err.message : String(err)}`
      };
    }
    const total = lines.length;
    const rawStart = params.start;
    const rawEnd = params.end;
    let s = 1;
    let e = total;
    const startValid = rawStart === void 0 || Number.isFinite(rawStart) && rawStart > 0;
    const endValid = rawEnd === void 0 || Number.isFinite(rawEnd) && rawEnd > 0;
    if (startValid && endValid) {
      s = rawStart ?? 1;
      e = Math.min(rawEnd ?? total, total);
      if (s > total && total > 0 || s > e) {
        s = 1;
        e = total;
      }
    }
    const out = [];
    for (let i = s; i <= e; i += 1) {
      const content = lines[i - 1] ?? "";
      out.push(`${i}|${content}`);
    }
    if (out.length > AGENT_CONFIG.MAX_READ_LINES) {
      const truncated = out.slice(0, AGENT_CONFIG.MAX_READ_LINES);
      truncated.push(`... [truncated: showing ${AGENT_CONFIG.MAX_READ_LINES} of ${out.length} lines]`);
      return { lines: truncated };
    }
    return { lines: out };
  }
  async listDirectory(params) {
    let abs;
    try {
      abs = resolveUnderRepo(this.repoRoot, params.path);
    } catch {
      return [];
    }
    const stat = await import_promises2.default.stat(abs).catch(() => null);
    if (!stat || !stat.isDirectory()) {
      return [];
    }
    const maxResults = params.maxResults ?? AGENT_CONFIG.MAX_OUTPUT_LINES;
    const maxDepth = params.maxDepth ?? AGENT_CONFIG.MAX_LIST_DEPTH;
    const regex = params.pattern ? new RegExp(params.pattern) : null;
    const repoRoot = this.repoRoot;
    const results = [];
    let timedOut = false;
    const startTime = Date.now();
    async function walk(dir, depth) {
      if (Date.now() - startTime > AGENT_CONFIG.LIST_TIMEOUT_MS) {
        timedOut = true;
        return;
      }
      if (depth > maxDepth || results.length >= maxResults) return;
      let entries;
      try {
        entries = await import_promises2.default.readdir(dir, { withFileTypes: true });
      } catch {
        return;
      }
      for (const entry of entries) {
        if (timedOut || results.length >= maxResults) break;
        if (shouldSkip(entry.name)) continue;
        if (regex && !regex.test(entry.name)) continue;
        const full = import_path2.default.join(dir, entry.name);
        const isDir = entry.isDirectory();
        results.push({
          name: entry.name,
          path: toRepoRelative(repoRoot, full),
          type: isDir ? "dir" : "file",
          depth
        });
        if (isDir) {
          await walk(full, depth + 1);
        }
      }
    }
    await walk(abs, 0);
    return results;
  }
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  LocalRipgrepProvider
});
//# sourceMappingURL=local.cjs.map