"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/browser/profiles/index.ts
var profiles_exports = {};
__export(profiles_exports, {
  ProfilesClient: () => ProfilesClient,
  createProfile: () => createProfile,
  deleteProfile: () => deleteProfile,
  getProfile: () => getProfile,
  getProfileState: () => getProfileState,
  listProfiles: () => listProfiles,
  listRepos: () => listRepos,
  saveProfileSession: () => saveProfileSession,
  startProfileSession: () => startProfileSession,
  updateProfile: () => updateProfile
});
module.exports = __toCommonJS(profiles_exports);

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

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

// tools/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;
  options = { ...options, headers: { "X-Morph-SDK-Version": SDK_VERSION, ...options.headers } };
  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");
}
function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

// tools/browser/errors.ts
var MorphError = class extends Error {
  /** Error code for programmatic handling */
  code;
  /** Original cause of the error, if any */
  cause;
  constructor(message, code, cause) {
    super(message);
    this.name = "MorphError";
    this.code = code;
    this.cause = cause;
    if (Error.captureStackTrace) {
      Error.captureStackTrace(this, this.constructor);
    }
  }
  /**
   * Returns a JSON representation of the error for logging.
   */
  toJSON() {
    return {
      name: this.name,
      message: this.message,
      code: this.code,
      cause: this.cause?.message
    };
  }
};
var MorphValidationError = class extends MorphError {
  /** The field that failed validation */
  field;
  constructor(message, field) {
    super(message, "validation_error");
    this.name = "MorphValidationError";
    this.field = field;
  }
  toJSON() {
    return {
      ...super.toJSON(),
      field: this.field
    };
  }
};
var MorphAPIError = class extends MorphError {
  /** HTTP status code */
  statusCode;
  /** Request ID for debugging (if available) */
  requestId;
  /** Raw response body */
  rawResponse;
  constructor(message, code, statusCode, options) {
    super(message, code, options?.cause);
    this.name = "MorphAPIError";
    this.statusCode = statusCode;
    this.requestId = options?.requestId;
    this.rawResponse = options?.rawResponse;
  }
  toJSON() {
    return {
      ...super.toJSON(),
      statusCode: this.statusCode,
      requestId: this.requestId
    };
  }
};
var MorphAuthenticationError = class extends MorphAPIError {
  constructor(message = "Authentication required. Please provide a valid API key.") {
    super(message, "authentication_required", 401);
    this.name = "MorphAuthenticationError";
  }
};
var MorphRateLimitError = class extends MorphAPIError {
  /** When the rate limit resets (Unix timestamp) */
  resetAt;
  /** Number of seconds until reset */
  retryAfter;
  constructor(message = "Rate limit exceeded. Please retry later.", options) {
    super(message, "rate_limit_exceeded", 429, { requestId: options?.requestId });
    this.name = "MorphRateLimitError";
    this.resetAt = options?.resetAt;
    this.retryAfter = options?.retryAfter;
  }
  toJSON() {
    return {
      ...super.toJSON(),
      resetAt: this.resetAt,
      retryAfter: this.retryAfter
    };
  }
};
var MorphNotFoundError = class extends MorphAPIError {
  /** The type of resource that was not found */
  resourceType;
  /** The ID of the resource that was not found */
  resourceId;
  constructor(resourceType, resourceId) {
    const message = resourceId ? `${resourceType} '${resourceId}' not found` : `${resourceType} not found`;
    super(message, "resource_not_found", 404);
    this.name = "MorphNotFoundError";
    this.resourceType = resourceType;
    this.resourceId = resourceId;
  }
  toJSON() {
    return {
      ...super.toJSON(),
      resourceType: this.resourceType,
      resourceId: this.resourceId
    };
  }
};
var MorphProfileLimitError = class extends MorphAPIError {
  /** Current number of profiles */
  currentCount;
  /** Maximum allowed profiles for the plan */
  maxAllowed;
  constructor(message = "Profile limit exceeded for your plan.", options) {
    super(message, "profile_limit_exceeded", 403, { requestId: options?.requestId });
    this.name = "MorphProfileLimitError";
    this.currentCount = options?.currentCount;
    this.maxAllowed = options?.maxAllowed;
  }
  toJSON() {
    return {
      ...super.toJSON(),
      currentCount: this.currentCount,
      maxAllowed: this.maxAllowed
    };
  }
};
function parseAPIError(statusCode, responseText, requestId) {
  let errorData = {};
  try {
    errorData = JSON.parse(responseText);
  } catch {
  }
  const message = errorData.detail || errorData.message || responseText || "Unknown error";
  const code = errorData.code;
  switch (statusCode) {
    case 401:
      return new MorphAuthenticationError(message);
    case 403:
      if (code === "profile_limit_exceeded" || message.toLowerCase().includes("limit")) {
        return new MorphProfileLimitError(message, { requestId });
      }
      return new MorphAPIError(message, "insufficient_permissions", statusCode, { requestId, rawResponse: responseText });
    case 404:
      if (message.toLowerCase().includes("profile")) {
        return new MorphNotFoundError("Profile", void 0);
      }
      if (message.toLowerCase().includes("session")) {
        return new MorphNotFoundError("Session", void 0);
      }
      return new MorphAPIError(message, "resource_not_found", statusCode, { requestId, rawResponse: responseText });
    case 429:
      return new MorphRateLimitError(message, { requestId });
    case 422:
      return new MorphAPIError(message, "validation_error", statusCode, { requestId, rawResponse: responseText });
    case 500:
    case 502:
    case 503:
    case 504:
      return new MorphAPIError(message, "service_unavailable", statusCode, { requestId, rawResponse: responseText });
    default:
      return new MorphAPIError(message, "network_error", statusCode, { requestId, rawResponse: responseText });
  }
}

