@koda-sl/baker-cli 0.124.0-dev.2ddde71d7 → 0.124.0-dev.8e4328629

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/README.md CHANGED
@@ -2132,8 +2132,6 @@ Auto-ingests with prefetched bytes (no double-fetch). The screenshot bytes thems
2132
2132
 
2133
2133
  ScreenshotOne caches captures for 30 days, so re-shotting the same URL within that window returns the cached capture.
2134
2134
 
2135
- If the target page is unreachable or returns a non-2xx status (e.g. a 404 path or a login wall), the command fails with an actionable `VALIDATION_ERROR` naming the page and the status it returned, plus a `fix` hint — verify the URL and retry, or continue without the screenshot. It no longer surfaces a generic "Internal server error".
2136
-
2137
2135
  **Flags:**
2138
2136
 
2139
2137
  | Flag | Description |
@@ -2504,46 +2502,6 @@ Rules:
2504
2502
 
2505
2503
  ---
2506
2504
 
2507
- ### Marketing Tags (`baker tags`)
2508
-
2509
- Read the client's marketing/analytics tags (Meta pixel, GA4, Google Ads, GTM, Clarity, Hotjar, PostHog, …) — production tags overlaid with the changes staged in this chat.
2510
-
2511
- **The CLI is read-only.** Every tag change (create, edit, delete) goes through the `request_tag_input` tool (`baker_ui` MCP server): the agent proposes one or more changes — each becomes a tab in one blocking approval form — pre-filling the non-secret fields it knows; the user reviews, edits, fills secret fields, and approves or skips each tab. Approved changes stage on the chat and apply when the chat is published; discarding the chat drops them.
2512
-
2513
- `BAKER_CHAT_ID` must be set.
2514
-
2515
- ```bash
2516
- baker tags list # effective view: production + staged, full readable config + secret status
2517
- baker tags draft # review the staged changes awaiting publish
2518
- ```
2519
-
2520
- Notes:
2521
-
2522
- - **`list` prints each tag's full readable config.** Every non-secret field is shown in full under the tag — the Clarity `projectId`, GA4 `measurementId`, the entire custom `code` snippet, etc. — so the agent reuses a stored value to pre-fill a follow-up change instead of asking the user for something already installed. Secrets are never among these fields. (`--json` emits the same data as the raw envelope.)
2523
- - **Secrets never travel through this CLI or the chat.** Secret fields (`accessToken`, `apiSecret`, `authorizationToken`, `apiKey`, `conversionToken`, `oauthProviderId`) are entered only in the dashboard's secure tag form and flow straight into the staged draft; tool responses only ever name which secret fields are set/pending.
2524
- - Staged creates get a server-generated `tag_temp_*` ref (returned in the tool result and printed by `list`). Use it (or a real tag id) as flow side-effect `tagIds` — the published tag keeps resolving under the temp ref.
2525
- - Proposing a delete on a `tag_temp_*` ref drops the staged create instead.
2526
- - Single-instance types (`code`, `posthog`, `datafast`) reject a second instance against the chat's effective view.
2527
- - Conflicts at publish (tag deleted in the dashboard, config invalid) skip the op with a recorded reason — they never block the publish.
2528
-
2529
- ### Forms / Flows (`baker flows`)
2530
-
2531
- Read this workspace's Forms (flows) and the configuration status of each one's **confidential fields** — side-effect connection secrets, OAuth connections, and third-party field definitions (HubSpot, Calendly, HighLevel, SavvyCal). Reads the local `_data.json` files; no secret values are ever decrypted or printed.
2532
-
2533
- **The CLI is read-only.** Author a Form's structure (nodes, conditions, side effects, field mappings) by editing its `_data.json` with the flow-builder skill. Configure the confidential fields it reports as `[missing]` / `[needs connection]` / `not selected` through the `request_flow_input` tool (`baker_ui` MCP server): the agent authors the surrounding structure, references it by `nodeId`/`sideEffectId`, and the user enters secrets, connects/picks OAuth accounts, and picks third-party forms in the dashboard. Those values are written (encrypted, where a secret) into the Form on the chat's branch and go live when the chat is published.
2534
-
2535
- ```bash
2536
- baker flows list # every Form + how many confidential fields still need setup
2537
- baker flows show contact # one Form's confidential fields and their status
2538
- baker flows show contact --full # include the full flow tree (secret values redacted)
2539
- ```
2540
-
2541
- Notes:
2542
-
2543
- - **Secrets never travel through this CLI or the chat.** `show` reports only whether each field is configured (`[set]`/`[missing]`, `[connected]`/`[needs connection]`, selected/not selected) — never a value. Configured secrets appear only as `[configured]` ciphertext markers.
2544
- - Confidential side-effect types: `httpWebhook`, `zapier`, `crmble` (typed credentials); `pipedrive`, `googleSpreadsheet`, `hubspotForm`, `goHighlevelContact` (OAuth connection + resource); `email`. Widget node types needing a resource pick: `calendly`, `savvycal`, `hubspot`, `hubspotMeeting`, `highlevel`, `highlevelForm`.
2545
- - `request_flow_input` changes stage on the chat's branch and apply when the chat is published; discarding the chat drops them.
2546
-
2547
2505
  ### Action Items (`baker actions`)
