"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: 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
    };
    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";
  }
});

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

// tools/warp_grep/gemini.ts
var gemini_exports = {};
__export(gemini_exports, {
  createGitHubReadFileTool: () => createGitHubReadFileTool,
  createGitHubSearchTool: () => createGitHubSearchTool,
  createMorphWarpGrepTool: () => createMorphWarpGrepTool,
  createWarpGrepTool: () => createWarpGrepTool,
  default: () => gemini_default,
  execute: () => execute,
  formatResult: () => formatResult,
  warpGrepFunctionDeclaration: () => warpGrepFunctionDeclaration
});
module.exports = __toCommonJS(gemini_exports);

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

// tools/warp_grep/agent/parser.ts
var VALID_COMMANDS = ["list_directory", "ripgrep", "read", "finish"];
function isValidCommand(name) {
  return VALID_COMMANDS.includes(name);
}
function parseQwen3ToolCalls(text) {
  const tools = [];
  const toolCallRegex = /<tool_call>\s*<function=([a-z_][a-z0-9_]*)>([\s\S]*?)<\/function>\s*<\/tool_call>/gi;
  let match;
  while ((match = toolCallRegex.exec(text)) !== null) {
    const funcName = match[1].toLowerCase();
    const body = match[2];
    if (!isValidCommand(funcName)) continue;
    const params = {};
    const paramRegex = /<parameter=([a-z_][a-z0-9_]*)>([\s\S]*?)<\/parameter>/gi;
    let paramMatch;
    while ((paramMatch = paramRegex.exec(body)) !== null) {
      params[paramMatch[1].toLowerCase()] = paramMatch[2].trim();
    }
    if (funcName === "ripgrep") {
      const pattern = params.pattern;
      if (!pattern) continue;
      const args = {
        pattern,
        path: params.path || ".",
        ...params.glob && { glob: params.glob },
        ...params.context_lines && { context_lines: parseInt(params.context_lines, 10) },
        ...params.case_sensitive && { case_sensitive: params.case_sensitive === "true" }
      };
      tools.push({ name: "grep", arguments: args });
    } else if (funcName === "list_directory") {
      const command = params.command;
      const directPath = params.path;
      let dirPath = directPath || ".";
      if (!directPath && command) {
        const tokens = command.trim().split(/\s+/);
        const pathTokens = tokens.slice(1).filter((t) => !t.startsWith("-") && !t.startsWith("|") && !t.startsWith("\\("));
        if (pathTokens.length > 0) {
          dirPath = pathTokens[0];
        }
      }
      tools.push({ name: "list_directory", arguments: { path: dirPath, pattern: params.pattern || null } });
    } else if (funcName === "read") {
      const filePath = params.path;
      if (!filePath) continue;
      const args = { path: filePath };
      const linesStr = params.lines;
      if (linesStr) {
        const ranges = [];
        for (const rangeStr of linesStr.split(",")) {
          const trimmed = rangeStr.trim();
          if (!trimmed) continue;
          const [s, e] = trimmed.split("-").map((v) => parseInt(v.trim(), 10));
          if (Number.isFinite(s) && Number.isFinite(e)) {
            ranges.push([s, e]);
          } else if (Number.isFinite(s)) {
            ranges.push([s, s]);
          }
        }
        if (ranges.length === 1) {
          args.start = ranges[0][0];
          args.end = ranges[0][1];
        } else if (ranges.length > 1) {
          args.lines = ranges;
        }
      }
      tools.push({ name: "read", arguments: args });
    } else if (funcName === "finish") {
      if (params.result && !params.files) {
        tools.push({ name: "finish", arguments: { files: [], textResult: params.result } });
        continue;
      }
      const filesStr = params.files;
      if (!filesStr) {
        tools.push({ name: "finish", arguments: { files: [], textResult: "No relevant code found." } });
        continue;
      }
      const files = [];
      for (const line of filesStr.split("\n")) {
        const trimmed = line.trim();
        if (!trimmed) continue;
        const colonIdx = trimmed.indexOf(":");
        if (colonIdx === -1) {
          files.push({ path: trimmed, lines: "*" });
        } else {
          const filePath = trimmed.slice(0, colonIdx);
          const rangesPart = trimmed.slice(colonIdx + 1);
          const ranges = [];
          for (const rangeStr of rangesPart.split(",")) {
            const rt = rangeStr.trim();
            if (!rt || rt === "*") {
              files.push({ path: filePath, lines: "*" });
              break;
            }
            const [s, e] = rt.split("-").map((v) => parseInt(v.trim(), 10));
            if (Number.isFinite(s) && Number.isFinite(e)) {
              ranges.push([s, e]);
            } else if (Number.isFinite(s)) {
              ranges.push([s, s]);
            }
          }
          if (ranges.length > 0) {
            files.push({ path: filePath, lines: ranges });
          } else if (!files.some((f) => f.path === filePath)) {
            files.push({ path: filePath, lines: "*" });
          }
        }
      }
      if (files.length > 0) {
        tools.push({ name: "finish", arguments: { files } });
      } else {
        tools.push({ name: "finish", arguments: { files: [], textResult: filesStr } });
      }
    }
  }
  return tools;
}
var LLMResponseParser = class {
  parse(text) {
    if (typeof text !== "string") {
      throw new TypeError("Command text must be a string.");
    }
    const withoutThink = text.replace(/<think>[\s\S]*?<\/think>/gi, "");
    return parseQwen3ToolCalls(withoutThink);
  }
};

