@koda-sl/baker-cli 0.39.29 → 0.66.2
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 +1754 -7
- package/canvas/avocado-tutorial.json +89 -0
- package/canvas/hello-world-composition/index.html +83 -0
- package/canvas/hello-world-composition/meta.json +41 -0
- package/canvas/hello-world-overlay.json +37 -0
- package/canvas/phone-scroll-composition/index.html +141 -0
- package/canvas/phone-scroll-composition/meta.json +39 -0
- package/canvas/tiktok-captions-composition/index.html +126 -0
- package/canvas/tiktok-captions-composition/meta.json +46 -0
- package/canvas/video-overlay-composition/index.html +239 -0
- package/canvas/video-overlay-composition/meta.json +29 -0
- package/dist/cli.js +2 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/ads/meta/creatives.js +1 -1
- package/dist/commands/canvas/catalog.d.ts +2 -0
- package/dist/commands/canvas/catalog.d.ts.map +1 -0
- package/dist/commands/canvas/catalog.js +13 -0
- package/dist/commands/canvas/catalog.js.map +1 -0
- package/dist/commands/canvas/index.d.ts +2 -0
- package/dist/commands/canvas/index.d.ts.map +1 -0
- package/dist/commands/canvas/index.js +32 -0
- package/dist/commands/canvas/index.js.map +1 -0
- package/dist/commands/canvas/inspect.d.ts +16 -0
- package/dist/commands/canvas/inspect.d.ts.map +1 -0
- package/dist/commands/canvas/inspect.js +115 -0
- package/dist/commands/canvas/inspect.js.map +1 -0
- package/dist/commands/canvas/run.d.ts +24 -0
- package/dist/commands/canvas/run.d.ts.map +1 -0
- package/dist/commands/canvas/run.js +56 -0
- package/dist/commands/canvas/run.js.map +1 -0
- package/dist/commands/canvas/scaffold-static-ad.d.ts +40 -0
- package/dist/commands/canvas/scaffold-static-ad.d.ts.map +1 -0
- package/dist/commands/canvas/scaffold-static-ad.js +265 -0
- package/dist/commands/canvas/scaffold-static-ad.js.map +1 -0
- package/dist/commands/canvas/scaffold-video.d.ts +44 -0
- package/dist/commands/canvas/scaffold-video.d.ts.map +1 -0
- package/dist/commands/canvas/scaffold-video.js +235 -0
- package/dist/commands/canvas/scaffold-video.js.map +1 -0
- package/dist/commands/canvas/validate.d.ts +8 -0
- package/dist/commands/canvas/validate.d.ts.map +1 -0
- package/dist/commands/canvas/validate.js +37 -0
- package/dist/commands/canvas/validate.js.map +1 -0
- package/dist/commands/images/find.d.ts +1 -1
- package/dist/commands/images/find.d.ts.map +1 -1
- package/dist/commands/images/find.js +12 -3
- package/dist/commands/images/find.js.map +1 -1
- package/dist/commands/images/google.d.ts +1 -1
- package/dist/commands/images/google.d.ts.map +1 -1
- package/dist/commands/images/google.js +12 -3
- package/dist/commands/images/google.js.map +1 -1
- package/dist/commands/images/stock.d.ts +1 -1
- package/dist/commands/images/stock.d.ts.map +1 -1
- package/dist/commands/images/stock.js +7 -3
- package/dist/commands/images/stock.js.map +1 -1
- package/dist/engine/client/backend-client.d.ts +50 -0
- package/dist/engine/client/backend-client.d.ts.map +1 -0
- package/dist/engine/client/backend-client.js +20 -0
- package/dist/engine/client/backend-client.js.map +1 -0
- package/dist/engine/client/env.d.ts +7 -0
- package/dist/engine/client/env.d.ts.map +1 -0
- package/dist/engine/client/env.js +18 -0
- package/dist/engine/client/env.js.map +1 -0
- package/dist/engine/client/http.d.ts +56 -0
- package/dist/engine/client/http.d.ts.map +1 -0
- package/dist/engine/client/http.js +168 -0
- package/dist/engine/client/http.js.map +1 -0
- package/dist/engine/engine/cache-key.d.ts +19 -0
- package/dist/engine/engine/cache-key.d.ts.map +1 -0
- package/dist/engine/engine/cache-key.js +33 -0
- package/dist/engine/engine/cache-key.js.map +1 -0
- package/dist/engine/engine/canonical.d.ts +14 -0
- package/dist/engine/engine/canonical.d.ts.map +1 -0
- package/dist/engine/engine/canonical.js +53 -0
- package/dist/engine/engine/canonical.js.map +1 -0
- package/dist/engine/engine/composition-hash.d.ts +14 -0
- package/dist/engine/engine/composition-hash.d.ts.map +1 -0
- package/dist/engine/engine/composition-hash.js +51 -0
- package/dist/engine/engine/composition-hash.js.map +1 -0
- package/dist/engine/engine/composition-meta.d.ts +77 -0
- package/dist/engine/engine/composition-meta.d.ts.map +1 -0
- package/dist/engine/engine/composition-meta.js +199 -0
- package/dist/engine/engine/composition-meta.js.map +1 -0
- package/dist/engine/engine/context.d.ts +16 -0
- package/dist/engine/engine/context.d.ts.map +1 -0
- package/dist/engine/engine/context.js +2 -0
- package/dist/engine/engine/context.js.map +1 -0
- package/dist/engine/engine/define.d.ts +69 -0
- package/dist/engine/engine/define.d.ts.map +1 -0
- package/dist/engine/engine/define.js +9 -0
- package/dist/engine/engine/define.js.map +1 -0
- package/dist/engine/engine/didyoumean.d.ts +2 -0
- package/dist/engine/engine/didyoumean.d.ts.map +1 -0
- package/dist/engine/engine/didyoumean.js +58 -0
- package/dist/engine/engine/didyoumean.js.map +1 -0
- package/dist/engine/engine/errors.d.ts +41 -0
- package/dist/engine/engine/errors.d.ts.map +1 -0
- package/dist/engine/engine/errors.js +45 -0
- package/dist/engine/engine/errors.js.map +1 -0
- package/dist/engine/engine/executor.d.ts +72 -0
- package/dist/engine/engine/executor.d.ts.map +1 -0
- package/dist/engine/engine/executor.js +445 -0
- package/dist/engine/engine/executor.js.map +1 -0
- package/dist/engine/engine/refs.d.ts +12 -0
- package/dist/engine/engine/refs.d.ts.map +1 -0
- package/dist/engine/engine/refs.js +48 -0
- package/dist/engine/engine/refs.js.map +1 -0
- package/dist/engine/engine/registry.d.ts +11 -0
- package/dist/engine/engine/registry.d.ts.map +1 -0
- package/dist/engine/engine/registry.js +26 -0
- package/dist/engine/engine/registry.js.map +1 -0
- package/dist/engine/engine/scheduler.d.ts +10 -0
- package/dist/engine/engine/scheduler.d.ts.map +1 -0
- package/dist/engine/engine/scheduler.js +89 -0
- package/dist/engine/engine/scheduler.js.map +1 -0
- package/dist/engine/engine/validator.d.ts +31 -0
- package/dist/engine/engine/validator.d.ts.map +1 -0
- package/dist/engine/engine/validator.js +501 -0
- package/dist/engine/engine/validator.js.map +1 -0
- package/dist/engine/index.d.ts +33 -0
- package/dist/engine/index.d.ts.map +1 -0
- package/dist/engine/index.js +104 -0
- package/dist/engine/index.js.map +1 -0
- package/dist/engine/lib/ulid.d.ts +3 -0
- package/dist/engine/lib/ulid.d.ts.map +1 -0
- package/dist/engine/lib/ulid.js +36 -0
- package/dist/engine/lib/ulid.js.map +1 -0
- package/dist/engine/models/canvas-ad-params.test.d.ts +2 -0
- package/dist/engine/models/canvas-ad-params.test.d.ts.map +1 -0
- package/dist/engine/models/canvas-ad-params.test.js +60 -0
- package/dist/engine/models/canvas-ad-params.test.js.map +1 -0
- package/dist/engine/models/registry.d.ts +63 -0
- package/dist/engine/models/registry.d.ts.map +1 -0
- package/dist/engine/models/registry.js +432 -0
- package/dist/engine/models/registry.js.map +1 -0
- package/dist/engine/models/validateParams.d.ts +38 -0
- package/dist/engine/models/validateParams.d.ts.map +1 -0
- package/dist/engine/models/validateParams.js +166 -0
- package/dist/engine/models/validateParams.js.map +1 -0
- package/dist/engine/nodes/ingest.d.ts +113 -0
- package/dist/engine/nodes/ingest.d.ts.map +1 -0
- package/dist/engine/nodes/ingest.js +555 -0
- package/dist/engine/nodes/ingest.js.map +1 -0
- package/dist/engine/nodes/ingest.svg.test.d.ts +2 -0
- package/dist/engine/nodes/ingest.svg.test.d.ts.map +1 -0
- package/dist/engine/nodes/ingest.svg.test.js +30 -0
- package/dist/engine/nodes/ingest.svg.test.js.map +1 -0
- package/dist/engine/nodes/local/audioTimeline.d.ts +82 -0
- package/dist/engine/nodes/local/audioTimeline.d.ts.map +1 -0
- package/dist/engine/nodes/local/audioTimeline.js +97 -0
- package/dist/engine/nodes/local/audioTimeline.js.map +1 -0
- package/dist/engine/nodes/local/ffmpeg.d.ts +56 -0
- package/dist/engine/nodes/local/ffmpeg.d.ts.map +1 -0
- package/dist/engine/nodes/local/ffmpeg.js +50 -0
- package/dist/engine/nodes/local/ffmpeg.js.map +1 -0
- package/dist/engine/nodes/local/fontSpecimen.d.ts +50 -0
- package/dist/engine/nodes/local/fontSpecimen.d.ts.map +1 -0
- package/dist/engine/nodes/local/fontSpecimen.js +198 -0
- package/dist/engine/nodes/local/fontSpecimen.js.map +1 -0
- package/dist/engine/nodes/local/hyperframe-snapshot.d.ts +116 -0
- package/dist/engine/nodes/local/hyperframe-snapshot.d.ts.map +1 -0
- package/dist/engine/nodes/local/hyperframe-snapshot.js +230 -0
- package/dist/engine/nodes/local/hyperframe-snapshot.js.map +1 -0
- package/dist/engine/nodes/local/hyperframe.d.ts +123 -0
- package/dist/engine/nodes/local/hyperframe.d.ts.map +1 -0
- package/dist/engine/nodes/local/hyperframe.js +367 -0
- package/dist/engine/nodes/local/hyperframe.js.map +1 -0
- package/dist/engine/nodes/local/imagemagick.d.ts +56 -0
- package/dist/engine/nodes/local/imagemagick.d.ts.map +1 -0
- package/dist/engine/nodes/local/imagemagick.js +71 -0
- package/dist/engine/nodes/local/imagemagick.js.map +1 -0
- package/dist/engine/nodes/local/lib/assets.d.ts +20 -0
- package/dist/engine/nodes/local/lib/assets.d.ts.map +1 -0
- package/dist/engine/nodes/local/lib/assets.js +40 -0
- package/dist/engine/nodes/local/lib/assets.js.map +1 -0
- package/dist/engine/nodes/local/lib/cli-runner.d.ts +78 -0
- package/dist/engine/nodes/local/lib/cli-runner.d.ts.map +1 -0
- package/dist/engine/nodes/local/lib/cli-runner.js +254 -0
- package/dist/engine/nodes/local/lib/cli-runner.js.map +1 -0
- package/dist/engine/nodes/local/lib/ffmpeg.d.ts +23 -0
- package/dist/engine/nodes/local/lib/ffmpeg.d.ts.map +1 -0
- package/dist/engine/nodes/local/lib/ffmpeg.js +75 -0
- package/dist/engine/nodes/local/lib/ffmpeg.js.map +1 -0
- package/dist/engine/nodes/local/lib/hyperframe-errors.d.ts +2 -0
- package/dist/engine/nodes/local/lib/hyperframe-errors.d.ts.map +1 -0
- package/dist/engine/nodes/local/lib/hyperframe-errors.js +47 -0
- package/dist/engine/nodes/local/lib/hyperframe-errors.js.map +1 -0
- package/dist/engine/nodes/local/lib/templating.d.ts +22 -0
- package/dist/engine/nodes/local/lib/templating.d.ts.map +1 -0
- package/dist/engine/nodes/local/lib/templating.js +85 -0
- package/dist/engine/nodes/local/lib/templating.js.map +1 -0
- package/dist/engine/nodes/local/text.d.ts +6 -0
- package/dist/engine/nodes/local/text.d.ts.map +1 -0
- package/dist/engine/nodes/local/text.js +15 -0
- package/dist/engine/nodes/local/text.js.map +1 -0
- package/dist/engine/nodes/remote/delegate.d.ts +25 -0
- package/dist/engine/nodes/remote/delegate.d.ts.map +1 -0
- package/dist/engine/nodes/remote/delegate.js +160 -0
- package/dist/engine/nodes/remote/delegate.js.map +1 -0
- package/dist/engine/nodes/remote/dialogue.d.ts +34 -0
- package/dist/engine/nodes/remote/dialogue.d.ts.map +1 -0
- package/dist/engine/nodes/remote/dialogue.js +54 -0
- package/dist/engine/nodes/remote/dialogue.js.map +1 -0
- package/dist/engine/nodes/remote/image.d.ts +42 -0
- package/dist/engine/nodes/remote/image.d.ts.map +1 -0
- package/dist/engine/nodes/remote/image.js +43 -0
- package/dist/engine/nodes/remote/image.js.map +1 -0
- package/dist/engine/nodes/remote/imageAspectAdapt.d.ts +30 -0
- package/dist/engine/nodes/remote/imageAspectAdapt.d.ts.map +1 -0
- package/dist/engine/nodes/remote/imageAspectAdapt.js +42 -0
- package/dist/engine/nodes/remote/imageAspectAdapt.js.map +1 -0
- package/dist/engine/nodes/remote/imageBackgroundRemove.d.ts +39 -0
- package/dist/engine/nodes/remote/imageBackgroundRemove.d.ts.map +1 -0
- package/dist/engine/nodes/remote/imageBackgroundRemove.js +37 -0
- package/dist/engine/nodes/remote/imageBackgroundRemove.js.map +1 -0
- package/dist/engine/nodes/remote/imageDescribe.d.ts +29 -0
- package/dist/engine/nodes/remote/imageDescribe.d.ts.map +1 -0
- package/dist/engine/nodes/remote/imageDescribe.js +25 -0
- package/dist/engine/nodes/remote/imageDescribe.js.map +1 -0
- package/dist/engine/nodes/remote/imageReferenceSheet.d.ts +34 -0
- package/dist/engine/nodes/remote/imageReferenceSheet.d.ts.map +1 -0
- package/dist/engine/nodes/remote/imageReferenceSheet.js +38 -0
- package/dist/engine/nodes/remote/imageReferenceSheet.js.map +1 -0
- package/dist/engine/nodes/remote/imageSearch.d.ts +18 -0
- package/dist/engine/nodes/remote/imageSearch.d.ts.map +1 -0
- package/dist/engine/nodes/remote/imageSearch.js +22 -0
- package/dist/engine/nodes/remote/imageSearch.js.map +1 -0
- package/dist/engine/nodes/remote/imageSelect.d.ts +39 -0
- package/dist/engine/nodes/remote/imageSelect.d.ts.map +1 -0
- package/dist/engine/nodes/remote/imageSelect.js +45 -0
- package/dist/engine/nodes/remote/imageSelect.js.map +1 -0
- package/dist/engine/nodes/remote/music.d.ts +45 -0
- package/dist/engine/nodes/remote/music.d.ts.map +1 -0
- package/dist/engine/nodes/remote/music.js +73 -0
- package/dist/engine/nodes/remote/music.js.map +1 -0
- package/dist/engine/nodes/remote/soundEffect.d.ts +21 -0
- package/dist/engine/nodes/remote/soundEffect.d.ts.map +1 -0
- package/dist/engine/nodes/remote/soundEffect.js +41 -0
- package/dist/engine/nodes/remote/soundEffect.js.map +1 -0
- package/dist/engine/nodes/remote/textGenerate.d.ts +21 -0
- package/dist/engine/nodes/remote/textGenerate.d.ts.map +1 -0
- package/dist/engine/nodes/remote/textGenerate.js +27 -0
- package/dist/engine/nodes/remote/textGenerate.js.map +1 -0
- package/dist/engine/nodes/remote/tts.d.ts +45 -0
- package/dist/engine/nodes/remote/tts.d.ts.map +1 -0
- package/dist/engine/nodes/remote/tts.js +66 -0
- package/dist/engine/nodes/remote/tts.js.map +1 -0
- package/dist/engine/nodes/remote/video.d.ts +58 -0
- package/dist/engine/nodes/remote/video.d.ts.map +1 -0
- package/dist/engine/nodes/remote/video.js +44 -0
- package/dist/engine/nodes/remote/video.js.map +1 -0
- package/dist/engine/nodes/remote/videoBackgroundRemove.d.ts +30 -0
- package/dist/engine/nodes/remote/videoBackgroundRemove.d.ts.map +1 -0
- package/dist/engine/nodes/remote/videoBackgroundRemove.js +29 -0
- package/dist/engine/nodes/remote/videoBackgroundRemove.js.map +1 -0
- package/dist/engine/nodes/remote/videoDeconstruct.d.ts +61 -0
- package/dist/engine/nodes/remote/videoDeconstruct.d.ts.map +1 -0
- package/dist/engine/nodes/remote/videoDeconstruct.js +40 -0
- package/dist/engine/nodes/remote/videoDeconstruct.js.map +1 -0
- package/dist/engine/nodes/remote/videoLipsync.d.ts +37 -0
- package/dist/engine/nodes/remote/videoLipsync.d.ts.map +1 -0
- package/dist/engine/nodes/remote/videoLipsync.js +26 -0
- package/dist/engine/nodes/remote/videoLipsync.js.map +1 -0
- package/dist/engine/nodes/remote/videoTranscribe.d.ts +116 -0
- package/dist/engine/nodes/remote/videoTranscribe.d.ts.map +1 -0
- package/dist/engine/nodes/remote/videoTranscribe.js +123 -0
- package/dist/engine/nodes/remote/videoTranscribe.js.map +1 -0
- package/dist/engine/nodes/remote/voiceSelect.d.ts +28 -0
- package/dist/engine/nodes/remote/voiceSelect.d.ts.map +1 -0
- package/dist/engine/nodes/remote/voiceSelect.js +25 -0
- package/dist/engine/nodes/remote/voiceSelect.js.map +1 -0
- package/dist/engine/scaffold/staticAd.d.ts +44 -0
- package/dist/engine/scaffold/staticAd.d.ts.map +1 -0
- package/dist/engine/scaffold/staticAd.js +243 -0
- package/dist/engine/scaffold/staticAd.js.map +1 -0
- package/dist/engine/scaffold/video.d.ts +56 -0
- package/dist/engine/scaffold/video.d.ts.map +1 -0
- package/dist/engine/scaffold/video.js +709 -0
- package/dist/engine/scaffold/video.js.map +1 -0
- package/dist/engine/schema/canvas.d.ts +41 -0
- package/dist/engine/schema/canvas.d.ts.map +1 -0
- package/dist/engine/schema/canvas.js +67 -0
- package/dist/engine/schema/canvas.js.map +1 -0
- package/dist/engine/schema/catalog.d.ts +25 -0
- package/dist/engine/schema/catalog.d.ts.map +1 -0
- package/dist/engine/schema/catalog.js +48 -0
- package/dist/engine/schema/catalog.js.map +1 -0
- package/dist/engine/schema/primitives.d.ts +6 -0
- package/dist/engine/schema/primitives.d.ts.map +1 -0
- package/dist/engine/schema/primitives.js +4 -0
- package/dist/engine/schema/primitives.js.map +1 -0
- package/dist/engine/schema/prompts.d.ts +4 -0
- package/dist/engine/schema/prompts.d.ts.map +1 -0
- package/dist/engine/schema/prompts.js +23 -0
- package/dist/engine/schema/prompts.js.map +1 -0
- package/dist/engine/schema/refs.d.ts +113 -0
- package/dist/engine/schema/refs.d.ts.map +1 -0
- package/dist/engine/schema/refs.js +35 -0
- package/dist/engine/schema/refs.js.map +1 -0
- package/dist/engine/storage/asset-store.d.ts +48 -0
- package/dist/engine/storage/asset-store.d.ts.map +1 -0
- package/dist/engine/storage/asset-store.js +166 -0
- package/dist/engine/storage/asset-store.js.map +1 -0
- package/dist/engine/storage/cache-store.d.ts +21 -0
- package/dist/engine/storage/cache-store.d.ts.map +1 -0
- package/dist/engine/storage/cache-store.js +31 -0
- package/dist/engine/storage/cache-store.js.map +1 -0
- package/dist/engine/storage/output-writer.d.ts +18 -0
- package/dist/engine/storage/output-writer.d.ts.map +1 -0
- package/dist/engine/storage/output-writer.js +52 -0
- package/dist/engine/storage/output-writer.js.map +1 -0
- package/dist/engine/storage/sha256.d.ts +2 -0
- package/dist/engine/storage/sha256.d.ts.map +1 -0
- package/dist/engine/storage/sha256.js +7 -0
- package/dist/engine/storage/sha256.js.map +1 -0
- package/package.json +15 -3
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AssetRef } from "../../../schema/refs.ts";
|
|
2
|
+
export type StageableRef = {
|
|
3
|
+
kind: string;
|
|
4
|
+
mime: string;
|
|
5
|
+
path?: string;
|
|
6
|
+
url?: string;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Copy a local asset into `destDir` under `filename` (or, when `filename` is
|
|
10
|
+
* omitted, `<key><ext>` derived from the ref's mime). Throws if the ref has no
|
|
11
|
+
* local path — callers must materialise upstream assets before staging.
|
|
12
|
+
*/
|
|
13
|
+
export declare function stageAsset(ref: StageableRef, destDir: string, filename: string): Promise<string>;
|
|
14
|
+
/**
|
|
15
|
+
* Returns an AssetRef as a URL string browser code can consume.
|
|
16
|
+
* Prefers `ref.url`; falls back to a base64 `data:` URL built from `ref.path`.
|
|
17
|
+
*/
|
|
18
|
+
export declare function refToUrl(ref: Pick<AssetRef, "mime" | "path" | "url">): Promise<string>;
|
|
19
|
+
export declare function isAssetRefLike(value: unknown): value is AssetRef;
|
|
20
|
+
//# sourceMappingURL=assets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../../../../../src/engine/nodes/local/lib/assets.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAKxD,MAAM,MAAM,YAAY,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvF;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAOtG;AAED;;;GAGG;AACH,wBAAsB,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAO5F;AAID,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAUhE"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { copyFile, readFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
/**
|
|
4
|
+
* Copy a local asset into `destDir` under `filename` (or, when `filename` is
|
|
5
|
+
* omitted, `<key><ext>` derived from the ref's mime). Throws if the ref has no
|
|
6
|
+
* local path — callers must materialise upstream assets before staging.
|
|
7
|
+
*/
|
|
8
|
+
export async function stageAsset(ref, destDir, filename) {
|
|
9
|
+
if (!ref.path) {
|
|
10
|
+
throw new Error(`stageAsset: ref (${ref.kind}/${ref.mime}) has no local path`);
|
|
11
|
+
}
|
|
12
|
+
const dest = path.join(destDir, filename);
|
|
13
|
+
await copyFile(ref.path, dest);
|
|
14
|
+
return dest;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Returns an AssetRef as a URL string browser code can consume.
|
|
18
|
+
* Prefers `ref.url`; falls back to a base64 `data:` URL built from `ref.path`.
|
|
19
|
+
*/
|
|
20
|
+
export async function refToUrl(ref) {
|
|
21
|
+
if (ref.url)
|
|
22
|
+
return ref.url;
|
|
23
|
+
if (!ref.path) {
|
|
24
|
+
throw new Error("refToUrl: AssetRef has neither url nor path");
|
|
25
|
+
}
|
|
26
|
+
const bytes = await readFile(ref.path);
|
|
27
|
+
return `data:${ref.mime};base64,${bytes.toString("base64")}`;
|
|
28
|
+
}
|
|
29
|
+
const ASSET_KINDS = new Set(["image", "video", "audio", "json", "text", "font"]);
|
|
30
|
+
export function isAssetRefLike(value) {
|
|
31
|
+
if (!value || typeof value !== "object")
|
|
32
|
+
return false;
|
|
33
|
+
const v = value;
|
|
34
|
+
return (typeof v.kind === "string" &&
|
|
35
|
+
ASSET_KINDS.has(v.kind) &&
|
|
36
|
+
typeof v.mime === "string" &&
|
|
37
|
+
typeof v.sha256 === "string" &&
|
|
38
|
+
(typeof v.url === "string" || typeof v.path === "string"));
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=assets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assets.js","sourceRoot":"","sources":["../../../../../src/engine/nodes/local/lib/assets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,IAAI,MAAM,WAAW,CAAC;AAQ7B;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAiB,EAAE,OAAe,EAAE,QAAgB;IACnF,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,oBAAoB,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,qBAAqB,CAAC,CAAC;IACjF,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC1C,MAAM,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC/B,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,GAA4C;IACzE,IAAI,GAAG,CAAC,GAAG;QAAE,OAAO,GAAG,CAAC,GAAG,CAAC;IAC5B,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IACjE,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACvC,OAAO,QAAQ,GAAG,CAAC,IAAI,WAAW,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;AAC/D,CAAC;AAED,MAAM,WAAW,GAAwB,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAEtG,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACtD,MAAM,CAAC,GAAG,KAAgC,CAAC;IAC3C,OAAO,CACL,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ;QAC1B,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;QACvB,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ;QAC1B,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ;QAC5B,CAAC,OAAO,CAAC,CAAC,GAAG,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAC1D,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { ExecCtx } from "../../../engine/context.ts";
|
|
2
|
+
import type { AssetKind, AssetRef } from "../../../schema/refs.ts";
|
|
3
|
+
type CliOutputSpec = {
|
|
4
|
+
kind: AssetKind;
|
|
5
|
+
ext: string;
|
|
6
|
+
};
|
|
7
|
+
type RunCliArgs = {
|
|
8
|
+
/** Binary to spawn (must be on PATH). */
|
|
9
|
+
bin: string;
|
|
10
|
+
/** argv list with `{{in.<slot>}}` and `{{out.<name>}}` placeholders. */
|
|
11
|
+
args: readonly string[];
|
|
12
|
+
/** Input slots — each becomes `{{in.<slot>}}` (single asset) or `{{in.<slot>.<index>}}` (array). */
|
|
13
|
+
inputs: Record<string, AssetRef | AssetRef[]>;
|
|
14
|
+
/** Output declarations — each becomes `{{out.<name>}}`; engine allocates the path. */
|
|
15
|
+
outputs: Record<string, CliOutputSpec>;
|
|
16
|
+
ctx: ExecCtx;
|
|
17
|
+
/** Process timeout. Default: 10 minutes. */
|
|
18
|
+
timeoutMs?: number;
|
|
19
|
+
};
|
|
20
|
+
declare function mimeForExt(ext: string): string;
|
|
21
|
+
declare function extForAssetRef(ref: AssetRef): string;
|
|
22
|
+
/**
|
|
23
|
+
* Build the placeholder → absolute-path lookup table for one node invocation.
|
|
24
|
+
* - Single AssetRef inputs register as `in.<slot>`.
|
|
25
|
+
* - Array AssetRef inputs register each element as `in.<slot>.<index>`.
|
|
26
|
+
* - Declared outputs register as `out.<name>`.
|
|
27
|
+
*
|
|
28
|
+
* Returns the lookup table plus the list of staged input paths and allocated
|
|
29
|
+
* output paths so the caller can copy/read them.
|
|
30
|
+
*/
|
|
31
|
+
type Placeholders = {
|
|
32
|
+
lookup: Map<string, string>;
|
|
33
|
+
stagedInputs: {
|
|
34
|
+
srcPath: string;
|
|
35
|
+
destPath: string;
|
|
36
|
+
}[];
|
|
37
|
+
outputPaths: {
|
|
38
|
+
name: string;
|
|
39
|
+
absPath: string;
|
|
40
|
+
spec: CliOutputSpec;
|
|
41
|
+
}[];
|
|
42
|
+
};
|
|
43
|
+
declare function planPlaceholders(tmpDir: string, inputs: Record<string, AssetRef | AssetRef[]>, outputs: Record<string, CliOutputSpec>): Placeholders;
|
|
44
|
+
/**
|
|
45
|
+
* Substitute `{{in.X}}` / `{{out.Y}}` placeholders in a single arg string.
|
|
46
|
+
* Returns the new string and the set of placeholder keys it consumed.
|
|
47
|
+
* Throws if a placeholder isn't in the lookup.
|
|
48
|
+
*/
|
|
49
|
+
declare function substituteArg(arg: string, lookup: Map<string, string>): string;
|
|
50
|
+
/**
|
|
51
|
+
* After substitution, reject arg strings that look like raw filesystem paths
|
|
52
|
+
* outside our staging dir, or URL inputs. The threat model is "trusted local
|
|
53
|
+
* canvas shouldn't accidentally reach outside the engine's content-addressed
|
|
54
|
+
* world." Args that resolve to staging-dir paths via placeholders pass cleanly.
|
|
55
|
+
*/
|
|
56
|
+
declare function rejectRawPaths(substituted: string, original: string, stagingDir: string): void;
|
|
57
|
+
/**
|
|
58
|
+
* Run a local CLI binary with engine-staged inputs and engine-allocated outputs.
|
|
59
|
+
*
|
|
60
|
+
* Contract:
|
|
61
|
+
* - `args` are passed as argv (no shell). `{{in.<slot>}}` / `{{out.<name>}}`
|
|
62
|
+
* placeholders are substituted with absolute paths under a per-node tmp dir.
|
|
63
|
+
* - After substitution, raw filesystem paths and URL-style inputs are rejected.
|
|
64
|
+
* - Every declared `outputs` entry must exist and be non-empty after exit.
|
|
65
|
+
* - Outputs are ingested into the asset store as the declared `kind`.
|
|
66
|
+
* - Tmp dir is removed in `finally`.
|
|
67
|
+
*/
|
|
68
|
+
export declare function runCli(opts: RunCliArgs): Promise<Record<string, AssetRef>>;
|
|
69
|
+
export declare function getToolVersion(bin: string): Promise<string>;
|
|
70
|
+
export declare const _internal: {
|
|
71
|
+
planPlaceholders: typeof planPlaceholders;
|
|
72
|
+
substituteArg: typeof substituteArg;
|
|
73
|
+
rejectRawPaths: typeof rejectRawPaths;
|
|
74
|
+
mimeForExt: typeof mimeForExt;
|
|
75
|
+
extForAssetRef: typeof extForAssetRef;
|
|
76
|
+
};
|
|
77
|
+
export {};
|
|
78
|
+
//# sourceMappingURL=cli-runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-runner.d.ts","sourceRoot":"","sources":["../../../../../src/engine/nodes/local/lib/cli-runner.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAInE,KAAK,aAAa,GAAG;IACnB,IAAI,EAAE,SAAS,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,KAAK,UAAU,GAAG;IAChB,yCAAyC;IACzC,GAAG,EAAE,MAAM,CAAC;IACZ,wEAAwE;IACxE,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACxB,oGAAoG;IACpG,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,GAAG,QAAQ,EAAE,CAAC,CAAC;IAC9C,sFAAsF;IACtF,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACvC,GAAG,EAAE,OAAO,CAAC;IACb,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAuBF,iBAAS,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGvC;AAED,iBAAS,cAAc,CAAC,GAAG,EAAE,QAAQ,GAAG,MAAM,CAmB7C;AAED;;;;;;;;GAQG;AACH,KAAK,YAAY,GAAG;IAClB,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,YAAY,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACtD,WAAW,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,aAAa,CAAA;KAAE,EAAE,CAAC;CACvE,CAAC;AA+CF,iBAAS,gBAAgB,CACvB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,GAAG,QAAQ,EAAE,CAAC,EAC7C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,GACrC,YAAY,CAcd;AAID;;;;GAIG;AACH,iBAAS,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAUvE;AAED;;;;;GAKG;AACH,iBAAS,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAwBvF;AAkDD;;;;;;;;;;GAUG;AACH,wBAAsB,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAyChF;AAQD,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAcjE;AAGD,eAAO,MAAM,SAAS;;;;;;CAMrB,CAAC"}
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import { execFile as execFileCb, spawn } from "node:child_process";
|
|
2
|
+
import { copyFile, mkdtemp, readFile, rm, stat } from "node:fs/promises";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { promisify } from "node:util";
|
|
6
|
+
const execFile = promisify(execFileCb);
|
|
7
|
+
const DEFAULT_TIMEOUT_MS = 10 * 60 * 1000;
|
|
8
|
+
const URL_SCHEME_RE = /^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//;
|
|
9
|
+
const MIME_BY_EXT = {
|
|
10
|
+
png: "image/png",
|
|
11
|
+
jpg: "image/jpeg",
|
|
12
|
+
jpeg: "image/jpeg",
|
|
13
|
+
webp: "image/webp",
|
|
14
|
+
gif: "image/gif",
|
|
15
|
+
avif: "image/avif",
|
|
16
|
+
mp4: "video/mp4",
|
|
17
|
+
webm: "video/webm",
|
|
18
|
+
mov: "video/quicktime",
|
|
19
|
+
mp3: "audio/mpeg",
|
|
20
|
+
wav: "audio/wav",
|
|
21
|
+
m4a: "audio/mp4",
|
|
22
|
+
ogg: "audio/ogg",
|
|
23
|
+
flac: "audio/flac",
|
|
24
|
+
};
|
|
25
|
+
function mimeForExt(ext) {
|
|
26
|
+
const clean = ext.startsWith(".") ? ext.slice(1) : ext;
|
|
27
|
+
return MIME_BY_EXT[clean.toLowerCase()] ?? "application/octet-stream";
|
|
28
|
+
}
|
|
29
|
+
function extForAssetRef(ref) {
|
|
30
|
+
// Prefer the on-disk extension if we have a local path; fall back to mime.
|
|
31
|
+
if (ref.path) {
|
|
32
|
+
const e = path.extname(ref.path);
|
|
33
|
+
if (e)
|
|
34
|
+
return e;
|
|
35
|
+
}
|
|
36
|
+
const reverse = {
|
|
37
|
+
"image/png": ".png",
|
|
38
|
+
"image/jpeg": ".jpg",
|
|
39
|
+
"image/webp": ".webp",
|
|
40
|
+
"video/mp4": ".mp4",
|
|
41
|
+
"video/webm": ".webm",
|
|
42
|
+
"video/quicktime": ".mov",
|
|
43
|
+
"audio/mpeg": ".mp3",
|
|
44
|
+
"audio/wav": ".wav",
|
|
45
|
+
"audio/mp4": ".m4a",
|
|
46
|
+
"audio/ogg": ".ogg",
|
|
47
|
+
};
|
|
48
|
+
return reverse[ref.mime] ?? ".bin";
|
|
49
|
+
}
|
|
50
|
+
function planArrayInputSlot(tmpDir, slot, values, lookup, stagedInputs) {
|
|
51
|
+
for (let i = 0; i < values.length; i++) {
|
|
52
|
+
const ref = values[i];
|
|
53
|
+
if (!ref)
|
|
54
|
+
continue;
|
|
55
|
+
if (!ref.path)
|
|
56
|
+
throw new Error(`cli-runner: inputs.${slot}[${i}] has no local path`);
|
|
57
|
+
const dest = path.join(tmpDir, `in_${slot}_${i}${extForAssetRef(ref)}`);
|
|
58
|
+
stagedInputs.push({ srcPath: ref.path, destPath: dest });
|
|
59
|
+
lookup.set(`in.${slot}.${i}`, dest);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function planSingleInputSlot(tmpDir, slot, ref, lookup, stagedInputs) {
|
|
63
|
+
if (!ref.path)
|
|
64
|
+
throw new Error(`cli-runner: inputs.${slot} has no local path`);
|
|
65
|
+
const dest = path.join(tmpDir, `in_${slot}${extForAssetRef(ref)}`);
|
|
66
|
+
stagedInputs.push({ srcPath: ref.path, destPath: dest });
|
|
67
|
+
lookup.set(`in.${slot}`, dest);
|
|
68
|
+
}
|
|
69
|
+
function planOutputs(tmpDir, outputs, lookup) {
|
|
70
|
+
const outputPaths = [];
|
|
71
|
+
for (const [name, spec] of Object.entries(outputs)) {
|
|
72
|
+
const ext = spec.ext.startsWith(".") ? spec.ext : `.${spec.ext}`;
|
|
73
|
+
const absPath = path.join(tmpDir, `out_${name}${ext}`);
|
|
74
|
+
outputPaths.push({ name, absPath, spec });
|
|
75
|
+
lookup.set(`out.${name}`, absPath);
|
|
76
|
+
}
|
|
77
|
+
return outputPaths;
|
|
78
|
+
}
|
|
79
|
+
function planPlaceholders(tmpDir, inputs, outputs) {
|
|
80
|
+
const lookup = new Map();
|
|
81
|
+
const stagedInputs = [];
|
|
82
|
+
for (const [slot, value] of Object.entries(inputs)) {
|
|
83
|
+
if (Array.isArray(value)) {
|
|
84
|
+
planArrayInputSlot(tmpDir, slot, value, lookup, stagedInputs);
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
planSingleInputSlot(tmpDir, slot, value, lookup, stagedInputs);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const outputPaths = planOutputs(tmpDir, outputs, lookup);
|
|
91
|
+
return { lookup, stagedInputs, outputPaths };
|
|
92
|
+
}
|
|
93
|
+
const PLACEHOLDER_RE = /\{\{\s*([a-zA-Z0-9_.]+)\s*\}\}/g;
|
|
94
|
+
/**
|
|
95
|
+
* Substitute `{{in.X}}` / `{{out.Y}}` placeholders in a single arg string.
|
|
96
|
+
* Returns the new string and the set of placeholder keys it consumed.
|
|
97
|
+
* Throws if a placeholder isn't in the lookup.
|
|
98
|
+
*/
|
|
99
|
+
function substituteArg(arg, lookup) {
|
|
100
|
+
return arg.replace(PLACEHOLDER_RE, (_match, key) => {
|
|
101
|
+
const value = lookup.get(key);
|
|
102
|
+
if (value === undefined) {
|
|
103
|
+
throw new Error(`cli-runner: unknown placeholder "{{${key}}}" — declared inputs/outputs: ${[...lookup.keys()].join(", ")}`);
|
|
104
|
+
}
|
|
105
|
+
return value;
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* After substitution, reject arg strings that look like raw filesystem paths
|
|
110
|
+
* outside our staging dir, or URL inputs. The threat model is "trusted local
|
|
111
|
+
* canvas shouldn't accidentally reach outside the engine's content-addressed
|
|
112
|
+
* world." Args that resolve to staging-dir paths via placeholders pass cleanly.
|
|
113
|
+
*/
|
|
114
|
+
function rejectRawPaths(substituted, original, stagingDir) {
|
|
115
|
+
// URL schemes — block ffmpeg/magick from fetching arbitrary http/file/data inputs.
|
|
116
|
+
if (URL_SCHEME_RE.test(substituted)) {
|
|
117
|
+
throw new Error(`cli-runner: URL-style arg "${original}" not allowed — ingest the asset upstream (e.g. via the ingest node) and wire it as an input slot.`);
|
|
118
|
+
}
|
|
119
|
+
// Home-relative — never allow.
|
|
120
|
+
if (substituted.startsWith("~/") || substituted === "~") {
|
|
121
|
+
throw new Error(`cli-runner: home-relative path "${original}" not allowed in args.`);
|
|
122
|
+
}
|
|
123
|
+
// Absolute paths must live under the staging dir.
|
|
124
|
+
if (substituted.startsWith("/")) {
|
|
125
|
+
const resolved = path.resolve(substituted);
|
|
126
|
+
if (!resolved.startsWith(`${stagingDir}${path.sep}`) && resolved !== stagingDir) {
|
|
127
|
+
throw new Error(`cli-runner: raw filesystem path "${original}" not allowed — declare an input slot and use {{in.<slot>}} instead.`);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// Relative path tokens — `./foo`, `../foo` — block.
|
|
131
|
+
if (substituted.startsWith("./") || substituted.startsWith("../")) {
|
|
132
|
+
throw new Error(`cli-runner: relative path "${original}" not allowed in args.`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
async function stageInputs(staged) {
|
|
136
|
+
for (const { srcPath, destPath } of staged) {
|
|
137
|
+
await copyFile(srcPath, destPath);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
function spawnAndWait(bin, args, timeoutMs) {
|
|
141
|
+
return new Promise((resolve, reject) => {
|
|
142
|
+
const child = spawn(bin, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
143
|
+
const stderrChunks = [];
|
|
144
|
+
let stderrLen = 0;
|
|
145
|
+
const MAX_STDERR = 256 * 1024;
|
|
146
|
+
child.stdout.on("data", () => {
|
|
147
|
+
// Discard stdout — large CLI tools can flood it; we surface stderr on failure.
|
|
148
|
+
});
|
|
149
|
+
child.stderr.on("data", (chunk) => {
|
|
150
|
+
if (stderrLen < MAX_STDERR) {
|
|
151
|
+
stderrChunks.push(chunk);
|
|
152
|
+
stderrLen += chunk.length;
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
const timer = setTimeout(() => {
|
|
156
|
+
child.kill("SIGKILL");
|
|
157
|
+
reject(new Error(`cli-runner: ${bin} timed out after ${timeoutMs}ms`));
|
|
158
|
+
}, timeoutMs);
|
|
159
|
+
child.on("error", (err) => {
|
|
160
|
+
clearTimeout(timer);
|
|
161
|
+
reject(new Error(`cli-runner: failed to spawn "${bin}" — ${err.message}`));
|
|
162
|
+
});
|
|
163
|
+
child.on("close", (code) => {
|
|
164
|
+
clearTimeout(timer);
|
|
165
|
+
const stderr = Buffer.concat(stderrChunks).toString("utf8");
|
|
166
|
+
resolve({ code: code ?? -1, stderr });
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
function tailLines(text, maxLines) {
|
|
171
|
+
const lines = text.split("\n");
|
|
172
|
+
return lines.slice(-maxLines).join("\n");
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Run a local CLI binary with engine-staged inputs and engine-allocated outputs.
|
|
176
|
+
*
|
|
177
|
+
* Contract:
|
|
178
|
+
* - `args` are passed as argv (no shell). `{{in.<slot>}}` / `{{out.<name>}}`
|
|
179
|
+
* placeholders are substituted with absolute paths under a per-node tmp dir.
|
|
180
|
+
* - After substitution, raw filesystem paths and URL-style inputs are rejected.
|
|
181
|
+
* - Every declared `outputs` entry must exist and be non-empty after exit.
|
|
182
|
+
* - Outputs are ingested into the asset store as the declared `kind`.
|
|
183
|
+
* - Tmp dir is removed in `finally`.
|
|
184
|
+
*/
|
|
185
|
+
export async function runCli(opts) {
|
|
186
|
+
const { bin, args, inputs, outputs, ctx, timeoutMs = DEFAULT_TIMEOUT_MS } = opts;
|
|
187
|
+
const tmpDir = await mkdtemp(path.join(tmpdir(), `cli-${bin.replace(/[^a-z0-9]/gi, "")}-`));
|
|
188
|
+
try {
|
|
189
|
+
const { lookup, stagedInputs, outputPaths } = planPlaceholders(tmpDir, inputs, outputs);
|
|
190
|
+
await stageInputs(stagedInputs);
|
|
191
|
+
ctx.log(`staged ${stagedInputs.length} inputs in ${tmpDir}`);
|
|
192
|
+
const substituted = args.map((arg) => {
|
|
193
|
+
const next = substituteArg(arg, lookup);
|
|
194
|
+
rejectRawPaths(next, arg, tmpDir);
|
|
195
|
+
return next;
|
|
196
|
+
});
|
|
197
|
+
ctx.log(`running ${bin} (${substituted.length} args)`);
|
|
198
|
+
const { code, stderr } = await spawnAndWait(bin, substituted, timeoutMs);
|
|
199
|
+
if (code !== 0) {
|
|
200
|
+
throw new Error(`cli-runner: ${bin} exited ${code}\n${tailLines(stderr, 40)}`);
|
|
201
|
+
}
|
|
202
|
+
const result = {};
|
|
203
|
+
for (const { name, absPath, spec } of outputPaths) {
|
|
204
|
+
const s = await stat(absPath).catch(() => null);
|
|
205
|
+
if (!s?.isFile() || s.size === 0) {
|
|
206
|
+
throw new Error(`cli-runner: declared output "${name}" missing or empty at ${absPath}`);
|
|
207
|
+
}
|
|
208
|
+
const bytes = await readFile(absPath);
|
|
209
|
+
const ref = await ctx.assets.ingestBytes({
|
|
210
|
+
bytes: Buffer.from(bytes),
|
|
211
|
+
kind: spec.kind,
|
|
212
|
+
mime: mimeForExt(spec.ext),
|
|
213
|
+
});
|
|
214
|
+
result[name] = ref;
|
|
215
|
+
}
|
|
216
|
+
return result;
|
|
217
|
+
}
|
|
218
|
+
finally {
|
|
219
|
+
await rm(tmpDir, { recursive: true, force: true }).catch((e) => {
|
|
220
|
+
ctx.log(`cli-runner: tmp cleanup failed (${e.message})`);
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Capture the binary's `-version` first line for cache-key inclusion.
|
|
226
|
+
* Memoized per-binary per-process. Bumping the host CLI busts cache automatically.
|
|
227
|
+
*/
|
|
228
|
+
const VERSION_CACHE = new Map();
|
|
229
|
+
export async function getToolVersion(bin) {
|
|
230
|
+
const cached = VERSION_CACHE.get(bin);
|
|
231
|
+
if (cached !== undefined)
|
|
232
|
+
return cached;
|
|
233
|
+
try {
|
|
234
|
+
const { stdout } = await execFile(bin, ["-version"], { encoding: "utf-8", maxBuffer: 1024 * 1024 });
|
|
235
|
+
const firstLine = stdout.split("\n")[0]?.trim() ?? "";
|
|
236
|
+
VERSION_CACHE.set(bin, firstLine);
|
|
237
|
+
return firstLine;
|
|
238
|
+
}
|
|
239
|
+
catch {
|
|
240
|
+
// Don't fail the run on version probe issues; cache key folds in a stable marker.
|
|
241
|
+
const fallback = `${bin}:unknown`;
|
|
242
|
+
VERSION_CACHE.set(bin, fallback);
|
|
243
|
+
return fallback;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
// Exported for tests.
|
|
247
|
+
export const _internal = {
|
|
248
|
+
planPlaceholders,
|
|
249
|
+
substituteArg,
|
|
250
|
+
rejectRawPaths,
|
|
251
|
+
mimeForExt,
|
|
252
|
+
extForAssetRef,
|
|
253
|
+
};
|
|
254
|
+
//# sourceMappingURL=cli-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-runner.js","sourceRoot":"","sources":["../../../../../src/engine/nodes/local/lib/cli-runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
type VideoProbe = {
|
|
2
|
+
duration_seconds: number;
|
|
3
|
+
codec_name: string;
|
|
4
|
+
profile: string | null;
|
|
5
|
+
level: number | null;
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
pix_fmt: string | null;
|
|
9
|
+
fps_num: number;
|
|
10
|
+
fps_den: number;
|
|
11
|
+
has_audio: boolean;
|
|
12
|
+
audio_codec: string | null;
|
|
13
|
+
sample_rate: number | null;
|
|
14
|
+
channels: number | null;
|
|
15
|
+
};
|
|
16
|
+
export declare function probeVideo(filePath: string): Promise<VideoProbe>;
|
|
17
|
+
type RunFfmpegOpts = {
|
|
18
|
+
timeout_ms: number;
|
|
19
|
+
log?: (msg: string) => void;
|
|
20
|
+
};
|
|
21
|
+
export declare function runFfmpeg(args: readonly string[], opts: RunFfmpegOpts): Promise<void>;
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=ffmpeg.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ffmpeg.d.ts","sourceRoot":"","sources":["../../../../../src/engine/nodes/local/lib/ffmpeg.ts"],"names":[],"mappings":"AAKA,KAAK,UAAU,GAAG;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,CAAC;AAyBF,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAOtE;AA+DD,KAAK,aAAa,GAAG;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B,CAAC;AAEF,wBAAsB,SAAS,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAY3F"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { promisify } from "node:util";
|
|
3
|
+
const execFileAsync = promisify(execFile);
|
|
4
|
+
export async function probeVideo(filePath) {
|
|
5
|
+
const { stdout } = await execFileAsync("ffprobe", ["-v", "error", "-show_streams", "-show_format", "-of", "json", filePath], { encoding: "utf-8", maxBuffer: 8 * 1024 * 1024 });
|
|
6
|
+
return parseProbeJson(stdout, filePath);
|
|
7
|
+
}
|
|
8
|
+
function parseProbeJson(stdout, filePath) {
|
|
9
|
+
let parsed;
|
|
10
|
+
try {
|
|
11
|
+
parsed = JSON.parse(stdout);
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
throw new Error(`ffprobe: unparseable JSON output for ${filePath}`);
|
|
15
|
+
}
|
|
16
|
+
const streams = parsed.streams ?? [];
|
|
17
|
+
const video = streams.find((s) => s.codec_type === "video");
|
|
18
|
+
if (!video)
|
|
19
|
+
throw new Error(`ffprobe: no video stream found in ${filePath}`);
|
|
20
|
+
if (typeof video.width !== "number" || typeof video.height !== "number") {
|
|
21
|
+
throw new Error(`ffprobe: missing video dimensions for ${filePath}`);
|
|
22
|
+
}
|
|
23
|
+
const duration = Number.parseFloat(parsed.format?.duration ?? "");
|
|
24
|
+
if (!Number.isFinite(duration) || duration <= 0) {
|
|
25
|
+
throw new Error(`ffprobe: invalid duration for ${filePath}: ${parsed.format?.duration}`);
|
|
26
|
+
}
|
|
27
|
+
const audio = streams.find((s) => s.codec_type === "audio");
|
|
28
|
+
return buildVideoProbe(video, video.width, video.height, audio, duration);
|
|
29
|
+
}
|
|
30
|
+
function buildVideoProbe(video, width, height, audio, duration) {
|
|
31
|
+
const fps = parseFrameRate(video.r_frame_rate ?? video.avg_frame_rate ?? "30/1");
|
|
32
|
+
return {
|
|
33
|
+
duration_seconds: duration,
|
|
34
|
+
codec_name: video.codec_name ?? "unknown",
|
|
35
|
+
profile: video.profile ?? null,
|
|
36
|
+
level: typeof video.level === "number" ? video.level : null,
|
|
37
|
+
width,
|
|
38
|
+
height,
|
|
39
|
+
pix_fmt: video.pix_fmt ?? null,
|
|
40
|
+
fps_num: fps.num,
|
|
41
|
+
fps_den: fps.den,
|
|
42
|
+
has_audio: audio !== undefined,
|
|
43
|
+
audio_codec: audio?.codec_name ?? null,
|
|
44
|
+
sample_rate: audio?.sample_rate ? Number.parseInt(audio.sample_rate, 10) : null,
|
|
45
|
+
channels: typeof audio?.channels === "number" ? audio.channels : null,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function parseFrameRate(rate) {
|
|
49
|
+
const match = rate.match(/^(\d+)\/(\d+)$/);
|
|
50
|
+
if (match) {
|
|
51
|
+
const num = Number.parseInt(match[1] ?? "0", 10);
|
|
52
|
+
const den = Number.parseInt(match[2] ?? "0", 10);
|
|
53
|
+
if (den > 0)
|
|
54
|
+
return { num, den };
|
|
55
|
+
}
|
|
56
|
+
const flat = Number.parseFloat(rate);
|
|
57
|
+
if (Number.isFinite(flat) && flat > 0)
|
|
58
|
+
return { num: Math.round(flat * 1000), den: 1000 };
|
|
59
|
+
return { num: 30, den: 1 };
|
|
60
|
+
}
|
|
61
|
+
export async function runFfmpeg(args, opts) {
|
|
62
|
+
try {
|
|
63
|
+
await execFileAsync("ffmpeg", args, {
|
|
64
|
+
timeout: opts.timeout_ms,
|
|
65
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
catch (e) {
|
|
69
|
+
const stderr = e.stderr ?? "";
|
|
70
|
+
const stdout = e.stdout ?? "";
|
|
71
|
+
const detail = stderr || stdout || e.message;
|
|
72
|
+
throw new Error(`ffmpeg failed:\n${detail.slice(-4000)}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=ffmpeg.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ffmpeg.js","sourceRoot":"","sources":["../../../../../src/engine/nodes/local/lib/ffmpeg.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hyperframe-errors.d.ts","sourceRoot":"","sources":["../../../../../src/engine/nodes/local/lib/hyperframe-errors.ts"],"names":[],"mappings":"AAkDA,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOtE"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// Map noisy Hyperframes/ffmpeg/Chromium stderr into actionable messages.
|
|
2
|
+
// Each entry's `match` is tested in order — first hit wins. The matcher
|
|
3
|
+
// returns the friendly message (with a suggested next step) or null when
|
|
4
|
+
// no pattern applies; callers fall back to raw stderr.
|
|
5
|
+
//
|
|
6
|
+
// New patterns: add an entry; the engine doesn't need updating.
|
|
7
|
+
const KNOWN_ERROR_PATTERNS = [
|
|
8
|
+
{
|
|
9
|
+
match: /Variable issue[^\n]*\bduration\b[^\n]*not declared/i,
|
|
10
|
+
message: () => `Variable "duration" cannot be passed in params or declared in the composition — the engine injects it from the input video's duration. Remove "duration" from params.`,
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
match: /BeginFrame auto-worker calibration timed out/i,
|
|
14
|
+
message: () => `Hyperframes' renderer is overloaded calibrating its frame workers. Try params.quality = "draft", params.workers = 2, or split the composition into smaller pieces.`,
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
match: /media_missing_id:\s*<audio>/i,
|
|
18
|
+
message: () => `A <audio> element in the composition is missing an "id" attribute. Add id="…" (e.g. id="bg-audio") so Hyperframes can discover it.`,
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
match: /media_missing_id:\s*<video>/i,
|
|
22
|
+
message: () => `A <video> element in the composition is missing an "id" attribute. Add id="…" (e.g. id="bg") so Hyperframes can discover it.`,
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
match: /Overlapping clips? detected/i,
|
|
26
|
+
message: () => `Two clip elements overlap in time. Shave 1 ms off the previous clip's data-duration to introduce a sub-frame gap, or re-stitch upstream with the ffmpeg node.`,
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
match: /ENOENT[^\n]*gsap\.min\.js/i,
|
|
30
|
+
message: () => `Composition references ./gsap.min.js but the file wasn't found in the render directory. The engine vendors gsap from node_modules; ensure 'gsap' is installed in the CLI package, or self-supply gsap.min.js inside your composition directory.`,
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
match: /chromium.*could not be launched|Executable doesn't exist/i,
|
|
34
|
+
message: () => `Headless Chrome is missing. Install Playwright Chromium (\`pnpm exec playwright install chromium\`) or run with params.docker = true for a sandboxed render.`,
|
|
35
|
+
},
|
|
36
|
+
];
|
|
37
|
+
export function mapKnownHyperframesError(stderr) {
|
|
38
|
+
if (!stderr)
|
|
39
|
+
return null;
|
|
40
|
+
for (const pattern of KNOWN_ERROR_PATTERNS) {
|
|
41
|
+
const m = stderr.match(pattern.match);
|
|
42
|
+
if (m)
|
|
43
|
+
return `${pattern.message(m)}\n\n--- raw output ---\n${stderr.slice(0, 1500)}`;
|
|
44
|
+
}
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=hyperframe-errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hyperframe-errors.js","sourceRoot":"","sources":["../../../../../src/engine/nodes/local/lib/hyperframe-errors.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,wEAAwE;AACxE,yEAAyE;AACzE,uDAAuD;AACvD,EAAE;AACF,gEAAgE;AAOhE,MAAM,oBAAoB,GAAc;IACtC;QACE,KAAK,EAAE,qDAAqD;QAC5D,OAAO,EAAE,GAAG,EAAE,CACZ,uKAAuK;KAC1K;IACD;QACE,KAAK,EAAE,+CAA+C;QACtD,OAAO,EAAE,GAAG,EAAE,CACZ,oKAAoK;KACvK;IACD;QACE,KAAK,EAAE,8BAA8B;QACrC,OAAO,EAAE,GAAG,EAAE,CACZ,oIAAoI;KACvI;IACD;QACE,KAAK,EAAE,8BAA8B;QACrC,OAAO,EAAE,GAAG,EAAE,CACZ,8HAA8H;KACjI;IACD;QACE,KAAK,EAAE,8BAA8B;QACrC,OAAO,EAAE,GAAG,EAAE,CACZ,+JAA+J;KAClK;IACD;QACE,KAAK,EAAE,4BAA4B;QACnC,OAAO,EAAE,GAAG,EAAE,CACZ,iPAAiP;KACpP;IACD;QACE,KAAK,EAAE,2DAA2D;QAClE,OAAO,EAAE,GAAG,EAAE,CACZ,8JAA8J;KACjK;CACF,CAAC;AAEF,MAAM,UAAU,wBAAwB,CAAC,MAAc;IACrD,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,KAAK,MAAM,OAAO,IAAI,oBAAoB,EAAE,CAAC;QAC3C,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACtC,IAAI,CAAC;YAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,2BAA2B,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC;IACxF,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Replace every `{{name}}` token in `source` with the JS literal form of
|
|
3
|
+
* `values[name]`. Strings render as their plain text (no surrounding quotes
|
|
4
|
+
* — convenient for both `font-size: {{size_px}}px` and `var X = {{name}};`).
|
|
5
|
+
*
|
|
6
|
+
* Complex values (arrays/objects/numbers/booleans) render via JSON.stringify
|
|
7
|
+
* so the result is a syntactically valid JS literal **and** valid JSON.
|
|
8
|
+
*
|
|
9
|
+
* Missing keys are reported in the returned `missing` array; the engine
|
|
10
|
+
* collects these and surfaces a single aggregated error.
|
|
11
|
+
*/
|
|
12
|
+
export declare function substituteVariables(source: string, values: Record<string, unknown>): {
|
|
13
|
+
output: string;
|
|
14
|
+
missing: string[];
|
|
15
|
+
replaced: string[];
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* List every `{{name}}` token referenced in `source`. Used by validators to
|
|
19
|
+
* cross-check declared params vs. tokens actually present in the composition.
|
|
20
|
+
*/
|
|
21
|
+
export declare function extractReferencedTokens(source: string): string[];
|
|
22
|
+
//# sourceMappingURL=templating.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templating.d.ts","sourceRoot":"","sources":["../../../../../src/engine/nodes/local/lib/templating.ts"],"names":[],"mappings":"AAYA;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CAsB3D;AA4BD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAOhE"}
|