2548
2506
 
2549
2507
  Manage action items for the current chat. Most write operations stage on the chat's draft and apply atomically when the chat is published. Claim/release run live so other chats can see who's working on what.
@@ -3987,7 +3945,6 @@ Validate, then execute the graph. Blocks until done. Logs one line per node. Ret
3987
3945
  | `--cache-policy <policy>` | `read_write` | `read_write`, `bypass`, or `read_only`. |
3988
3946
  | `--concurrency <n>` | `5` (or `BAKER_CANVAS_CONCURRENCY`) | Max nodes executing at once within a layer. |
3989
3947
  | `--remote-cache <on\|off>` | `on` (or `BAKER_CANVAS_REMOTE_CACHE`) | Company-scoped remote cache + durable asset persistence. |
3990
- | `--max-credits <n>` | uncapped (or `BAKER_CANVAS_MAX_CREDITS`) | Credit ceiling: aborts before billing when the estimate exceeds it, and at layer boundaries once actual spend does. Completed nodes stay cached, so retrying with a higher cap loses nothing. |
3991
3948
  | `--no-record` | records | Skip posting the durable run-history record (and its live progress). |
3992
3949
 
3993
3950
  **Run history streams live.** The run posts its plan (every node + its dependency edges) the moment validation passes, then re-posts a progress snapshot as each node starts and settles — the dashboard's creative workflow graph shows nodes flipping pending → running → done in real time, with each node's outputs attached as they land. A failed run keeps its per-node trail (what completed, what died). All best-effort: an unreachable backend never changes the run's outcome.
@@ -4112,25 +4069,7 @@ baker canvas run ./static-ad.canvas.json
4112
4069
 
4113
4070
  Scaffolding runs (and bills) the two vision passes; **running** the result generates a billed image. `baker canvas validate` does not check that the `[TODO]` paths exist — supply the real files before `run`.
4114
4071
 
