"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// tools/fastapply/core.ts
var core_exports = {};
__export(core_exports, {
  FastApplyClient: () => FastApplyClient,
  applyEdit: () => applyEdit,
  countChanges: () => countChanges,
  executeEditFile: () => executeEditFile,
  generateUdiff: () => generateUdiff
});
module.exports = __toCommonJS(core_exports);
var import_promises = require("fs/promises");
var import_path = require("path");
var import_diff = require("diff");

// tools/utils/resilience.ts
var DEFAULT_RETRY_CONFIG = {
  maxRetries: 3,
  initialDelay: 1e3,
  maxDelay: 3e4,
  backoffMultiplier: 2,
  retryableErrors: ["ECONNREFUSED", "ETIMEDOUT", "ENOTFOUND"]
};
async function fetchWithRetry(url, options, retryConfig = {}) {
  const {
    maxRetries = DEFAULT_RETRY_CONFIG.maxRetries,
    initialDelay = DEFAULT_RETRY_CONFIG.initialDelay,
    maxDelay = DEFAULT_RETRY_CONFIG.maxDelay,
    backoffMultiplier = DEFAULT_RETRY_CONFIG.backoffMultiplier,
    retryableErrors = DEFAULT_RETRY_CONFIG.retryableErrors,
    onRetry
  } = retryConfig;
  let lastError = null;
  let delay = initialDelay;
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
      const response = await fetch(url, options);
      if (response.status === 429 || response.status === 503) {
        if (attempt < maxRetries) {
          const retryAfter = response.headers.get("Retry-After");
          const waitTime = retryAfter ? parseInt(retryAfter) * 1e3 : Math.min(delay, maxDelay);
          const error = new Error(`HTTP ${response.status}: Retrying after ${waitTime}ms`);
          if (onRetry) {
            onRetry(attempt + 1, error);
          }
          await sleep(waitTime);
          delay *= backoffMultiplier;
          continue;
        }
      }
      return response;
    } catch (error) {
      lastError = error;
      const isRetryable = retryableErrors.some(
        (errType) => lastError?.message?.includes(errType)
      );
      if (!isRetryable || attempt === maxRetries) {
        throw lastError;
      }
      const waitTime = Math.min(delay, maxDelay);
      if (onRetry) {
        onRetry(attempt + 1, lastError);
      }
      await sleep(waitTime);
      delay *= backoffMultiplier;
    }
  }
  throw lastError || new Error("Max retries exceeded");
}
async function withTimeout(promise, timeoutMs, errorMessage) {
  let timeoutId;
  const timeoutPromise = new Promise((_, reject) => {
    timeoutId = setTimeout(() => {
      reject(new Error(errorMessage || `Operation timed out after ${timeoutMs}ms`));
    }, timeoutMs);
  });
  try {
    const result = await Promise.race([promise, timeoutPromise]);
    clearTimeout(timeoutId);
    return result;
  } catch (error) {
    clearTimeout(timeoutId);
    throw error;
  }
}
function sleep(ms) {
  return new Promise((resolve2) => setTimeout(resolve2, ms));
}

