// src/hosted/types.ts
var HOSTED_WIRE_VERSION = "2026-05-26.v1";

// src/hosted/client.ts
function sleep(ms) {
  return new Promise((resolve) => {
    const t = setTimeout(resolve, ms);
    if (typeof t.unref === "function")
      t.unref();
  });
}
async function post(tenant, path, body, opts = {}) {
  const timeoutMs = tenant.timeoutMs ?? 3e4;
  const maxRetries = tenant.retries ?? 2;
  const f = tenant.fetchImpl ?? ((...args) => fetch(...args));
  const base = tenant.endpoint.replace(/\/+$/, "").replace(/\/v1$/, "");
  const url = `${base}${path}`;
  let lastError;
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    const ourTimeout = AbortSignal.timeout(timeoutMs);
    const combinedSignal = opts.signal ? AbortSignal.any([opts.signal, ourTimeout]) : ourTimeout;
    try {
      const headers = {
        "content-type": "application/json",
        authorization: `Bearer ${tenant.apiKey}`,
        "x-tangle-tenant-id": tenant.tenantId,
        "x-tangle-wire-version": HOSTED_WIRE_VERSION
      };
      if (opts.idempotencyKey) headers["idempotency-key"] = opts.idempotencyKey;
      const res = await f(url, {
        method: "POST",
        headers,
        body: JSON.stringify(body),
        signal: combinedSignal
      });
      if (!res.ok) {
        const retryable = res.status >= 500 || res.status === 408 || res.status === 429;
        if (!retryable || attempt === maxRetries) {
          const text = await res.text().catch(() => "");
          throw new Error(`hosted ingest ${url} failed (${res.status}): ${text.slice(0, 500)}`);
        }
        await sleep(2 ** attempt * 200 + Math.random() * 200);
        continue;
      }
      return await res.json();
    } catch (err) {
      if (opts.signal?.aborted) throw err;
      lastError = err;
      if (attempt === maxRetries) throw err;
      await sleep(2 ** attempt * 200 + Math.random() * 200);
    }
  }
  throw lastError ?? new Error("hosted ingest exhausted retries");
}
function createHostedClient(tenant) {
  return {
    tenant,
    wireVersion: HOSTED_WIRE_VERSION,
    async ingestEvalRun(event, idempotencyKey) {
      return this.ingestEvalRuns([event], idempotencyKey);
    },
    async ingestEvalRuns(events, idempotencyKey) {
      const body = { wireVersion: HOSTED_WIRE_VERSION, events };
      return post(tenant, "/v1/ingest/eval-runs", body, {
        idempotencyKey
      });
    },
    async ingestTraces(spans, idempotencyKey) {
      const body = { wireVersion: HOSTED_WIRE_VERSION, spans };
      return post(tenant, "/v1/ingest/traces", body, {
        idempotencyKey
      });
    }
  };
}
function hostedTenantFromEnv(overrides = {}) {
  const env = overrides.env ?? process.env;
  const endpoint = (overrides.endpoint ?? env.TANGLE_INGEST_URL ?? env.TANGLE_ORCHESTRATOR_URL)?.trim();
  const apiKey = (overrides.apiKey ?? env.TANGLE_INGEST_API_KEY ?? env.TANGLE_API_KEY)?.trim();
  const tenantId = (overrides.tenantId ?? env.TANGLE_TENANT_ID)?.trim();
  if (!endpoint || !apiKey || !tenantId) return void 0;
  const tenant = { endpoint: endpoint.replace(/\/+$/, ""), apiKey, tenantId };
  if (overrides.fetchImpl) tenant.fetchImpl = overrides.fetchImpl;
  if (overrides.timeoutMs !== void 0) tenant.timeoutMs = overrides.timeoutMs;
  if (overrides.retries !== void 0) tenant.retries = overrides.retries;
  return tenant;
}
function hostedClientFromEnv(overrides = {}) {
  const tenant = hostedTenantFromEnv(overrides);
  return tenant ? createHostedClient(tenant) : void 0;
}

export {
  HOSTED_WIRE_VERSION,
  createHostedClient,
  hostedTenantFromEnv,
  hostedClientFromEnv
};
//# sourceMappingURL=chunk-ZZUXHH3R.js.map