@koda-sl/baker-cli 0.421.0 → 0.422.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/README.md +7 -1
- package/dist/{chunk-GLPQQP5C.js → chunk-2S6QIXLX.js} +80 -9
- package/dist/{chunk-GLPQQP5C.js.map → chunk-2S6QIXLX.js.map} +1 -1
- package/dist/{chunk-LRRWIOJG.js → chunk-3X2EMLBQ.js} +3 -3
- package/dist/{chunk-YZLLC7DL.js → chunk-5JVAP5DC.js} +12 -1
- package/dist/chunk-5JVAP5DC.js.map +1 -0
- package/dist/{chunk-ZADYWHL5.js → chunk-G5L5FX2B.js} +3 -3
- package/dist/{chunk-FKFJKE75.js → chunk-S36N4SOX.js} +2 -2
- package/dist/{chunk-EXWIIEZP.js → chunk-XNFV6BQU.js} +4 -4
- package/dist/cli.js +703 -607
- package/dist/cli.js.map +1 -1
- package/dist/{client-CUHMSNK5.js → client-PIKJZFRA.js} +4 -4
- package/dist/engine/index.js +3 -3
- package/dist/{env-PJTJTW3N.js → env-6UAIAY4M.js} +6 -2
- package/dist/{output-A2ASA36U.js → output-CFDBWWYJ.js} +5 -5
- package/dist/{shared-LV6PIKFE.js → shared-3O5RKQYZ.js} +6 -6
- package/package.json +1 -1
- package/dist/chunk-YZLLC7DL.js.map +0 -1
- /package/dist/{chunk-LRRWIOJG.js.map → chunk-3X2EMLBQ.js.map} +0 -0
- /package/dist/{chunk-ZADYWHL5.js.map → chunk-G5L5FX2B.js.map} +0 -0
- /package/dist/{chunk-FKFJKE75.js.map → chunk-S36N4SOX.js.map} +0 -0
- /package/dist/{chunk-EXWIIEZP.js.map → chunk-XNFV6BQU.js.map} +0 -0
- /package/dist/{client-CUHMSNK5.js.map → client-PIKJZFRA.js.map} +0 -0
- /package/dist/{env-PJTJTW3N.js.map → env-6UAIAY4M.js.map} +0 -0
- /package/dist/{output-A2ASA36U.js.map → output-CFDBWWYJ.js.map} +0 -0
- /package/dist/{shared-LV6PIKFE.js.map → shared-3O5RKQYZ.js.map} +0 -0
package/README.md
CHANGED
|
@@ -5988,14 +5988,20 @@ baker canvas catalog --category audio --full
|
|
|
5988
5988
|
// Path source — an absolute path is used as-is, and so resolves only on the machine that wrote it.
|
|
5989
5989
|
// Keep canvases portable: creative canvases are validated for this (`absolute-reference`).
|
|
5990
5990
|
{ "id": "src", "type": "ingest", "params": { "source": "path", "path": "/abs/work/clip.mp4", "expect": "video" } }
|
|
5991
|
+
|
|
5992
|
+
// URL source — an earlier output, by its durable canvas-assets URL: the same bytes and sha back
|
|
5993
|
+
{ "id": "src", "type": "ingest", "params": { "source": "url", "url": "https://media.withbaker.com/canvas-assets/5b/5b50…c672.mp3", "expect": "audio" } }
|
|
5991
5994
|
```
|
|
5992
5995
|
|
|
5996
|
+
**Never point `path` into `canvas/`.** `canvas/.cache/` and `canvas/r_<id>/` are the engine's own working folder and are never committed, so a canvas that reads from them renders only where it was written. `canvas validate` and `canvas run` rewrite such a path to the durable URL of the same bytes (reported under `normalized_paths`), keeping the file first if the store does not hold it yet.
|
|
5997
|
+
|
|
5993
5998
|
**Strategy resolution** (deterministic from `source` + `expect` + URL extension for text):
|
|
5994
5999
|
|
|
5995
6000
|
| `source` | `expect` | URL / path | Strategy |
|
|
5996
6001
|
|----------|---------------|----------------------------------|-----------------|
|
|
5997
6002
|
| path | any | any | `local_file` — read from disk, sniff mime, upload to R2 via presign |
|
|
5998
|
-
| url |
|
|
6003
|
+
| url | any | `…/canvas-assets/<xx>/<sha>.<ext>` | `canvas_asset` — the stored asset, verbatim, its sha checked |
|
|
6004
|
+
| url | video / audio | any other | `yt_dlp` (works on platform URLs *and* direct file URLs via the generic extractor; verifies TLS against the system bundle) |
|
|
5999
6005
|
| url | image / json / font | any | `direct_fetch` (HTTP GET) |
|
|
6000
6006
|
| url | text | ends in `.txt` or `.md` | `direct_fetch` |
|
|
6001
6007
|
| url | text | anything else (HTML, PDF, …) | `firecrawl` `/v2/scrape` (extracted markdown — HTML/PDF made readable) |
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
debugLogHttp,
|
|
3
3
|
readBodyForLog
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-S36N4SOX.js";
|
|
5
5
|
import {
|
|
6
6
|
API_KEY_FORMAT_MESSAGE,
|
|
7
7
|
DIRECT_ROUTE,
|
|
8
8
|
__commonJS,
|
|
9
9
|
__toESM,
|
|
10
|
+
canvasAssetOriginsSetting,
|
|
10
11
|
captureProxyCredentials,
|
|
11
12
|
childEnvWith,
|
|
12
13
|
hasFrameVisionKey,
|
|
@@ -21,7 +22,7 @@ import {
|
|
|
21
22
|
refuseNonPublicUrl,
|
|
22
23
|
requireConnection,
|
|
23
24
|
shouldEscalate
|
|
24
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-5JVAP5DC.js";
|
|
25
26
|
|
|
26
27
|
// ../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/index.js
|
|
27
28
|
var require_safe_stable_stringify = __commonJS({
|
|
@@ -12495,6 +12496,38 @@ function isAssetRefLike(v) {
|
|
|
12495
12496
|
|
|
12496
12497
|
// src/engine/storage/remote-cache-store.ts
|
|
12497
12498
|
var CANVAS_ASSETS_URL_SEGMENT = "/canvas-assets/";
|
|
12499
|
+
function canvasAssetOrigins(setting = canvasAssetOriginsSetting()) {
|
|
12500
|
+
return (setting ?? "https://media.withbaker.com,https://media.dev-baker.com").split(",").map((origin) => origin.trim().replace(/\/+$/, "")).filter(Boolean);
|
|
12501
|
+
}
|
|
12502
|
+
function isCanvasAssetOrigin(url) {
|
|
12503
|
+
try {
|
|
12504
|
+
const { origin } = new URL(url);
|
|
12505
|
+
return canvasAssetOrigins().some((allowed) => {
|
|
12506
|
+
try {
|
|
12507
|
+
return new URL(allowed).origin === origin;
|
|
12508
|
+
} catch {
|
|
12509
|
+
return false;
|
|
12510
|
+
}
|
|
12511
|
+
});
|
|
12512
|
+
} catch {
|
|
12513
|
+
return false;
|
|
12514
|
+
}
|
|
12515
|
+
}
|
|
12516
|
+
function parseCanvasAssetUrl(url) {
|
|
12517
|
+
let pathname;
|
|
12518
|
+
try {
|
|
12519
|
+
const parsed = new URL(url);
|
|
12520
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") return null;
|
|
12521
|
+
pathname = parsed.pathname;
|
|
12522
|
+
} catch {
|
|
12523
|
+
return null;
|
|
12524
|
+
}
|
|
12525
|
+
const match = /\/canvas-assets\/([0-9a-f]{2})\/([0-9a-f]{64})\.([a-z0-9]+)$/.exec(pathname);
|
|
12526
|
+
if (!match) return null;
|
|
12527
|
+
const [, shard, sha256, ext] = match;
|
|
12528
|
+
if (shard === void 0 || sha256 === void 0 || ext === void 0 || !sha256.startsWith(shard)) return null;
|
|
12529
|
+
return { sha256, ext };
|
|
12530
|
+
}
|
|
12498
12531
|
function isPersistedAssetRef(ref) {
|
|
12499
12532
|
const { url, sha256 } = ref;
|
|
12500
12533
|
if (typeof url !== "string" || typeof sha256 !== "string") return false;
|
|
@@ -18202,6 +18235,7 @@ function ytDlpBlockSignal(stderr) {
|
|
|
18202
18235
|
var YT_DLP_BIN = "yt-dlp";
|
|
18203
18236
|
var YT_DLP_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
18204
18237
|
var YT_DLP_PROBE_TIMEOUT_MS = 60 * 1e3;
|
|
18238
|
+
var TRUST_SYSTEM_CERTS = ["--compat-options", "no-certifi"];
|
|
18205
18239
|
var YtDlpError = class extends Error {
|
|
18206
18240
|
constructor(message2, stderrTail) {
|
|
18207
18241
|
super(message2);
|
|
@@ -18222,6 +18256,7 @@ async function runYtDlp(args) {
|
|
|
18222
18256
|
"--no-warnings",
|
|
18223
18257
|
"--quiet",
|
|
18224
18258
|
"--write-info-json",
|
|
18259
|
+
...TRUST_SYSTEM_CERTS,
|
|
18225
18260
|
"-o",
|
|
18226
18261
|
outTemplate
|
|
18227
18262
|
];
|
|
@@ -18270,7 +18305,8 @@ async function probeYtDlp(args) {
|
|
|
18270
18305
|
// exits "Requested format is not available" and we learn nothing — measured
|
|
18271
18306
|
// against a stale build, which returned full metadata the moment this flag
|
|
18272
18307
|
// was added. Duration and id come from the page, not from a format.
|
|
18273
|
-
"--ignore-no-formats-error"
|
|
18308
|
+
"--ignore-no-formats-error",
|
|
18309
|
+
...TRUST_SYSTEM_CERTS
|
|
18274
18310
|
];
|
|
18275
18311
|
if (args.cookieDir) {
|
|
18276
18312
|
const cookieFile = await writeVimeoCookieFile(args.vimeoCookie, args.cookieDir);
|
|
@@ -18588,6 +18624,7 @@ var IngestOutputs = z44.object({ asset: AssetRef }).strict();
|
|
|
18588
18624
|
var RAW_TEXT_EXTENSIONS = [".txt", ".md"];
|
|
18589
18625
|
function resolveStrategy(params) {
|
|
18590
18626
|
if (params.source === "path") return "local_file";
|
|
18627
|
+
if (takesCanvasAssetVerbatim(params.url, params.expect)) return "canvas_asset";
|
|
18591
18628
|
switch (params.expect) {
|
|
18592
18629
|
case "video":
|
|
18593
18630
|
case "audio":
|
|
@@ -18619,8 +18656,8 @@ var ingestNode = defineNode({
|
|
|
18619
18656
|
version: "1.3.0",
|
|
18620
18657
|
category: "io",
|
|
18621
18658
|
location: "local",
|
|
18622
|
-
summary: "Ingest an external URL or a local file into the asset store. Declare the kind you expect (image/video/audio/text/json/font); the node picks the strategy. For source=url: yt-dlp for video/audio (YouTube/TikTok/Vimeo/etc. and direct file URLs), Firecrawl for HTML/PDF pages \u2192 markdown, direct HTTP fetch for binary URLs (images, fonts) and raw .txt/.md. For source=path: read from the
|
|
18623
|
-
when_to_use: 'Use as the on-ramp for any external asset a canvas needs. `expect` makes the output port statically typed so downstream wiring is checked before any byte is fetched. Pick `source: "url"` for portable canvas; pick `source: "path"` for
|
|
18659
|
+
summary: "Ingest an external URL or a local file into the asset store. Declare the kind you expect (image/video/audio/text/json/font); the node picks the strategy. For source=url: a canvas-assets URL (`\u2026/canvas-assets/<xx>/<sha>.<ext>`, the durable copy of an earlier output) is taken back byte-for-byte with its sha unchanged; yt-dlp for other video/audio (YouTube/TikTok/Vimeo/etc. and direct file URLs), Firecrawl for HTML/PDF pages \u2192 markdown, direct HTTP fetch for binary URLs (images, fonts) and raw .txt/.md. For source=path: read a committed file from the workspace and upload to R2.",
|
|
18660
|
+
when_to_use: 'Use as the on-ramp for any external asset a canvas needs. `expect` makes the output port statically typed so downstream wiring is checked before any byte is fetched. Pick `source: "url"` for portable canvas; pick `source: "path"` only for a file committed to the workspace (`src/brand/\u2026`, `src/creatives/<slug>/assets/\u2026`) \u2014 the canvas is rendered again in other Sessions, which have only what is committed. To reuse an earlier output (a voice take, a clip, a frame), ingest its canvas-assets URL from the run outputs: it comes back with the same sha, so nothing downstream re-renders. Never point `path` into `canvas/` (`canvas/.cache/`, `canvas/r_*`): that folder is not committed, and validate rewrites a cache path to its canvas-assets URL. Compose with other nodes for richer pipelines (e.g. `ingest expect=video` \u2192 `video_transcribe`).',
|
|
18624
18661
|
inputs: IngestInputs,
|
|
18625
18662
|
params: IngestParams,
|
|
18626
18663
|
outputs: IngestOutputs,
|
|
@@ -18644,6 +18681,8 @@ function runStrategy(strategy, params, ctx) {
|
|
|
18644
18681
|
return execLocalFile(params, ctx);
|
|
18645
18682
|
}
|
|
18646
18683
|
switch (strategy) {
|
|
18684
|
+
case "canvas_asset":
|
|
18685
|
+
return execCanvasAsset(params, ctx);
|
|
18647
18686
|
case "direct_fetch":
|
|
18648
18687
|
return execDirectFetch(params, ctx);
|
|
18649
18688
|
case "firecrawl":
|
|
@@ -18658,6 +18697,30 @@ function runStrategy(strategy, params, ctx) {
|
|
|
18658
18697
|
}
|
|
18659
18698
|
}
|
|
18660
18699
|
}
|
|
18700
|
+
function canvasAssetMime(url, expect) {
|
|
18701
|
+
const address = parseCanvasAssetUrl(url);
|
|
18702
|
+
const mime = address ? EXT_TO_MIME[address.ext] : void 0;
|
|
18703
|
+
return mime !== void 0 && inferKindFromMime(mime) === expect ? mime : null;
|
|
18704
|
+
}
|
|
18705
|
+
function takesCanvasAssetVerbatim(url, expect) {
|
|
18706
|
+
return isCanvasAssetOrigin(url) && canvasAssetMime(url, expect) !== null;
|
|
18707
|
+
}
|
|
18708
|
+
async function execCanvasAsset(params, ctx) {
|
|
18709
|
+
const address = parseCanvasAssetUrl(params.url);
|
|
18710
|
+
const mime = canvasAssetMime(params.url, params.expect);
|
|
18711
|
+
if (!address || mime === null) throw new Error(`ingest: invariant \u2014 canvas_asset strategy for ${params.url}`);
|
|
18712
|
+
try {
|
|
18713
|
+
return await ctx.assets.ingestRemote({
|
|
18714
|
+
kind: params.expect,
|
|
18715
|
+
url: params.url,
|
|
18716
|
+
sha256: address.sha256,
|
|
18717
|
+
mime,
|
|
18718
|
+
metadata: { strategy: "canvas_asset", source_url: params.url, ingested_at: (/* @__PURE__ */ new Date()).toISOString() }
|
|
18719
|
+
});
|
|
18720
|
+
} catch (e) {
|
|
18721
|
+
throw localExecError(ctx, e.message);
|
|
18722
|
+
}
|
|
18723
|
+
}
|
|
18661
18724
|
async function execDirectFetch(params, ctx) {
|
|
18662
18725
|
if (params.expect === "image") {
|
|
18663
18726
|
return ingestImageUrl(params.url, ctx);
|
|
@@ -19077,13 +19140,19 @@ async function runYtDlpForNode(args) {
|
|
|
19077
19140
|
if (error instanceof YtDlpError) {
|
|
19078
19141
|
throw new NodeExecutionError(args.ctx.nodeId, args.ctx.nodeType, {
|
|
19079
19142
|
kind: "local",
|
|
19080
|
-
cause: new Error(error.
|
|
19081
|
-
${error.stderrTail}` : error.message)
|
|
19143
|
+
cause: new Error(describeYtDlpFailure(error.message, error.stderrTail))
|
|
19082
19144
|
});
|
|
19083
19145
|
}
|
|
19084
19146
|
throw error;
|
|
19085
19147
|
}
|
|
19086
19148
|
}
|
|
19149
|
+
function describeYtDlpFailure(message2, stderrTail) {
|
|
19150
|
+
const base = stderrTail ? `${message2}
|
|
19151
|
+
${stderrTail}` : message2;
|
|
19152
|
+
if (!/CERTIFICATE_VERIFY_FAILED|SSL certificate problem/i.test(stderrTail)) return base;
|
|
19153
|
+
return `${base}
|
|
19154
|
+
This machine could not verify the download's TLS certificate; the file itself is fine. Report it and leave this ingest as it is. Never copy the file out of canvas/ (the render cache or a run folder) to work around it: canvas/ is not committed, so the creative would fail every later publish. To reuse one of our own outputs, ingest its canvas-assets URL, which does not go through this downloader.`;
|
|
19155
|
+
}
|
|
19087
19156
|
function buildYtDlpMetadata(sourceUrl, info) {
|
|
19088
19157
|
const out = {
|
|
19089
19158
|
source_url: sourceUrl,
|
|
@@ -19128,7 +19197,7 @@ ingestNode.cacheKeyExtras = async ({ params }) => {
|
|
|
19128
19197
|
} catch {
|
|
19129
19198
|
}
|
|
19130
19199
|
}
|
|
19131
|
-
if (p.source === "url" && (p.expect === "video" || p.expect === "audio")) {
|
|
19200
|
+
if (p.source === "url" && (p.expect === "video" || p.expect === "audio") && !(typeof p.url === "string" && takesCanvasAssetVerbatim(p.url, p.expect))) {
|
|
19132
19201
|
extras.yt_dlp_version = await ytDlpVersion();
|
|
19133
19202
|
}
|
|
19134
19203
|
return extras;
|
|
@@ -24434,6 +24503,8 @@ export {
|
|
|
24434
24503
|
durationSeconds,
|
|
24435
24504
|
canonicalUrl,
|
|
24436
24505
|
coercePathUrlToUrl,
|
|
24506
|
+
canvasAssetMime,
|
|
24507
|
+
inferMimeFromPath,
|
|
24437
24508
|
toModelSafeImage,
|
|
24438
24509
|
loadCompositionMeta,
|
|
24439
24510
|
videoPathFromOutput,
|
|
@@ -24459,4 +24530,4 @@ export {
|
|
|
24459
24530
|
defaultRegistry,
|
|
24460
24531
|
createEngineFromEnv
|
|
24461
24532
|
};
|
|
24462
|
-
//# sourceMappingURL=chunk-
|
|
24533
|
+
//# sourceMappingURL=chunk-2S6QIXLX.js.map
|