"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 __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
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);
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);

// src/index.ts
var index_exports = {};
__export(index_exports, {
  AmigoClient: () => AmigoClient,
  AmigoError: () => AmigoError,
  AuthenticationError: () => AuthenticationError,
  BadRequestError: () => BadRequestError,
  ConfigurationError: () => ConfigurationError,
  ConflictError: () => ConflictError,
  NetworkError: () => NetworkError,
  NotFoundError: () => NotFoundError,
  ParseError: () => ParseError,
  PermissionError: () => PermissionError,
  RateLimitError: () => RateLimitError,
  ServerError: () => ServerError,
  ServiceUnavailableError: () => ServiceUnavailableError,
  ValidationError: () => ValidationError,
  agentId: () => agentId,
  apiKeyId: () => apiKeyId,
  conversationId: () => conversationId,
  dynamicBehaviorSetId: () => dynamicBehaviorSetId,
  interactionId: () => interactionId,
  isAmigoError: () => isAmigoError,
  messageId: () => messageId,
  metricId: () => metricId,
  orgId: () => orgId,
  parseRateLimitHeaders: () => parseRateLimitHeaders,
  roleId: () => roleId,
  serviceId: () => serviceId,
  simulationPersonaId: () => simulationPersonaId,
  simulationScenarioId: () => simulationScenarioId,
  simulationUnitTestId: () => simulationUnitTestId,
  simulationUnitTestSetId: () => simulationUnitTestSetId,
  toolId: () => toolId,
  userId: () => userId,
  webhookDestinationId: () => webhookDestinationId,
  webhooks: () => webhooks_exports
});
module.exports = __toCommonJS(index_exports);

// src/core/utils.ts
async function extractData(responsePromise) {
  const result = await responsePromise;
  const data = result.data;
  if (data === void 0 || data === null) {
    throw new ParseError("Expected response data to be present for successful request", "response");
  }
  return data;
}
async function* parseNdjsonStream(response) {
  const body = response.body;
  if (!body) return;
  const reader = body.getReader();
  const decoder = new TextDecoder();
  let bufferedText = "";
  try {
    while (true) {
      const { done, value } = await reader.read();
      if (done) break;
      bufferedText += decoder.decode(value, { stream: true });
      let newlineIndex;
      while ((newlineIndex = bufferedText.indexOf("\n")) !== -1) {
        const line = bufferedText.slice(0, newlineIndex).trim();
        bufferedText = bufferedText.slice(newlineIndex + 1);
        if (!line) continue;
        try {
          yield JSON.parse(line);
        } catch (err) {
          throw new ParseError("Failed to parse NDJSON line", "json", err);
        }
      }
    }
    const trailing = bufferedText.trim();
    if (trailing) {
      try {
        yield JSON.parse(trailing);
      } catch (err) {
        throw new ParseError("Failed to parse trailing NDJSON line", "json", err);
      }
    }
  } finally {
    reader.releaseLock();
  }
}
async function parseResponseBody(response) {
  try {
    const text = await response.text();
    if (!text) return void 0;
    try {
      return JSON.parse(text);
    } catch {
      return text;
    }
  } catch {
    return void 0;
  }
}
function isNetworkError(error) {
  if (!(error instanceof Error)) return false;
  return error instanceof TypeError || error.message.includes("fetch") || error.message.includes("Failed to fetch") || error.message.includes("Network request failed") || error.message.includes("ECONNREFUSED") || error.message.includes("ETIMEDOUT") || error.message.includes("ENOTFOUND") || error.message.includes("network");
}