// tools/fastapply/core.ts
var DEFAULT_CONFIG = {
  morphApiUrl: "https://api.morphllm.com",
  baseDir: process.cwd(),
  generateUdiff: true,
  autoWrite: true,
  timeout: 3e4,
  debug: false
};
var FastApplyClient = class {
  config;
  constructor(config = {}) {
    this.config = {
      morphApiKey: config.apiKey,
      morphApiUrl: DEFAULT_CONFIG.morphApiUrl,
      debug: config.debug,
      timeout: config.timeout || DEFAULT_CONFIG.timeout,
      retryConfig: config.retryConfig,
      generateUdiff: DEFAULT_CONFIG.generateUdiff,
      autoWrite: DEFAULT_CONFIG.autoWrite
    };
  }
  /**
   * Execute a file edit operation
   * 
   * @param input - Edit parameters including filepath, instructions, and code_edit
   * @param overrides - Optional config overrides for this operation
   * @returns Edit result with success status and changes
   */
  async execute(input, overrides) {
    return executeEditFile(input, { ...this.config, ...overrides });
  }
  /**
   * Apply an edit to code directly without file I/O
   * 
   * Useful for sandbox environments or when you manage your own file system.
   * Compatible with the earlier OpenAI client API contract.
   * 
   * @param input - Code and edit parameters
   * @param overrides - Optional config overrides for this operation
   * @returns Result with merged code
   * 
   * @example
   * ```typescript
   * const result = await client.applyEdit({
   *   originalCode: 'function hello() { return "world"; }',
   *   codeEdit: 'function hello() { return "universe"; }',
   *   instructions: 'Change return value'
   * });
   * console.log(result.mergedCode);
   * ```
   */
  async applyEdit(input, overrides) {
    return applyEdit(input, { ...this.config, ...overrides });
  }
};
function generateUdiff(original, modified, filepath) {
  return (0, import_diff.createTwoFilesPatch)(
    filepath,
    filepath,
    original,
    modified,
    "Original",
    "Modified"
  );
}
function countChanges(original, modified) {
  const diff = generateUdiff(original, modified, "file");
  const lines = diff.split("\n");
  let linesAdded = 0;
  let linesRemoved = 0;
  for (const line of lines) {
    if (line.startsWith("+") && !line.startsWith("+++")) {
      linesAdded++;
    } else if (line.startsWith("-") && !line.startsWith("---")) {
      linesRemoved++;
    }
  }
  const linesModified = Math.min(linesAdded, linesRemoved);
  return {
    linesAdded: linesAdded - linesModified,
    linesRemoved: linesRemoved - linesModified,
    linesModified
  };
}
async function callMorphAPI(originalCode, codeEdit, instructions, filepath, config) {
  const apiKey = config.morphApiKey || process.env.MORPH_API_KEY;
  const apiUrl = config.morphApiUrl || DEFAULT_CONFIG.morphApiUrl;
  const timeout = config.timeout || DEFAULT_CONFIG.timeout;
  const debug = 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 message = `<instruction>${instructions}</instruction>
<code>${originalCode}</code>
<update>${codeEdit}</update>`;
  if (debug) {
    console.log(`[FastApply] Calling ${apiUrl}/v1/chat/completions`);
    console.log(`[FastApply] File: ${filepath}, Instructions: ${instructions.slice(0, 60)}...`);
    console.log(`[FastApply] Original: ${originalCode.length} chars, Edit: ${codeEdit.length} chars`);
  }
  const startTime = Date.now();
  const fetchPromise = fetchWithRetry(
    `${apiUrl}/v1/chat/completions`,
    {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "Authorization": `Bearer ${apiKey}`
      },
      body: JSON.stringify({
        model: "morph-v3-fast",
        messages: [{ role: "user", content: message }]
      })
    },
    config.retryConfig
  );
  const response = await withTimeout(
    fetchPromise,
    timeout,
    `Morph API request timed out after ${timeout}ms`
  );
  if (!response.ok) {
    const error = await response.text();
    if (debug) console.error(`[FastApply] API error: ${response.status} - ${error}`);
    throw new Error(`Morph API error (${response.status}): ${error}`);
  }
  const data = await response.json();
  const elapsed = Date.now() - startTime;
  if (debug) {
    console.log(`[FastApply] \u2705 Success in ${elapsed}ms, merged: ${data.choices[0].message.content.length} chars`);
  }
  return data.choices[0].message.content;
}
async function executeEditFile(input, config = {}) {
  const baseDir = config.baseDir || DEFAULT_CONFIG.baseDir;
  const fullPath = (0, import_path.resolve)((0, import_path.join)(baseDir, input.target_filepath));
  const debug = config.debug || false;
  const relativePath = (0, import_path.relative)(baseDir, fullPath);
  if (relativePath.startsWith("..") || fullPath === baseDir) {
    return {
      success: false,
      filepath: input.target_filepath,
      changes: { linesAdded: 0, linesRemoved: 0, linesModified: 0 },
      error: `Invalid filepath: '${input.target_filepath}' is outside baseDir`
    };
  }
  try {
    if (debug) console.log(`[FastApply] Reading file: ${input.target_filepath}`);
    let originalCode = "";
    try {
      originalCode = await (0, import_promises.readFile)(fullPath, "utf-8");
    } catch (error) {
      if (error.code !== "ENOENT") {
        throw error;
      }
      if (debug) console.log(`[FastApply] File doesn't exist, will create new file`);
    }
    const mergedCode = await callMorphAPI(originalCode, input.code_edit, input.instructions, input.target_filepath, config);
    const udiff = config.generateUdiff !== false ? generateUdiff(originalCode, mergedCode, input.target_filepath) : void 0;
    if (config.autoWrite !== false) {
      await (0, import_promises.writeFile)(fullPath, mergedCode, "utf-8");
      if (debug) console.log(`[FastApply] Wrote ${mergedCode.length} chars to ${input.target_filepath}`);
    }
    const changes = countChanges(originalCode, mergedCode);
    return {
      success: true,
      filepath: input.target_filepath,
      udiff,
      changes
    };
  } catch (error) {
    const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
    if (debug) console.error(`[FastApply] Error: ${errorMessage}`);
    return {
      success: false,
      filepath: input.target_filepath,
      changes: { linesAdded: 0, linesRemoved: 0, linesModified: 0 },
      error: errorMessage
    };
  }
}
async function applyEdit(input, config = {}) {
  const debug = config.debug || false;
  const filepath = input.filepath || "file";
  try {
    if (debug) {
      console.log(`[FastApply] Applying edit to code (${input.originalCode.length} chars)`);
    }
    const mergedCode = await callMorphAPI(
      input.originalCode,
      input.codeEdit,
      input.instructions,
      filepath,
      config
    );
    const udiff = config.generateUdiff !== false ? generateUdiff(input.originalCode, mergedCode, filepath) : void 0;
    const changes = countChanges(input.originalCode, mergedCode);
    return {
      success: true,
      mergedCode,
      udiff,
      changes
    };
  } catch (error) {
    const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
    if (debug) console.error(`[FastApply] Error: ${errorMessage}`);
    return {
      success: false,
      changes: { linesAdded: 0, linesRemoved: 0, linesModified: 0 },
      error: errorMessage
    };
  }
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  FastApplyClient,
  applyEdit,
  countChanges,
  executeEditFile,
  generateUdiff
});
//# sourceMappingURL=core.cjs.map