"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 __esm = (fn, res) => function __init() {
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
};
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/agent/config.ts
var parseEnvTimeout, AGENT_CONFIG, BUILTIN_EXCLUDES, DEFAULT_EXCLUDES, DEFAULT_MODEL;
var init_config = __esm({
  "tools/warp_grep/agent/config.ts"() {
    "use strict";
    parseEnvTimeout = (envValue, defaultMs) => {
      if (!envValue) return defaultMs;
      const parsed = parseInt(envValue, 10);
      return isNaN(parsed) || parsed <= 0 ? defaultMs : parsed;
    };
    AGENT_CONFIG = {
      MAX_TURNS: 6,
      /** 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: 321600,
      MAX_OUTPUT_LINES: 200,
      MAX_LIST_RESULTS: 500,
      MAX_READ_LINES: 800,
      MAX_LIST_DEPTH: 3,
      LIST_TIMEOUT_MS: 2e3
    };
    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
      ".*"
    ];
    DEFAULT_EXCLUDES = (process.env.MORPH_WARP_GREP_EXCLUDE || "").split(",").map((s) => s.trim()).filter(Boolean).concat(BUILTIN_EXCLUDES);
    DEFAULT_MODEL = "morph-warp-grep-v2.1";
  }
});

// tools/warp_grep/utils/ripgrep.ts
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
  };
}
var import_child_process, import_ripgrep, resolvedRgPath, rgPathChecked;
var init_ripgrep = __esm({
  "tools/warp_grep/utils/ripgrep.ts"() {
    "use strict";
    import_child_process = require("child_process");
    import_ripgrep = require("@vscode/ripgrep");
    resolvedRgPath = null;
    rgPathChecked = false;
  }
});

// tools/warp_grep/utils/paths.ts
function resolveUnderRepo(repoRoot, targetPath) {
  const absRoot = import_path4.default.resolve(repoRoot);
  const resolved = import_path4.default.resolve(absRoot, targetPath);
  ensureWithinRepo(absRoot, resolved);
  return resolved;
}
function ensureWithinRepo(repoRoot, absTarget) {
  const rel = import_path4.default.relative(import_path4.default.resolve(repoRoot), import_path4.default.resolve(absTarget));
  if (rel.startsWith("..") || import_path4.default.isAbsolute(rel)) {
    throw new Error(`Path outside repository root: ${absTarget}`);
  }
}
function toRepoRelative(repoRoot, absPath) {
  return import_path4.default.relative(import_path4.default.resolve(repoRoot), import_path4.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_path4.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_path4.default.sep + fixed.join(import_path4.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;
  }
}
var import_fs, import_path4;
var init_paths = __esm({
  "tools/warp_grep/utils/paths.ts"() {
    "use strict";
    import_fs = __toESM(require("fs"), 1);
    import_path4 = __toESM(require("path"), 1);
  }
});

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

// tools/warp_grep/providers/local.ts
var local_exports = {};
__export(local_exports, {
  LocalRipgrepProvider: () => LocalRipgrepProvider
});
function shouldSkip2(name, allowNames) {
  if (allowNames?.has(name)) return false;
  if (SKIP_NAMES2.has(name)) return true;
  if (name.startsWith(".")) return true;
  for (const ext of SKIP_EXTENSIONS2) {
    if (name.endsWith(ext)) return true;
  }
  return false;
}
var import_promises2, import_path5, SKIP_NAMES2, SKIP_EXTENSIONS2, LocalRipgrepProvider;
var init_local = __esm({
  "tools/warp_grep/providers/local.ts"() {
    "use strict";
    import_promises2 = __toESM(require("fs/promises"), 1);
    import_path5 = __toESM(require("path"), 1);
    init_ripgrep();
    init_paths();
    init_files();
    init_config();
    SKIP_NAMES2 = /* @__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"
    ]);
    SKIP_EXTENSIONS2 = /* @__PURE__ */ new Set([
      ".min.js",
      ".min.css",
      ".bundle.js",
      ".wasm",
      ".so",
      ".dll",
      ".pyc",
      ".map",
      ".js.map"
    ]);
    LocalRipgrepProvider = class {
      constructor(repoRoot, excludes = DEFAULT_EXCLUDES, options) {
        this.repoRoot = repoRoot;
        this.excludes = excludes;
        if (options?.allowNames?.length) {
          this.allowNames = new Set(options.allowNames);
        }
      }
      allowNames;
      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_path5.default.resolve(this.repoRoot) ? "." : toRepoRelative(this.repoRoot, abs);
        const contextLines = params.context_lines !== void 0 ? String(params.context_lines) : "1";
        const args = [
          "--no-config",
          "--no-heading",
          "--with-filename",
          "--line-number",
          "--color=never",
          "--trim",
          "--max-columns=400",
          "-C",
          contextLines,
          ...params.case_sensitive === false ? ["--ignore-case"] : [],
          ...params.glob ? ["--glob", params.glob] : [],
          ...this.excludes.filter((e) => !this.allowNames?.has(e)).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) {
          const truncated = lines.slice(0, AGENT_CONFIG.MAX_OUTPUT_LINES);
          truncated.push(`... (output truncated at ${AGENT_CONFIG.MAX_OUTPUT_LINES} of ${lines.length} lines)`);
          return { lines: truncated };
        }
        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(`... (output truncated at ${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 allowNames = this.allowNames;
        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 (shouldSkip2(entry.name, allowNames)) continue;
            if (regex && !regex.test(entry.name)) continue;
            const full = import_path5.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;
      }
      async glob(params) {
        let abs;
        try {
          abs = params.path ? resolveUnderRepo(this.repoRoot, params.path) : this.repoRoot;
        } catch (err) {
          return { files: [], searchDir: this.repoRoot, totalFound: 0, error: `[PATH ERROR] ${err instanceof Error ? err.message : String(err)}` };
        }
        const stat = await import_promises2.default.stat(abs).catch(() => null);
        if (!stat || !stat.isDirectory()) {
          return { files: [], searchDir: abs, totalFound: 0, error: `[PATH ERROR] Directory not found: ${params.path || "."}` };
        }
        const targetArg = abs === import_path5.default.resolve(this.repoRoot) ? "." : toRepoRelative(this.repoRoot, abs);
        const args = [
          "--no-config",
          "--files",
          "--color=never",
          "-g",
          params.pattern,
          ...this.excludes.filter((e) => !this.allowNames?.has(e)).flatMap((e) => ["-g", `!${e}`]),
          targetArg || "."
        ];
        const res = await runRipgrep(args, { cwd: this.repoRoot });
        if (res.exitCode === -1) {
          return { files: [], searchDir: abs, totalFound: 0, error: `[RIPGREP NOT AVAILABLE] ripgrep (rg) is required for glob search.` };
        }
        if (res.exitCode !== 0 && res.exitCode !== 1) {
          return { files: [], searchDir: abs, totalFound: 0, error: `[GLOB ERROR] glob failed with exit code ${res.exitCode}${res.stderr ? `: ${res.stderr}` : ""}` };
        }
        const absRoot = import_path5.default.resolve(this.repoRoot);
        const relFiles = (res.stdout || "").trim().split(/\r?\n/).filter((l) => l.length > 0);
        const absFiles = relFiles.map((f) => import_path5.default.resolve(absRoot, f));
        const withMtime = [];
        for (const f of absFiles) {
          const s = await import_promises2.default.stat(f).catch(() => null);
          withMtime.push({ file: f, mtime: s?.mtimeMs ?? 0 });
        }
        withMtime.sort((a, b) => b.mtime - a.mtime);
        const totalFound = withMtime.length;
        return { files: withMtime.slice(0, 100).map((f) => f.file), searchDir: abs, totalFound };
      }
    };
  }
});

// tools/warp_grep/anthropic.ts
var anthropic_exports = {};
__export(anthropic_exports, {
  createGitHubReadFileTool: () => createGitHubReadFileTool,
  createGitHubSearchTool: () => createGitHubSearchTool,
  createWarpGrepTool: () => createWarpGrepTool,
  execute: () => execute,
  formatResult: () => formatResult,
  warpGrepTool: () => warpGrepTool
});
module.exports = __toCommonJS(anthropic_exports);

// tools/warp_grep/agent/runner.ts
init_config();

// tools/warp_grep/agent/parser.ts
function parseReadLines(linesStr) {
  const ranges = [];
  for (const rangeStr of linesStr.split(",")) {
    const trimmed = rangeStr.trim();
    if (!trimmed) continue;
    const parts = trimmed.split("-").map((v) => parseInt(v.trim(), 10));
    if (parts.length >= 2 && Number.isFinite(parts[0]) && Number.isFinite(parts[1])) {
      ranges.push([parts[0], parts[1]]);
    } else if (Number.isFinite(parts[0])) {
      ranges.push([parts[0], parts[0]]);
    }
  }
  if (ranges.length === 1) return { start: ranges[0][0], end: ranges[0][1] };
  if (ranges.length > 1) return { lines: ranges };
  return {};
}
function parseFinishFiles(filesStr) {
  const files = [];
  for (const line of filesStr.trim().split(/\s+/)) {
    const trimmed = line.trim();
    if (!trimmed) continue;
    const searchFrom = /^[A-Za-z]:/.test(trimmed) ? 2 : 0;
    const colonIdx = trimmed.indexOf(":", searchFrom);
    if (colonIdx === -1) {
      files.push({ path: trimmed, lines: "*" });
      continue;
    }
    const filePath = trimmed.slice(0, colonIdx);
    const rangesPart = trimmed.slice(colonIdx + 1);
    if (!rangesPart.trim() || rangesPart.trim() === "*") {
      files.push({ path: filePath, lines: "*" });
      continue;
    }
    const ranges = [];
    for (const rangeStr of rangesPart.split(",")) {
      const rt = rangeStr.trim();
      if (!rt) continue;
      const parts = rt.split("-").map((v) => parseInt(v.trim(), 10));
      if (parts.length >= 2 && Number.isFinite(parts[0]) && Number.isFinite(parts[1])) {
        ranges.push([parts[0], parts[1]]);
      } else if (Number.isFinite(parts[0])) {
        ranges.push([parts[0], parts[0]]);
      }
    }
    files.push({ path: filePath, lines: ranges.length > 0 ? ranges : "*" });
  }
  return files;
}
function extractPathFromCommand(command) {
  const tokens = command.trim().split(/\s+/);
  const pathTokens = tokens.slice(1).filter((t) => !t.startsWith("-") && !t.startsWith("|") && !t.startsWith("\\("));
  return pathTokens[0] || ".";
}

// tools/warp_grep/agent/tools/grep.ts
async function toolGrep(provider, args) {
  const res = await provider.grep(args);
  if (res.error) {
    return { output: res.error };
  }
  if (!res.lines.length) {
    return { output: "no matches" };
  }
  return { output: res.lines.join("\n") };
}

// tools/warp_grep/agent/tools/read.ts
function isValidRange(start, end) {
  return typeof start === "number" && typeof end === "number" && Number.isFinite(start) && Number.isFinite(end) && start > 0 && end >= start;
}
async function toolRead(provider, args) {
  if (args.lines && Array.isArray(args.lines) && args.lines.length > 0) {
    const validRanges = [];
    for (const range of args.lines) {
      if (Array.isArray(range) && range.length >= 2 && isValidRange(range[0], range[1])) {
        validRanges.push([range[0], range[1]]);
      }
    }
    if (validRanges.length === 0) {
      const res2 = await provider.read({ path: args.path });
      if (res2.error) return res2.error;
      if (!res2.lines.length) return "(empty file)";
      return res2.lines.join("\n");
    }
    const chunks = [];
    for (const [start, end] of validRanges) {
      const res2 = await provider.read({ path: args.path, start, end });
      if (res2.error) return res2.error;
      chunks.push(res2.lines.join("\n"));
    }
    if (chunks.every((c) => c === "")) return "(empty file)";
    return chunks.join("\n...\n");
  }
  const res = await provider.read({ path: args.path, start: args.start, end: args.end });
  if (res.error) {
    return res.error;
  }
  if (!res.lines.length) return "(empty file)";
  return res.lines.join("\n");
}

// tools/warp_grep/agent/tools/list_directory.ts
init_config();
var import_path = __toESM(require("path"), 1);
async function toolListDirectory(provider, args, repoRoot) {
  const maxResults = args.maxResults ?? AGENT_CONFIG.MAX_LIST_RESULTS;
  const maxDepth = args.maxDepth ?? AGENT_CONFIG.MAX_LIST_DEPTH;
  const entries = await provider.listDirectory({
    path: args.path,
    pattern: args.pattern ?? null,
    maxResults,
    maxDepth
  });
  if (!entries.length) return "empty";
  if (repoRoot) {
    const absRoot = repoRoot;
    const lines = entries.map((e) => import_path.default.join(absRoot, e.path));
    return lines.join("\n");
  }
  return entries.map((e) => e.path).join("\n");
}

// tools/warp_grep/agent/tools/glob.ts
async function toolGlob(provider, args) {
  const res = await provider.glob(args);
  if (res.error) {
    return res.error;
  }
  if (!res.files.length) {
    return "no matches";
  }
  const header = `Found ${res.totalFound} file(s) matching "${args.pattern}" within ${res.searchDir}, sorted by modification time (newest first):`;
  const body = res.files.join("\n");
  const truncated = res.totalFound > res.files.length ? `
[${res.totalFound - res.files.length} files truncated]` : "";
  return `${header}
---
${body}
---${truncated}`;
}

// tools/warp_grep/agent/tools/finish.ts
function isValidRange2(range) {
  return Array.isArray(range) && range.length >= 2 && typeof range[0] === "number" && typeof range[1] === "number" && Number.isFinite(range[0]) && Number.isFinite(range[1]) && range[0] > 0 && range[1] >= range[0];
}
function extractValidRanges(lines) {
  if (!Array.isArray(lines)) return null;
  const valid = [];
  for (const range of lines) {
    if (isValidRange2(range)) {
      valid.push([range[0], range[1]]);
    }
  }
  return valid.length > 0 ? valid : null;
}
async function readFinishFiles(repoRoot, files, reader) {
  const out = [];
  for (const f of files) {
    const validRanges = f.lines === "*" ? null : extractValidRanges(f.lines);
    if (f.lines === "*" || !validRanges) {
      const lines = await reader(f.path);
      out.push({ path: f.path, ranges: "*", content: lines.join("\n") });
    } else {
      const ranges = mergeRanges(validRanges);
      const chunks = [];
      for (let i = 0; i < ranges.length; i++) {
        const [s, e] = ranges[i];
        if (i === 0 && s > 1) {
          chunks.push(`// ... existing code, block starting at line ${s} ...`);
        } else if (i > 0) {
          chunks.push(`// ... existing code, block starting at line ${s} ...`);
        }
        const lines = await reader(f.path, s, e);
        chunks.push(lines.join("\n"));
      }
      out.push({ path: f.path, ranges, content: chunks.join("\n") });
    }
  }
  return out;
}
function mergeRanges(ranges) {
  if (!ranges.length) return [];
  const sorted = [...ranges].sort((a, b) => a[0] - b[0]);
  const merged = [];
  let [cs, ce] = sorted[0];
  for (let i = 1; i < sorted.length; i++) {
    const [s, e] = sorted[i];
    if (s <= ce + 1) {
      ce = Math.max(ce, e);
    } else {
      merged.push([cs, ce]);
      cs = s;
      ce = e;
    }
  }
  merged.push([cs, ce]);
  return merged;
}

// tools/warp_grep/agent/helpers.ts
var import_path2 = __toESM(require("path"), 1);
init_config();
var TRUNCATED_MARKER = "[truncated for context limit]";
function getMessageSize(m) {
  if (m.role === "tool") return m.content.length;
  if (m.role === "assistant") {
    let size = typeof m.content === "string" ? m.content.length : 0;
    if (m.tool_calls) {
      size += m.tool_calls.reduce((s, tc) => s + tc.function.name.length + tc.function.arguments.length, 0);
    }
    return size;
  }
  return m.content.length;
}
function formatTurnMessage(turnsUsed, maxTurns) {
  const turnsRemaining = maxTurns - turnsUsed;
  if (turnsRemaining === 1) {
    return `
You have used ${turnsUsed} turns, you only have 1 turn remaining. You have run out of turns to explore the code base and MUST call the finish tool now`;
  }
  return `
You have used ${turnsUsed} turn${turnsUsed === 1 ? "" : "s"} and have ${turnsRemaining} remaining`;
}
function calculateContextBudget(messages) {
  const totalChars = messages.reduce((sum, m) => sum + getMessageSize(m), 0);
  const maxChars = AGENT_CONFIG.MAX_CONTEXT_CHARS;
  const percent = Math.floor(totalChars / maxChars * 100);
  const usedK = Math.floor(totalChars / 1e3);
  const maxK = Math.floor(maxChars / 1e3);
  return `<context_budget>${percent}% (${usedK}K/${maxK}K chars)</context_budget>`;
}
async function buildInitialState(repoRoot, searchTerm, provider, options) {
  const budget = calculateContextBudget([]);
  const turnTag = `You have used 0 turns and have ${AGENT_CONFIG.MAX_TURNS} remaining`;
  const treeDepth = options?.search_type === "node_modules" ? 1 : 2;
  const absRoot = repoRoot;
  try {
    const entries = await provider.listDirectory({
      path: ".",
      maxResults: AGENT_CONFIG.MAX_OUTPUT_LINES,
      maxDepth: treeDepth
    });
    const lines = [absRoot];
    for (const e of entries) {
      lines.push(import_path2.default.join(absRoot, e.path));
    }
    return `<repo_structure>
${lines.join("\n")}
</repo_structure>

<search_string>
${searchTerm}
</search_string>
${budget}
${turnTag}`;
  } catch {
    return `<repo_structure>
${absRoot}
</repo_structure>

<search_string>
${searchTerm}
</search_string>
${budget}
${turnTag}`;
  }
}
function enforceContextLimit(messages, maxChars = AGENT_CONFIG.MAX_CONTEXT_CHARS) {
  const getTotalChars = () => messages.reduce((sum, m) => sum + getMessageSize(m), 0);
  if (getTotalChars() <= maxChars) {
    return messages;
  }
  const truncatableIndices = [];
  let firstUserSkipped = false;
  for (let i = 0; i < messages.length; i++) {
    const m = messages[i];
    if (m.role === "tool") {
      truncatableIndices.push(i);
    } else if (m.role === "user") {
      if (!firstUserSkipped) {
        firstUserSkipped = true;
        continue;
      }
      truncatableIndices.push(i);
    }
  }
  for (const idx of truncatableIndices) {
    if (getTotalChars() <= maxChars) {
      break;
    }
    const m = messages[idx];
    if (m.role === "tool" && m.content !== TRUNCATED_MARKER) {
      messages[idx] = { role: "tool", tool_call_id: m.tool_call_id, content: TRUNCATED_MARKER };
    } else if (m.role === "user" && m.content !== TRUNCATED_MARKER) {
      messages[idx] = { role: "user", content: TRUNCATED_MARKER };
    }
  }
  return messages;
}

// tools/warp_grep/agent/runner.ts
var import_openai = __toESM(require("openai"), 1);

// package.json
var package_default = {
  name: "@morphllm/morphsdk",
  version: "0.2.168",
  description: "TypeScript SDK and CLI for Morph Fast Apply integration",
  type: "module",
  main: "./dist/index.cjs",
  module: "./dist/index.js",
  types: "./dist/index.d.ts",
  exports: {
    ".": {
      types: "./dist/index.d.ts",
      import: "./dist/index.js",
      require: "./dist/index.cjs"
    },
    "./logger": {
      types: "./dist/logger.d.ts",
      import: "./dist/logger.js",
      require: "./dist/logger.cjs"
    },
    "./edge": {
      types: "./dist/edge.d.ts",
      import: "./dist/edge.js",
      require: "./dist/edge.cjs"
    },
    "./tools/warp-grep": {
      types: "./dist/tools/warp_grep/index.d.ts",
      import: "./dist/tools/warp_grep/index.js",
      require: "./dist/tools/warp_grep/index.cjs"
    },
    "./tools/warp-grep/openai": {
      types: "./dist/tools/warp_grep/openai.d.ts",
      import: "./dist/tools/warp_grep/openai.js",
      require: "./dist/tools/warp_grep/openai.cjs"
    },
    "./tools/warp-grep/anthropic": {
      types: "./dist/tools/warp_grep/anthropic.d.ts",
      import: "./dist/tools/warp_grep/anthropic.js",
      require: "./dist/tools/warp_grep/anthropic.cjs"
    },
    "./tools/warp-grep/vercel": {
      types: "./dist/tools/warp_grep/vercel.d.ts",
      import: "./dist/tools/warp_grep/vercel.js",
      require: "./dist/tools/warp_grep/vercel.cjs"
    },
    "./tools/warp-grep/client": {
      types: "./dist/tools/warp_grep/client.d.ts",
      import: "./dist/tools/warp_grep/client.js",
      require: "./dist/tools/warp_grep/client.cjs"
    },
    "./tools/warp-grep/gemini": {
      types: "./dist/tools/warp_grep/gemini.d.ts",
      import: "./dist/tools/warp_grep/gemini.js",
      require: "./dist/tools/warp_grep/gemini.cjs"
    },
    "./tools/warp-grep/harness": {
      types: "./dist/tools/warp_grep/harness.d.ts",
      import: "./dist/tools/warp_grep/harness.js",
      require: "./dist/tools/warp_grep/harness.cjs"
    },
    "./tools/fastapply": {
      types: "./dist/tools/fastapply/index.d.ts",
      import: "./dist/tools/fastapply/index.js",
      require: "./dist/tools/fastapply/index.cjs"
    },
    "./tools/fastapply/anthropic": {
      types: "./dist/tools/fastapply/anthropic.d.ts",
      import: "./dist/tools/fastapply/anthropic.js",
      require: "./dist/tools/fastapply/anthropic.cjs"
    },
    "./tools/fastapply/openai": {
      types: "./dist/tools/fastapply/openai.d.ts",
      import: "./dist/tools/fastapply/openai.js",
      require: "./dist/tools/fastapply/openai.cjs"
    },
    "./tools/fastapply/vercel": {
      types: "./dist/tools/fastapply/vercel.d.ts",
      import: "./dist/tools/fastapply/vercel.js",
      require: "./dist/tools/fastapply/vercel.cjs"
    },
    "./tools/codebase-search": {
      types: "./dist/tools/codebase_search/index.d.ts",
      import: "./dist/tools/codebase_search/index.js",
      require: "./dist/tools/codebase_search/index.cjs"
    },
    "./tools/codebase-search/anthropic": {
      types: "./dist/tools/codebase_search/anthropic.d.ts",
      import: "./dist/tools/codebase_search/anthropic.js",
      require: "./dist/tools/codebase_search/anthropic.cjs"
    },
    "./tools/codebase-search/openai": {
      types: "./dist/tools/codebase_search/openai.d.ts",
      import: "./dist/tools/codebase_search/openai.js",
      require: "./dist/tools/codebase_search/openai.cjs"
    },
    "./tools/codebase-search/vercel": {
      types: "./dist/tools/codebase_search/vercel.d.ts",
      import: "./dist/tools/codebase_search/vercel.js",
      require: "./dist/tools/codebase_search/vercel.cjs"
    },
    "./tools/git": {
      types: "./dist/git/index.d.ts",
      import: "./dist/git/index.js",
      require: "./dist/git/index.cjs"
    },
    "./tools/browser": {
      types: "./dist/tools/browser/index.d.ts",
      import: "./dist/tools/browser/index.js",
      require: "./dist/tools/browser/index.cjs"
    },
    "./tools/browser/anthropic": {
      types: "./dist/tools/browser/anthropic.d.ts",
      import: "./dist/tools/browser/anthropic.js",
      require: "./dist/tools/browser/anthropic.cjs"
    },
    "./tools/browser/openai": {
      types: "./dist/tools/browser/openai.d.ts",
      import: "./dist/tools/browser/openai.js",
      require: "./dist/tools/browser/openai.cjs"
    },
    "./tools/browser/vercel": {
      types: "./dist/tools/browser/vercel.d.ts",
      import: "./dist/tools/browser/vercel.js",
      require: "./dist/tools/browser/vercel.cjs"
    },
    "./tools/browser/profiles": {
      types: "./dist/tools/browser/profiles/index.d.ts",
      import: "./dist/tools/browser/profiles/index.js",
      require: "./dist/tools/browser/profiles/index.cjs"
    },
    "./modelrouter": {
      types: "./dist/modelrouter/index.d.ts",
      import: "./dist/modelrouter/index.js",
      require: "./dist/modelrouter/index.cjs"
    },
    "./tools/compact": {
      types: "./dist/tools/compact/index.d.ts",
      import: "./dist/tools/compact/index.js",
      require: "./dist/tools/compact/index.cjs"
    },
    "./subagents": {
      types: "./dist/subagents/index.d.ts",
      import: "./dist/subagents/index.js",
      require: "./dist/subagents/index.cjs"
    },
    "./subagents/vercel": {
      types: "./dist/subagents/vercel.d.ts",
      import: "./dist/subagents/vercel.js",
      require: "./dist/subagents/vercel.cjs"
    },
    "./subagents/anthropic": {
      types: "./dist/subagents/anthropic.d.ts",
      import: "./dist/subagents/anthropic.js",
      require: "./dist/subagents/anthropic.cjs"
    }
  },
  files: [
    "dist/**/*.js",
    "dist/**/*.cjs",
    "dist/**/*.d.ts",
    "dist/**/*.map",
    "!dist/**/__tests__/**",
    "!dist/**/*.test.*"
  ],
  scripts: {
    build: "tsup version.ts index.ts edge.ts client.ts tools/index.ts tools/fastapply/index.ts tools/fastapply/core.ts tools/fastapply/apply.ts tools/fastapply/types.ts tools/fastapply/prompts.ts tools/fastapply/anthropic.ts tools/fastapply/openai.ts tools/fastapply/vercel.ts tools/codebase_search/index.ts tools/codebase_search/core.ts tools/codebase_search/types.ts tools/codebase_search/prompts.ts tools/codebase_search/anthropic.ts tools/codebase_search/openai.ts tools/codebase_search/vercel.ts tools/warp_grep/index.ts tools/warp_grep/client.ts tools/warp_grep/openai.ts tools/warp_grep/anthropic.ts tools/warp_grep/vercel.ts tools/warp_grep/gemini.ts tools/warp_grep/harness.ts tools/warp_grep/agent/config.ts tools/warp_grep/agent/parser.ts tools/warp_grep/agent/runner.ts tools/warp_grep/agent/types.ts tools/warp_grep/agent/formatter.ts tools/warp_grep/providers/types.ts tools/warp_grep/providers/local.ts tools/warp_grep/providers/remote.ts tools/warp_grep/providers/code_storage_http.ts tools/warp_grep/tools/grep.ts tools/warp_grep/tools/analyse.ts tools/warp_grep/tools/read.ts tools/warp_grep/tools/finish.ts tools/warp_grep/utils/paths.ts tools/warp_grep/utils/github.ts tools/warp_grep/utils/ripgrep.ts tools/warp_grep/utils/format.ts tools/warp_grep/utils/files.ts git/index.ts git/client.ts git/config.ts git/types.ts tools/browser/index.ts tools/browser/core.ts tools/browser/types.ts tools/browser/prompts.ts tools/browser/anthropic.ts tools/browser/openai.ts tools/browser/vercel.ts tools/browser/live.ts tools/browser/errors.ts tools/browser/profiles/index.ts tools/browser/profiles/core.ts tools/browser/profiles/types.ts modelrouter/index.ts modelrouter/core.ts modelrouter/types.ts tools/compact/index.ts tools/compact/core.ts tools/compact/types.ts tools/utils/resilience.ts subagents/index.ts subagents/types.ts subagents/prompts.ts subagents/vercel.ts subagents/anthropic.ts --format esm,cjs --sourcemap --clean --dts --dts-resolve",
    prepare: "npm run build",
    typecheck: "tsc --noEmit",
    lint: "eslint .",
    test: "vitest run",
    "test:watch": "vitest watch",
    "test:anthropic": "vitest run anthropic",
    "test:openai": "vitest run openai",
    "test:vercel": "vitest run vercel",
    "test:git": "vitest run git",
    "test:browser": "vitest run browser",
    "test:agent": "npx tsx tests/fullAgentTest.ts",
    "test:integration": "npx tsx tests/fullIntegrationTest.ts",
    "test:e2e": "vitest run --config vitest.e2e.config.ts",
    "release:patch": "npm version patch && npm publish",
    "release:minor": "npm version minor && npm publish",
    "release:major": "npm version major && npm publish"
  },
  keywords: [
    "morph",
    "fast-apply",
    "cli",
    "sdk",
    "edit-file"
  ],
  engines: {
    node: ">=18"
  },
  license: "MIT",
  dependencies: {
    "@vscode/ripgrep": "^1.17.0",
    ai: ">=5.0.0",
    diff: "^7.0.0",
    "isomorphic-git": "^1.25.10",
    openai: "^4.52.7",
    zod: ">=3.23.0"
  },
  devDependencies: {
    "@ai-sdk/anthropic": "^2.0.70",
    "@ai-sdk/openai": "^2.0.35",
    "@anthropic-ai/sdk": "^0.30.1",
    "@google/generative-ai": "^0.24.1",
    "@types/diff": "^7.0.2",
    "@types/node": "^20.14.10",
    "@typescript-eslint/eslint-plugin": "^7.18.0",
    "@typescript-eslint/parser": "^7.18.0",
    dotenv: "^16.4.5",
    eslint: "^8.57.0",
    shx: "^0.3.4",
    tsup: "^8.5.0",
    tsx: "^4.16.2",
    typescript: "^5.5.4",
    vitest: "^2.1.6"
  },
  peerDependencies: {
    "@anthropic-ai/sdk": ">=0.25.0",
    "@google/generative-ai": ">=0.21.0",
    ai: ">=5.0.0",
    zod: ">=3.23.0"
  },
  peerDependenciesMeta: {
    "@anthropic-ai/sdk": {
      optional: true
    },
    "@google/generative-ai": {
      optional: true
    },
    ai: {
      optional: true
    },
    zod: {
      optional: true
    }
  },
  publishConfig: {
    access: "public"
  }
};

// version.ts
var SDK_VERSION = package_default.version;

// tools/warp_grep/agent/runner.ts
var import_path3 = __toESM(require("path"), 1);

// logger.ts
var MorphLogger = class {
  enabled;
  fileStream;
  /** Resolves once the file stream is initialized (or immediately if no file logging). */
  ready;
  constructor() {
    this.enabled = typeof process !== "undefined" && (process.env.MORPH_DEBUG === "1" || !!process.env.MORPH_LOG_FILE);
    this.fileStream = null;
    const f = typeof process !== "undefined" ? process.env.MORPH_LOG_FILE : void 0;
    if (f) {
      this.ready = import("fs").then((fs4) => {
        this.fileStream = fs4.createWriteStream(f, { flags: "a" });
      }).catch(() => {
      });
    } else {
      this.ready = Promise.resolve();
    }
  }
  debug(component, msg, data) {
    this._log("debug", component, msg, data);
  }
  info(component, msg, data) {
    this._log("info", component, msg, data);
  }
  warn(component, msg, data) {
    this._log("warn", component, msg, data);
  }
  error(component, msg, data) {
    this._log("error", component, msg, data);
  }
  enable() {
    this.enabled = true;
  }
  get isEnabled() {
    return this.enabled;
  }
  _log(level, component, msg, data) {
    if (level !== "error" && !this.enabled) return;
    const ts = (/* @__PURE__ */ new Date()).toISOString();
    const prefix = `[${ts}] [${level.toUpperCase()}] [${component}]`;
    console.error(data ? `${prefix} ${msg} ${JSON.stringify(data)}` : `${prefix} ${msg}`);
    this.fileStream?.write(JSON.stringify({ ts, level, component, msg, ...data && { data } }) + "\n");
  }
};
var logger = new MorphLogger();

// tools/warp_grep/agent/runner.ts
var DEFAULT_API_URL = "https://api.morphllm.com";
var TOOL_SPECS = [
  {
    type: "function",
    function: {
      name: "list_directory",
      description: "Execute ls or find commands to explore directory structure. Max 500 results. Common junk directories are excluded automatically.",
      parameters: {
        type: "object",
        properties: {
          command: {
            type: "string",
            description: "Full ls or find command (e.g. ls -la src/, find . -maxdepth 2 -type f -name '*.py', find . -type d, ls -d */)."
          }
        },
        required: ["command"]
      }
    }
  },
  {
    type: "function",
    function: {
      name: "grep_search",
      description: "Search for a regex pattern in file contents. Returns matching lines with file paths and line numbers. Case-insensitive. Respects .gitignore.",
      parameters: {
        type: "object",
        properties: {
          pattern: {
            type: "string",
            description: "Regex pattern to search for in file contents (e.g. 'class\\s+\\w+Error', 'import|require|from', 'def (get|set|update)_user')."
          },
          path: {
            type: "string",
            description: "File or directory to search in. Defaults to current working directory."
          },
          glob: {
            type: "string",
            description: "Glob pattern to filter files (e.g. '*.py', '*.{ts,tsx,js,jsx,py,go}', 'src/**/*.go', '!*.test.*')."
          },
          limit: {
            type: "integer",
            description: "Limit output to first N matching lines. Shows all matches if not specified."
          }
        },
        required: ["pattern"]
      }
    }
  },
  {
    type: "function",
    function: {
      name: "glob",
      description: "Find files by name/extension using glob patterns. Returns absolute paths sorted by modification time (newest first). Respects .gitignore. Max 100 results.",
      parameters: {
        type: "object",
        properties: {
          pattern: {
            type: "string",
            description: "Glob pattern to match files (e.g. '*.py', 'src/**/*.js', '*.{ts,tsx}', 'test_*.py')."
          },
          path: {
            type: "string",
            description: "Directory to search in. Defaults to repository root."
          }
        },
        required: ["pattern"]
      }
    }
  },
  {
    type: "function",
    function: {
      name: "read",
      description: "Read entire files or specific line ranges using absolute paths.",
      parameters: {
        type: "object",
        properties: {
          path: {
            type: "string",
            description: "File path to read, using absolute path (e.g. '/home/ubuntu/repo/src/main.py' or windows path)."
          },
          lines: {
            type: "string",
            description: "Optional line range (e.g. '1-50' or '1-20,45-80'). Omit to read entire file."
          }
        },
        required: ["path"]
      }
    }
  },
  {
    type: "function",
    function: {
      name: "finish",
      description: "Submit final answer with all relevant code locations. Include imports and over-include rather than miss context.",
      parameters: {
        type: "object",
        properties: {
          files: {
            type: "string",
            description: "One file per line as path:lines (e.g. 'src/auth.py:1-15,25-50\\nsrc/user.py'). Omit line range to include entire file."
          }
        },
        required: ["files"]
      }
    }
  }
];
async function callModel(messages, model, options = {}) {
  const baseUrl = options.morphApiUrl || DEFAULT_API_URL;
  const apiKey = options.morphApiKey || process.env.MORPH_API_KEY || "";
  const timeoutMs = options.timeout ?? AGENT_CONFIG.TIMEOUT_MS;
  const parsedUrl = new URL(baseUrl);
  const baseURL = parsedUrl.pathname === "/" ? `${baseUrl}/v1` : baseUrl;
  const client = new import_openai.default({
    apiKey,
    baseURL,
    maxRetries: options.retryConfig?.maxRetries,
    timeout: timeoutMs,
    defaultHeaders: { "X-Morph-SDK-Version": SDK_VERSION }
  });
  const MAX_EMPTY_RETRIES = 1;
  logger.debug("WarpGrep", "model_call", { url: baseURL, model, message_count: messages.length });
  const callStartTime = Date.now();
  for (let attempt = 0; attempt <= MAX_EMPTY_RETRIES; attempt++) {
    let data;
    try {
      data = await client.chat.completions.create({
        model,
        temperature: 0,
        max_tokens: 2048,
        messages,
        tools: TOOL_SPECS,
        ...options.search_type ? { search_type: options.search_type } : {}
      });
    } catch (error) {
      const callLatencyMs = Date.now() - callStartTime;
      if (error instanceof import_openai.default.APIError) {
        logger.error("WarpGrep", "model_call_error", { status: error.status, error: error.message, latency_ms: callLatencyMs });
        if (error.status === 404) {
          const defaultMsg = "The endpoint you are trying to call is likely deprecated. Please update with: npm cache clean --force && npx -y @morphllm/morphmcp@latest or visit: https://morphllm.com/mcp";
          const errorText = error.message?.trim();
          throw new Error(errorText || defaultMsg);
        }
      } else {
        logger.error("WarpGrep", "model_call_error", { status: void 0, error: error instanceof Error ? error.message : String(error), latency_ms: callLatencyMs });
      }
      throw error;
    }
    const choice = data?.choices?.[0];
    const message = choice?.message;
    if (!message) {
      if (attempt === MAX_EMPTY_RETRIES) {
        throw new Error("Invalid response from model: no message in response");
      }
      await new Promise((resolve) => setTimeout(resolve, 200));
      continue;
    }
    const toolCalls = (message.tool_calls || []).map((tc) => ({
      id: tc.id,
      type: "function",
      function: { name: tc.function.name, arguments: tc.function.arguments }
    }));
    if (message.content || toolCalls.length > 0) {
      logger.debug("WarpGrep", "model_call_complete", { latency_ms: Date.now() - callStartTime, tool_calls_count: toolCalls.length, finish_reason: choice?.finish_reason ?? "unknown" });
      return { content: message.content ?? null, tool_calls: toolCalls };
    }
    if (attempt === MAX_EMPTY_RETRIES) {
      const finishReason = choice?.finish_reason ?? "unknown";
      throw new Error(
        `Invalid response from model: no content and no tool_calls, finish_reason=${finishReason}`
      );
    }
    await new Promise((resolve) => setTimeout(resolve, 200));
  }
  throw new Error("Invalid response from model");
}
function safeParseJSON(s) {
  try {
    return JSON.parse(s);
  } catch {
    return {};
  }
}
async function executeTool(provider, name, args, repoRoot) {
  switch (name) {
    case "grep_search": {
      const grepArgs = {
        pattern: args.pattern,
        path: args.path || "."
      };
      if (args.glob) grepArgs.glob = args.glob;
      if (args.case_sensitive !== void 0) grepArgs.case_sensitive = args.case_sensitive;
      const result = await toolGrep(provider, grepArgs);
      let output = result.output;
      if (args.limit && typeof args.limit === "number") {
        const lines = output.split("\n");
        if (lines.length > args.limit) {
          output = lines.slice(0, args.limit).join("\n") + `
... (truncated at ${args.limit} lines)`;
        }
      }
      return output;
    }
    case "glob": {
      return toolGlob(provider, {
        pattern: args.pattern,
        path: args.path
      });
    }
    case "list_directory": {
      const dirPath = extractPathFromCommand(args.command || ".");
      return toolListDirectory(provider, { path: dirPath }, repoRoot);
    }
    case "read": {
      const readArgs = {
        path: args.path
      };
      if (args.lines && typeof args.lines === "string") {
        Object.assign(readArgs, parseReadLines(args.lines));
      }
      return toolRead(provider, readArgs);
    }
    default:
      return `Unknown tool: ${name}`;
  }
}
async function* runWarpGrepStreaming(config) {
  const totalStart = Date.now();
  const timeoutMs = config.timeout ?? AGENT_CONFIG.TIMEOUT_MS;
  const timings = { turns: [], timeout_ms: timeoutMs };
  const repoRoot = config.repoRoot || process.cwd();
  const model = config.model || DEFAULT_MODEL;
  const messages = [];
  const maxTurns = AGENT_CONFIG.MAX_TURNS;
  logger.debug("WarpGrep", "session_start", { search_term: config.searchTerm, model, max_turns: maxTurns });
  const initialStateStart = Date.now();
  const initialState = await buildInitialState(repoRoot, config.searchTerm, config.provider, { search_type: config.search_type });
  timings.initial_state_ms = Date.now() - initialStateStart;
  logger.debug("WarpGrep", "initial_state", { system_prompt_len: initialState.length, user_message_len: initialState.length });
  messages.push({ role: "user", content: initialState });
  const provider = config.provider;
  const errors = [];
  let finishMeta;
  let terminationReason = "terminated";
  for (let turn = 1; turn <= maxTurns; turn += 1) {
    const turnMetrics = { turn, morph_api_ms: 0, local_tools_ms: 0 };
    logger.debug("WarpGrep", "turn_start", { turn, message_count: messages.length });
    const beforeChars = messages.reduce((sum, m) => sum + (typeof m.content === "string" ? m.content.length : 0), 0);
    enforceContextLimit(messages);
    const afterChars = messages.reduce((sum, m) => sum + (typeof m.content === "string" ? m.content.length : 0), 0);
    if (afterChars < beforeChars) {
      logger.debug("WarpGrep", "context_truncated", { before_chars: beforeChars, after_chars: afterChars });
    }
    const modelCallStart = Date.now();
    const response = await callModel(messages, model, {
      morphApiKey: config.morphApiKey,
      morphApiUrl: config.morphApiUrl,
      retryConfig: config.retryConfig,
      timeout: timeoutMs,
      search_type: config.search_type
    }).catch((e) => {
      const errMsg = e instanceof Error ? e.message : String(e);
      console.error(`[warp_grep] Morph API call failed on turn ${turn}:`, errMsg);
      logger.error("WarpGrep", "error", { turn, error: errMsg, phase: "model_call" });
      errors.push({ message: errMsg });
      return null;
    });
    turnMetrics.morph_api_ms = Date.now() - modelCallStart;
    if (!response) {
      timings.turns.push(turnMetrics);
      break;
    }
    const toolCalls = response.tool_calls;
    logger.debug("WarpGrep", "model_response", { turn, tool_calls: toolCalls.map((tc) => tc.function.name), latency_ms: turnMetrics.morph_api_ms });
    messages.push({
      role: "assistant",
      content: response.content,
      ...toolCalls.length > 0 ? { tool_calls: toolCalls } : {}
    });
    if (toolCalls.length === 0) {
      console.error(`[warp_grep] No tool calls on turn ${turn}. Content: ${(response.content || "").slice(0, 500)}`);
      errors.push({ message: "No tool calls produced by the model." });
      terminationReason = "terminated";
      timings.turns.push(turnMetrics);
      break;
    }
    yield {
      turn,
      toolCalls: toolCalls.map((tc) => ({
        name: tc.function.name,
        arguments: safeParseJSON(tc.function.arguments)
      }))
    };
    const finishCall = toolCalls.find((tc) => tc.function.name === "finish");
    if (finishCall) {
      const args = safeParseJSON(finishCall.function.arguments);
      const filesStr = args.files || "";
      const files = parseFinishFiles(filesStr);
      finishMeta = { files };
      terminationReason = "completed";
      logger.debug("WarpGrep", "finish", { turns: turn, files: files.map((f) => f.path) });
      if (files.length === 0) {
        const payload2 = filesStr || "No relevant code found.";
        timings.turns.push(turnMetrics);
        timings.total_ms = Date.now() - totalStart;
        return {
          terminationReason: "completed",
          messages,
          finish: { payload: payload2, metadata: finishMeta },
          timings
        };
      }
      timings.turns.push(turnMetrics);
      break;
    }
    const toolExecStart = Date.now();
    const results = await Promise.all(
      toolCalls.map(async (tc) => {
        const args = safeParseJSON(tc.function.arguments);
        const argsSummary = Object.fromEntries(Object.entries(args).map(([k, v]) => [k, typeof v === "string" && v.length > 100 ? v.slice(0, 100) + "..." : v]));
        logger.debug("WarpGrep", "tool_exec", { turn, tool: tc.function.name, args_summary: argsSummary });
        const toolStart = Date.now();
        const output = await executeTool(provider, tc.function.name, args, repoRoot).catch((err) => String(err));
        logger.debug("WarpGrep", "tool_result", { turn, tool: tc.function.name, result_len: output.length, latency_ms: Date.now() - toolStart });
        return { tool_call_id: tc.id, content: output };
      })
    );
    turnMetrics.local_tools_ms = Date.now() - toolExecStart;
    for (const result of results) {
      messages.push({ role: "tool", tool_call_id: result.tool_call_id, content: result.content });
    }
    const turnMsg = formatTurnMessage(turn, maxTurns);
    const budget = calculateContextBudget(messages);
    messages.push({ role: "user", content: turnMsg + "\n" + budget });
    timings.turns.push(turnMetrics);
  }
  if (terminationReason !== "completed" || !finishMeta) {
    timings.total_ms = Date.now() - totalStart;
    return { terminationReason, messages, errors, timings };
  }
  const parts = ["Relevant context found:"];
  for (const f of finishMeta.files) {
    const ranges = f.lines === "*" ? "*" : Array.isArray(f.lines) ? f.lines.map(([s, e]) => `${s}-${e}`).join(", ") : "*";
    parts.push(`- ${f.path}: ${ranges}`);
  }
  const payload = parts.join("\n");
  const finishResolutionStart = Date.now();
  const fileReadErrors = [];
  const resolved = await readFinishFiles(
    repoRoot,
    finishMeta.files,
    async (p, s, e) => {
      let resolvedPath = p;
      if (!p.startsWith(repoRoot)) {
        const relative = p.startsWith("/") ? p.slice(1) : p;
        resolvedPath = import_path3.default.join(repoRoot, relative);
      }
      try {
        const rr = await provider.read({ path: resolvedPath, start: s, end: e });
        return rr.lines.map((l) => {
          const idx = l.indexOf("|");
          return idx >= 0 ? l.slice(idx + 1) : l;
        });
      } catch (err) {
        const errorMsg = err instanceof Error ? err.message : String(err);
        fileReadErrors.push({ path: resolvedPath, error: errorMsg });
        console.error(`[warp_grep] Failed to read file: ${resolvedPath} - ${errorMsg}`);
        return [`[couldn't find: ${resolvedPath}]`];
      }
    }
  );
  timings.finish_resolution_ms = Date.now() - finishResolutionStart;
  if (fileReadErrors.length > 0) {
    errors.push(...fileReadErrors.map((e) => ({ message: `File read error: ${e.path} - ${e.error}` })));
  }
  timings.total_ms = Date.now() - totalStart;
  return {
    terminationReason: "completed",
    messages,
    finish: { payload, metadata: finishMeta, resolved },
    timings
  };
}
async function runWarpGrep(config) {
  const gen = runWarpGrepStreaming(config);
  let result = await gen.next();
  while (!result.done) {
    result = await gen.next();
  }
  return result.value;
}

// tools/warp_grep/providers/remote.ts
init_config();
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 RemoteCommandsProvider = class {
  constructor(repoRoot, commands) {
    this.repoRoot = repoRoot;
    this.commands = commands;
  }
  /**
   * Run grep command and parse ripgrep output
   */
  async grep(params) {
    try {
      const stdout = await this.commands.grep(params.pattern, params.path, params.glob);
      const lines = (stdout || "").trim().split(/\r?\n/).filter((l) => l.length > 0);
      if (lines.length > AGENT_CONFIG.MAX_OUTPUT_LINES) {
        const truncated = lines.slice(0, AGENT_CONFIG.MAX_OUTPUT_LINES);
        truncated.push(`... (output truncated at ${AGENT_CONFIG.MAX_OUTPUT_LINES} of ${lines.length} lines)`);
        return { lines: truncated };
      }
      return { lines };
    } catch (error) {
      return {
        lines: [],
        error: `[GREP ERROR] ${error instanceof Error ? error.message : String(error)}`
      };
    }
  }
  /**
   * Read file and add line numbers
   */
  async read(params) {
    const rawStart = params.start;
    const rawEnd = params.end;
    const startValid = rawStart === void 0 || Number.isFinite(rawStart) && rawStart > 0;
    const endValid = rawEnd === void 0 || Number.isFinite(rawEnd) && rawEnd > 0;
    const rangeValid = startValid && endValid && (rawStart === void 0 || rawEnd === void 0 || rawStart <= rawEnd);
    const start = rangeValid && rawStart !== void 0 ? rawStart : 1;
    const end = rangeValid && rawEnd !== void 0 ? rawEnd : 1e6;
    try {
      const stdout = await this.commands.read(params.path, start, end);
      const contentLines = (stdout || "").split("\n");
      if (contentLines.length > 0 && contentLines[contentLines.length - 1] === "") {
        contentLines.pop();
      }
      const lines = contentLines.map((content, idx) => `${start + idx}|${content}`);
      if (lines.length > AGENT_CONFIG.MAX_READ_LINES) {
        const truncated = lines.slice(0, AGENT_CONFIG.MAX_READ_LINES);
        truncated.push(`... (output truncated at ${AGENT_CONFIG.MAX_READ_LINES} of ${lines.length} lines)`);
        return { lines: truncated };
      }
      return { lines };
    } catch (error) {
      return {
        lines: [],
        error: `[READ ERROR] ${error instanceof Error ? error.message : String(error)}`
      };
    }
  }
  /**
   * List directory and parse find output
   */
  async listDirectory(params) {
    const maxDepth = params.maxDepth ?? AGENT_CONFIG.MAX_LIST_DEPTH;
    const maxResults = params.maxResults ?? AGENT_CONFIG.MAX_OUTPUT_LINES;
    try {
      const stdout = await this.commands.listDir(params.path, maxDepth);
      const paths = (stdout || "").trim().split(/\r?\n/).filter((p) => p.length > 0);
      const regex = params.pattern ? new RegExp(params.pattern) : null;
      const entries = [];
      for (const fullPath of paths) {
        if (fullPath === params.path || fullPath === this.repoRoot) continue;
        const name = fullPath.split("/").pop() || "";
        if (shouldSkip(name)) continue;
        if (regex && !regex.test(name)) continue;
        let relativePath = fullPath;
        if (fullPath.startsWith(this.repoRoot)) {
          relativePath = fullPath.slice(this.repoRoot.length).replace(/^\//, "");
        }
        const depth = relativePath.split("/").filter(Boolean).length - 1;
        const hasExtension = name.includes(".") && !name.startsWith(".");
        const type = hasExtension ? "file" : "dir";
        entries.push({
          name,
          path: relativePath,
          type,
          depth: Math.max(0, depth)
        });
        if (entries.length >= maxResults) break;
      }
      return entries;
    } catch (error) {
      return [];
    }
  }
  /**
   * Glob search - finds files matching a pattern.
   * Falls back to a grep --files approach via the listDir command.
   */
  async glob(params) {
    const searchPath = params.path || this.repoRoot;
    try {
      const stdout = await this.commands.listDir(searchPath, 10);
      const allPaths = (stdout || "").trim().split(/\r?\n/).filter((p) => p.length > 0);
      const globToRegex = (glob) => {
        const escaped = glob.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, ".");
        return new RegExp(escaped);
      };
      const regex = globToRegex(params.pattern);
      const matched = allPaths.filter((p) => {
        const name = p.split("/").pop() || "";
        return regex.test(name) && !shouldSkip(name);
      });
      const totalFound = matched.length;
      return { files: matched.slice(0, 100), searchDir: searchPath, totalFound };
    } catch (error) {
      return {
        files: [],
        searchDir: searchPath,
        totalFound: 0,
        error: `[GLOB ERROR] ${error instanceof Error ? error.message : String(error)}`
      };
    }
  }
};

// tools/warp_grep/providers/code_storage_http.ts
async function post(url, body, op) {
  const res = await fetch(url, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(body)
  });
  if (!res.ok) {
    const text = await res.text().catch(() => res.statusText);
    try {
      const parsed = JSON.parse(text);
      if (parsed.error) return `Error: ${parsed.error}`;
    } catch {
    }
    return `Error: ${op} failed (${res.status}): ${text}`;
  }
  const data = await res.json();
  if (data.error) throw new Error(data.error);
  return data.stdout;
}
function createCodeStorageHttpCommands(config) {
  const { baseUrl, repoId, branch } = config;
  const encodedRepoId = encodeURIComponent(repoId);
  return {
    grep: (pattern, path6, glob) => post(`${baseUrl}/api/code-search/${encodedRepoId}/grep`, { pattern, path: path6, glob, branch }, "grep"),
    read: (path6, start, end) => post(`${baseUrl}/api/code-search/${encodedRepoId}/read`, { path: path6, start, end, branch }, "read"),
    listDir: (path6, maxDepth) => post(`${baseUrl}/api/code-search/${encodedRepoId}/list`, { path: path6, maxDepth, branch }, "list")
  };
}