// src/core/errors.ts
var SENSITIVE_FIELDS = /* @__PURE__ */ new Set([
  "id_token",
  "access_token",
  "refresh_token",
  "authorization",
  "api_key",
  "apikey",
  "token",
  "secret",
  "password",
  "x-api-key"
]);
function sanitizeErrorContext(obj) {
  if (obj === null || obj === void 0) return obj;
  if (typeof obj !== "object") return obj;
  if (Array.isArray(obj)) return obj.map(sanitizeErrorContext);
  const result = {};
  for (const [key, value] of Object.entries(obj)) {
    if (SENSITIVE_FIELDS.has(key.toLowerCase())) {
      result[key] = "[REDACTED]";
    } else if (typeof value === "object" && value !== null) {
      result[key] = sanitizeErrorContext(value);
    } else {
      result[key] = value;
    }
  }
  return result;
}
var AmigoError = class extends Error {
  constructor(message, options) {
    super(message);
    /** Unique error code for programmatic error handling */
    __publicField(this, "errorCode");
    /** HTTP status code if applicable */
    __publicField(this, "statusCode");
    /** Additional context data */
    __publicField(this, "context");
    this.name = this.constructor.name;
    Object.setPrototypeOf(this, new.target.prototype);
    if (Error.captureStackTrace) {
      Error.captureStackTrace(this, this.constructor);
    }
    this.statusCode = options?.statusCode;
    this.errorCode = options?.errorCode;
    this.context = options?.context;
  }
  /**
   * Returns a JSON-serializable representation of the error.
   * Sensitive fields (tokens, keys) are redacted to prevent leakage.
   */
  toJSON() {
    return {
      name: this.name,
      message: this.message,
      code: this.errorCode,
      statusCode: this.statusCode,
      context: sanitizeErrorContext(this.context),
      stack: this.stack
    };
  }
};
var BadRequestError = class extends AmigoError {
};
var AuthenticationError = class extends AmigoError {
};
var PermissionError = class extends AmigoError {
};
var NotFoundError = class extends AmigoError {
};
var ConflictError = class extends AmigoError {
};
var RateLimitError = class extends AmigoError {
};
var ServerError = class extends AmigoError {
};
var ServiceUnavailableError = class extends ServerError {
};
var ConfigurationError = class extends AmigoError {
  constructor(message, field) {
    super(message, { context: { field } });
    this.field = field;
  }
};
var ValidationError = class extends BadRequestError {
  constructor(msg, fieldErrors) {
    super(msg);
    this.fieldErrors = fieldErrors;
  }
};
var NetworkError = class extends AmigoError {
  constructor(message, originalError, request) {
    super(message, { context: { request } });
    this.originalError = originalError;
    this.request = request;
  }
};
var ParseError = class extends AmigoError {
  constructor(message, parseType, originalError) {
    super(message, { context: { parseType } });
    this.parseType = parseType;
    this.originalError = originalError;
  }
};
function isAmigoError(error) {
  return error instanceof AmigoError;
}
function createApiError(response, body) {
  const map = {
    400: BadRequestError,
    401: AuthenticationError,
    403: PermissionError,
    404: NotFoundError,
    409: ConflictError,
    422: ValidationError,
    429: RateLimitError,
    500: ServerError,
    503: ServiceUnavailableError
  };
  const errorMessageKeys = ["message", "error", "detail"];
  const ErrorClass = map[response.status] ?? AmigoError;
  let message = `HTTP ${response.status} ${response.statusText}`;
  if (body && typeof body === "object") {
    for (const key of errorMessageKeys) {
      if (key in body) {
        message = String(body[key]);
        break;
      }
    }
  }
  const error = new ErrorClass(message, {
    statusCode: response.status,
    errorCode: body && typeof body === "object" && "code" in body ? String(body.code) : void 0,
    context: { response: sanitizeErrorContext(body) }
  });
  return error;
}
function createErrorMiddleware() {
  return {
    onResponse: async ({ response }) => {
      if (!response.ok) {
        const body = await parseResponseBody(response);
        throw createApiError(response, body);
      }
    },
    onError: async ({ error, request }) => {
      if (isNetworkError(error)) {
        throw new NetworkError(
          `Network error: ${error instanceof Error ? error.message : String(error)}`,
          error instanceof Error ? error : new Error(String(error)),
          {
            url: request?.url,
            method: request?.method
          }
        );
      }
      throw error;
    }
  };
}

// src/core/openapi-client.ts
var import_openapi_fetch = __toESM(require("openapi-fetch"), 1);