// 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();
async function toolListDirectory(provider, args) {
  const maxResults = args.maxResults ?? AGENT_CONFIG.MAX_OUTPUT_LINES;
  const initialDepth = args.maxDepth ?? AGENT_CONFIG.MAX_LIST_DEPTH;
  async function getListRecursive(currentDepth) {
    const entries = await provider.listDirectory({
      path: args.path,
      pattern: args.pattern ?? null,
      maxResults,
      maxDepth: currentDepth
    });
    if (entries.length >= maxResults && currentDepth > 0) {
      return getListRecursive(currentDepth - 1);
    }
    return { entries };
  }
  const { entries: list } = await getListRecursive(initialDepth);
  if (!list.length) return "empty";
  const tree = list.map((e) => {
    const indent = "  ".repeat(e.depth);
    const name = e.type === "dir" ? `${e.name}/` : e.name;
    return `${indent}${name}`;
  }).join("\n");
  return tree;
}

// 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/formatter.ts
var ToolOutputFormatter = class {
  format(toolName, _args, output, options = {}) {
    const name = (toolName ?? "").trim();
    if (!name) {
      return "";
    }
    const payload = output?.toString?.()?.trim?.() ?? "";
    const isError = Boolean(options.isError);
    if (!payload && !isError) {
      return "";
    }
    return `<tool_response>
${payload}
</tool_response>`;
  }
};
var sharedFormatter = new ToolOutputFormatter();
function formatAgentToolOutput(toolName, args, output, options = {}) {
  return sharedFormatter.format(toolName, args, output, options);
}