// tools/browser/profiles/types.ts
function transformProfile(api) {
  return {
    id: api.id,
    name: api.name,
    repoId: api.repo_id,
    cookieDomains: api.cookie_domains,
    lastUsedAt: api.last_used_at,
    createdAt: api.created_at,
    updatedAt: api.updated_at
  };
}
function transformCreateInput(input) {
  return {
    name: input.name,
    repo_id: input.repoId
  };
}
function transformSession(api) {
  return {
    sessionId: api.session_id,
    debugUrl: api.debug_url || ""
  };
}
function transformSaveInput(input) {
  return {
    session_id: input.sessionId,
    profile_id: input.profileId
  };
}
function transformStateResponse(api) {
  return {
    profileId: api.profile_id,
    stateUrl: api.state_url,
    expiresIn: api.expires_in
  };
}

// tools/browser/profiles/core.ts
var DEFAULT_API_URL = process.env.MORPH_ENVIRONMENT === "DEV" ? "http://localhost:8000" : "https://browser.morphllm.com";
var ProfilesClient = class {
  config;
  constructor(config) {
    this.config = config;
  }
  /**
    * Create a new browser profile and immediately start a live session.
    *
    * @param input - Profile creation parameters
    * @returns Profile setup handle with live URL + save()
    * @throws {MorphValidationError} If input validation fails
    * @throws {MorphProfileLimitError} If profile limit is exceeded
    * @throws {MorphAuthenticationError} If API key is missing or invalid
    *
    * @example
    * ```typescript
  * const setup = await morph.browser.profiles.createProfile({
  *   name: 'LinkedIn Production',
  *   repoId: 'owner/repo'
  * });
  * console.log(setup.session.debugUrl);
  * await setup.save();
    * ```
    */
  async createProfile(input) {
    return createProfile(input, this.config);
  }
  /**
   * List all profiles for the authenticated user.
   *
   * @param repoId - Optional repository ID to filter by
   * @returns Array of profiles
   *
   * @example
   * ```typescript
   * // List all profiles
   * const allProfiles = await morph.browser.profiles.listProfiles();
   *
   * // List profiles for a specific repo
   * const repoProfiles = await morph.browser.profiles.listProfiles('owner/repo');
   * ```
   */
  async listProfiles(repoId) {
    return listProfiles(this.config, repoId);
  }
  /**
   * Get a profile by ID with convenience methods.
   *
   * @param id - Profile ID
   * @returns Profile with attached methods
   * @throws {MorphNotFoundError} If profile is not found
   *
   * @example
   * ```typescript
   * const profile = await morph.browser.profiles.getProfile('profile-id');
   * const state = await profile.getState();
   * await profile.delete();
   * ```
   */
  async getProfile(id) {
    return getProfile(id, this.config);
  }
  /**
   * Update a profile by opening a live session (no rename).
   *
   * @param id - Profile ID
   * @returns Profile setup handle with live URL + save()
   */
  async updateProfile(id) {
    return updateProfile(id, this.config);
  }
  /**
   * Delete a profile.
   *
   * @param id - Profile ID
   * @throws {MorphNotFoundError} If profile is not found
   */
  async deleteProfile(id) {
    return deleteProfile(id, this.config);
  }
  /**
   * Start a browser session for profile setup.
   *
   * Returns a live URL where the user can sign into accounts.
   * After signing in, call `saveSession` to persist the state.
   *
   * @param input - Optional session parameters
   * @returns Session with debug URL
   *
   * @example
   * ```typescript
   * const session = await morph.browser.profiles.startSession();
   * console.log('Sign in at:', session.debugUrl);
   * // Open debugUrl in browser, user signs in...
   * await morph.browser.profiles.saveSession(session.sessionId, profile.id);
   * ```
   */
  async startSession(input) {
    return startProfileSession(this.config, input);
  }
  /**
   * Save browser state from a session to a profile.
   *
   * Call this after the user is done signing into accounts.
   * Extracts cookies, localStorage, and sessionStorage.
   *
   * @param sessionId - Browser session ID from startSession
   * @param profileId - Profile ID to save state to
   * @returns Updated profile with cookie domains
   */
  async saveSession(sessionId, profileId) {
    return saveProfileSession({ sessionId, profileId }, this.config);
  }
  /**
   * List available repo IDs (discovery).
   *
   * @returns Repo summaries with profile counts
   */
  async listRepos() {
    return listRepos(this.config);
  }
  /**
   * Get the presigned URL for a profile's state.
   *
   * Use this to download the raw state JSON for debugging
   * or to restore state manually.
   *
   * @param profileId - Profile ID
   * @returns State URL with expiry information
   */
  async getProfileState(profileId) {
    return getProfileState(profileId, this.config);
  }
};
function validateCreateInput(input) {
  if (!input.name || typeof input.name !== "string") {
    throw new MorphValidationError("name is required", "name");
  }
  const trimmedName = input.name.trim();
  if (trimmedName.length === 0) {
    throw new MorphValidationError("name cannot be empty", "name");
  }
  if (trimmedName.length > 100) {
    throw new MorphValidationError("name must be 100 characters or less", "name");
  }
  if (!input.repoId || typeof input.repoId !== "string") {
    throw new MorphValidationError("repoId is required", "repoId");
  }
  if (input.repoId.trim().length === 0) {
    throw new MorphValidationError("repoId cannot be empty", "repoId");
  }
}
function validateId(id, fieldName) {
  if (!id || typeof id !== "string") {
    throw new MorphValidationError(`${fieldName} is required`, fieldName);
  }
  if (id.trim().length === 0) {
    throw new MorphValidationError(`${fieldName} cannot be empty`, fieldName);
  }
}
async function createProfile(input, config = {}) {
  validateCreateInput(input);
  const apiUrl = config.apiUrl || DEFAULT_API_URL;
  const headers = buildHeaders(config);
  const response = await fetchWithRetry(
    `${apiUrl}/profiles`,
    {
      method: "POST",
      headers,
      body: JSON.stringify(transformCreateInput(input))
    },
    config.retryConfig
  );
  if (!response.ok) {
    const errorText = await response.text().catch(() => response.statusText);
    const requestId = response.headers.get("x-request-id") || void 0;
    throw parseAPIError(response.status, errorText, requestId);
  }
  const apiProfile = await response.json();
  const profile = transformProfile(apiProfile);
  const session = await startProfileSession(config, { profileId: profile.id });
  return buildProfileSetup(profile, session, config);
}
async function listProfiles(config = {}, repoId) {
  const apiUrl = config.apiUrl || DEFAULT_API_URL;
  const headers = buildHeaders(config);
  const url = repoId ? `${apiUrl}/profiles?repo_id=${encodeURIComponent(repoId)}` : `${apiUrl}/profiles`;
  const response = await fetchWithRetry(
    url,
    { method: "GET", headers },
    config.retryConfig
  );
  if (!response.ok) {
    const errorText = await response.text().catch(() => response.statusText);
    const requestId = response.headers.get("x-request-id") || void 0;
    throw parseAPIError(response.status, errorText, requestId);
  }
  const data = await response.json();
  return data.profiles.map(transformProfile);
}
async function getProfile(id, config = {}) {
  validateId(id, "id");
  const apiUrl = config.apiUrl || DEFAULT_API_URL;
  const headers = buildHeaders(config);
  const response = await fetchWithRetry(
    `${apiUrl}/profiles/${encodeURIComponent(id)}`,
    { method: "GET", headers },
    config.retryConfig
  );
  if (!response.ok) {
    const errorText = await response.text().catch(() => response.statusText);
    const requestId = response.headers.get("x-request-id") || void 0;
    throw parseAPIError(response.status, errorText, requestId);
  }
  const apiProfile = await response.json();
  const profile = transformProfile(apiProfile);
  return {
    ...profile,
    getState: () => getProfileState(id, config),
    delete: () => deleteProfile(id, config)
  };
}
async function updateProfile(id, config = {}) {
  validateId(id, "id");
  const profile = await fetchProfile(id, config);
  const session = await startProfileSession(config, { profileId: profile.id });
  return buildProfileSetup(profile, session, config);
}
async function deleteProfile(id, config = {}) {
  validateId(id, "id");
  const apiUrl = config.apiUrl || DEFAULT_API_URL;
  const headers = buildHeaders(config);
  const response = await fetchWithRetry(
    `${apiUrl}/profiles/${encodeURIComponent(id)}`,
    { method: "DELETE", headers },
    config.retryConfig
  );
  if (!response.ok) {
    const errorText = await response.text().catch(() => response.statusText);
    const requestId = response.headers.get("x-request-id") || void 0;
    throw parseAPIError(response.status, errorText, requestId);
  }
}
async function startProfileSession(config = {}, input) {
  if (!config.apiKey) {
    throw new MorphAuthenticationError();
  }
  const apiUrl = config.apiUrl || DEFAULT_API_URL;
  const headers = buildHeaders(config);
  const body = input?.profileId ? { profile_id: input.profileId } : {};
  const response = await fetchWithRetry(
    `${apiUrl}/profiles/session/start`,
    {
      method: "POST",
      headers,
      body: JSON.stringify(body)
    },
    config.retryConfig
  );
  if (!response.ok) {
    const errorText = await response.text().catch(() => response.statusText);
    const requestId = response.headers.get("x-request-id") || void 0;
    throw parseAPIError(response.status, errorText, requestId);
  }
  const apiSession = await response.json();
  return transformSession(apiSession);
}
async function saveProfileSession(input, config = {}) {
  validateId(input.sessionId, "sessionId");
  validateId(input.profileId, "profileId");
  const apiUrl = config.apiUrl || DEFAULT_API_URL;
  const headers = buildHeaders(config);
  const response = await fetchWithRetry(
    `${apiUrl}/profiles/session/save`,
    {
      method: "POST",
      headers,
      body: JSON.stringify(transformSaveInput(input))
    },
    config.retryConfig
  );
  if (!response.ok) {
    const errorText = await response.text().catch(() => response.statusText);
    const requestId = response.headers.get("x-request-id") || void 0;
    throw parseAPIError(response.status, errorText, requestId);
  }
  const apiProfile = await response.json();
  return transformProfile(apiProfile);
}
async function listRepos(config = {}) {
  const apiUrl = config.apiUrl || DEFAULT_API_URL;
  const headers = buildHeaders(config);
  const response = await fetchWithRetry(
    `${apiUrl}/repos`,
    { method: "GET", headers },
    config.retryConfig
  );
  if (!response.ok) {
    const errorText = await response.text().catch(() => response.statusText);
    const requestId = response.headers.get("x-request-id") || void 0;
    throw parseAPIError(response.status, errorText, requestId);
  }
  const data = await response.json();
  const repos = Array.isArray(data?.repos) ? data.repos : [];
  return repos.map((repo) => ({
    repoId: repo.repo_id,
    repoFullName: repo.repo_full_name,
    profileCount: repo.profile_count ?? 0
  }));
}
async function getProfileState(profileId, config = {}) {
  validateId(profileId, "profileId");
  const apiUrl = config.apiUrl || DEFAULT_API_URL;
  const headers = buildHeaders(config);
  const response = await fetchWithRetry(
    `${apiUrl}/profiles/${encodeURIComponent(profileId)}/state`,
    { method: "GET", headers },
    config.retryConfig
  );
  if (!response.ok) {
    const errorText = await response.text().catch(() => response.statusText);
    const requestId = response.headers.get("x-request-id") || void 0;
    throw parseAPIError(response.status, errorText, requestId);
  }
  const apiState = await response.json();
  return transformStateResponse(apiState);
}
function buildHeaders(config) {
  const headers = { "Content-Type": "application/json" };
  if (config.apiKey) {
    headers["Authorization"] = `Bearer ${config.apiKey}`;
  }
  return headers;
}
async function fetchProfile(id, config) {
  const apiUrl = config.apiUrl || DEFAULT_API_URL;
  const headers = buildHeaders(config);
  const response = await fetchWithRetry(
    `${apiUrl}/profiles/${encodeURIComponent(id)}`,
    { method: "GET", headers },
    config.retryConfig
  );
  if (!response.ok) {
    const errorText = await response.text().catch(() => response.statusText);
    const requestId = response.headers.get("x-request-id") || void 0;
    throw parseAPIError(response.status, errorText, requestId);
  }
  const apiProfile = await response.json();
  return transformProfile(apiProfile);
}
function buildProfileSetup(profile, session, config) {
  return {
    profile,
    session,
    save: () => saveProfileSession({ sessionId: session.sessionId, profileId: profile.id }, config)
  };
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  ProfilesClient,
  createProfile,
  deleteProfile,
  getProfile,
  getProfileState,
  listProfiles,
  listRepos,
  saveProfileSession,
  startProfileSession,
  updateProfile
});
//# sourceMappingURL=index.cjs.map