// src/core/auth.ts
async function getBearerToken(config) {
  const url = `${config.baseUrl}/v1/${config.orgId}/user/signin_with_api_key`;
  try {
    const response = await fetch(url, {
      method: "POST",
      headers: {
        "x-api-key": config.apiKey,
        "x-api-key-id": config.apiKeyId,
        "x-user-id": config.userId
      }
    });
    if (!response.ok) {
      const body = await parseResponseBody(response);
      const apiError = createApiError(response, body);
      if (response.status === 401) {
        throw new AuthenticationError(`Authentication failed: ${apiError.message}`, {
          ...apiError,
          context: { ...apiError.context, endpoint: "signin_with_api_key" }
        });
      }
      throw apiError;
    }
    return await response.json();
  } catch (err) {
    if (err instanceof AmigoError) {
      throw err;
    }
    if (isNetworkError(err)) {
      throw new NetworkError("Failed to connect to authentication endpoint", err, {
        url,
        method: "POST"
      });
    }
    throw new ParseError(
      "Failed to parse authentication response",
      "json",
      err instanceof Error ? err : new Error(String(err))
    );
  }
}
function createAuthMiddleware(config) {
  let token = null;
  let refreshPromise = null;
  const shouldRefreshToken = (tokenData) => {
    if (!tokenData.expires_at) return false;
    const expiryTime = new Date(tokenData.expires_at).getTime();
    const currentTime = Date.now();
    const timeUntilExpiry = expiryTime - currentTime;
    const refreshThreshold = 5 * 60 * 1e3;
    return timeUntilExpiry <= refreshThreshold;
  };
  const ensureValidToken = async () => {
    if (!token || shouldRefreshToken(token)) {
      if (!refreshPromise) {
        refreshPromise = getBearerToken(config);
        try {
          token = await refreshPromise;
        } finally {
          refreshPromise = null;
        }
      } else {
        token = await refreshPromise;
      }
    }
    return token;
  };
  return {
    onRequest: async ({ request }) => {
      try {
        const validToken = await ensureValidToken();
        if (validToken?.id_token) {
          request.headers.set("Authorization", `Bearer ${validToken.id_token}`);
        }
      } catch (error) {
        token = null;
        throw error;
      }
      return request;
    },
    onResponse: async ({ response }) => {
      if (response.status === 401) {
        token = null;
      }
    },
    onError: async ({ error }) => {
      token = null;
      throw error;
    }
  };
}

// src/core/retry.ts
var DEFAULT_RETRYABLE_STATUS = /* @__PURE__ */ new Set([408, 429, 500, 502, 503, 504]);
var DEFAULT_RETRYABLE_METHODS = /* @__PURE__ */ new Set(["GET"]);
function resolveRetryOptions(options) {
  return {
    maxAttempts: options?.maxAttempts ?? 3,
    backoffBaseMs: options?.backoffBaseMs ?? 250,
    maxDelayMs: options?.maxDelayMs ?? 3e4,
    retryOnStatus: new Set(options?.retryOnStatus ?? DEFAULT_RETRYABLE_STATUS),
    retryOnMethods: new Set(options?.retryOnMethods ?? DEFAULT_RETRYABLE_METHODS)
  };
}
function clamp(value, min, max) {
  return Math.max(min, Math.min(max, value));
}
function parseRetryAfterMs(headerValue, maxDelayMs) {
  if (!headerValue) return null;
  const seconds = Number(headerValue);
  if (Number.isFinite(seconds)) {
    return clamp(seconds * 1e3, 0, maxDelayMs);
  }
  const date = new Date(headerValue);
  const ms = date.getTime() - Date.now();
  if (Number.isFinite(ms)) {
    return clamp(ms, 0, maxDelayMs);
  }
  return null;
}
function computeBackoffWithJitterMs(attemptIndexZeroBased, baseMs, capMs) {
  const windowMs = Math.min(capMs, baseMs * Math.pow(2, attemptIndexZeroBased));
  return Math.random() * windowMs;
}
function isAbortError(err) {
  return typeof err === "object" && err !== null && "name" in err && err["name"] === "AbortError";
}
function isNetworkError2(err) {
  return err instanceof TypeError && !isAbortError(err);
}
async function abortableSleep(ms, signal) {
  if (ms <= 0) {
    signal?.throwIfAborted?.();
    return;
  }
  await new Promise((resolve, reject) => {
    const rejectWith = signal?.reason instanceof Error ? signal.reason : signal?.reason ?? new Error("AbortError");
    if (signal?.aborted) {
      reject(rejectWith);
      return;
    }
    const t = setTimeout(() => {
      off();
      resolve();
    }, ms);
    const onAbort = () => {
      off();
      clearTimeout(t);
      reject(rejectWith);
    };
    const off = () => signal?.removeEventListener("abort", onAbort);
    signal?.addEventListener("abort", onAbort, { once: true });
  });
}
function createRetryingFetch(retryOptions, baseFetch) {
  const resolved = resolveRetryOptions(retryOptions);
  const underlying = baseFetch ?? globalThis.fetch;
  const retryingFetch = async (input, init) => {
    const inputMethod = typeof Request !== "undefined" && input instanceof Request ? input.method : void 0;
    const method = (init?.method ?? inputMethod ?? "GET").toUpperCase();
    const signal = init?.signal;
    const isMethodRetryableByDefault = resolved.retryOnMethods.has(method);
    const maxAttempts = Math.max(1, resolved.maxAttempts);
    for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
      let response = null;
      let error = null;
      try {
        response = await underlying(input, init);
      } catch (err) {
        error = err;
      }
      if (!error && response && response.ok) {
        return response;
      }
      let shouldRetry = false;
      let delayMs = null;
      if (isNetworkError2(error)) {
        shouldRetry = isMethodRetryableByDefault;
        if (shouldRetry) {
          delayMs = computeBackoffWithJitterMs(
            attempt - 1,
            resolved.backoffBaseMs,
            resolved.maxDelayMs
          );
        }
      } else if (response) {
        const status = response.status;
        if (method === "POST") {
          if (status === 429) {
            const ra = response.headers.get("Retry-After");
            const parsed = parseRetryAfterMs(ra, resolved.maxDelayMs);
            if (parsed !== null) {
              shouldRetry = true;
              delayMs = parsed;
            }
          }
        } else if (isMethodRetryableByDefault && resolved.retryOnStatus.has(status)) {
          const ra = response.headers.get("Retry-After");
          delayMs = parseRetryAfterMs(ra, resolved.maxDelayMs) ?? computeBackoffWithJitterMs(attempt - 1, resolved.backoffBaseMs, resolved.maxDelayMs);
          shouldRetry = true;
        }
      }
      const attemptsRemain = attempt < maxAttempts;
      if (!shouldRetry || !attemptsRemain) {
        if (error) throw error;
        return response;
      }
      if (signal?.aborted) {
        if (error) throw error;
        return response;
      }
      await abortableSleep(delayMs ?? 0, signal ?? void 0);
    }
    throw new Error("Retry loop exited unexpectedly");
  };
  return retryingFetch;
}