// tools/warp_grep/agent/helpers.ts
var import_path = __toESM(require("path"), 1);
init_config();
var TRUNCATED_MARKER = "[truncated for context limit]";
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 + m.content.length, 0);
  const maxChars = AGENT_CONFIG.MAX_CONTEXT_CHARS;
  const percent = Math.round(totalChars / maxChars * 100);
  const usedK = Math.round(totalChars / 1e3);
  const maxK = Math.round(maxChars / 1e3);
  return `<context_budget>${percent}% (${usedK}K/${maxK}K chars)</context_budget>`;
}
async function buildInitialState(repoRoot, query, provider, options) {
  const budget = calculateContextBudget([]);
  const turnTag = `Turn 0/${AGENT_CONFIG.MAX_TURNS}`;
  const treeDepth = options?.search_type === "node_modules" ? 1 : 2;
  try {
    const entries = await provider.listDirectory({
      path: ".",
      maxResults: AGENT_CONFIG.MAX_OUTPUT_LINES,
      maxDepth: treeDepth
    });
    const treeLines = entries.map((e) => {
      const indent = "  ".repeat(e.depth);
      const name = e.type === "dir" ? `${e.name}/` : e.name;
      return `${indent}${name}`;
    });
    const repoName = import_path.default.basename(repoRoot);
    const treeOutput = treeLines.length > 0 ? `${repoName}/
${treeLines.join("\n")}` : `${repoName}/`;
    return `<repo_structure>
${treeOutput}
</repo_structure>

<search_string>
${query}
</search_string>
${budget}
${turnTag}`;
  } catch {
    const repoName = import_path.default.basename(repoRoot);
    return `<repo_structure>
${repoName}/
</repo_structure>

<search_string>
${query}
</search_string>
${budget}
${turnTag}`;
  }
}
function enforceContextLimit(messages, maxChars = AGENT_CONFIG.MAX_CONTEXT_CHARS) {
  const getTotalChars = () => messages.reduce((sum, m) => sum + m.content.length, 0);
  if (getTotalChars() <= maxChars) {
    return messages;
  }
  const userIndices = [];
  let firstUserSkipped = false;
  for (let i = 0; i < messages.length; i++) {
    if (messages[i].role === "user") {
      if (!firstUserSkipped) {
        firstUserSkipped = true;
        continue;
      }
      userIndices.push(i);
    }
  }
  for (const idx of userIndices) {
    if (getTotalChars() <= maxChars) {
      break;
    }
    if (messages[idx].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.128",
  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"
    },
    "./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"
    }
  },
  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 --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",
    "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.8"
  },
  devDependencies: {
    "@ai-sdk/anthropic": "^1.0.9",
    "@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_path2 = __toESM(require("path"), 1);
var parser = new LLMResponseParser();
var DEFAULT_API_URL = "https://api.morphllm.com";
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 client = new import_openai.default({
    apiKey,
    baseURL: `${baseUrl}/v1`,
    maxRetries: options.retryConfig?.maxRetries,
    timeout: timeoutMs,
    defaultHeaders: { "X-Morph-SDK-Version": SDK_VERSION }
  });
  const MAX_EMPTY_RETRIES = 1;
  for (let attempt = 0; attempt <= MAX_EMPTY_RETRIES; attempt++) {
    let data;
    try {
      data = await client.chat.completions.create({
        model,
        temperature: 0,
        max_tokens: 1024,
        messages
      });
    } catch (error) {
      if (error instanceof import_openai.default.APIError && 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);
      }
      throw error;
    }
    const choice = data?.choices?.[0];
    const content = choice?.message?.content;
    if (content && typeof content === "string") {
      return content;
    }
    if (attempt === MAX_EMPTY_RETRIES) {
      const finishReason = choice?.finish_reason ?? "unknown";
      const hasToolCalls = Array.isArray(choice?.message?.tool_calls) && choice.message.tool_calls.length > 0;
      const choicesLen = data?.choices?.length ?? 0;
      const contentType = content === null ? "null" : content === void 0 ? "undefined" : typeof content;
      throw new Error(
        `Invalid response from model: content=${contentType}, finish_reason=${finishReason}, has_tool_calls=${hasToolCalls}, choices_length=${choicesLen}`
      );
    }
    await new Promise((resolve) => setTimeout(resolve, 200));
  }
  throw new Error("Invalid response from model");
}
async function runWarpGrep(config) {
  const totalStart = Date.now();
  const timeoutMs = config.timeout ?? AGENT_CONFIG.TIMEOUT_MS;
  const timings = { turns: [], timeout_ms: timeoutMs };
  const repoRoot = import_path2.default.resolve(config.repoRoot || process.cwd());
  const model = config.model || DEFAULT_MODEL;
  const messages = [];
  const maxTurns = AGENT_CONFIG.MAX_TURNS;
  const initialStateStart = Date.now();
  const initialState = await buildInitialState(repoRoot, config.query, config.provider, { search_type: config.search_type });
  timings.initial_state_ms = Date.now() - initialStateStart;
  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 };
    enforceContextLimit(messages);
    const modelCallStart = Date.now();
    const assistantContent = await callModel(messages, model, {
      morphApiKey: config.morphApiKey,
      morphApiUrl: config.morphApiUrl,
      retryConfig: config.retryConfig,
      timeout: timeoutMs
    }).catch((e) => {
      const errMsg = e instanceof Error ? e.message : String(e);
      console.error(`[warp_grep] Morph API call failed on turn ${turn}:`, errMsg);
      errors.push({ message: errMsg });
      return "";
    });
    turnMetrics.morph_api_ms = Date.now() - modelCallStart;
    if (!assistantContent) {
      console.error(`[warp_grep] Empty response from Morph API on turn ${turn}. Errors so far:`, errors);
      timings.turns.push(turnMetrics);
      break;
    }
    messages.push({ role: "assistant", content: assistantContent });
    const toolCalls = parser.parse(assistantContent);
    if (toolCalls.length === 0) {
      console.error(`[warp_grep] No tool calls parsed on turn ${turn}. Assistant content (first 500 chars):`, assistantContent.slice(0, 500));
      errors.push({ message: "No tool calls produced by the model. Your MCP is likely out of date! Update it by running: rm -rf ~/.npm/_npx && npm cache clean --force && npx -y @morphllm/morphmcp@latest" });
      terminationReason = "terminated";
      timings.turns.push(turnMetrics);
      break;
    }
    const finishCalls = toolCalls.filter((c) => c.name === "finish");
    const grepCalls = toolCalls.filter((c) => c.name === "grep");
    const listDirCalls = toolCalls.filter((c) => c.name === "list_directory");
    const readCalls = toolCalls.filter((c) => c.name === "read");
    const skipCalls = toolCalls.filter((c) => c.name === "_skip");
    const formatted = [];
    for (const c of skipCalls) {
      const msg = c.arguments?.message || "Command skipped due to parsing error";
      formatted.push(msg);
    }
    const allPromises = [];
    for (const c of grepCalls) {
      const args = c.arguments ?? {};
      allPromises.push(
        toolGrep(provider, args).then(
          ({ output }) => formatAgentToolOutput("grep", args, output),
          (err) => formatAgentToolOutput("grep", args, String(err), { isError: true })
        )
      );
    }
    for (const c of listDirCalls) {
      const args = c.arguments ?? {};
      allPromises.push(
        toolListDirectory(provider, args).then(
          (p) => formatAgentToolOutput("list_directory", args, p),
          (err) => formatAgentToolOutput("list_directory", args, String(err), { isError: true })
        )
      );
    }
    for (const c of readCalls) {
      const args = c.arguments ?? {};
      allPromises.push(
        toolRead(provider, args).then(
          (p) => formatAgentToolOutput("read", args, p),
          (err) => formatAgentToolOutput("read", args, String(err), { isError: true })
        )
      );
    }
    const toolExecStart = Date.now();
    const allResults = await Promise.all(allPromises);
    turnMetrics.local_tools_ms = Date.now() - toolExecStart;
    for (const result of allResults) {
      formatted.push(result);
    }
    if (formatted.length > 0) {
      const turnMessage = formatTurnMessage(turn, maxTurns);
      const contextBudget = calculateContextBudget(messages);
      messages.push({ role: "user", content: formatted.join("\n") + turnMessage + "\n" + contextBudget });
    }
    timings.turns.push(turnMetrics);
    if (finishCalls.length) {
      const fc = finishCalls[0];
      const files = fc.arguments?.files ?? [];
      const textResult = fc.arguments?.textResult;
      finishMeta = { files };
      terminationReason = "completed";
      if (files.length === 0) {
        const payload2 = textResult || "No relevant code found.";
        timings.turns.push(turnMetrics);
        timings.total_ms = Date.now() - totalStart;
        return {
          terminationReason: "completed",
          messages,
          finish: { payload: payload2, metadata: finishMeta },
          timings
        };
      }
      break;
    }
  }
  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) => {
      try {
        const rr = await provider.read({ path: p, 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: p, error: errorMsg });
        console.error(`[warp_grep] Failed to read file: ${p} - ${errorMsg}`);
        return [`[couldn't find: ${p}]`];
      }
    }
  );
  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* runWarpGrepStreaming(config) {
  const totalStart = Date.now();
  const timeoutMs = config.timeout ?? AGENT_CONFIG.TIMEOUT_MS;
  const timings = { turns: [], timeout_ms: timeoutMs };
  const repoRoot = import_path2.default.resolve(config.repoRoot || process.cwd());
  const model = config.model || DEFAULT_MODEL;
  const messages = [];
  const maxTurns = AGENT_CONFIG.MAX_TURNS;
  const initialStateStart = Date.now();
  const initialState = await buildInitialState(repoRoot, config.query, config.provider, { search_type: config.search_type });
  timings.initial_state_ms = Date.now() - initialStateStart;
  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 };
    enforceContextLimit(messages);
    const modelCallStart = Date.now();
    const assistantContent = await callModel(messages, model, {
      morphApiKey: config.morphApiKey,
      morphApiUrl: config.morphApiUrl,
      retryConfig: config.retryConfig,
      timeout: timeoutMs
    }).catch((e) => {
      const errMsg = e instanceof Error ? e.message : String(e);
      console.error(`[warp_grep:stream] Morph API call failed on turn ${turn}:`, errMsg);
      errors.push({ message: errMsg });
      return "";
    });
    turnMetrics.morph_api_ms = Date.now() - modelCallStart;
    if (!assistantContent) {
      console.error(`[warp_grep:stream] Empty response from Morph API on turn ${turn}. Errors so far:`, errors);
      timings.turns.push(turnMetrics);
      break;
    }
    messages.push({ role: "assistant", content: assistantContent });
    const toolCalls = parser.parse(assistantContent);
    if (toolCalls.length === 0) {
      console.error(`[warp_grep:stream] No tool calls parsed on turn ${turn}. Assistant content (first 500 chars):`, assistantContent.slice(0, 500));
      errors.push({ message: "No tool calls produced by the model. Your MCP is likely out of date! Update it by running: rm -rf ~/.npm/_npx && npm cache clean --force && npx -y @morphllm/morphmcp@latest" });
      terminationReason = "terminated";
      timings.turns.push(turnMetrics);
      break;
    }
    yield {
      turn,
      toolCalls: toolCalls.map((c) => ({
        name: c.name,
        arguments: c.arguments ?? {}
      }))
    };
    const finishCalls = toolCalls.filter((c) => c.name === "finish");
    const grepCalls = toolCalls.filter((c) => c.name === "grep");
    const listDirCalls = toolCalls.filter((c) => c.name === "list_directory");
    const readCalls = toolCalls.filter((c) => c.name === "read");
    const skipCalls = toolCalls.filter((c) => c.name === "_skip");
    const formatted = [];
    for (const c of skipCalls) {
      const msg = c.arguments?.message || "Command skipped due to parsing error";
      formatted.push(msg);
    }
    const allPromises = [];
    for (const c of grepCalls) {
      const args = c.arguments ?? {};
      allPromises.push(
        toolGrep(provider, args).then(
          ({ output }) => formatAgentToolOutput("grep", args, output),
          (err) => formatAgentToolOutput("grep", args, String(err), { isError: true })
        )
      );
    }
    for (const c of listDirCalls) {
      const args = c.arguments ?? {};
      allPromises.push(
        toolListDirectory(provider, args).then(
          (p) => formatAgentToolOutput("list_directory", args, p),
          (err) => formatAgentToolOutput("list_directory", args, String(err), { isError: true })
        )
      );
    }
    for (const c of readCalls) {
      const args = c.arguments ?? {};
      allPromises.push(
        toolRead(provider, args).then(
          (p) => formatAgentToolOutput("read", args, p),
          (err) => formatAgentToolOutput("read", args, String(err), { isError: true })
        )
      );
    }
    const toolExecStart = Date.now();
    const allResults = await Promise.all(allPromises);
    turnMetrics.local_tools_ms = Date.now() - toolExecStart;
    for (const result of allResults) {
      formatted.push(result);
    }
    if (formatted.length > 0) {
      const turnMessage = formatTurnMessage(turn, maxTurns);
      const contextBudget = calculateContextBudget(messages);
      messages.push({ role: "user", content: formatted.join("\n") + turnMessage + "\n" + contextBudget });
    }
    timings.turns.push(turnMetrics);
    if (finishCalls.length) {
      const fc = finishCalls[0];
      const files = fc.arguments?.files ?? [];
      const textResult = fc.arguments?.textResult;
      finishMeta = { files };
      terminationReason = "completed";
      if (files.length === 0) {
        const payload2 = textResult || "No relevant code found.";
        timings.total_ms = Date.now() - totalStart;
        return {
          terminationReason: "completed",
          messages,
          finish: { payload: payload2, metadata: finishMeta },
          timings
        };
      }
      break;
    }
  }
  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) => {
      try {
        const rr = await provider.read({ path: p, 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: p, error: errorMsg });
        console.error(`[warp_grep] Failed to read file: ${p} - ${errorMsg}`);
        return [`[couldn't find: ${p}]`];
      }
    }
  );
  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
  };
}

