@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 +1 -62
- package/dist/{chunk-TKL2CJ6G.js → chunk-Q3K5TXC6.js} +14 -100
- package/dist/chunk-Q3K5TXC6.js.map +1 -0
- package/dist/cli.js +1513 -2526
- package/dist/cli.js.map +1 -1
- package/dist/engine/index.d.ts +1 -40
- package/dist/engine/index.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-TKL2CJ6G.js.map +0 -1
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.
|
|
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
|
|
815
|
+
presignAssetUpload(sha256, mime, signal) {
|
|
816
816
|
return this.http.postJson(
|
|
817
817
|
"/api/canvas/assets/presign",
|
|
818
|
-
{ sha256, mime
|
|
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
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
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-
|
|
6958
|
+
//# sourceMappingURL=chunk-Q3K5TXC6.js.map
|