// tools/warp_grep/utils/github.ts
function parseGitHubUrl(input) {
  input = input.trim();
  const urlPattern = /^(?:https?:\/\/)?github\.com\/([^\/]+)\/([^\/\?\#]+)/;
  const match = input.match(urlPattern);
  if (match) {
    return { owner: match[1], repo: match[2].replace(/\.git$/, "") };
  }
  const shortPattern = /^([^\/]+)\/([^\/]+)$/;
  const shortMatch = input.match(shortPattern);
  if (shortMatch && !shortMatch[1].includes(".")) {
    return { owner: shortMatch[1], repo: shortMatch[2].replace(/\.git$/, "") };
  }
  throw new Error(
    `Invalid GitHub URL or shorthand: "${input}". Expected "owner/repo" or "https://github.com/owner/repo"`
  );
}

// tools/compact/core.ts
var DEFAULT_API_URL2 = "https://api.morphllm.com";
var DEFAULT_TIMEOUT = 12e4;
var CompactClient = class {
  config;
  constructor(config = {}) {
    this.config = {
      ...config,
      morphApiUrl: config.morphApiUrl ?? DEFAULT_API_URL2,
      timeout: config.timeout ?? DEFAULT_TIMEOUT
    };
  }
  /**
   * Compact messages or text via /v1/compact.
   * Returns per-message `compacted_line_ranges` showing which lines were removed.
   *
   * @example
   * ```typescript
   * const client = new CompactClient({ morphApiKey: 'sk-...' });
   * const result = await client.compact({
   *   input: codeFile,
   *   query: "authentication",
   *   compressionRatio: 0.5,
   * });
   * console.log(result.output);
   * ```
   */
  async compact(input) {
    const apiKey = this.config.morphApiKey || (typeof process !== "undefined" ? process.env?.MORPH_API_KEY : void 0);
    const debug = this.config.debug || false;
    if (!apiKey) {
      throw new Error(
        "Morph API key not found. Set MORPH_API_KEY environment variable or pass morphApiKey in config."
      );
    }
    const url = `${this.config.morphApiUrl}/v1/compact`;
    if (debug) {
      console.log(`[Compact] Calling ${url}`);
    }
    const body = {
      compression_ratio: input.compressionRatio ?? 0.5,
      preserve_recent: input.preserveRecent ?? 2,
      model: input.model ?? "morph-compactor",
      include_line_ranges: input.includeLineRanges ?? true,
      include_markers: input.includeMarkers ?? true
    };
    if (input.query !== void 0) {
      body.query = input.query;
    }
    if (input.messages) {
      body.messages = input.messages;
    } else if (typeof input.input === "string") {
      body.input = input.input;
    } else if (Array.isArray(input.input)) {
      body.messages = input.input;
    } else {
      throw new Error("Either 'input' or 'messages' must be provided");
    }
    const startTime = Date.now();
    const response = await fetch(url, {
      method: "POST",
      headers: {
        "Authorization": `Bearer ${apiKey}`,
        "Content-Type": "application/json"
      },
      body: JSON.stringify(body),
      signal: AbortSignal.timeout(this.config.timeout)
    });
    if (!response.ok) {
      const text = await response.text();
      throw new Error(`Compact API error ${response.status}: ${text}`);
    }
    const data = await response.json();
    if (debug) {
      console.log(`[Compact] compact() done in ${Date.now() - startTime}ms`);
    }
    return data;
  }
};

// tools/compact/utils.ts
async function compactFileContexts(files, query, apiKey, apiUrl, maxTokens = 1e4, maxConcurrency = 3) {
  const totalLength = files.reduce((sum, file) => sum + file.content.length, 0);
  const estimatedTokens = totalLength / 3;
  if (estimatedTokens <= maxTokens) {
    return files;
  }
  let compressionRatio = maxTokens / estimatedTokens;
  compressionRatio = Math.max(0.3, Math.min(0.99, compressionRatio));
  const client = new CompactClient({
    morphApiKey: apiKey,
    morphApiUrl: apiUrl
  });
  const results = [];
  const inProgress = /* @__PURE__ */ new Set();
  for (const file of files) {
    if (file.content.length < 500) {
      results.push({ path: file.path, content: file.content });
      continue;
    }
    const task = async () => {
      try {
        const result = await client.compact({
          input: file.content,
          query,
          compressionRatio,
          preserveRecent: 0
        });
        results.push({ path: file.path, content: result.output });
      } catch (error) {
        console.error(`[compactFileContexts] Failed to compact file ${file.path}:`, error);
        results.push({ path: file.path, content: file.content });
      }
    };
    const promise = task().finally(() => inProgress.delete(promise));
    inProgress.add(promise);
    if (inProgress.size >= maxConcurrency) {
      await Promise.race(inProgress);
    }
  }
  await Promise.all(inProgress);
  const orderMap = new Map(files.map((f, i) => [f.path, i]));
  return results.sort((a, b) => (orderMap.get(a.path) ?? 0) - (orderMap.get(b.path) ?? 0));
}

// tools/warp_grep/client.ts
var DEFAULT_CODE_SEARCH_URL = "https://morphllm.com";
async function getLocalProvider(repoRoot, excludes, allowNames) {
  const { LocalRipgrepProvider: LocalRipgrepProvider2 } = await Promise.resolve().then(() => (init_local(), local_exports));
  const opts = allowNames?.length ? { allowNames } : void 0;
  return new LocalRipgrepProvider2(repoRoot, excludes, opts);
}
var WarpGrepClient = class {
  config;
  constructor(config = {}) {
    this.config = { ...config };
  }
  execute(input) {
    const toolConfig = {
      repoRoot: input.repoRoot,
      remoteCommands: input.remoteCommands,
      provider: input.provider,
      excludes: input.excludes,
      includes: input.includes,
      debug: input.debug ?? this.config.debug,
      morphApiKey: this.config.morphApiKey,
      morphApiUrl: this.config.morphApiUrl,
      retryConfig: this.config.retryConfig,
      timeout: this.config.timeout,
      search_type: input.search_type
    };
    if (input.streamSteps) {
      return executeToolCallStreaming({ search_term: input.searchTerm }, toolConfig);
    }
    return executeToolCall({ search_term: input.searchTerm }, toolConfig);
  }
  searchGitHub(input) {
    if (input.streamSteps) {
      return this._searchGitHubStreaming(input);
    }
    return this._searchGitHubAsync(input);
  }
  /**
   * Read a single file from a public GitHub repository
   *
   * @example
   * ```typescript
   * const result = await client.readGitHubFile({
   *   github: 'vercel/next.js',
   *   path: 'src/server/app-render/index.tsx',
   *   startLine: 1,
   *   endLine: 50,
   * });
   * if (result.success) console.log(result.content);
   * ```
   */
  async readGitHubFile(input) {
    return executeGitHubReadFile(input, { timeout: this.config.timeout });
  }
  async _resolveGitHubRepo(input) {
    const { owner, repo } = parseGitHubUrl(input.github);
    const baseUrl = this.config.codeSearchUrl || DEFAULT_CODE_SEARCH_URL;
    logger.debug("WarpGrep", "github_resolve", { owner_repo: `${owner}/${repo}`, branch: input.branch });
    const resolveStart = Date.now();
    const importRes = await fetch(`${baseUrl}/api/code-search/get-or-create?url=${encodeURIComponent(`${owner}/${repo}`)}`);
    if (!importRes.ok) {
      const text = await importRes.text().catch(() => importRes.statusText);
      logger.error("WarpGrep", "github_resolve_failed", { owner_repo: `${owner}/${repo}`, status: importRes.status, error: text });
      throw new Error(`Failed to import repo ${owner}/${repo}: ${text}`);
    }
    const { repoId, defaultBranch } = await importRes.json();
    logger.debug("WarpGrep", "github_repo_fetched", { repo_id: repoId, default_branch: defaultBranch, latency_ms: Date.now() - resolveStart });
    return {
      repo,
      remoteCommands: createCodeStorageHttpCommands({ baseUrl, repoId, branch: input.branch || defaultBranch })
    };
  }
  async _searchGitHubAsync(input) {
    try {
      const { remoteCommands } = await this._resolveGitHubRepo(input);
      return this.execute({
        searchTerm: input.searchTerm,
        repoRoot: ".",
        remoteCommands
      });
    } catch (error) {
      return { success: false, error: error instanceof Error ? error.message : String(error) };
    }
  }
  async *_searchGitHubStreaming(input) {
    let remoteCommands;
    try {
      ({ remoteCommands } = await this._resolveGitHubRepo(input));
    } catch (error) {
      return { success: false, error: error instanceof Error ? error.message : String(error) };
    }
    const generator = this.execute({
      searchTerm: input.searchTerm,
      repoRoot: ".",
      remoteCommands,
      streamSteps: true
    });
    let result;
    for (; ; ) {
      const { value, done } = await generator.next();
      if (done) {
        result = value;
        break;
      }
      yield value;
    }
    return result;
  }
};
async function executeToolCall(input, config) {
  const parsed = typeof input === "string" ? JSON.parse(input) : input;
  const allowNames = config.search_type === "node_modules" ? ["node_modules"] : void 0;
  const provider = config.remoteCommands ? new RemoteCommandsProvider(config.repoRoot, config.remoteCommands) : config.provider ?? await getLocalProvider(config.repoRoot, config.excludes, allowNames);
  const result = await runWarpGrep({
    searchTerm: parsed.search_term,
    repoRoot: config.repoRoot,
    provider,
    excludes: config.excludes,
    includes: config.includes,
    debug: config.debug ?? false,
    morphApiKey: config.morphApiKey,
    morphApiUrl: config.morphApiUrl,
    retryConfig: config.retryConfig,
    timeout: config.timeout,
    search_type: config.search_type
  });
  return processAgentResult(result, parsed.search_term, config.morphApiKey, config.morphApiUrl);
}
async function processAgentResult(result, searchTerm, apiKey, apiUrl) {
  const finish = result.finish;
  if (result.terminationReason !== "completed" || !finish?.metadata) {
    const errorDetails = result.errors?.map((e) => e.message).join("; ") || "unknown reason";
    console.error(`[warp_grep] processAgentResult failed. Reason: ${result.terminationReason}. Errors: ${errorDetails}. Turns: ${result.timings?.turns?.length ?? 0}`);
    return { success: false, error: `Search did not complete: ${errorDetails}` };
  }
  const contexts = (finish.resolved ?? []).map((r) => ({
    file: r.path,
    content: r.content,
    lines: r.ranges
  }));
  try {
    const compactable = contexts.map((c) => ({ path: c.file, content: c.content }));
    const compacted = await compactFileContexts(compactable, searchTerm, apiKey, apiUrl);
    for (let i = 0; i < contexts.length; i++) {
      contexts[i].content = compacted[i].content;
    }
  } catch (error) {
    console.error(`[warp_grep] Failed to compact result contexts:`, error);
  }
  return { success: true, contexts, summary: finish.payload };
}
async function* executeToolCallStreaming(input, config) {
  const parsed = typeof input === "string" ? JSON.parse(input) : input;
  const allowNames = config.search_type === "node_modules" ? ["node_modules"] : void 0;
  const provider = config.remoteCommands ? new RemoteCommandsProvider(config.repoRoot, config.remoteCommands) : config.provider ?? await getLocalProvider(config.repoRoot, config.excludes, allowNames);
  const generator = runWarpGrepStreaming({
    searchTerm: parsed.search_term,
    repoRoot: config.repoRoot,
    provider,
    excludes: config.excludes,
    includes: config.includes,
    debug: config.debug ?? false,
    morphApiKey: config.morphApiKey,
    morphApiUrl: config.morphApiUrl,
    retryConfig: config.retryConfig,
    timeout: config.timeout,
    search_type: config.search_type
  });
  let agentResult;
  for (; ; ) {
    const { value, done } = await generator.next();
    if (done) {
      agentResult = value;
      break;
    }
    yield value;
  }
  return processAgentResult(agentResult, parsed.search_term, config.morphApiKey, config.morphApiUrl);
}
async function fetchRawGitHubFile(owner, repo, filePath, branch, timeout) {
  const branches = branch ? [branch] : ["HEAD"];
  const fallbacks = ["main", "master", "develop"];
  const fetchWithTimeout = (url) => timeout ? fetch(url, { signal: AbortSignal.timeout(timeout) }) : fetch(url);
  for (const b of branches) {
    const url = `https://raw.githubusercontent.com/${owner}/${repo}/${b}/${filePath}`;
    const res = await fetchWithTimeout(url);
    if (res.ok) return { content: await res.text(), branch: b };
  }
  for (const fb of fallbacks) {
    if (branch && fb === branch) continue;
    const url = `https://raw.githubusercontent.com/${owner}/${repo}/${fb}/${filePath}`;
    const res = await fetchWithTimeout(url);
    if (res.ok) return { content: await res.text(), branch: fb };
  }
  throw new Error(`File not found: ${owner}/${repo}/${filePath}`);
}
async function executeGitHubReadFile(input, config) {
  try {
    const { owner, repo } = parseGitHubUrl(input.github);
    const { content: raw, branch } = await fetchRawGitHubFile(
      owner,
      repo,
      input.path,
      input.branch,
      config?.timeout
    );
    const allLines = raw.split("\n");
    const totalLines = allLines.length;
    const start = Math.max(1, input.startLine ?? 1);
    const end = Math.min(totalLines, input.endLine ?? totalLines);
    const selected = allLines.slice(start - 1, end);
    const padWidth = String(end).length;
    const numbered = selected.map((line, i) => `${String(start + i).padStart(padWidth)}|${line}`).join("\n");
    return {
      success: true,
      content: numbered,
      path: input.path,
      github: `${owner}/${repo}`,
      branch,
      lineRange: [start, end],
      totalLines
    };
  } catch (error) {
    return {
      success: false,
      error: error instanceof Error ? error.message : String(error)
    };
  }
}
function formatGitHubReadFileResult(result) {
  if (!result.success) {
    return `Failed to read file: ${result.error}`;
  }
  const rangeStr = result.lineRange ? ` (lines ${result.lineRange[0]}-${result.lineRange[1]} of ${result.totalLines})` : "";
  return `File: ${result.github}/${result.path}${rangeStr}

${result.content}`;
}
function formatResult(result) {
  if (!result.success) {
    return `Search failed: ${result.error}`;
  }
  if (!result.contexts || result.contexts.length === 0) {
    return "No relevant code found. Try rephrasing your search term.";
  }
  const parts = [];
  parts.push(`Morph Fast Context subagent performed search on repository:
`);
  parts.push("Relevant context found:");
  for (const ctx of result.contexts) {
    const rangeStr = !ctx.lines || ctx.lines === "*" ? "*" : ctx.lines.map(([s, e]) => `${s}-${e}`).join(",");
    parts.push(`- ${ctx.file}:${rangeStr}`);
  }
  parts.push("\nHere is the content of files:\n");
  for (const ctx of result.contexts) {
    const rangeStr = !ctx.lines || ctx.lines === "*" ? "" : ` lines="${ctx.lines.map(([s, e]) => `${s}-${e}`).join(",")}"`;
    parts.push(`<file path="${ctx.file}"${rangeStr}>`);
    parts.push(ctx.content);
    parts.push("</file>\n");
  }
  return parts.join("\n");
}

// tools/warp_grep/prompts.ts
var WARP_GREP_TOOL_NAME = "codebase_search";
var WARP_GREP_DESCRIPTION = 'Very fast code search exploration subagent (not a grep tool) that runs parallel grep and file read calls over multiple turns to locate relevant files and line ranges. The search term should be a targeted natural-language query describing what you are trying to find or accomplish, e.g. "Find where authentication requests are handled in the Express routes" or "How do callers of processOrder handle the error case?". Fill in extra context you can infer to make the query specific. Do not pass bare keywords or symbol names \u2014 use grep directly for exact symbol lookups. Use this tool first when exploring unfamiliar code. The results may be partial \u2014 follow up with classical search tools or direct file reads if needed.';
var GITHUB_WARP_GREP_SEARCH_TOOL_NAME = "github_codebase_search";
var GITHUB_WARP_GREP_SEARCH_DESCRIPTION = "Always use this when debugging errors in third-party dependencies to check for upstream fixes, open issues, or newer code pathsSearch tool for public GitHub repositories.Code search exploration subagent for public GitHub repositories (not your local workspace \u2014 use codebase_search for that). Runs parallel grep and file read calls to locate relevant files and line ranges in external github repositories without cloning the repository. Pass a targeted natural-language query, not bare keywords. Useful for understanding how a library works or investigating upstream bugs. You must provide either github_url or owner_repo (at least one required). ";
var GITHUB_WARP_GREP_SEARCH_INPUT_SCHEMA = {
  type: "object",
  properties: {
    search_term: { type: "string", description: 'A targeted natural-language query describing what to find (e.g. "How does auth work for SSO users?"). Not a keyword or symbol name.' },
    github_url: { type: "string", description: 'GitHub repository URL to search (e.g. "https://github.com/vercel/next.js"). You must provide either github_url or owner_repo.' },
    owner_repo: { type: "string", description: 'Repository owner/repo shorthand (e.g. "vercel/next.js"). You must provide either github_url or owner_repo.' },
    branch: { type: "string", description: "Branch to search (defaults to the repository default branch)" }
  },
  required: ["search_term"]
};
var GITHUB_SEARCH_TOOL_NAME = GITHUB_WARP_GREP_SEARCH_TOOL_NAME;
var GITHUB_SEARCH_DESCRIPTION = GITHUB_WARP_GREP_SEARCH_DESCRIPTION;
var GITHUB_SEARCH_INPUT_SCHEMA = GITHUB_WARP_GREP_SEARCH_INPUT_SCHEMA;
var GITHUB_READ_FILE_TOOL_NAME = "readfile_github_search";
var GITHUB_READ_FILE_DESCRIPTION = "Read a single file (or a line range) from a public GitHub repository. ONLY USE THIS WHEN YOU ALREADY KNOW THE EXACT FILE PATH YOU WANT TO READ, for example after finding it via github_codebase_search results. Takes owner/repo shorthand and the file path within the repo. Optionally specify startLine and endLine (1-based) to read a specific range. Returns the file content with line numbers.";
var GITHUB_READ_FILE_INPUT_SCHEMA = {
  type: "object",
  properties: {
    github: { type: "string", description: 'owner/repo shorthand (e.g., "vercel/next.js")' },
    path: { type: "string", description: 'File path within the repository (e.g., "src/server/index.ts")' },
    startLine: { type: "number", description: "Start line number (1-based). Omit to start from beginning." },
    endLine: { type: "number", description: "End line number (1-based, inclusive). Omit to read to the end." },
    branch: { type: "string", description: "Branch to read from (defaults to the repository default branch)" }
  },
  required: ["github", "path"]
};

// tools/warp_grep/anthropic.ts
var INPUT_SCHEMA = {
  type: "object",
  properties: {
    search_term: { type: "string", description: "Search problem statement that this subagent is supposed to research for" }
  },
  required: ["search_term"]
};
var warpGrepTool = {
  name: WARP_GREP_TOOL_NAME,
  description: WARP_GREP_DESCRIPTION,
  input_schema: INPUT_SCHEMA
};
async function execute(input, config) {
  return executeToolCall(input, config);
}
function createWarpGrepTool(config) {
  const tool = {
    name: config.name ?? WARP_GREP_TOOL_NAME,
    description: config.description ?? WARP_GREP_DESCRIPTION,
    input_schema: INPUT_SCHEMA
  };
  return Object.assign(tool, {
    execute: async (input) => {
      return executeToolCall(input, config);
    },
    formatResult: (result) => {
      return formatResult(result);
    }
  });
}
function createGitHubSearchTool(config) {
  const client = new WarpGrepClient(config);
  const tool = {
    name: GITHUB_SEARCH_TOOL_NAME,
    description: GITHUB_SEARCH_DESCRIPTION,
    input_schema: GITHUB_SEARCH_INPUT_SCHEMA
  };
  return Object.assign(tool, {
    execute: async (input) => {
      const github = input.github_url || input.owner_repo;
      if (!github) {
        throw new Error("Please provide github search url or owner/repo id");
      }
      return client.searchGitHub({ searchTerm: input.search_term, github, branch: input.branch });
    },
    formatResult: (result) => {
      return formatResult(result);
    }
  });
}
function createGitHubReadFileTool(config) {
  const tool = {
    name: GITHUB_READ_FILE_TOOL_NAME,
    description: GITHUB_READ_FILE_DESCRIPTION,
    input_schema: GITHUB_READ_FILE_INPUT_SCHEMA
  };
  return Object.assign(tool, {
    execute: async (input) => {
      return executeGitHubReadFile(input, config);
    },
    formatResult: (result) => {
      return formatGitHubReadFileResult(result);
    }
  });
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  createGitHubReadFileTool,
  createGitHubSearchTool,
  createWarpGrepTool,
  execute,
  formatResult,
  warpGrepTool
});
//# sourceMappingURL=anthropic.cjs.map