// 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 [];
    }
  }
};

// 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, path5, glob) => post(`${baseUrl}/api/code-search/${encodedRepoId}/grep`, { pattern, path: path5, glob, branch }, "grep"),
    read: (path5, start, end) => post(`${baseUrl}/api/code-search/${encodedRepoId}/read`, { path: path5, start, end, branch }, "read"),
    listDir: (path5, maxDepth) => post(`${baseUrl}/api/code-search/${encodedRepoId}/list`, { path: path5, 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/warp_grep/client.ts
var DEFAULT_CODE_SEARCH_URL = "https://morphllm.com";
async function getLocalProvider(repoRoot, excludes) {
  const { LocalRipgrepProvider: LocalRipgrepProvider2 } = await Promise.resolve().then(() => (init_local(), local_exports));
  return new LocalRipgrepProvider2(repoRoot, excludes);
}
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
    };
    if (input.streamSteps) {
      return executeToolCallStreaming({ query: input.query }, toolConfig);
    }
    return executeToolCall({ query: input.query }, 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;
    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);
      throw new Error(`Failed to import repo ${owner}/${repo}: ${text}`);
    }
    const { repoId, defaultBranch } = await importRes.json();
    return {
      repo,
      remoteCommands: createCodeStorageHttpCommands({ baseUrl, repoId, branch: input.branch || defaultBranch })
    };
  }
  async _searchGitHubAsync(input) {
    try {
      const { repo, remoteCommands } = await this._resolveGitHubRepo(input);
      return this.execute({
        query: input.query,
        repoRoot: repo,
        remoteCommands
      });
    } catch (error) {
      return { success: false, error: error instanceof Error ? error.message : String(error) };
    }
  }
  async *_searchGitHubStreaming(input) {
    let repo;
    let remoteCommands;
    try {
      ({ repo, remoteCommands } = await this._resolveGitHubRepo(input));
    } catch (error) {
      return { success: false, error: error instanceof Error ? error.message : String(error) };
    }
    const generator = this.execute({
      query: input.query,
      repoRoot: repo,
      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 provider = config.remoteCommands ? new RemoteCommandsProvider(config.repoRoot, config.remoteCommands) : config.provider ?? await getLocalProvider(config.repoRoot, config.excludes);
  const result = await runWarpGrep({
    query: parsed.query,
    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
  });
  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] executeToolCall 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
  }));
  return { success: true, contexts, summary: finish.payload };
}
function processAgentResult(result) {
  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
  }));
  return { success: true, contexts, summary: finish.payload };
}
async function* executeToolCallStreaming(input, config) {
  const parsed = typeof input === "string" ? JSON.parse(input) : input;
  const provider = config.remoteCommands ? new RemoteCommandsProvider(config.repoRoot, config.remoteCommands) : config.provider ?? await getLocalProvider(config.repoRoot, config.excludes);
  const generator = runWarpGrepStreaming({
    query: parsed.query,
    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
  });
  let agentResult;
  for (; ; ) {
    const { value, done } = await generator.next();
    if (done) {
      agentResult = value;
      break;
    }
    yield value;
  }
  return processAgentResult(agentResult);
}
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 query.";
  }
  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 = "warpgrep_codebase_search";