// src/core/openapi-client.ts
var createClient = typeof import_openapi_fetch.default === "function" ? import_openapi_fetch.default : import_openapi_fetch.default.default;
function createAmigoFetch(config, mockFetch) {
  const wrappedFetch = createRetryingFetch(
    config.retry,
    mockFetch ?? globalThis.fetch
  );
  const client = createClient({
    baseUrl: config.baseUrl,
    fetch: wrappedFetch
  });
  client.use(createErrorMiddleware());
  client.use(createAuthMiddleware(config));
  return client;
}

// src/resources/organization.ts
var OrganizationResource = class {
  constructor(c, orgId2) {
    this.c = c;
    this.orgId = orgId2;
  }
  /**
   * Get organization details
   * @param headers - The headers
   * @returns The organization details
   */
  async getOrganization(headers) {
    return extractData(
      this.c.GET("/v1/{organization}/organization/", {
        params: { path: { organization: this.orgId } },
        headers
      })
    );
  }
  /** Alias for getOrganization. */
  async get(headers) {
    return this.getOrganization(headers);
  }
};

// src/resources/conversation.ts
var ConversationResource = class {
  constructor(c, orgId2) {
    this.c = c;
    this.orgId = orgId2;
  }
  /** Create a new conversation and return an async stream of NDJSON events. */
  async createConversation(options) {
    const { body, query, headers, signal } = options;
    const resp = await this.c.POST("/v1/{organization}/conversation/", {
      params: { path: { organization: this.orgId }, query },
      body,
      headers: {
        Accept: "application/x-ndjson",
        ...headers ?? {}
      },
      // Ensure we receive a stream for NDJSON
      parseAs: "stream",
      ...signal && { signal }
    });
    return parseNdjsonStream(
      resp.response
    );
  }
  /** Send a text or voice interaction and return an async stream of NDJSON events. */
  async interactWithConversation(options) {
    const { conversationId: conversationId2, input, query, headers, signal } = options;
    let bodyToSend;
    const mergedHeaders = {
      Accept: "application/x-ndjson",
      ...headers ?? {}
    };
    if (query.request_format === "text") {
      if (typeof input !== "string") {
        throw new BadRequestError("textMessage is required when request_format is 'text'");
      }
      const form = new FormData();
      form.append("initial_message_type", "user-message");
      form.append("recorded_message", input);
      bodyToSend = form;
    } else if (query.request_format === "voice") {
      if (typeof input === "string") {
        throw new BadRequestError(
          "voice input must be a byte source when request_format is 'voice'"
        );
      }
      bodyToSend = input;
    } else {
      throw new BadRequestError("Unsupported or missing request_format in params");
    }
    if (query.request_format === "text") {
      delete mergedHeaders["content-type"];
      delete mergedHeaders["Content-Type"];
    }
    if (query.request_format === "voice") {
      const hasContentType = mergedHeaders["content-type"] !== void 0 || mergedHeaders["Content-Type"] !== void 0;
      if (!hasContentType && typeof Blob !== "undefined" && input instanceof Blob && input.type) {
        mergedHeaders["content-type"] = input.type;
      }
    }
    const headersToSend = mergedHeaders;
    const normalizedQuery = {
      ...query,
      request_audio_config: typeof query.request_audio_config === "object" && query.request_audio_config !== null ? JSON.stringify(query.request_audio_config) : query.request_audio_config ?? void 0
    };
    const resp = await this.c.POST("/v1/{organization}/conversation/{conversation_id}/interact", {
      params: {
        path: { organization: this.orgId, conversation_id: conversationId2 },
        query: normalizedQuery,
        header: headersToSend
      },
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      body: bodyToSend,
      // FormData/Blob not represented in generated OpenAPI types
      parseAs: "stream",
      ...signal && { signal }
    });
    return parseNdjsonStream(resp.response);
  }
  /** List conversations, optionally filtered by query parameters. */
  async getConversations(queryParams, headers) {
    return extractData(
      this.c.GET("/v1/{organization}/conversation/", {
        params: { path: { organization: this.orgId }, query: queryParams },
        headers
      })
    );
  }
  /** Get messages for a conversation. */
  async getConversationMessages(options) {
    const { conversationId: conversationId2, query, headers } = options;
    return extractData(
      this.c.GET("/v1/{organization}/conversation/{conversation_id}/messages/", {
        params: {
          path: { organization: this.orgId, conversation_id: conversationId2 },
          query
        },
        headers
      })
    );
  }
  /**
   * Finish (close) a conversation.
   * @returns void
   */
  async finishConversation(options) {
    const { conversationId: conversationId2, headers } = options;
    await this.c.POST("/v1/{organization}/conversation/{conversation_id}/finish/", {
      params: { path: { organization: this.orgId, conversation_id: conversationId2 } },
      headers,
      // No content is expected; parse as text to access raw Response
      parseAs: "text"
    });
    return void 0;
  }
  /** Get recommended responses for an interaction. */
  async recommendResponsesForInteraction(options) {
    const { conversationId: conversationId2, interactionId: interactionId2, body, headers } = options;
    return extractData(
      this.c.POST(
        "/v1/{organization}/conversation/{conversation_id}/interaction/{interaction_id}/recommend_responses",
        {
          params: {
            path: {
              organization: this.orgId,
              conversation_id: conversationId2,
              interaction_id: interactionId2
            }
          },
          body,
          headers
        }
      )
    );
  }
  /** Get insights for an interaction. */
  async getInteractionInsights(options) {
    const { conversationId: conversationId2, interactionId: interactionId2, headers } = options;
    return extractData(
      this.c.GET(
        "/v1/{organization}/conversation/{conversation_id}/interaction/{interaction_id}/insights",
        {
          params: {
            path: {
              organization: this.orgId,
              conversation_id: conversationId2,
              interaction_id: interactionId2
            }
          },
          headers
        }
      )
    );
  }
  /** Get the audio/media source URL for a message. */
  async getMessageSource(options) {
    const { conversationId: conversationId2, messageId: messageId2, headers } = options;
    return extractData(
      this.c.GET("/v1/{organization}/conversation/{conversation_id}/messages/{message_id}/source", {
        params: {
          path: {
            organization: this.orgId,
            conversation_id: conversationId2,
            message_id: messageId2
          }
        },
        headers
      })
    );
  }
  /** Generate conversation starter suggestions. */
  async generateConversationStarters(body, headers) {
    return extractData(
      this.c.POST("/v1/{organization}/conversation/conversation_starter", {
        params: { path: { organization: this.orgId } },
        body,
        headers
      })
    );
  }
  // --- Convenience aliases ---
  /** Alias for getConversations. */
  async list(queryParams, headers) {
    return this.getConversations(queryParams, headers);
  }
  /** Alias for createConversation. */
  async create(options) {
    return this.createConversation(options);
  }
  /** Alias for interactWithConversation. */
  async interact(options) {
    return this.interactWithConversation(options);
  }
  /** Alias for finishConversation. */
  async finish(options) {
    return this.finishConversation(options);
  }
  /** Alias for getConversationMessages. */
  async messages(options) {
    return this.getConversationMessages(options);
  }
};

