// dist/src/sdk/contracts.js
function notImplemented(what) {
  throw new Error(`PRD-019e: not implemented \u2014 ${what}`);
}
var HoneycombError = class extends Error {
  constructor(message) {
    super(message);
    this.name = new.target.name;
  }
};
var ApiError = class extends HoneycombError {
  status;
  body;
  constructor(message, status, body) {
    super(message);
    this.status = status;
    this.body = body;
  }
};
var NetworkError = class extends HoneycombError {
  cause;
  constructor(message, cause) {
    super(message);
    this.cause = cause;
  }
};
var TimeoutError = class extends HoneycombError {
  timeoutMs;
  constructor(message, timeoutMs) {
    super(message);
    this.timeoutMs = timeoutMs;
  }
};
function defaultRetryPolicy() {
  return {
    maxAttempts(method) {
      return method === "GET" ? 3 : 1;
    },
    backoffMs(attempt) {
      return attempt * 100;
    }
  };
}

// dist/src/sdk/client.js
var DEFAULT_TIMEOUT_MS = 3e4;
var SECRET_REDACTED = "[REDACTED]";
var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "::1", "[::1]"]);
function isTokenTransportSafe(baseUrl) {
  let parsed;
  try {
    parsed = new URL(baseUrl);
  } catch {
    return false;
  }
  if (parsed.protocol === "https:")
    return true;
  if (parsed.protocol === "http:")
    return LOOPBACK_HOSTS.has(parsed.hostname);
  return false;
}
var HEADER_ACTOR = "x-honeycomb-actor";
var HEADER_ACTOR_TYPE = "x-honeycomb-actor-type";
var HEADER_RUNTIME_PATH = "x-honeycomb-runtime-path";
var HEADER_SESSION = "x-honeycomb-session";
var SESSION_GROUP_PREFIXES = ["/api/memories", "/memory"];
function isSdkSessionGroupPath(path) {
  return SESSION_GROUP_PREFIXES.some((p) => path === p || path.startsWith(`${p}/`) || path.startsWith(`${p}?`));
}
function createHoneycombClient(opts) {
  const fetchImpl = opts.fetch ?? ((input, init) => fetch(input, init));
  const retry = opts.retry ?? defaultRetryPolicy();
  const clientTimeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
  const baseUrl = opts.daemonUrl.replace(/\/+$/, "");
  const tokenTransportSafe = isTokenTransportSafe(baseUrl);
  let sdkSessionCounter = 0;
  function mintSdkSessionId() {
    sdkSessionCounter += 1;
    return `sdk-${opts.actor}-${sdkSessionCounter}`;
  }
  function buildHeaders(hasBody, path) {
    const headers = {
      [HEADER_ACTOR]: opts.actor,
      [HEADER_ACTOR_TYPE]: opts.actorType,
      // The SDK is a plugin-path thin client; the daemon enforces, we stamp (D-6).
      [HEADER_RUNTIME_PATH]: "plugin"
    };
    if (isSdkSessionGroupPath(path))
      headers[HEADER_SESSION] = mintSdkSessionId();
    if (hasBody)
      headers["content-type"] = "application/json";
    if (opts.token !== void 0 && opts.token.length > 0 && tokenTransportSafe) {
      headers.authorization = `Bearer ${opts.token}`;
    }
    return headers;
  }
  async function dispatchOnce(req, budgetMs) {
    const controller = new AbortController();
    let timedOut = false;
    const timer = setTimeout(() => {
      timedOut = true;
      controller.abort();
    }, budgetMs);
    try {
      const init = {
        method: req.method,
        headers: buildHeaders(req.body !== void 0, req.path),
        signal: controller.signal
      };
      if (req.body !== void 0)
        init.body = JSON.stringify(req.body);
      return await fetchImpl(`${baseUrl}${req.path}`, init);
    } catch (err) {
      if (timedOut) {
        throw new TimeoutError(`request to ${req.path} exceeded ${budgetMs}ms`, budgetMs);
      }
      throw new NetworkError(`transport failure calling ${req.path}`, err);
    } finally {
      clearTimeout(timer);
    }
  }
  function isTransientStatus(status) {
    return status === 429 || status >= 500 && status <= 599;
  }
  function sleep(ms) {
    if (ms <= 0)
      return Promise.resolve();
    return new Promise((resolve) => setTimeout(resolve, ms));
  }
  async function request(req) {
    const budgetMs = req.timeoutMs ?? clientTimeoutMs;
    const maxAttempts = retry.maxAttempts(req.method);
    let lastError;
    for (let attempt = 1; attempt <= maxAttempts; attempt++) {
      let res;
      try {
        res = await dispatchOnce(req, budgetMs);
      } catch (err) {
        lastError = err;
        if (err instanceof TimeoutError)
          throw err;
        if (attempt < maxAttempts) {
          await sleep(retry.backoffMs(attempt));
          continue;
        }
        throw err;
      }
      if (res.ok)
        return await parseBody(res);
      if (isTransientStatus(res.status) && attempt < maxAttempts) {
        lastError = new ApiError(`daemon returned ${res.status} for ${req.path}`, res.status, await safeBody(res));
        await sleep(retry.backoffMs(attempt));
        continue;
      }
      throw new ApiError(`daemon returned ${res.status} for ${req.path}`, res.status, await safeBody(res));
    }
    if (lastError !== void 0)
      throw lastError;
    throw new NetworkError(`request to ${req.path} failed after ${maxAttempts} attempts`);
  }
  async function parseBody(res) {
    const text = await res.text();
    if (text.length === 0)
      return void 0;
    try {
      return JSON.parse(text);
    } catch {
      return text;
    }
  }
  async function safeBody(res) {
    try {
      return await parseBody(res);
    } catch {
      return void 0;
    }
  }
  const memory = {
    async search(query, o) {
      const body = await request({
        method: "POST",
        path: "/api/memories/recall",
        body: o?.limit !== void 0 ? { query, limit: o.limit } : { query }
      });
      if (body?.results !== void 0)
        return body.results;
      return (body?.hits ?? []).map((h) => ({
        path: h.id ?? "",
        text: h.text ?? "",
        ...h.score !== void 0 ? { score: h.score } : {}
      }));
    },
    async store(text, o) {
      await request({
        method: "POST",
        path: "/api/memories",
        body: o?.path !== void 0 ? { content: text, normalizedContent: o.path } : { content: text }
      });
    },
    async get(path) {
      return await request({
        method: "GET",
        path: `/api/memories/${encodeURIComponent(path)}`
      });
    },
    async list(prefix) {
      const qs = prefix !== void 0 ? `?prefix=${encodeURIComponent(prefix)}` : "";
      const body = await request({
        method: "GET",
        path: `/api/memories${qs}`
      });
      return body?.results ?? [];
    }
  };
  const hooks = {
    async call(endpoint, body) {
      return await request({ method: "POST", path: `/api/hooks/${endpoint}`, body });
    }
  };
  const connectors = {
    async list() {
      return await listOf("/api/connectors");
    }
  };
  const documents = {
    async list() {
      return await listOf("/api/documents");
    }
  };
  const sources = {
    async list() {
      return await listOf("/api/sources");
    }
  };
  const skills = {
    async list() {
      return await listOf("/api/skills");
    }
  };
  const goals = {
    async list() {
      return await listOf("/api/goals");
    },
    async add(goal) {
      await request({ method: "POST", path: "/api/goals", body: { goal } });
    }
  };
  const health = {
    async check() {
      const body = await request({ method: "GET", path: "/health" });
      return { ok: body?.ok === true || body?.status === "ok" };
    }
  };
  async function listOf(path) {
    const body = await request({ method: "GET", path });
    if (Array.isArray(body))
      return body;
    if (body !== null && typeof body === "object") {
      const values = Object.values(body);
      const arr = values.find((v) => Array.isArray(v));
      if (Array.isArray(arr))
        return arr;
    }
    return [];
  }
  const secrets = {
    async list(prefix) {
      const body = await request({ method: "GET", path: "/api/secrets" });
      const names = body?.names ?? [];
      const filtered = prefix !== void 0 ? names.filter((n) => n.startsWith(prefix)) : names;
      return filtered.map((name) => ({ name }));
    },
    async exec(command) {
      const body = await request({
        method: "POST",
        path: "/api/secrets/exec",
        body: { command }
      });
      const redactedOutput = typeof body?.redactedOutput === "string" ? body.redactedOutput : SECRET_REDACTED;
      return { redactedOutput };
    }
  };
  return {
    async remember(text, o) {
      await memory.store(text, o);
    },
    async recall(query, o) {
      return await memory.search(query, o);
    },
    memory,
    hooks,
    connectors,
    documents,
    sources,
    skills,
    goals,
    health,
    secrets
  };
}
export {
  ApiError,
  DEFAULT_TIMEOUT_MS,
  HoneycombError,
  NetworkError,
  SECRET_REDACTED,
  TimeoutError,
  createHoneycombClient,
  defaultRetryPolicy,
  isTokenTransportSafe,
  notImplemented
};