var WARP_GREP_DESCRIPTION = 'IMPORTANT: If you need to explore the codebase to gather context, and the task does not involve a single file or function which is provided by name, you should ALWAYS use the warpgrep codebase search tool first instead of running search commands. When the task requires exploration beyond a single known file, invoke warpgrep first with a natural-language query describing the target functionality, bug, or architectural concern. Warp Grep is a fast and accurate tool that can search for all relevant context in a codebase. Keep queries action-oriented (e.g., "Find where billing invoices are generated and emailed"), and after reviewing the summarized results, you may verify important findings with other search tools or direct file reads to ensure completeness. Warp Grep can be used for query types like: find function responsible for <small feature>; find code that does <description>; find code path for <big feature>; Where does <minimal error message> come from?; or any query of that type. When a task requires exploration beyond a single known file, ALWAYS default to warpgrep codebase search before other search mechanisms.';
var GITHUB_WARP_GREP_SEARCH_TOOL_NAME = "warpgrep_github_search";
var GITHUB_WARP_GREP_SEARCH_DESCRIPTION = 'IMPORTANT: If you need to explore the codebase of a public GitHub repository (not your local workspace), use warpgrep_github_search instead of warpgrep_codebase_search. ONLY use this tool when the task requires understanding code in an external repo, and invoke warpgrep_github_search with a natural-language query describing the target functionality, bug, or architectural concern. DO NOT use this tool when the task requires understanding code in your local workspace. Use warpgrep_codebase_search instead.Useful when you suspect a library or framework is being used in a way that is not documented, or if you suspect an update or a bug in the library or framework.WarpGrep searches GitHub repos the same way it searches local codebases: fast and accurate. Keep queries action-oriented (e.g., "Find where how the new use workflow directive works"), and after reviewing the results, you may verify important findings with other tools or direct file reads. WarpGrep can be used for query types like: find function responsible for <small feature>; find code that does <description>; find code path for <big feature>; Where does <minimal error message> come from?; or any query of that type. When a task involves exploring code in an external public repo, ALWAYS use warpgrep_github_search. You must provide either a github_url or owner_repo parameter (at least one is required).';
var GITHUB_SEARCH_TOOL_NAME = GITHUB_WARP_GREP_SEARCH_TOOL_NAME;
var GITHUB_SEARCH_DESCRIPTION = GITHUB_WARP_GREP_SEARCH_DESCRIPTION;
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 warpgrep_github_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.";

