import {
  parseGitHubUrl
} from "./chunk-63VHBANJ.js";
import {
  runWarpGrep,
  runWarpGrepStreaming
} from "./chunk-TURYLQJ3.js";
import {
  createCodeStorageHttpCommands
} from "./chunk-GVGJIXV2.js";
import {
  RemoteCommandsProvider
} from "./chunk-B3AKP3RA.js";
import {
  compactFileContexts
} from "./chunk-GLQWEINZ.js";
import {
  logger
} from "./chunk-F3NCFNUX.js";

// tools/warp_grep/client.ts
var DEFAULT_CODE_SEARCH_URL = "https://morphllm.com";
async function getLocalProvider(repoRoot, excludes, allowNames) {
  const { LocalRipgrepProvider } = await import("./tools/warp_grep/providers/local.js");
  const opts = allowNames?.length ? { allowNames } : void 0;
  return new LocalRipgrepProvider(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;
  }
};
function executeWarpGrep(input, config) {
  const client = new WarpGrepClient(config);
  if (input.streamSteps) {
    return client.execute({ ...input, streamSteps: true });
  }
  return client.execute({ ...input, streamSteps: false });
}
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");
}

export {
  WarpGrepClient,
  executeWarpGrep,
  executeToolCall,
  executeToolCallStreaming,
  executeGitHubReadFile,
  formatGitHubReadFileResult,
  formatResult
};
//# sourceMappingURL=chunk-75F5XTPD.js.map