// src/resources/services.ts
var ServiceResource = class {
  constructor(c, orgId2) {
    this.c = c;
    this.orgId = orgId2;
  }
  /** List services for the organization. */
  async getServices(queryParams, headers) {
    return extractData(
      this.c.GET("/v1/{organization}/service/", {
        params: { path: { organization: this.orgId }, query: queryParams },
        headers
      })
    );
  }
  /** Create a new service. */
  async createService(options) {
    const { body, headers } = options;
    return extractData(
      this.c.POST("/v1/{organization}/service/", {
        params: { path: { organization: this.orgId } },
        body,
        headers
      })
    );
  }
  /** Update a service. */
  async updateService(options) {
    const { serviceId: serviceId2, body, headers } = options;
    return extractData(
      this.c.POST("/v1/{organization}/service/{service_id}/", {
        params: { path: { organization: this.orgId, service_id: serviceId2 } },
        body,
        headers
      })
    );
  }
  /** Upsert a service version set. */
  async upsertVersionSet(options) {
    const { serviceId: serviceId2, versionSetName, body, headers } = options;
    return extractData(
      this.c.PUT("/v1/{organization}/service/{service_id}/version_sets/{version_set_name}/", {
        params: {
          path: {
            organization: this.orgId,
            service_id: serviceId2,
            version_set_name: versionSetName
          }
        },
        body,
        headers
      })
    );
  }
  /** Delete a service version set. */
  async deleteVersionSet(options) {
    const { serviceId: serviceId2, versionSetName, headers } = options;
    await this.c.DELETE(
      "/v1/{organization}/service/{service_id}/version_sets/{version_set_name}/",
      {
        params: {
          path: {
            organization: this.orgId,
            service_id: serviceId2,
            version_set_name: versionSetName
          }
        },
        headers
      }
    );
    return void 0;
  }
  // --- Convenience aliases ---
  /** Alias for getServices. */
  async list(queryParams, headers) {
    return this.getServices(queryParams, headers);
  }
  /** Alias for createService. */
  async create(options) {
    return this.createService(options);
  }
};

