@koda-sl/baker-cli 0.125.0 → 0.129.1-dev.972f3c9aa

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.
@@ -15,12 +15,33 @@ type ExecRequest = {
15
15
  /** Run-scoped dedupe key: the backend replays the stored response for a
16
16
  * repeated key instead of re-dispatching to the provider (and re-charging). */
17
17
  idempotency_key?: string;
18
+ /** Run + node identity, so a completed async job can be mapped back to its
19
+ * frozen run's node by the backend stale-run reconciliation sweep. */
20
+ canvas_run_id?: string;
21
+ node_id?: string;
18
22
  };
19
23
  type ExecResponse = {
20
24
  outputs: Record<string, RawAssetOutput | RawAssetOutput[] | unknown>;
21
25
  credits_charged?: number;
22
26
  duration_ms?: number;
23
27
  };
28
+ /** A resumable run as reported by `GET /api/canvas/runs/active`. */
29
+ type ActiveRunInfo = {
30
+ runId: string;
31
+ status: "running" | "completed" | "failed";
32
+ interrupted?: boolean;
33
+ updatedAt?: number;
34
+ canvasSha?: string;
35
+ canvasSnapshotUrl?: string;
36
+ };
37
+ /** The newest snapshot-bearing run for a creative — `GET /api/canvas/runs/latest`. */
38
+ type SnapshotRunInfo = {
39
+ runId: string;
40
+ status: "running" | "completed" | "failed";
41
+ interrupted?: boolean;
42
+ canvasSha?: string;
43
+ canvasSnapshotUrl: string;
44
+ };
24
45
  type ArtifactResponse = {
25
46
  artifact: {
26
47
  kind: string;
@@ -43,10 +64,37 @@ declare class BackendClient$1 {
43
64
  });
44
65
  exec(req: ExecRequest, signal?: AbortSignal): Promise<ExecResponse>;
45
66
  private pollJob;
46
- presignAssetUpload(sha256: string, mime: string, signal?: AbortSignal): Promise<{
67
+ presignAssetUpload(sha256: string, mime: string, signal?: AbortSignal, purpose?: "output" | "source" | "blueprint"): Promise<{
47
68
  putUrl: string;
48
69
  publicUrl: string;
49
70
  }>;
71
+ /** Remote cache lookup. A miss (404) — or an old backend without the route — returns null. */
72
+ getCacheEntry<T>(cacheKey: string, signal?: AbortSignal): Promise<T | null>;
73
+ putCacheEntry(entry: {
74
+ cacheKey: string;
75
+ }, signal?: AbortSignal): Promise<void>;
76
+ /** Durable run-history record — POST /api/canvas/runs (idempotent server-side on runId). */
77
+ recordRun(payload: unknown, signal?: AbortSignal): Promise<void>;
78
+ /**
79
+ * Resumable-run lookup — GET /api/canvas/runs/active. Returns the newest
80
+ * still-running/interrupted run for the creative (pinned to the exact canvas
81
+ * sha), so a fresh sandbox can adopt its run id and re-attach billed
82
+ * in-flight jobs. Null on no active run — or an older backend without the
83
+ * route (both 404).
84
+ */
85
+ getActiveRun(creativeSlug: string, canvasSha?: string, signal?: AbortSignal): Promise<ActiveRunInfo | null>;
86
+ /**
87
+ * Portable-rerun lookup — GET /api/canvas/runs/latest. The newest run for
88
+ * the creative that recorded a canvas snapshot manifest; null when none
89
+ * exists (or the backend predates the route — both 404).
90
+ */
91
+ getLatestSnapshotRun(creativeSlug: string, signal?: AbortSignal): Promise<SnapshotRunInfo | null>;
92
+ /**
93
+ * Chat-scoped blueprint sync — POST /api/creatives/definition. Lets the
94
+ * dashboard draw a scaffolded creative's workflow graph BEFORE the first run.
95
+ * Additive on the backend (never archives siblings, never sets definitionPath).
96
+ */
97
+ syncCreativeDefinition(payload: unknown, signal?: AbortSignal): Promise<void>;
50
98
  getArtifact(kind: string, name: string, version?: string, signal?: AbortSignal): Promise<ArtifactResponse>;
51
99
  }
52
100
 
@@ -78,6 +126,11 @@ declare const CanvasSchema: z.ZodObject<{
78
126
  todo: z.ZodOptional<z.ZodUnknown>;
79
127
  video: z.ZodOptional<z.ZodObject<{
80
128
  duration_s: z.ZodNumber;
129
+ timeline: z.ZodOptional<z.ZodObject<{
130
+ spine_node: z.ZodString;
131
+ expected_total_s: z.ZodNumber;
132
+ audio_mix_node: z.ZodOptional<z.ZodString>;
133
+ }, z.core.$strict>>;
81
134
  vo_segments: z.ZodDefault<z.ZodArray<z.ZodObject<{
82
135
  slot: z.ZodString;
83
136
  start_s: z.ZodNumber;
@@ -120,6 +173,7 @@ declare const CanvasSchema: z.ZodObject<{
120
173
  inputs: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
121
174
  params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
122
175
  when: z.ZodOptional<z.ZodUnknown>;
176
+ regenerate: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
123
177
  }, z.core.$strict>>;
124
178
  output: z.ZodOptional<z.ZodObject<{
125
179
  node: z.ZodString;
@@ -249,6 +303,14 @@ type ExecCtx = {
249
303
  /** Content-addressed cache key for this node execution. Remote delegation
250
304
  * derives its idempotency key from it so backend retries never double-charge. */
251
305
  cacheKey?: string;
306
+ /**
307
+ * Whether this node's outputs must be downloaded to the local content store.
308
+ * False when NO downstream consumer is a local (ffmpeg/magick) node — the
309
+ * backend already persisted the bytes to R2 with a durable sha256 URL, so the
310
+ * redundant R2→sandbox transfer is skipped and the ref is kept URL-only.
311
+ * Absent/true means download (the safe default for older call sites).
312
+ */
313
+ downloadOutputs?: boolean;
252
314
  client: BackendClient$1;
253
315
  assets: AssetStore;
254
316
  log: LogFn;
@@ -311,6 +373,12 @@ type NodeDefinition<I = unknown, P = unknown, O = unknown> = {
311
373
  outputs: z.ZodType<O>;
312
374
  /** "local" runs in-process; "remote" delegates to Convex via ctx.client */
313
375
  location: "local" | "remote";
376
+ /**
377
+ * Local node that only forwards asset refs and never reads their bytes
378
+ * (e.g. `collect`). Exempts its upstream producers from the forced R2→disk
379
+ * download local consumers otherwise trigger.
380
+ */
381
+ passthroughRefs?: true;
314
382
  cost?: CostFn<P>;
315
383
  validateExtra?: ValidateExtraFn;
316
384
  cacheKeyExtras?: CacheKeyExtrasFn;
@@ -339,13 +407,62 @@ type RunResult = {
339
407
  duration_ms: number;
340
408
  };
341
409
  outputs_dir: string;
410
+ node_runs: NodeRunRecord[];
411
+ };
412
+ type NodeRunRecord = {
413
+ node_id: string;
414
+ node_type: string;
415
+ cached: boolean;
416
+ duration_ms: number;
417
+ credits: number;
418
+ };
419
+ /**
420
+ * Live run telemetry: the plan (post-prune node list + dependency edges) fires
421
+ * once before any node executes, then start/settled/failed per node. Consumers
422
+ * stream these into run-history progress snapshots; a throwing consumer is
423
+ * swallowed — telemetry must never fail a paid run.
424
+ */
425
+ type RunProgressEvent = {
426
+ kind: "plan";
427
+ nodes: Array<{
428
+ node_id: string;
429
+ node_type: string;
430
+ deps: string[];
431
+ params: unknown;
432
+ }>;
433
+ } | {
434
+ kind: "node_start";
435
+ node_id: string;
436
+ } | {
437
+ kind: "node_settled";
438
+ run: NodeRunRecord;
439
+ outputs: Record<string, unknown>;
440
+ } | {
441
+ kind: "node_failed";
442
+ node_id: string;
342
443
  };
343
444
  type RunOptions = {
344
445
  signal?: AbortSignal;
345
446
  run_id?: string;
346
447
  cache_policy?: "read_write" | "bypass" | "read_only";
347
- /** Max nodes of one layer in flight at once; invalid or missing → 5. */
448
+ /** Max nodes of one layer in flight at once; invalid or missing → 8 (DEFAULT_CONCURRENCY). */
348
449
  concurrency?: number;
450
+ /**
451
+ * Credit ceiling (`--max-credits`). Enforced pre-flight against the deep
452
+ * validator's estimate (nothing billed) and at layer boundaries against
453
+ * actual spend — a boundary is the only point with no async job in flight,
454
+ * so aborting there strands nothing. Cached nodes cost 0, so a capped run
455
+ * retried with a higher cap loses no completed work.
456
+ */
457
+ max_credits?: number;
458
+ /**
459
+ * Node ids to force fresh for THIS run only (the `--regenerate` flag). Folds
460
+ * the run id into each named node's cache key so it re-renders regardless of
461
+ * the content cache, without editing the canvas. Persistent regeneration uses
462
+ * the per-node `regenerate` field instead.
463
+ */
464
+ regenerate?: ReadonlySet<string>;
465
+ onProgress?: (event: RunProgressEvent) => void;
349
466
  };
350
467
  type EngineOptions = {
351
468
  registry: NodeRegistry;
@@ -354,6 +471,13 @@ type EngineOptions = {
354
471
  cache: CacheStore;
355
472
  outputsDir: string;
356
473
  log?: LogFn;
474
+ /**
475
+ * Stamp durable canvas-assets URLs onto fresh node outputs before they are
476
+ * cached — the precondition for remote cache portability and run-history
477
+ * records. Best-effort: a failed upload logs a warning and keeps the entry
478
+ * local-only, never fails the node.
479
+ */
480
+ persistAssets?: boolean;
357
481
  };
358
482
  declare class Engine$1 {
359
483
  private readonly registry;
@@ -362,6 +486,7 @@ declare class Engine$1 {
362
486
  private readonly cache;
363
487
  private readonly outputsDir;
364
488
  private readonly log;
489
+ private readonly persistAssets;
365
490
  constructor(opts: EngineOptions);
366
491
  validate(canvas: unknown): {
367
492
  ok: true;
@@ -390,6 +515,8 @@ declare class Engine$1 {
390
515
  }>;
391
516
  run(input: unknown, opts?: RunOptions): Promise<RunResult>;
392
517
  private runLayers;
518
+ /** Progress consumers are observers only — an exception there must never fail the run. */
519
+ private emitProgress;
393
520
  /**
394
521
  * Dead-node elimination: when the canvas declares an `output`, execute only the
395
522
  * nodes that output transitively depends on. Orphaned nodes (left by an edit or
@@ -400,6 +527,13 @@ declare class Engine$1 {
400
527
  private writeFinal;
401
528
  private executeOne;
402
529
  private materializeNodeOutputs;
530
+ /**
531
+ * Download any URL-only asset ref reachable in a local node's inputs so the
532
+ * bytes are on disk before the local runner stages them. Returns a copy —
533
+ * refs are replaced, never mutated in place, so the producer's cached output
534
+ * (shared object) keeps its URL-only shape.
535
+ */
536
+ private materializeLocalInputs;
403
537
  }
404
538
 
405
539
  type ValidationResult = {
@@ -467,6 +601,13 @@ declare function createEngineFromEnv(opts?: {
467
601
  cacheDir?: string;
468
602
  outputsDir?: string;
469
603
  log?: (line: string) => void;
604
+ /**
605
+ * Layer the company-scoped remote cache over the local one (and stamp
606
+ * durable asset URLs onto fresh outputs) so a fresh sandbox re-runs an
607
+ * already-computed canvas at zero credits. Defaults to on; disable with
608
+ * `remoteCache: false` or env BAKER_CANVAS_REMOTE_CACHE=off.
609
+ */
610
+ remoteCache?: boolean;
470
611
  }): Engine$1;
471
612
 
472
613
  export { BackendClient, Engine, LocalAssetStore, LocalCacheStore, ValidationError, createEngineFromEnv, defaultRegistry, generateCatalog, validateCanvasDeep };
@@ -1,5 +1,5 @@
1
1
  import {
2
- BackendClient,
2
+ BackendClient2 as BackendClient,
3
3
  Engine,
4
4
  LocalAssetStore,
5
5
  LocalCacheStore,
@@ -8,7 +8,7 @@ import {
8
8
  defaultRegistry,
9
9
  generateCatalog,
10
10
  validateCanvasDeep
11
- } from "../chunk-4EPKHOTF.js";
11
+ } from "../chunk-J2LYFDVC.js";
12
12
  import "../chunk-5WRI5ZAA.js";
13
13
  export {
14
14
  BackendClient,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@koda-sl/baker-cli",
3
- "version": "0.125.0",
3
+ "version": "0.129.1-dev.972f3c9aa",
4
4
  "description": "AI-agent-first CLI for interacting with Baker, including the Baker creative canvas.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -15,7 +15,9 @@
15
15
  },
16
16
  "files": [
17
17
  "dist",
18
- "canvas"
18
+ "canvas",
19
+ "!canvas/.cache",
20
+ "!canvas/r_*"
19
21
  ],
20
22
  "scripts": {
21
23
  "build": "tsup",