@koda-sl/baker-cli 0.419.0 → 0.420.0

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.
package/dist/cli.js CHANGED
@@ -262,7 +262,7 @@ import {
262
262
  wordCount,
263
263
  xDraftOpInputSchema,
264
264
  ytDlpBlockSignal
265
- } from "./chunk-IS5ERYGR.js";
265
+ } from "./chunk-M2E2OYY6.js";
266
266
  import {
267
267
  NAME_CONTAINS_ARG,
268
268
  csvOrJson,
@@ -59684,7 +59684,8 @@ function plannedBand(nodes, format, model) {
59684
59684
  }
59685
59685
  function unnamedReference(id, taken) {
59686
59686
  const [prefix, role] = /person|avatar/.test(id) ? ["PERSON", "identity"] : /_sheet$|animal|dog|cat|pet|hero/.test(id) ? ["ANIMAL", "identity"] : /product|package|bottle|box/.test(id) ? ["PRODUCT", "product"] : ["PROP", "prop"];
59687
- const n = taken.filter((r) => r.id.startsWith(`${prefix}_`)).length + 1;
59687
+ let n = 1;
59688
+ while (taken.some((r) => r.id === `${prefix}_${n}`)) n++;
59688
59689
  return {
59689
59690
  id: `${prefix}_${n}`,
59690
59691
  role,
@@ -61654,14 +61655,17 @@ async function resolveRunId(opts) {
61654
61655
  }
61655
61656
  if (opts.explicitRunId) return { runId: opts.explicitRunId, resumed: false };
61656
61657
  if (!opts.fresh) {
61657
- if (existing) return { runId: existing.runId, resumed: true, source: "local" };
61658
- if (opts.adoptedRunId) return { runId: opts.adoptedRunId, resumed: true, source: "remote" };
61658
+ if (existing) {
61659
+ const sameSource = existing.sourceSha !== void 0 && existing.sourceSha === opts.sourceSha;
61660
+ return { runId: existing.runId, resumed: true, source: "local", sameSource };
61661
+ }
61662
+ if (opts.adoptedRunId) return { runId: opts.adoptedRunId, resumed: true, source: "remote", sameSource: true };
61659
61663
  if (opts.remote) {
61660
61664
  try {
61661
61665
  const active = await opts.remote.getActiveRun(opts.remote.creativeSlug, opts.remote.sourceSha);
61662
61666
  if (active) {
61663
61667
  const decision = classifyRemoteRun(active);
61664
- if (decision === "adopt") return { runId: active.runId, resumed: true, source: "remote" };
61668
+ if (decision === "adopt") return { runId: active.runId, resumed: true, source: "remote", sameSource: true };
61665
61669
  if (decision === "concurrent") {
61666
61670
  return { runId: `r_${ulid()}`, resumed: false, concurrentRunId: active.runId };
61667
61671
  }
@@ -61685,19 +61689,28 @@ async function readMarker(outputsDir, canvasPath) {
61685
61689
  ...Number.isInteger(parsed.pid) ? { pid: parsed.pid } : {},
61686
61690
  ...typeof parsed.token === "string" ? { token: parsed.token } : {},
61687
61691
  ...num4(parsed.startedAt) !== void 0 ? { startedAt: num4(parsed.startedAt) } : {},
61688
- ...num4(parsed.heartbeatAt) !== void 0 ? { heartbeatAt: num4(parsed.heartbeatAt) } : {}
61692
+ ...num4(parsed.heartbeatAt) !== void 0 ? { heartbeatAt: num4(parsed.heartbeatAt) } : {},
61693
+ ...typeof parsed.sourceSha === "string" ? { sourceSha: parsed.sourceSha } : {}
61689
61694
  };
61690
61695
  } catch {
61691
61696
  return null;
61692
61697
  }
61693
61698
  }
61694
- async function markRunInFlight(outputsDir, canvasPath, runId) {
61699
+ async function markRunInFlight(outputsDir, canvasPath, runId, sourceSha) {
61695
61700
  const file = markerFile(outputsDir, canvasPath);
61696
61701
  const token = randomUUID();
61697
61702
  const startedAt = Date.now();
61698
61703
  const write = (heartbeatAt) => writeFile8(
61699
61704
  file,
61700
- JSON.stringify({ runId, pid: process.pid, token, canvasPath: path18.resolve(canvasPath), startedAt, heartbeatAt })
61705
+ JSON.stringify({
61706
+ runId,
61707
+ pid: process.pid,
61708
+ token,
61709
+ canvasPath: path18.resolve(canvasPath),
61710
+ startedAt,
61711
+ heartbeatAt,
61712
+ ...sourceSha ? { sourceSha } : {}
61713
+ })
61701
61714
  );
61702
61715
  try {
61703
61716
  await mkdir4(path18.dirname(file), { recursive: true });
@@ -62256,12 +62269,25 @@ async function takeUnbilledSpend(cacheDir) {
62256
62269
  async function sendBillingSpend(cacheDir, usage, send) {
62257
62270
  try {
62258
62271
  await send();
62272
+ return null;
62259
62273
  } catch (e) {
62260
62274
  await holdUnbilledSpend(cacheDir, usage).catch(() => {
62261
62275
  });
62262
- throw e;
62276
+ return e instanceof Error ? e.message : String(e);
62263
62277
  }
62264
62278
  }
62279
+ function holdWhenSettled(cacheDir, spendOf) {
62280
+ const pending = [];
62281
+ return {
62282
+ settled: (run2, outputs) => {
62283
+ pending.push(holdUnbilledSpend(cacheDir, spendOf(run2, outputs)).catch(() => {
62284
+ }));
62285
+ },
62286
+ drained: async () => {
62287
+ await Promise.all(pending);
62288
+ }
62289
+ };
62290
+ }
62265
62291
 
62266
62292
  // src/commands/canvas/viewer-check.ts
62267
62293
  var VIEWER_QUESTIONS = ["offer", "for_whom", "next_step"];
@@ -63215,12 +63241,13 @@ ${describeRewrites(prepared.rewrites)}
63215
63241
  const sourceSha = prepared.sourceSha;
63216
63242
  const client = opts.record === false ? null : buildBackendClient();
63217
63243
  const outputsDir = opts.outputsDir ? path25.resolve(opts.outputsDir) : canvasRoot;
63218
- const { runId, resumed, source, concurrentRunId, rendering } = await resolveRunId({
63244
+ const { runId, resumed, source, sameSource, concurrentRunId, rendering } = await resolveRunId({
63219
63245
  explicitRunId: opts.runId,
63220
63246
  adoptedRunId: adoptRunId,
63221
63247
  fresh: opts.fresh === true || opts.fix !== void 0 || opts.useVariant !== void 0 || relaidFrom !== void 0,
63222
63248
  outputsDir,
63223
63249
  canvasPath: filePath,
63250
+ sourceSha,
63224
63251
  remote: client && creativeSlug && sourceSha ? { creativeSlug, sourceSha, getActiveRun: (slug, sha) => client.getActiveRun(slug, sha) } : void 0
63225
63252
  });
63226
63253
  if (rendering) {
@@ -63246,7 +63273,7 @@ ${describeRewrites(prepared.rewrites)}
63246
63273
  creativeDir: path25.dirname(filePath),
63247
63274
  cacheDir,
63248
63275
  slug: creativeSlug,
63249
- skip: opts.fix !== void 0 || opts.useVariant !== void 0 || relaidFrom !== void 0 ? "fix" : resumed ? "resume" : opts.skipViewerCheck ? "asked" : null,
63276
+ skip: opts.fix !== void 0 || opts.useVariant !== void 0 || relaidFrom !== void 0 ? "fix" : resumed && sameSource ? "resume" : opts.skipViewerCheck ? "asked" : null,
63250
63277
  lookups: liveViewerLookups(path25.dirname(canvasRoot)),
63251
63278
  model: VIEWER_CHECK_MODEL,
63252
63279
  ask: gatewayViewerModel(VIEWER_CHECK_MODEL, (usage) => viewerUsage.push(usage))
@@ -63293,7 +63320,7 @@ ${describeRewrites(prepared.rewrites)}
63293
63320
  abort.abort(new Error(`aborted by ${signalName}`));
63294
63321
  });
63295
63322
  }
63296
- const inFlight = await markRunInFlight(outputsDir, filePath, runId);
63323
+ const inFlight = await markRunInFlight(outputsDir, filePath, runId, sourceSha);
63297
63324
  const clearMarker = () => {
63298
63325
  inFlight.stop();
63299
63326
  return clearRunMarker(outputsDir, filePath, inFlight.token);
@@ -63328,15 +63355,20 @@ ${describeRewrites(prepared.rewrites)}
63328
63355
  );
63329
63356
  }
63330
63357
  }
63331
- const record = client ? recordVia(client) : null;
63358
+ const record = client ? (payload) => client.recordRun(payload) : null;
63332
63359
  const finalLabels = finalOutputLabelsFromCanvas(parsed) ?? void 0;
63333
63360
  const progress = record ? new RunProgressTracker(runId, recordMeta, finalLabels) : null;
63334
63361
  const poster = record ? new RunRecordPoster(record) : null;
63335
- const flushBilled = (p, payload) => sendBillingSpend(cacheDir, payload.reviewUsage ?? [], () => p.flush(payload));
63362
+ const flushBilled = async (p, payload) => {
63363
+ const failure = await sendBillingSpend(cacheDir, payload.reviewUsage ?? [], () => p.flush(payload));
63364
+ if (failure !== null) process.stderr.write(`[warn] run record not persisted (${failure})
63365
+ `);
63366
+ };
63336
63367
  if (progress && poster) {
63337
63368
  poster.startKeepalive(() => progress.hasPlan() ? progress.snapshot() : null);
63338
63369
  }
63339
63370
  const frameUrls = [];
63371
+ const readerSpend = holdWhenSettled(cacheDir, (run2, outputs) => prefilterSpend(parsed, { [run2.node_id]: outputs }, [run2]));
63340
63372
  const isFrameNode = (id) => parsed.nodes?.find((n) => n.id === id)?.type === "image_generate";
63341
63373
  try {
63342
63374
  const policy = opts.cachePolicy ?? "read_write";
@@ -63351,6 +63383,7 @@ ${describeRewrites(prepared.rewrites)}
63351
63383
  // reporting progress to a backend — without it a checkpoint stops with nothing to
63352
63384
  // show, which is the only thing a checkpoint is for.
63353
63385
  onProgress: (event) => {
63386
+ if (event.kind === "node_settled") readerSpend.settled(event.run, event.outputs);
63354
63387
  if (event.kind === "node_settled" && isFrameNode(event.run.node_id)) {
63355
63388
  for (const out of Object.values(event.outputs ?? {})) {
63356
63389
  const url = out?.url;
@@ -63373,6 +63406,7 @@ ${describeRewrites(prepared.rewrites)}
63373
63406
  if (round4?.allowed && creativeSlug) await settleSpentRender(canvasRoot, creativeSlug, optionalChatId() ?? null);
63374
63407
  const roundAfter = round4 ? { renders: round4.renders, of: RENDERS_PER_ROUND } : null;
63375
63408
  const reviewable = videoPathFromOutput(result.output);
63409
+ await readerSpend.drained();
63376
63410
  const reviewUsage = poster ? await takeUnbilledSpend(cacheDir) : [];
63377
63411
  const review = reviewable ? await reviewRenderedVideo({
63378
63412
  video: reviewable,
@@ -63389,7 +63423,6 @@ ${describeRewrites(prepared.rewrites)}
63389
63423
  round: roundAfter,
63390
63424
  viewer: viewerCheck?.viewer ?? null
63391
63425
  });
63392
- if (staticReview) reviewUsage.push(...prefilterSpend(parsed, result.outputs_by_node, result.node_runs));
63393
63426
  const hints2 = staticReview ? staticReview.hints : reviewable ? review === null ? [RENDER_REVIEW_UNAVAILABLE] : review.length === 0 ? ["Reviewed the finished video frame by frame \u2014 nothing to report."] : [
63394
63427
  `Reviewed the finished video and found ${review.length} thing${review.length === 1 ? "" : "s"} to fix. Show the user what is wrong before you show them the ad.`,
63395
63428
  ...review.map((f) => `${f.severity === "blocking" ? "Must fix" : "Should fix"} \u2014 ${f.what}`),
@@ -63444,6 +63477,7 @@ ${describeRewrites(prepared.rewrites)}
63444
63477
  );
63445
63478
  } catch (e) {
63446
63479
  const failedPayload = async (message) => {
63480
+ await readerSpend.drained();
63447
63481
  const payload = progress?.hasPlan() ? progress.failedSnapshot(message) : buildFailedRunRecord(runId, message, recordMeta);
63448
63482
  const held = await takeUnbilledSpend(cacheDir);
63449
63483
  return held.length > 0 ? { ...payload, reviewUsage: held } : payload;
@@ -63525,17 +63559,6 @@ function buildBackendClient() {
63525
63559
  return null;
63526
63560
  }
63527
63561
  }
63528
- function recordVia(client) {
63529
- return async (payload) => {
63530
- try {
63531
- await client.recordRun(payload);
63532
- } catch (e) {
63533
- const msg = e instanceof Error ? e.message : String(e);
63534
- process.stderr.write(`[warn] run record not persisted (${msg})
63535
- `);
63536
- }
63537
- };
63538
- }
63539
63562
  var sleep2 = (ms) => new Promise((resolve5) => setTimeout(resolve5, ms));
63540
63563
  async function postInitialRunRecord(client, payload) {
63541
63564
  for (let attempt = 0; attempt < 3; attempt++) {