4115
- **Resuming an interrupted run.** A long `baker canvas run` (multi-clip video) that is killed mid-render — session end, sandbox pause — leaves a marker under the outputs dir. The next `baker canvas run` of the same canvas automatically **resumes** that run: it reuses the run id so still-running billed jobs re-attach instead of being abandoned and re-billed, and completed nodes come from the cache. Resume also works from a **different workspace or a fresh sandbox**: when no local marker survives, the run history is consulted and an interrupted (or stale) run of the exact same canvas is adopted automatically. Ctrl-C / SIGTERM aborts gracefully — no new nodes dispatch, a resumable snapshot is flushed, and the marker survives. A clean completion (or a handled failure) clears the marker, so a normal re-run starts a fresh generation. Force a new run with `--fresh`, or pin a specific run with `--run-id <id>` (also the escape hatch to adopt a run that is reported as concurrently live). Independent same-layer nodes (e.g. video clips) fan out in parallel up to `--parallel`/`--concurrency` (default 8; env `BAKER_CANVAS_CONCURRENCY`).
4116
-
4117
- #### `baker canvas rerun <slug> [flags]`
4118
-
4119
- Re-run a creative's latest recorded canvas **from run history** — no local files needed. Every `canvas run` of a creative uploads a portable snapshot (the canvas JSON plus the local files it ingests: prompt blueprints, composition dirs, reference images) to durable storage and records it on the run. `rerun` restores those files into `src/creatives/<slug>/` (sha-verified; files already matching are left untouched) and then executes the normal run flow — so an interrupted run **resumes** (in-flight jobs re-attach) and a completed one re-renders from the cache at zero credits.
4120
-
4121
- | Flag | Default | Meaning |
4122
- | --- | --- | --- |
4123
- | `--force-remote` | off | Overwrite local files whose content differs from the snapshot (otherwise a conflict aborts with the differing paths). |
4124
- | `--fresh` | off | Start a new run id instead of resuming an interrupted one. |
4125
- | `--regenerate <ids>` | — | Same as `canvas run --regenerate`. |
4126
- | `--concurrency <n>` | — | Same as `canvas run --concurrency`. |
4127
-
4128
- ```bash
4129
- baker canvas rerun spring-offer-4x5
4130
- baker canvas rerun spring-offer-4x5 --force-remote --regenerate gen_4x5
4131
- ```
4132
-
4133
- Use it when a creative was built in another conversation (or its sandbox is gone) and you need to continue or re-render it here. Files the snapshot could not include (missing at run time, or oversized) are listed as warnings — supply those locally only if the run actually needs to regenerate the nodes that read them.
4072
+ **Resuming an interrupted run.** A long `baker canvas run` (multi-clip video) that is killed mid-render — session end, sandbox pause — leaves a marker under the outputs dir. The next `baker canvas run` of the same canvas automatically **resumes** that run: it reuses the run id so still-running billed jobs re-attach instead of being abandoned and re-billed, and completed nodes come from the cache. A clean completion (or a handled failure) clears the marker, so a normal re-run starts a fresh generation. Force a new run with `--fresh`, or pin a specific run with `--run-id <id>`. Independent same-layer nodes (e.g. video clips) fan out in parallel up to `--parallel`/`--concurrency` (default 8; env `BAKER_CANVAS_CONCURRENCY`).
4134
4073
 
4135
4074
  #### `baker canvas inspect <run_id> [--thumbnails]`
4136
4075
 
@@ -812,10 +812,10 @@ var BackendClient = class {
812
812
  await sleep(pollInterval(attempt));
813
813
  }
814
814
  }
