// src/durable/spawn-journal.ts
import { createHash } from "crypto";
function contentAddress(artifact) {
  const hex = createHash("sha256").update(stableStringify(artifact), "utf-8").digest("hex");
  return `sha256:${hex}`;
}
function stableStringify(value) {
  if (value === null || typeof value !== "object") return JSON.stringify(value) ?? "null";
  if (Array.isArray(value)) return `[${value.map(stableStringify).join(",")}]`;
  const entries = Object.entries(value).filter(([, v]) => v !== void 0).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
  return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${stableStringify(v)}`).join(",")}}`;
}
var InMemoryResultBlobStore = class {
  blobs = /* @__PURE__ */ new Map();
  async put(outRef, artifact) {
    assertContentAddress(outRef, artifact);
    this.blobs.set(outRef, artifact);
  }
  async get(outRef) {
    return this.blobs.has(outRef) ? this.blobs.get(outRef) : void 0;
  }
};
function assertContentAddress(outRef, artifact) {
  const expected = contentAddress(artifact);
  if (outRef !== expected) {
    throw new Error(
      `blob outRef '${outRef}' does not match the artifact content hash '${expected}'; a content-addressed store refuses a mismatched ref (breaks the replay invariant)`
    );
  }
}
var InMemorySpawnJournal = class {
  trees = /* @__PURE__ */ new Map();
  async loadTree(root) {
    const tree = this.trees.get(root);
    if (!tree) return void 0;
    return tree.events.map((ev) => ({ ...ev }));
  }
  async beginTree(root, at) {
    const existing = this.trees.get(root);
    if (existing) {
      if (existing.begunAt !== at) {
        throw new Error(
          `spawn tree '${root}' already begun at ${existing.begunAt}; refusing to overwrite with ${at}`
        );
      }
      return;
    }
    this.trees.set(root, { begunAt: at, events: [] });
  }
  async appendEvent(root, ev) {
    const tree = this.trees.get(root);
    if (!tree) {
      throw new Error(`appendEvent called for unknown spawn tree '${root}'; call beginTree first`);
    }
    assertSeqUnique(root, tree.events, ev);
    tree.events.push({ ...ev });
  }
};
function assertSeqUnique(root, events, ev) {
  if (ev.kind === "spawned" || ev.kind === "metered") return;
  if (events.some((e) => e.kind !== "spawned" && e.kind !== "metered" && e.seq === ev.seq)) {
    throw new Error(
      `spawn journal corrupted: duplicate cursor seq ${ev.seq} in tree '${root}'; the cursor order replay relies on is not unique`
    );
  }
}

export {
  contentAddress,
  InMemoryResultBlobStore,
  InMemorySpawnJournal
};
//# sourceMappingURL=chunk-WIPGQ4GT.js.map