// tools/warp_grep/gemini.ts
var TOOL_PARAMETERS = {
  type: "OBJECT",
  properties: {
    query: {
      type: "STRING",
      description: "Free-form repository question"
    }
  },
  required: ["query"]
};
var warpGrepFunctionDeclaration = {
  name: WARP_GREP_TOOL_NAME,
  description: WARP_GREP_DESCRIPTION,
  parameters: TOOL_PARAMETERS
};
async function execute(input, config) {
  return executeToolCall(input, config);
}
function createWarpGrepTool(config) {
  const declaration = {
    name: config.name ?? WARP_GREP_TOOL_NAME,
    description: config.description ?? WARP_GREP_DESCRIPTION,
    parameters: TOOL_PARAMETERS
  };
  return Object.assign(declaration, {
    execute: async (input) => {
      return executeToolCall(input, config);
    },
    formatResult: (result) => {
      return formatResult(result);
    }
  });
}
var createMorphWarpGrepTool = createWarpGrepTool;
var GITHUB_SEARCH_PARAMETERS = {
  type: "OBJECT",
  properties: {
    query: { type: "STRING", description: "Natural language search query" },
    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 repo default branch)" }
  },
  required: ["query"]
};
function createGitHubSearchTool(config) {
  const client = new WarpGrepClient(config);
  const declaration = {
    name: GITHUB_SEARCH_TOOL_NAME,
    description: GITHUB_SEARCH_DESCRIPTION,
    parameters: GITHUB_SEARCH_PARAMETERS
  };
  return Object.assign(declaration, {
    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({ query: input.query, github, branch: input.branch });
    },
    formatResult: (result) => {
      return formatResult(result);
    }
  });
}
var GITHUB_READ_FILE_PARAMETERS = {
  type: "OBJECT",
  properties: {
    github: { type: "STRING", description: 'owner/repo shorthand (e.g., "vercel/next.js")' },
    path: { type: "STRING", description: "File path within the repository" },
    startLine: { type: "NUMBER", description: "Start line number (1-based)" },
    endLine: { type: "NUMBER", description: "End line number (1-based, inclusive)" },
    branch: { type: "STRING", description: "Branch to read from (defaults to repo default branch)" }
  },
  required: ["github", "path"]
};
function createGitHubReadFileTool(config) {
  const declaration = {
    name: GITHUB_READ_FILE_TOOL_NAME,
    description: GITHUB_READ_FILE_DESCRIPTION,
    parameters: GITHUB_READ_FILE_PARAMETERS
  };
  return Object.assign(declaration, {
    execute: async (input) => {
      return executeGitHubReadFile(input, config);
    },
    formatResult: (result) => {
      return formatGitHubReadFileResult(result);
    }
  });
}
var gemini_default = warpGrepFunctionDeclaration;
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  createGitHubReadFileTool,
  createGitHubSearchTool,
  createMorphWarpGrepTool,
  createWarpGrepTool,
  execute,
  formatResult,
  warpGrepFunctionDeclaration
});
//# sourceMappingURL=gemini.cjs.map