// src/resources/user.ts
var UserResource = class {
  constructor(c, orgId2) {
    this.c = c;
    this.orgId = orgId2;
  }
  /** List users in the organization. */
  async getUsers(queryParams, headers) {
    return extractData(
      this.c.GET("/v1/{organization}/user/", {
        params: { path: { organization: this.orgId }, query: queryParams },
        headers
      })
    );
  }
  /** Create (invite) a new user to the organization. */
  async createUser(body, headers) {
    return extractData(
      this.c.POST("/v1/{organization}/user/", {
        params: { path: { organization: this.orgId } },
        body,
        headers
      })
    );
  }
  /** Delete a user by ID. */
  async deleteUser(userId2, headers) {
    await this.c.DELETE("/v1/{organization}/user/{requested_user_id}", {
      params: { path: { organization: this.orgId, requested_user_id: userId2 } },
      headers
    });
    return void 0;
  }
  /** Update user information. */
  async updateUser(options) {
    const { userId: userId2, body, headers } = options;
    await this.c.POST("/v1/{organization}/user/{requested_user_id}", {
      params: { path: { organization: this.orgId, requested_user_id: userId2 } },
      body,
      headers
    });
    return void 0;
  }
  /** Get the user model for a user. */
  async getUserModel(userId2, headers) {
    return extractData(
      this.c.GET("/v1/{organization}/user/{user_id}/user_model", {
        params: { path: { organization: this.orgId, user_id: userId2 } },
        headers
      })
    );
  }
  // --- Convenience aliases ---
  /** Alias for getUsers. */
  async list(queryParams, headers) {
    return this.getUsers(queryParams, headers);
  }
  /** Alias for createUser. */
  async create(body, headers) {
    return this.createUser(body, headers);
  }
  /** Alias for getUserModel. */
  async getModel(userId2, headers) {
    return this.getUserModel(userId2, headers);
  }
  /** Alias for deleteUser. */
  async delete(userId2, headers) {
    return this.deleteUser(userId2, headers);
  }
  /** Alias for updateUser. */
  async update(options) {
    return this.updateUser(options);
  }
};

