@koda-sl/baker-cli 0.270.3-dev.e350bbc93 → 0.270.4-dev.12dd573e5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3131,6 +3131,16 @@ function dfsCycle(u, color, stack, reverseAdj) {
3131
3131
  stack.pop();
3132
3132
  return null;
3133
3133
  }
3134
+ function nodesBeforeCheckpoint(graph, types, stopKinds) {
3135
+ const all = new Set(graph.keys());
3136
+ if (!stopKinds?.size) return all;
3137
+ const running = /* @__PURE__ */ new Set();
3138
+ for (const layer of topologicalLayers(graph)) {
3139
+ if (layer.some((id) => stopKinds.has(types.get(id) ?? ""))) return running;
3140
+ for (const id of layer) running.add(id);
3141
+ }
3142
+ return running;
3143
+ }
3134
3144
 
3135
3145
  // src/engine/engine/validator.ts
3136
3146
  import { readFile as readFile2 } from "fs/promises";
@@ -3763,6 +3773,19 @@ function checkSlotsForNode(ctx, n, _i) {
3763
3773
  });
3764
3774
  }
3765
3775
  }
3776
+ function estimateCreditsFor(canvas, registry, ids) {
3777
+ let total = 0;
3778
+ for (const n of canvas.nodes) {
3779
+ if (!ids.has(n.id)) continue;
3780
+ const def = registry.get(n.type);
3781
+ if (!def?.cost) continue;
3782
+ try {
3783
+ total += def.cost({ params: def.params.parse(n.params ?? {}) }).credits;
3784
+ } catch {
3785
+ }
3786
+ }
3787
+ return total;
3788
+ }
3766
3789
  function estimateCredits(ctx) {
3767
3790
  let total = 0;
3768
3791
  for (const n of ctx.canvas.nodes) {
@@ -4587,6 +4610,13 @@ function unwrap(schema) {
4587
4610
  }
4588
4611
 
4589
4612
  // src/engine/engine/executor.ts
4613
+ function heldByCheckpoint(canvas, layer, kinds) {
4614
+ if (!kinds?.size) return [];
4615
+ return layer.filter((id) => {
4616
+ const type = canvas.nodes.find((n) => n.id === id)?.type;
4617
+ return type !== void 0 && kinds.has(type);
4618
+ });
4619
+ }
4590
4620
  var Engine = class {
4591
4621
  registry;
4592
4622
  client;
@@ -4614,7 +4644,7 @@ var Engine = class {
4614
4644
  async run(input, opts = {}) {
4615
4645
  const validation = await this.validateDeep(input);
4616
4646
  if (!validation.ok) throw new ValidationError(validation.issues);
4617
- if (opts.max_credits !== void 0 && validation.estimatedCredits > opts.max_credits) {
4647
+ if (!opts.stop_before_kinds?.size && opts.max_credits !== void 0 && validation.estimatedCredits > opts.max_credits) {
4618
4648
  throw new RunAbortedError(
4619
4649
  "cost_cap",
4620
4650
  `estimated ${validation.estimatedCredits} credits exceeds the ${opts.max_credits}-credit cap \u2014 nothing was billed; raise --max-credits or shrink the canvas`
@@ -4633,6 +4663,20 @@ var Engine = class {
4633
4663
  const counters = { cachedNodes: 0, totalCredits: 0 };
4634
4664
  const nodeRuns = [];
4635
4665
  const graph = this.pruneToOutput(canvas, buildGraph(canvas));
4666
+ if (opts.max_credits !== void 0 && opts.stop_before_kinds?.size) {
4667
+ const willRun = nodesBeforeCheckpoint(
4668
+ graph,
4669
+ new Map(canvas.nodes.map((n) => [n.id, n.type])),
4670
+ opts.stop_before_kinds
4671
+ );
4672
+ const estimate = estimateCreditsFor(canvas, this.registry, willRun);
4673
+ if (estimate > opts.max_credits) {
4674
+ throw new RunAbortedError(
4675
+ "cost_cap",
4676
+ `estimated ${estimate} credits exceeds the ${opts.max_credits}-credit cap \u2014 nothing was billed; raise --max-credits or shrink the canvas`
4677
+ );
4678
+ }
4679
+ }
4636
4680
  const needsBytes = computeNeedsLocalBytes(canvas, graph, this.registry);
4637
4681
  this.emitProgress(opts, {
4638
4682
  kind: "plan",
@@ -4677,6 +4721,13 @@ var Engine = class {
4677
4721
  `spent ${counters.totalCredits} credits, over the ${opts.max_credits}-credit cap \u2014 completed nodes are cached; raise --max-credits to continue where this stopped`
4678
4722
  );
4679
4723
  }
4724
+ const held = heldByCheckpoint(canvas, layer, opts.stop_before_kinds);
4725
+ if (held.length > 0) {
4726
+ throw new RunAbortedError(
4727
+ "checkpoint",
4728
+ `stopped before ${held.join(", ")} \u2014 everything up to here is done and cached, so continuing this run id pays for none of it again`
4729
+ );
4730
+ }
4680
4731
  const settled = await mapWithConcurrency(layer, limit, (nodeId) => {
4681
4732
  if (opts.signal?.aborted) {
4682
4733
  return Promise.reject(new RunAbortedError("signal", "run aborted before node dispatch"));
@@ -9294,4 +9345,4 @@ export {
9294
9345
  defaultRegistry,
9295
9346
  createEngineFromEnv
9296
9347
  };
9297
- //# sourceMappingURL=chunk-LJ5DIC4F.js.map
9348
+ //# sourceMappingURL=chunk-Y2GYULGB.js.map