815
- presignAssetUpload(sha256, mime, signal, purpose) {
815
+ presignAssetUpload(sha256, mime, signal) {
816
816
  return this.http.postJson(
817
817
  "/api/canvas/assets/presign",
818
- { sha256, mime, purpose },
818
+ { sha256, mime },
819
819
  signal
820
820
  );
821
821
  }
@@ -840,39 +840,6 @@ var BackendClient = class {
840
840
  async recordRun(payload, signal) {
841
841
  await this.http.postJson("/api/canvas/runs", payload, signal);
842
842
  }
843
- /**
844
- * Resumable-run lookup — GET /api/canvas/runs/active. Returns the newest
845
- * still-running/interrupted run for the creative (pinned to the exact canvas
846
- * sha), so a fresh sandbox can adopt its run id and re-attach billed
847
- * in-flight jobs. Null on no active run — or an older backend without the
848
- * route (both 404).
849
- */
850
- async getActiveRun(creativeSlug, canvasSha, signal) {
851
- const params = new URLSearchParams({ slug: creativeSlug });
852
- if (canvasSha) params.set("sha", canvasSha);
853
- try {
854
- const res = await this.http.getJson(`/api/canvas/runs/active?${params}`, signal);
855
- return res.run;
856
- } catch (e) {
857
- if (e instanceof BackendHttpError && "status" in e.detail && e.detail.status === 404) return null;
858
- throw e;
859
- }
860
- }
861
- /**
862
- * Portable-rerun lookup — GET /api/canvas/runs/latest. The newest run for
863
- * the creative that recorded a canvas snapshot manifest; null when none
864
- * exists (or the backend predates the route — both 404).
865
- */
866
- async getLatestSnapshotRun(creativeSlug, signal) {
867
- const params = new URLSearchParams({ slug: creativeSlug });
868
- try {
869
- const res = await this.http.getJson(`/api/canvas/runs/latest?${params}`, signal);
870
- return res.run;
871
- } catch (e) {
872
- if (e instanceof BackendHttpError && "status" in e.detail && e.detail.status === 404) return null;
873
- throw e;
874
- }
875
- }
876
843
  /**
877
844
  * Chat-scoped blueprint sync — POST /api/creatives/definition. Lets the
878
845
  * dashboard draw a scaffolded creative's workflow graph BEFORE the first run.
@@ -940,14 +907,6 @@ var NodeExecutionError = class extends CanvasError {
940
907
  this.cause = cause;
941
908
  }
942
909
  };
943
- var RunAbortedError = class extends CanvasError {
944
- reason;
945
- constructor(reason, message2) {
946
- super(message2);
947
- this.name = "RunAbortedError";
948
- this.reason = reason;
949
- }
950
- };
951
910
  var LayerExecutionError = class extends CanvasError {
952
911
  failures;
953
912
  constructor(failures) {
@@ -1773,43 +1732,18 @@ function message(e) {
1773
1732
  }
1774
1733
 
1775
1734
  // src/engine/nodes/remote/upload.ts
1776
- var PUT_MAX_ATTEMPTS = 4;
1777
- var sleep2 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
1778
1735
  async function presignAndPut(args) {
1779
- let lastFailure = null;
1780
- for (let attempt = 0; attempt < PUT_MAX_ATTEMPTS; attempt++) {
1781
- if (args.ctx.signal?.aborted) break;
1782
- if (attempt > 0) await sleep2(500 * 2 ** (attempt - 1) * (1 + Math.random() * 0.25));
1783
- const result = await attemptPresignedPut(args);
1784
- if (result.ok) return result.url;
1785
- lastFailure = result.failure;
1786
- if (!result.retryable) break;
1787
- }
1788
- throw lastFailure ?? new Error("upload: aborted before the PUT could start");
1789
- }
1790
- async function attemptPresignedPut(args) {
1791
- try {
1792
- const { putUrl, publicUrl } = await args.ctx.client.presignAssetUpload(args.sha256, args.mime, args.ctx.signal);
1793
- const putRes = await fetch(putUrl, {
1794
- method: "PUT",
1795
- body: new Uint8Array(args.bytes),
1796
- headers: { "Content-Type": args.mime },
1797
- signal: args.ctx.signal
1798
- });
1799
- if (putRes.ok) return { ok: true, url: publicUrl };
1800
- return {
1801
- ok: false,
1802
- failure: new Error(`upload: presigned PUT failed ${putRes.status} ${putRes.statusText}`),
1803
- // Only transient statuses warrant a replay — a 400/403 fails identically every attempt.
1804
- retryable: putRes.status >= 500 || putRes.status === 429 || putRes.status === 408
1805
- };
1806
- } catch (e) {
1807
- return {
1808
- ok: false,
1809
- failure: e instanceof Error ? e : new Error(String(e)),
1810
- retryable: args.ctx.signal?.aborted !== true
1811
- };
1736
+ const { putUrl, publicUrl } = await args.ctx.client.presignAssetUpload(args.sha256, args.mime, args.ctx.signal);
1737
+ const putRes = await fetch(putUrl, {
1738
+ method: "PUT",
1739
+ body: new Uint8Array(args.bytes),
1740
+ headers: { "Content-Type": args.mime },
1741
+ signal: args.ctx.signal
1742
+ });
1743
+ if (!putRes.ok) {
1744
+ throw new Error(`upload: presigned PUT failed ${putRes.status} ${putRes.statusText}`);
1812
1745
  }
1746
+ return publicUrl;
1813
1747
  }
1814
1748
  async function ensureUploaded(ref, ctx) {
1815
1749
  if (ref.url) return ref;
@@ -3131,12 +3065,6 @@ var Engine = class {
3131
3065
  async run(input, opts = {}) {
3132
3066
  const validation = await this.validateDeep(input);
3133
3067
  if (!validation.ok) throw new ValidationError(validation.issues);
3134
- if (opts.max_credits !== void 0 && validation.estimatedCredits > opts.max_credits) {
3135
- throw new RunAbortedError(
3136
- "cost_cap",
3137
- `estimated ${validation.estimatedCredits} credits exceeds the ${opts.max_credits}-credit cap \u2014 nothing was billed; raise --max-credits or shrink the canvas`
3138
- );
3139
- }
3140
3068
  const canvas = validation.canvas;
3141
3069
  const runId = opts.run_id ?? `r_${ulid()}`;
3142
3070
  const writer = new OutputWriter({ outputsDir: this.outputsDir, runId });
@@ -3187,17 +3115,7 @@ var Engine = class {
3187
3115
  const layers = topologicalLayers(graph);
3188
3116
  const limit = resolveConcurrency(opts.concurrency);
3189
3117
  for (const layer of layers) {
3190
- if (opts.signal?.aborted) throw new RunAbortedError("signal", "run aborted before layer dispatch");
3191
- if (opts.max_credits !== void 0 && counters.totalCredits > opts.max_credits) {
3192
- throw new RunAbortedError(
3193
- "cost_cap",
3194
- `spent ${counters.totalCredits} credits, over the ${opts.max_credits}-credit cap \u2014 completed nodes are cached; raise --max-credits to continue where this stopped`
3195
- );
3196
- }
3197
3118
  const settled = await mapWithConcurrency(layer, limit, (nodeId) => {
3198
- if (opts.signal?.aborted) {
3199
- return Promise.reject(new RunAbortedError("signal", "run aborted before node dispatch"));
3200
- }
3201
3119
  this.emitProgress(opts, { kind: "node_start", node_id: nodeId });
3202
3120
  return this.executeOne(canvas, nodeId, outputs, runId, writer, opts, needsBytes.has(nodeId)).then((r) => {
3203
3121
  if (r.cached) counters.cachedNodes++;
@@ -3220,12 +3138,10 @@ var Engine = class {
3220
3138
  settled.forEach((result, i) => {
3221
3139
  const nodeId = layer[i];
3222
3140
  if (result.status === "rejected" && nodeId) {
3223
- if (result.reason instanceof RunAbortedError) return;
3224
3141
  failures.push({ nodeId, reason: result.reason });
3225
3142
  this.emitProgress(opts, { kind: "node_failed", node_id: nodeId });
3226
3143
  }
3227
3144
  });
3228
- if (opts.signal?.aborted) throw new RunAbortedError("signal", "run aborted by signal");
3229
3145
  if (failures.length === 1 && failures[0]) throw failures[0].reason;
3230
3146
  if (failures.length > 1) throw new LayerExecutionError(failures);
3231
3147
  }
@@ -7013,9 +6929,7 @@ function createEngineFromEnv(opts = {}) {
7013
6929
  }
7014
6930
 
7015
6931
  export {
7016
- BackendClient,
7017
6932
  requireCredentialsFromEnv,
7018
- RunAbortedError,
7019
6933
  LayerExecutionError,
7020
6934
  describeFailureReason,
7021
6935
  SEEDANCE_DURATIONS,
@@ -7031,7 +6945,7 @@ export {
7031
6945
  sha256Hex,
7032
6946
  elementMentionKeywords,
7033
6947
  toModelSafeImage,
7034
- BackendClient2,
6948
+ BackendClient2 as BackendClient,
7035
6949
  Engine2 as Engine,
7036
6950
  LocalAssetStore2 as LocalAssetStore,
7037
6951
  LocalCacheStore2 as LocalCacheStore,
@@ -7041,4 +6955,4 @@ export {
7041
6955
  defaultRegistry,
7042
6956
  createEngineFromEnv
7043
6957
  };
7044
- //# sourceMappingURL=chunk-TKL2CJ6G.js.map
6958
+ //# sourceMappingURL=chunk-Q3K5TXC6.js.map