// src/resources/agent.ts
var AgentResource = class {
  constructor(c, orgId2) {
    this.c = c;
    this.orgId = orgId2;
  }
  /** Create a new agent for the organization. */
  async createAgent(options) {
    const { body, headers } = options;
    return extractData(
      this.c.POST("/v1/{organization}/organization/agent", {
        params: { path: { organization: this.orgId } },
        body,
        headers
      })
    );
  }
  /** List agents for the organization. */
  async getAgents(options) {
    const { query, headers } = options ?? {};
    return extractData(
      this.c.GET("/v1/{organization}/organization/agent", {
        params: { path: { organization: this.orgId }, query },
        headers
      })
    );
  }
  /** Delete an agent by ID. */
  async deleteAgent(options) {
    const { agentId: agentId2, headers } = options;
    await this.c.DELETE("/v1/{organization}/organization/agent/{agent_id}/", {
      params: { path: { organization: this.orgId, agent_id: agentId2 } },
      headers
    });
    return void 0;
  }
  /** Create a new version of an agent. */
  async createAgentVersion(options) {
    const { agentId: agentId2, body, query, headers } = options;
    return extractData(
      this.c.POST("/v1/{organization}/organization/agent/{agent_id}/", {
        params: { path: { organization: this.orgId, agent_id: agentId2 }, query },
        body,
        headers
      })
    );
  }
  /** Get versions of an agent. */
  async getAgentVersions(options) {
    const { agentId: agentId2, query, headers } = options;
    return extractData(
      this.c.GET("/v1/{organization}/organization/agent/{agent_id}/version", {
        params: { path: { organization: this.orgId, agent_id: agentId2 }, query },
        headers
      })
    );
  }
  // --- Convenience aliases ---
  /** Alias for getAgents. */
  async list(options) {
    return this.getAgents(options);
  }
  /** Alias for createAgent. */
  async create(options) {
    return this.createAgent(options);
  }
  /** Alias for deleteAgent. */
  async delete(options) {
    return this.deleteAgent(options);
  }
};

// src/resources/context-graph.ts
var ContextGraphResource = class {
  constructor(c, orgId2) {
    this.c = c;
    this.orgId = orgId2;
  }
  /** Create a new context graph. */
  async createContextGraph(options) {
    const { body, headers } = options;
    return extractData(
      this.c.POST("/v1/{organization}/organization/service_hierarchical_state_machine", {
        params: { path: { organization: this.orgId } },
        body,
        headers
      })
    );
  }
  /** List context graphs for the organization. */
  async getContextGraphs(options) {
    const { query, headers } = options ?? {};
    return extractData(
      this.c.GET("/v1/{organization}/organization/service_hierarchical_state_machine", {
        params: { path: { organization: this.orgId }, query },
        headers
      })
    );
  }
  /** Create a new version of a context graph. */
  async createContextGraphVersion(options) {
    const { contextGraphId, body, query, headers } = options;
    return extractData(
      this.c.POST(
        "/v1/{organization}/organization/service_hierarchical_state_machine/{service_hierarchical_state_machine_id}/",
        {
          params: {
            path: {
              organization: this.orgId,
              service_hierarchical_state_machine_id: contextGraphId
            },
            query
          },
          body,
          headers
        }
      )
    );
  }
  /** Delete a context graph. */
  async deleteContextGraph(options) {
    const { contextGraphId, headers } = options;
    await this.c.DELETE(
      "/v1/{organization}/organization/service_hierarchical_state_machine/{state_machine_id}/",
      {
        params: {
          path: { organization: this.orgId, state_machine_id: contextGraphId }
        },
        headers
      }
    );
    return void 0;
  }
  /** Get versions of a context graph. */
  async getContextGraphVersions(options) {
    const { contextGraphId, query, headers } = options;
    return extractData(
      this.c.GET(
        "/v1/{organization}/organization/service_hierarchical_state_machine/{service_hierarchical_state_machine_id}/version",
        {
          params: {
            path: {
              organization: this.orgId,
              service_hierarchical_state_machine_id: contextGraphId
            },
            query
          },
          headers
        }
      )
    );
  }
  // --- Convenience aliases ---
  /** Alias for getContextGraphs. */
  async list(options) {
    return this.getContextGraphs(options);
  }
  /** Alias for createContextGraph. */
  async create(options) {
    return this.createContextGraph(options);
  }
  /** Alias for deleteContextGraph. */
  async delete(options) {
    return this.deleteContextGraph(options);
  }
};

// src/webhooks/index.ts
var webhooks_exports = {};
__export(webhooks_exports, {
  WebhookVerificationError: () => WebhookVerificationError,
  parseWebhookEvent: () => parseWebhookEvent,
  verifySignature: () => verifySignature
});

// src/webhooks/parse.ts
var import_node_crypto = require("node:crypto");
var WebhookVerificationError = class extends Error {
  constructor(message) {
    super(message);
    this.name = "WebhookVerificationError";
  }
};
var KNOWN_EVENT_TYPES = /* @__PURE__ */ new Set(["conversation-post-processing-complete"]);
function parseWebhookEvent(options) {
  const { payload, signature, timestamp, secret, maxAge = 3e5 } = options;
  const body = typeof payload === "string" ? payload : payload.toString("utf-8");
  if (signature && timestamp && secret) {
    verifySignature(body, timestamp, signature, secret);
    const eventTime = parseInt(timestamp, 10);
    if (isNaN(eventTime)) {
      throw new WebhookVerificationError("Invalid timestamp");
    }
    if (Date.now() - eventTime > maxAge) {
      throw new WebhookVerificationError(
        `Webhook event is too old (received ${Date.now() - eventTime}ms ago, max ${maxAge}ms)`
      );
    }
  }
  let parsed;
  try {
    parsed = JSON.parse(body);
  } catch {
    throw new WebhookVerificationError("Invalid JSON payload");
  }
  if (!parsed || typeof parsed !== "object" || !("type" in parsed)) {
    throw new WebhookVerificationError('Payload missing "type" field');
  }
  const event = parsed;
  if (!KNOWN_EVENT_TYPES.has(event.type)) {
    throw new WebhookVerificationError(`Unknown webhook event type: ${event.type}`);
  }
  return parsed;
}
function verifySignature(body, timestamp, signature, secret) {
  const expected = (0, import_node_crypto.createHmac)("sha256", secret).update(`v1:${timestamp}:${body}`).digest("hex");
  const sigBuf = Buffer.from(signature, "utf-8");
  const expectedBuf = Buffer.from(expected, "utf-8");
  if (sigBuf.length !== expectedBuf.length || !(0, import_node_crypto.timingSafeEqual)(sigBuf, expectedBuf)) {
    throw new WebhookVerificationError("Signature verification failed");
  }
}

// src/core/rate-limit.ts
function parseRateLimitHeaders(headers) {
  const limit = headers.get("x-ratelimit-limit");
  const remaining = headers.get("x-ratelimit-remaining");
  const reset = headers.get("x-ratelimit-reset");
  if (limit === null || remaining === null || reset === null) {
    return void 0;
  }
  const limitNum = parseInt(limit, 10);
  const remainingNum = parseInt(remaining, 10);
  const resetEpoch = parseInt(reset, 10);
  if (isNaN(limitNum) || isNaN(remainingNum) || isNaN(resetEpoch)) {
    return void 0;
  }
  return {
    limit: limitNum,
    remaining: remainingNum,
    reset: new Date(resetEpoch * 1e3)
  };
}

// src/core/branded-types.ts
function conversationId(id) {
  return id;
}
function messageId(id) {
  return id;
}
function userId(id) {
  return id;
}
function orgId(id) {
  return id;
}
function interactionId(id) {
  return id;
}
function serviceId(id) {
  return id;
}
function agentId(id) {
  return id;
}
function toolId(id) {
  return id;
}
function dynamicBehaviorSetId(id) {
  return id;
}
function metricId(id) {
  return id;
}
function simulationPersonaId(id) {
  return id;
}
function simulationScenarioId(id) {
  return id;
}
function simulationUnitTestId(id) {
  return id;
}
function simulationUnitTestSetId(id) {
  return id;
}
function webhookDestinationId(id) {
  return id;
}
function roleId(id) {
  return id;
}
function apiKeyId(id) {
  return id;
}

// src/index.ts
var defaultBaseUrl = "https://api.amigo.ai";
var AmigoClient = class {
  /** Create a new Amigo client with the given configuration. */
  constructor(config) {
    __publicField(this, "organizations");
    __publicField(this, "conversations");
    __publicField(this, "services");
    __publicField(this, "users");
    __publicField(this, "agents");
    __publicField(this, "contextGraphs");
    __publicField(this, "config");
    this.config = validateConfig(config);
    const api = createAmigoFetch(this.config);
    this.organizations = new OrganizationResource(api, this.config.orgId);
    this.conversations = new ConversationResource(api, this.config.orgId);
    this.services = new ServiceResource(api, this.config.orgId);
    this.users = new UserResource(api, this.config.orgId);
    this.agents = new AgentResource(api, this.config.orgId);
    this.contextGraphs = new ContextGraphResource(api, this.config.orgId);
  }
};
function validateConfig(config) {
  if (!config.apiKey) {
    throw new ConfigurationError("API key is required", "apiKey");
  }
  if (!config.apiKeyId) {
    throw new ConfigurationError("API key ID is required", "apiKeyId");
  }
  if (!config.userId) {
    throw new ConfigurationError("User ID is required", "userId");
  }
  if (!config.orgId) {
    throw new ConfigurationError("Organization ID is required", "orgId");
  }
  if (!config.baseUrl) {
    config.baseUrl = defaultBaseUrl;
  }
  return config;
}
//# sourceMappingURL=index.cjs.map
