@koda-sl/baker-cli 0.129.1-dev.972f3c9aa → 0.131.0-dev.cad5e0bc7
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 +14 -4
- package/dist/{chunk-J2LYFDVC.js → chunk-5LCTMZJ5.js} +79 -5
- package/dist/chunk-5LCTMZJ5.js.map +1 -0
- package/dist/cli.js +572 -468
- package/dist/cli.js.map +1 -1
- package/dist/engine/index.d.ts +10 -0
- package/dist/engine/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-J2LYFDVC.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -26,10 +26,12 @@ import {
|
|
|
26
26
|
requireCredentialsFromEnv,
|
|
27
27
|
resolveConcurrency,
|
|
28
28
|
sha256Hex,
|
|
29
|
+
spineInputFlags,
|
|
30
|
+
spineInputOps,
|
|
29
31
|
toModelSafeImage,
|
|
30
32
|
ulid,
|
|
31
33
|
validateCanvasDeep
|
|
32
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-5LCTMZJ5.js";
|
|
33
35
|
import {
|
|
34
36
|
csvOrJson,
|
|
35
37
|
daysAgoIso,
|
|
@@ -65,7 +67,7 @@ import {
|
|
|
65
67
|
import "./chunk-5WRI5ZAA.js";
|
|
66
68
|
|
|
67
69
|
// src/cli.ts
|
|
68
|
-
import { defineCommand as
|
|
70
|
+
import { defineCommand as defineCommand166, runMain } from "citty";
|
|
69
71
|
|
|
70
72
|
// src/commands/actions/index.ts
|
|
71
73
|
import { defineCommand as defineCommand18 } from "citty";
|
|
@@ -4924,11 +4926,11 @@ function rawTextEntries(value) {
|
|
|
4924
4926
|
const values = Array.isArray(value) ? value : typeof value === "string" ? [value] : [];
|
|
4925
4927
|
return values.filter((v) => typeof v === "string").flatMap((v) => v.split(",")).map((v) => v.trim()).filter(Boolean);
|
|
4926
4928
|
}
|
|
4927
|
-
function rawFileEntries(
|
|
4928
|
-
if (typeof
|
|
4929
|
+
function rawFileEntries(path21) {
|
|
4930
|
+
if (typeof path21 !== "string" || path21.length === 0) {
|
|
4929
4931
|
return [];
|
|
4930
4932
|
}
|
|
4931
|
-
return readFileSync2(
|
|
4933
|
+
return readFileSync2(path21, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
4932
4934
|
}
|
|
4933
4935
|
function keywordEntries(args) {
|
|
4934
4936
|
const defaultMatch = typeof args["match-type"] === "string" ? args["match-type"].toUpperCase() : void 0;
|
|
@@ -4951,19 +4953,19 @@ function keywordEntries(args) {
|
|
|
4951
4953
|
}
|
|
4952
4954
|
return entries;
|
|
4953
4955
|
}
|
|
4954
|
-
function loadJsonFileArg(
|
|
4955
|
-
if (typeof
|
|
4956
|
+
function loadJsonFileArg(path21) {
|
|
4957
|
+
if (typeof path21 !== "string" || path21.length === 0) {
|
|
4956
4958
|
return {};
|
|
4957
4959
|
}
|
|
4958
4960
|
try {
|
|
4959
|
-
const parsed = JSON.parse(readFileSync2(
|
|
4961
|
+
const parsed = JSON.parse(readFileSync2(path21, "utf8"));
|
|
4960
4962
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
4961
|
-
failWriteValidation(`${
|
|
4963
|
+
failWriteValidation(`${path21} must contain a JSON object`);
|
|
4962
4964
|
}
|
|
4963
4965
|
return parsed;
|
|
4964
4966
|
} catch (err) {
|
|
4965
4967
|
if (err instanceof SyntaxError) {
|
|
4966
|
-
failWriteValidation(`${
|
|
4968
|
+
failWriteValidation(`${path21} is not valid JSON: ${err.message}`);
|
|
4967
4969
|
}
|
|
4968
4970
|
throw err;
|
|
4969
4971
|
}
|
|
@@ -5074,10 +5076,10 @@ async function stageUpdate(kind, customerId, target, payload) {
|
|
|
5074
5076
|
async function stageTarget(kind, customerId, target) {
|
|
5075
5077
|
await stageGoogleOp({ kind, customerId, target });
|
|
5076
5078
|
}
|
|
5077
|
-
async function draftAction(
|
|
5079
|
+
async function draftAction(path21, body) {
|
|
5078
5080
|
try {
|
|
5079
5081
|
const chatId = requireChatId();
|
|
5080
|
-
const response = await apiPost(
|
|
5082
|
+
const response = await apiPost(path21, { chatId, ...body });
|
|
5081
5083
|
writeJsonEnvelope(response);
|
|
5082
5084
|
} catch (err) {
|
|
5083
5085
|
handleGoogleError(err);
|
|
@@ -8832,19 +8834,19 @@ function failWriteValidation2(message) {
|
|
|
8832
8834
|
writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
|
|
8833
8835
|
process.exit(1);
|
|
8834
8836
|
}
|
|
8835
|
-
function loadJsonFileArg2(
|
|
8836
|
-
if (typeof
|
|
8837
|
+
function loadJsonFileArg2(path21) {
|
|
8838
|
+
if (typeof path21 !== "string" || path21.length === 0) {
|
|
8837
8839
|
return {};
|
|
8838
8840
|
}
|
|
8839
8841
|
try {
|
|
8840
|
-
const parsed = JSON.parse(readFileSync6(
|
|
8842
|
+
const parsed = JSON.parse(readFileSync6(path21, "utf8"));
|
|
8841
8843
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
8842
|
-
failWriteValidation2(`${
|
|
8844
|
+
failWriteValidation2(`${path21} must contain a JSON object`);
|
|
8843
8845
|
}
|
|
8844
8846
|
return parsed;
|
|
8845
8847
|
} catch (err) {
|
|
8846
8848
|
if (err instanceof SyntaxError) {
|
|
8847
|
-
failWriteValidation2(`${
|
|
8849
|
+
failWriteValidation2(`${path21} is not valid JSON: ${err.message}`);
|
|
8848
8850
|
}
|
|
8849
8851
|
throw err;
|
|
8850
8852
|
}
|
|
@@ -8929,15 +8931,15 @@ function parseLocaleFlag(value) {
|
|
|
8929
8931
|
}
|
|
8930
8932
|
return { language: match[1], country: match[2].toUpperCase() };
|
|
8931
8933
|
}
|
|
8932
|
-
function loadTargetingFileArg(
|
|
8933
|
-
if (typeof
|
|
8934
|
+
function loadTargetingFileArg(path21) {
|
|
8935
|
+
if (typeof path21 !== "string" || path21.length === 0) {
|
|
8934
8936
|
return void 0;
|
|
8935
8937
|
}
|
|
8936
|
-
const parsed = loadJsonFileArg2(
|
|
8938
|
+
const parsed = loadJsonFileArg2(path21);
|
|
8937
8939
|
const criteria = parsed.targetingCriteria ?? parsed;
|
|
8938
8940
|
if (!criteria.include) {
|
|
8939
8941
|
failWriteValidation2(
|
|
8940
|
-
`${
|
|
8942
|
+
`${path21} must contain targeting criteria with an "include" block (see baker schema ads.linkedin.campaigns.create)`
|
|
8941
8943
|
);
|
|
8942
8944
|
}
|
|
8943
8945
|
return criteria;
|
|
@@ -8972,14 +8974,14 @@ function parseCsvLine(line) {
|
|
|
8972
8974
|
cells.push(current);
|
|
8973
8975
|
return cells.map((cell) => cell.trim());
|
|
8974
8976
|
}
|
|
8975
|
-
function parseListFileArg(
|
|
8976
|
-
if (typeof
|
|
8977
|
+
function parseListFileArg(path21, maxRows) {
|
|
8978
|
+
if (typeof path21 !== "string" || path21.length === 0) {
|
|
8977
8979
|
return void 0;
|
|
8978
8980
|
}
|
|
8979
|
-
const raw = readFileSync6(
|
|
8981
|
+
const raw = readFileSync6(path21, "utf8");
|
|
8980
8982
|
const lines = raw.split(/\r?\n/).filter((line) => line.trim().length > 0);
|
|
8981
8983
|
if (lines.length < 2) {
|
|
8982
|
-
failWriteValidation2(`${
|
|
8984
|
+
failWriteValidation2(`${path21} needs a header row and at least one data row`);
|
|
8983
8985
|
}
|
|
8984
8986
|
const columns = parseCsvLine(lines[0]).map((column) => column.trim());
|
|
8985
8987
|
const rows = [];
|
|
@@ -8998,7 +9000,7 @@ function parseListFileArg(path18, maxRows) {
|
|
|
8998
9000
|
}
|
|
8999
9001
|
}
|
|
9000
9002
|
if (rows.length > maxRows) {
|
|
9001
|
-
failWriteValidation2(`${
|
|
9003
|
+
failWriteValidation2(`${path21} has ${rows.length} rows \u2014 the inline limit is ${maxRows}. Split the list.`);
|
|
9002
9004
|
}
|
|
9003
9005
|
return { columns, rows };
|
|
9004
9006
|
}
|
|
@@ -11081,11 +11083,11 @@ var updateStatusSchema = z11.enum(UPDATE_STATUSES);
|
|
|
11081
11083
|
function currencyMinimums2(currencyCode) {
|
|
11082
11084
|
return CURRENCY_MINIMUMS2[currencyCode] ?? DEFAULT_CURRENCY_MINIMUM2;
|
|
11083
11085
|
}
|
|
11084
|
-
function validateDailyBudgetFloor(money, ctx,
|
|
11086
|
+
function validateDailyBudgetFloor(money, ctx, path21) {
|
|
11085
11087
|
if (money?.currencyCode) {
|
|
11086
11088
|
const min = currencyMinimums2(money.currencyCode).dailyBudgetMin;
|
|
11087
11089
|
if (Number(money.amount) < min) {
|
|
11088
|
-
ctx.addIssue({ code: "custom", path:
|
|
11090
|
+
ctx.addIssue({ code: "custom", path: path21, message: `below the ${min} ${money.currencyCode} daily minimum` });
|
|
11089
11091
|
}
|
|
11090
11092
|
}
|
|
11091
11093
|
}
|
|
@@ -11573,19 +11575,19 @@ function failWriteValidation3(message) {
|
|
|
11573
11575
|
writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
|
|
11574
11576
|
process.exit(1);
|
|
11575
11577
|
}
|
|
11576
|
-
function loadJsonFileArg3(
|
|
11577
|
-
if (typeof
|
|
11578
|
+
function loadJsonFileArg3(path21) {
|
|
11579
|
+
if (typeof path21 !== "string" || path21.length === 0) {
|
|
11578
11580
|
return {};
|
|
11579
11581
|
}
|
|
11580
11582
|
try {
|
|
11581
|
-
const parsed = JSON.parse(readFileSync8(
|
|
11583
|
+
const parsed = JSON.parse(readFileSync8(path21, "utf8"));
|
|
11582
11584
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
11583
|
-
failWriteValidation3(`${
|
|
11585
|
+
failWriteValidation3(`${path21} must contain a JSON object`);
|
|
11584
11586
|
}
|
|
11585
11587
|
return parsed;
|
|
11586
11588
|
} catch (err) {
|
|
11587
11589
|
if (err instanceof SyntaxError) {
|
|
11588
|
-
failWriteValidation3(`${
|
|
11590
|
+
failWriteValidation3(`${path21} is not valid JSON: ${err.message}`);
|
|
11589
11591
|
}
|
|
11590
11592
|
throw err;
|
|
11591
11593
|
}
|
|
@@ -14517,7 +14519,7 @@ Examples:
|
|
|
14517
14519
|
});
|
|
14518
14520
|
|
|
14519
14521
|
// src/commands/canvas/index.ts
|
|
14520
|
-
import { defineCommand as
|
|
14522
|
+
import { defineCommand as defineCommand96 } from "citty";
|
|
14521
14523
|
|
|
14522
14524
|
// src/commands/canvas/catalog.ts
|
|
14523
14525
|
import { defineCommand as defineCommand86 } from "citty";
|
|
@@ -14807,12 +14809,12 @@ async function probeDuration(filePath) {
|
|
|
14807
14809
|
}
|
|
14808
14810
|
|
|
14809
14811
|
// src/commands/canvas/rerun.ts
|
|
14810
|
-
import
|
|
14812
|
+
import path11 from "path";
|
|
14811
14813
|
import { defineCommand as defineCommand90 } from "citty";
|
|
14812
14814
|
|
|
14813
14815
|
// src/commands/canvas/run.ts
|
|
14814
|
-
import { readFile as
|
|
14815
|
-
import
|
|
14816
|
+
import { readFile as readFile7 } from "fs/promises";
|
|
14817
|
+
import path10 from "path";
|
|
14816
14818
|
import { defineCommand as defineCommand89 } from "citty";
|
|
14817
14819
|
|
|
14818
14820
|
// src/commands/canvas/placeholders.ts
|
|
@@ -14856,8 +14858,35 @@ function isResolvableRelative(value) {
|
|
|
14856
14858
|
return typeof value === "string" && value.length > 0 && !value.includes("[TODO") && !path3.isAbsolute(value);
|
|
14857
14859
|
}
|
|
14858
14860
|
|
|
14861
|
+
// src/commands/canvas/source-version.ts
|
|
14862
|
+
import { readFile as readFile3 } from "fs/promises";
|
|
14863
|
+
import path4 from "path";
|
|
14864
|
+
async function computeSourceSha(canvasPath) {
|
|
14865
|
+
let canvasBytes;
|
|
14866
|
+
try {
|
|
14867
|
+
canvasBytes = await readFile3(canvasPath);
|
|
14868
|
+
} catch {
|
|
14869
|
+
return void 0;
|
|
14870
|
+
}
|
|
14871
|
+
const promptPath = path4.join(path4.dirname(canvasPath), "prompt.json");
|
|
14872
|
+
let promptBytes;
|
|
14873
|
+
try {
|
|
14874
|
+
promptBytes = await readFile3(promptPath);
|
|
14875
|
+
} catch {
|
|
14876
|
+
promptBytes = Buffer.alloc(0);
|
|
14877
|
+
}
|
|
14878
|
+
return sha256Hex(
|
|
14879
|
+
Buffer.concat([
|
|
14880
|
+
Buffer.from(`${canvasBytes.length}\0`),
|
|
14881
|
+
canvasBytes,
|
|
14882
|
+
Buffer.from(`${promptBytes.length}\0`),
|
|
14883
|
+
promptBytes
|
|
14884
|
+
])
|
|
14885
|
+
);
|
|
14886
|
+
}
|
|
14887
|
+
|
|
14859
14888
|
// src/commands/canvas/style-projection.ts
|
|
14860
|
-
import { readFile as
|
|
14889
|
+
import { readFile as readFile4, writeFile } from "fs/promises";
|
|
14861
14890
|
|
|
14862
14891
|
// src/engine/scaffold/video.ts
|
|
14863
14892
|
import { toCardinal as nwAr } from "n2words/ar-SA";
|
|
@@ -15184,32 +15213,7 @@ function pipOverlayArgs(dims, insets) {
|
|
|
15184
15213
|
return [...inputs, "-filter_complex", filt.join(";"), "-map", "[v]", "{{out.video}}"];
|
|
15185
15214
|
}
|
|
15186
15215
|
var FLASH_HOLD_MAX_S = 2;
|
|
15187
|
-
|
|
15188
|
-
return [
|
|
15189
|
-
"-loop",
|
|
15190
|
-
"1",
|
|
15191
|
-
"-i",
|
|
15192
|
-
"{{in.frame}}",
|
|
15193
|
-
"-t",
|
|
15194
|
-
durationS.toFixed(3),
|
|
15195
|
-
"-r",
|
|
15196
|
-
"30",
|
|
15197
|
-
"-vf",
|
|
15198
|
-
`scale=${dims.w}:${dims.h}:force_original_aspect_ratio=increase,crop=${dims.w}:${dims.h},setsar=1,format=yuv420p`,
|
|
15199
|
-
"-c:v",
|
|
15200
|
-
"libx264",
|
|
15201
|
-
// Near-visually-lossless re-encode. libx264 DEFAULTS (crf 23, preset medium)
|
|
15202
|
-
// roughly halve the source bitrate and add banding on smooth surfaces; the
|
|
15203
|
-
// spine concats these by stream-copy, so any loss here ships to the final cut.
|
|
15204
|
-
"-crf",
|
|
15205
|
-
"18",
|
|
15206
|
-
"-preset",
|
|
15207
|
-
"slow",
|
|
15208
|
-
"-pix_fmt",
|
|
15209
|
-
"yuv420p",
|
|
15210
|
-
"{{out.video}}"
|
|
15211
|
-
];
|
|
15212
|
-
}
|
|
15216
|
+
var MONTAGE_HOLD_MAX_S = 3.5;
|
|
15213
15217
|
function trimArgs(durationS, offsetS = 0, dims) {
|
|
15214
15218
|
return [
|
|
15215
15219
|
"-i",
|
|
@@ -15995,8 +15999,9 @@ function sceneShootMode(scene, present, nativeTurn, cameraOn, casts) {
|
|
|
15995
15999
|
hasProduct: present.some((s) => s.type.toLowerCase() === "product")
|
|
15996
16000
|
});
|
|
15997
16001
|
}
|
|
15998
|
-
function emitSceneNativeAudio(i, nativeTurn, ambientBroll, lengths, clock, nodes, voTracks, nativeSegments, clipRef
|
|
16002
|
+
function emitSceneNativeAudio(i, nativeTurn, ambientBroll, lengths, clock, nodes, voTracks, nativeSegments, clipRef) {
|
|
15999
16003
|
if (nativeTurn) {
|
|
16004
|
+
if (!clipRef) throw new Error(`scaffold invariant: scene ${i} has a native turn but no clip to extract audio from`);
|
|
16000
16005
|
const speechWindow = Math.max(0.5, nativeTurn.end_s - nativeTurn.start_s);
|
|
16001
16006
|
const extractLen = Math.min(speechWindow, lengths.genDur);
|
|
16002
16007
|
nodes.push({
|
|
@@ -16017,7 +16022,7 @@ function emitSceneNativeAudio(i, nativeTurn, ambientBroll, lengths, clock, nodes
|
|
|
16017
16022
|
nodes.push({
|
|
16018
16023
|
id: `s${i}_ambient`,
|
|
16019
16024
|
type: "ffmpeg",
|
|
16020
|
-
inputs: { clip:
|
|
16025
|
+
inputs: { clip: clipRef },
|
|
16021
16026
|
params: { args: audioExtractArgs(lengths.dur), outputs: { audio: { kind: "audio", ext: "mp3" } } }
|
|
16022
16027
|
});
|
|
16023
16028
|
voTracks.push({
|
|
@@ -16079,7 +16084,7 @@ function buildPerSpeakerVoiceConversion(segments, totalMs, nodes) {
|
|
|
16079
16084
|
}
|
|
16080
16085
|
return tracks;
|
|
16081
16086
|
}
|
|
16082
|
-
function emitSceneClip(i, scene, present, mode, nativeTurn, ambientBroll, frames, lengths, out, opts, nodes, tag = "") {
|
|
16087
|
+
function emitSceneClip(i, scene, present, mode, nativeTurn, ambientBroll, frames, lengths, out, opts, nodes, tag = "", defer = false) {
|
|
16083
16088
|
const profile = clipProfileFor(opts.videoModel) ?? SEEDANCE_PROFILE;
|
|
16084
16089
|
const clipParams = {
|
|
16085
16090
|
model: opts.videoModel,
|
|
@@ -16116,6 +16121,14 @@ function emitSceneClip(i, scene, present, mode, nativeTurn, ambientBroll, frames
|
|
|
16116
16121
|
const base = `$ref:s${i}${tag}_clip.video`;
|
|
16117
16122
|
const normDims = opts.outAr && opts.genAr !== opts.outAr ? canvasDims(opts.outAr) : void 0;
|
|
16118
16123
|
if (lengths.genDur === lengths.trimTarget && !normDims) return { ref: base, scene_s: lengths.dur, out };
|
|
16124
|
+
if (defer) {
|
|
16125
|
+
return {
|
|
16126
|
+
ref: base,
|
|
16127
|
+
scene_s: lengths.dur,
|
|
16128
|
+
out,
|
|
16129
|
+
...lengths.genDur !== lengths.trimTarget ? { trim: { offset_s: 0 } } : {}
|
|
16130
|
+
};
|
|
16131
|
+
}
|
|
16119
16132
|
nodes.push({
|
|
16120
16133
|
id: `s${i}${tag}_clip_trim`,
|
|
16121
16134
|
type: "ffmpeg",
|
|
@@ -16190,29 +16203,6 @@ function sceneIsFullScreenUi(scene, present) {
|
|
|
16190
16203
|
const hay = `${scene.summary ?? ""} ${scene.start_frame_prompt ?? ""} ${scene.end_frame_prompt ?? ""} ${scene.action_detail ?? ""}`;
|
|
16191
16204
|
return UI_SURFACE_RE.test(hay);
|
|
16192
16205
|
}
|
|
16193
|
-
function screenStillArgs(durationS, dims) {
|
|
16194
|
-
return [
|
|
16195
|
-
"-loop",
|
|
16196
|
-
"1",
|
|
16197
|
-
"-i",
|
|
16198
|
-
"{{in.frame}}",
|
|
16199
|
-
"-t",
|
|
16200
|
-
durationS.toFixed(3),
|
|
16201
|
-
"-r",
|
|
16202
|
-
"30",
|
|
16203
|
-
"-vf",
|
|
16204
|
-
`scale=${dims.w}:${dims.h}:force_original_aspect_ratio=decrease,pad=${dims.w}:${dims.h}:(ow-iw)/2:(oh-ih)/2:color=black,setsar=1,format=yuv420p`,
|
|
16205
|
-
"-c:v",
|
|
16206
|
-
"libx264",
|
|
16207
|
-
"-crf",
|
|
16208
|
-
"18",
|
|
16209
|
-
"-preset",
|
|
16210
|
-
"slow",
|
|
16211
|
-
"-pix_fmt",
|
|
16212
|
-
"yuv420p",
|
|
16213
|
-
"{{out.video}}"
|
|
16214
|
-
];
|
|
16215
|
-
}
|
|
16216
16206
|
function layeredComposition(scene, uiRouted) {
|
|
16217
16207
|
const regions = compositeRegionsOf(scene);
|
|
16218
16208
|
if (!regions) return null;
|
|
@@ -16383,7 +16373,7 @@ function emitCompositeScene(composite, scene, i, present, mode, nativeTurn, leng
|
|
|
16383
16373
|
);
|
|
16384
16374
|
clips.push(built.clip);
|
|
16385
16375
|
}
|
|
16386
|
-
function emitFlashHold(i, scene, slots, ctx, lengths, out,
|
|
16376
|
+
function emitFlashHold(i, scene, slots, ctx, lengths, out, nodes, clips) {
|
|
16387
16377
|
const frame = buildFrameRef(
|
|
16388
16378
|
"start",
|
|
16389
16379
|
scene.start_frame_asset?.url,
|
|
@@ -16392,18 +16382,9 @@ function emitFlashHold(i, scene, slots, ctx, lengths, out, outAr, nodes, clips)
|
|
|
16392
16382
|
ctx,
|
|
16393
16383
|
nodes
|
|
16394
16384
|
);
|
|
16395
|
-
|
|
16396
|
-
id: `s${i}_clip`,
|
|
16397
|
-
type: "ffmpeg",
|
|
16398
|
-
inputs: { frame },
|
|
16399
|
-
params: {
|
|
16400
|
-
args: stillHoldArgs(lengths.trimTarget, canvasDims(outAr)),
|
|
16401
|
-
outputs: { video: { kind: "video", ext: "mp4" } }
|
|
16402
|
-
}
|
|
16403
|
-
});
|
|
16404
|
-
clips.push({ ref: `$ref:s${i}_clip.video`, scene_s: lengths.dur, out });
|
|
16385
|
+
clips.push({ ref: frame, scene_s: lengths.dur, out, still: { fit: "fill" } });
|
|
16405
16386
|
}
|
|
16406
|
-
function emitScreenScene(i, scene, lengths, out,
|
|
16387
|
+
function emitScreenScene(i, scene, lengths, out, surfaceIngests, nodes, clips) {
|
|
16407
16388
|
const regions = (scene.composition?.regions ?? []).filter((r) => Boolean(r) && typeof r === "object");
|
|
16408
16389
|
const surfaceId = regions.find((r) => r.surface_id)?.surface_id;
|
|
16409
16390
|
let refId = surfaceId ? surfaceIngests.get(surfaceId) : void 0;
|
|
@@ -16421,16 +16402,7 @@ function emitScreenScene(i, scene, lengths, out, outAr, surfaceIngests, nodes, c
|
|
|
16421
16402
|
});
|
|
16422
16403
|
if (surfaceId) surfaceIngests.set(surfaceId, refId);
|
|
16423
16404
|
}
|
|
16424
|
-
|
|
16425
|
-
id: `s${i}_clip`,
|
|
16426
|
-
type: "ffmpeg",
|
|
16427
|
-
inputs: { frame: `$ref:${refId}.asset` },
|
|
16428
|
-
params: {
|
|
16429
|
-
args: screenStillArgs(lengths.trimTarget, canvasDims(outAr)),
|
|
16430
|
-
outputs: { video: { kind: "video", ext: "mp4" } }
|
|
16431
|
-
}
|
|
16432
|
-
});
|
|
16433
|
-
clips.push({ ref: `$ref:s${i}_clip.video`, scene_s: lengths.dur, out });
|
|
16405
|
+
clips.push({ ref: `$ref:${refId}.asset`, scene_s: lengths.dur, out, still: { fit: "pad" } });
|
|
16434
16406
|
}
|
|
16435
16407
|
function sceneIsAllGraphic(scene) {
|
|
16436
16408
|
const regions = (scene.composition?.regions ?? []).filter((r) => Boolean(r) && typeof r === "object");
|
|
@@ -16464,7 +16436,7 @@ function fullFrameGraphicScenes(blueprint) {
|
|
|
16464
16436
|
}
|
|
16465
16437
|
return graphic;
|
|
16466
16438
|
}
|
|
16467
|
-
function emitGraphicScene(i, scene, lengths, out,
|
|
16439
|
+
function emitGraphicScene(i, scene, lengths, out, surfaceIngests, nodes, clips) {
|
|
16468
16440
|
const regions = (scene.composition?.regions ?? []).filter((r) => Boolean(r) && typeof r === "object");
|
|
16469
16441
|
const surfaceId = regions.find((r) => r.surface_id)?.surface_id;
|
|
16470
16442
|
let refId = surfaceId ? surfaceIngests.get(surfaceId) : void 0;
|
|
@@ -16482,16 +16454,7 @@ function emitGraphicScene(i, scene, lengths, out, outAr, surfaceIngests, nodes,
|
|
|
16482
16454
|
});
|
|
16483
16455
|
if (surfaceId) surfaceIngests.set(surfaceId, refId);
|
|
16484
16456
|
}
|
|
16485
|
-
|
|
16486
|
-
id: `s${i}_clip`,
|
|
16487
|
-
type: "ffmpeg",
|
|
16488
|
-
inputs: { frame: `$ref:${refId}.asset` },
|
|
16489
|
-
params: {
|
|
16490
|
-
args: screenStillArgs(lengths.trimTarget, canvasDims(outAr)),
|
|
16491
|
-
outputs: { video: { kind: "video", ext: "mp4" } }
|
|
16492
|
-
}
|
|
16493
|
-
});
|
|
16494
|
-
clips.push({ ref: `$ref:s${i}_clip.video`, scene_s: lengths.dur, out });
|
|
16457
|
+
clips.push({ ref: `$ref:${refId}.asset`, scene_s: lengths.dur, out, still: { fit: "pad" } });
|
|
16495
16458
|
}
|
|
16496
16459
|
var BRAND_CARD_RE = /\b(?:solid|plain|flat|brand|logo|wordmark|end[- ]?card|cta card|title card|colou?r background|background colou?r)\b/i;
|
|
16497
16460
|
function sceneIsBrandCard(scene, present, isCta) {
|
|
@@ -17095,6 +17058,27 @@ function emitCompositeMultiSpeakerVoice(onCam, scene, i, canonical, ensureVoiceN
|
|
|
17095
17058
|
);
|
|
17096
17059
|
}
|
|
17097
17060
|
}
|
|
17061
|
+
function brollKeyframes(scene, i, env, ctx, lengths, prevEndFrame, nodes) {
|
|
17062
|
+
const sharesPrevFrame = Boolean(scene.continues_previous && prevEndFrame);
|
|
17063
|
+
const first = sharesPrevFrame && prevEndFrame ? prevEndFrame : buildFrameRef(
|
|
17064
|
+
"start",
|
|
17065
|
+
scene.start_frame_asset?.url,
|
|
17066
|
+
scene.start_frame_prompt,
|
|
17067
|
+
slotsForFrame(env.slots, i, "start"),
|
|
17068
|
+
ctx,
|
|
17069
|
+
nodes
|
|
17070
|
+
);
|
|
17071
|
+
const nextContinues = Boolean(env.blueprint.scenes[i + 1]?.continues_previous);
|
|
17072
|
+
const last = lengths.trimTarget <= 4 && !nextContinues ? void 0 : buildFrameRef(
|
|
17073
|
+
"end",
|
|
17074
|
+
scene.end_frame_asset?.url,
|
|
17075
|
+
scene.end_frame_prompt,
|
|
17076
|
+
slotsForFrame(env.slots, i, "end"),
|
|
17077
|
+
ctx,
|
|
17078
|
+
nodes
|
|
17079
|
+
);
|
|
17080
|
+
return { first, last, sharesPrevFrame };
|
|
17081
|
+
}
|
|
17098
17082
|
function emitBrollScene(scene, i, isLast, env, nodes, out, prevEndFrame) {
|
|
17099
17083
|
const present = slotsForScene(env.slots, i);
|
|
17100
17084
|
const mode = sceneShootMode(scene, present, void 0, env.cameraOn, env.casts);
|
|
@@ -17110,39 +17094,28 @@ function emitBrollScene(scene, i, isLast, env, nodes, out, prevEndFrame) {
|
|
|
17110
17094
|
ingestCache: env.ingestCache
|
|
17111
17095
|
};
|
|
17112
17096
|
if (!env.reuse && env.graphicScenes.has(i)) {
|
|
17113
|
-
emitGraphicScene(i, scene, lengths, lengths.out, env.
|
|
17097
|
+
emitGraphicScene(i, scene, lengths, lengths.out, env.surfaceIngests, nodes, out.clips);
|
|
17098
|
+
out.routes.set(i, "graphic_plate");
|
|
17114
17099
|
return void 0;
|
|
17115
17100
|
}
|
|
17116
17101
|
if (!env.reuse && sceneIsFullScreenUi(scene, present)) {
|
|
17117
|
-
emitScreenScene(i, scene, lengths, lengths.out, env.
|
|
17102
|
+
emitScreenScene(i, scene, lengths, lengths.out, env.surfaceIngests, nodes, out.clips);
|
|
17103
|
+
out.routes.set(i, "screen_still");
|
|
17118
17104
|
return void 0;
|
|
17119
17105
|
}
|
|
17120
17106
|
const isCta = scene.narrative_role?.trim() === "cta" || isLast;
|
|
17121
17107
|
if (!env.reuse && sceneIsBrandCard(scene, present, isCta)) {
|
|
17122
17108
|
emitBrandCardScene(i, lengths, lengths.out, env.outAr, brandPlateColor(env.blueprint), nodes, out.clips);
|
|
17109
|
+
out.routes.set(i, "brand_card");
|
|
17123
17110
|
return void 0;
|
|
17124
17111
|
}
|
|
17125
|
-
|
|
17126
|
-
|
|
17112
|
+
const holdCeiling = scene.motion_level === "static" || scene.motion_level === "subtle" ? MONTAGE_HOLD_MAX_S : FLASH_HOLD_MAX_S;
|
|
17113
|
+
if (!ambientBroll && lengths.dur <= holdCeiling && scene.motion_level !== "dynamic") {
|
|
17114
|
+
emitFlashHold(i, scene, env.slots, ctx, lengths, lengths.out, nodes, out.clips);
|
|
17115
|
+
out.routes.set(i, "still_hold");
|
|
17127
17116
|
return void 0;
|
|
17128
17117
|
}
|
|
17129
|
-
const sharesPrevFrame =
|
|
17130
|
-
const first = sharesPrevFrame && prevEndFrame ? prevEndFrame : buildFrameRef(
|
|
17131
|
-
"start",
|
|
17132
|
-
scene.start_frame_asset?.url,
|
|
17133
|
-
scene.start_frame_prompt,
|
|
17134
|
-
slotsForFrame(env.slots, i, "start"),
|
|
17135
|
-
ctx,
|
|
17136
|
-
nodes
|
|
17137
|
-
);
|
|
17138
|
-
const last = buildFrameRef(
|
|
17139
|
-
"end",
|
|
17140
|
-
scene.end_frame_asset?.url,
|
|
17141
|
-
scene.end_frame_prompt,
|
|
17142
|
-
slotsForFrame(env.slots, i, "end"),
|
|
17143
|
-
ctx,
|
|
17144
|
-
nodes
|
|
17145
|
-
);
|
|
17118
|
+
const { first, last, sharesPrevFrame } = brollKeyframes(scene, i, env, ctx, lengths, prevEndFrame, nodes);
|
|
17146
17119
|
const clip = emitSceneClip(
|
|
17147
17120
|
i,
|
|
17148
17121
|
scene,
|
|
@@ -17161,7 +17134,9 @@ function emitBrollScene(scene, i, isLast, env, nodes, out, prevEndFrame) {
|
|
|
17161
17134
|
nativeLang: env.ttsLanguageCode,
|
|
17162
17135
|
uiRouted: env.uiRouted.has(i)
|
|
17163
17136
|
},
|
|
17164
|
-
nodes
|
|
17137
|
+
nodes,
|
|
17138
|
+
"",
|
|
17139
|
+
true
|
|
17165
17140
|
);
|
|
17166
17141
|
if (ambientBroll) {
|
|
17167
17142
|
emitSceneNativeAudio(
|
|
@@ -17172,28 +17147,25 @@ function emitBrollScene(scene, i, isLast, env, nodes, out, prevEndFrame) {
|
|
|
17172
17147
|
env.clock,
|
|
17173
17148
|
nodes,
|
|
17174
17149
|
out.voTracks,
|
|
17175
|
-
out.nativeSegments
|
|
17150
|
+
out.nativeSegments,
|
|
17151
|
+
`$ref:s${i}_clip.video`
|
|
17176
17152
|
);
|
|
17177
17153
|
}
|
|
17178
17154
|
out.clips.push(sharesPrevFrame ? { ...clip, continuesFrame: true } : clip);
|
|
17155
|
+
out.routes.set(i, "clip");
|
|
17179
17156
|
return last;
|
|
17180
17157
|
}
|
|
17181
|
-
function emitPresenterSliceClip(
|
|
17158
|
+
function emitPresenterSliceClip(slice, out) {
|
|
17182
17159
|
if (slice.skip) return;
|
|
17183
17160
|
const cont = slice.continuesFrame ? { continuesFrame: true } : {};
|
|
17184
|
-
const
|
|
17185
|
-
|
|
17186
|
-
|
|
17187
|
-
|
|
17188
|
-
|
|
17189
|
-
|
|
17190
|
-
|
|
17191
|
-
id: `s${i}_seg`,
|
|
17192
|
-
type: "ffmpeg",
|
|
17193
|
-
inputs: { clip: slice.clipRef },
|
|
17194
|
-
params: { args: trimArgs(slice.len, slice.offset, normDims), outputs: { video: { kind: "video", ext: "mp4" } } }
|
|
17161
|
+
const whole = slice.offset === 0 && Math.abs(slice.len - slice.clipDur) <= 0.05;
|
|
17162
|
+
out.clips.push({
|
|
17163
|
+
ref: slice.clipRef,
|
|
17164
|
+
scene_s: slice.len,
|
|
17165
|
+
out: null,
|
|
17166
|
+
...cont,
|
|
17167
|
+
...whole ? {} : { trim: { offset_s: slice.offset } }
|
|
17195
17168
|
});
|
|
17196
|
-
out.clips.push({ ref: `$ref:s${i}_seg.video`, scene_s: slice.len, out: null, ...cont });
|
|
17197
17169
|
}
|
|
17198
17170
|
function buildTimeline(blueprint, slots, opts, nodes) {
|
|
17199
17171
|
const reuse = opts.frames === "reuse";
|
|
@@ -17224,6 +17196,7 @@ function buildTimeline(blueprint, slots, opts, nodes) {
|
|
|
17224
17196
|
ttsLanguageCode: deriveTtsLanguageCode(blueprint)
|
|
17225
17197
|
};
|
|
17226
17198
|
const out = {
|
|
17199
|
+
routes: /* @__PURE__ */ new Map(),
|
|
17227
17200
|
clips: [],
|
|
17228
17201
|
voTracks: [],
|
|
17229
17202
|
voSegments: [],
|
|
@@ -17263,12 +17236,14 @@ function buildTimeline(blueprint, slots, opts, nodes) {
|
|
|
17263
17236
|
nodes,
|
|
17264
17237
|
out
|
|
17265
17238
|
);
|
|
17239
|
+
out.routes.set(i, "composite");
|
|
17266
17240
|
prevEndFrame = void 0;
|
|
17267
17241
|
return;
|
|
17268
17242
|
}
|
|
17269
17243
|
const slice = out.sceneSlice.get(i);
|
|
17270
17244
|
if (slice) {
|
|
17271
|
-
emitPresenterSliceClip(
|
|
17245
|
+
emitPresenterSliceClip(slice, out);
|
|
17246
|
+
out.routes.set(i, slice.skip ? "phrase_run" : "phrase_slice");
|
|
17272
17247
|
prevEndFrame = void 0;
|
|
17273
17248
|
return;
|
|
17274
17249
|
}
|
|
@@ -17276,7 +17251,13 @@ function buildTimeline(blueprint, slots, opts, nodes) {
|
|
|
17276
17251
|
});
|
|
17277
17252
|
const totalMs = Math.round(env.clock.totalS * 1e3);
|
|
17278
17253
|
out.voTracks.push(...buildPerSpeakerVoiceConversion(out.nativeSegments, totalMs, nodes));
|
|
17279
|
-
return {
|
|
17254
|
+
return {
|
|
17255
|
+
clips: out.clips,
|
|
17256
|
+
voTracks: out.voTracks,
|
|
17257
|
+
vo_segments: out.voSegments,
|
|
17258
|
+
talking_scenes: out.talkingScenes,
|
|
17259
|
+
routes: out.routes
|
|
17260
|
+
};
|
|
17280
17261
|
}
|
|
17281
17262
|
function buildSfxMusic(blueprint, clock, nodes) {
|
|
17282
17263
|
const tracks = [];
|
|
@@ -17563,18 +17544,20 @@ function seamDropOps(clips, i, seam) {
|
|
|
17563
17544
|
return `reverse,trim=start_frame=1,setpts=PTS-STARTPTS,reverse,${SEAM_FRAME_PAD}`;
|
|
17564
17545
|
return null;
|
|
17565
17546
|
}
|
|
17566
|
-
function
|
|
17567
|
-
|
|
17547
|
+
function spineInputChain(clips, i, seam, dims) {
|
|
17548
|
+
const c = clips[i];
|
|
17549
|
+
const ops = spineInputOps(c, clipInputLen(c), dims);
|
|
17550
|
+
const seamOps = seamDropOps(clips, i, seam);
|
|
17551
|
+
return `[${i}:v]${ops}${seamOps ? `,${seamOps}` : ""}[c${i}]`;
|
|
17568
17552
|
}
|
|
17569
17553
|
var SPINE_OUTPUT_ENCODE = ["-r", "30", "-c:v", "libx264", "-crf", "18", "-preset", "slow", "-pix_fmt", "yuv420p"];
|
|
17570
17554
|
function concatArgs(clips, seam, dims) {
|
|
17571
17555
|
const inputs = [];
|
|
17572
17556
|
const pre = [];
|
|
17573
17557
|
const labels = [];
|
|
17574
|
-
clips.forEach((
|
|
17575
|
-
inputs.push("-i", `{{in.c${i}}}`);
|
|
17576
|
-
|
|
17577
|
-
pre.push(`[${i}:v]${spineInputNormalize(dims)}${ops ? `,${ops}` : ""}[c${i}]`);
|
|
17558
|
+
clips.forEach((c, i) => {
|
|
17559
|
+
inputs.push(...spineInputFlags(c, clipInputLen(c)), "-i", `{{in.c${i}}}`);
|
|
17560
|
+
pre.push(spineInputChain(clips, i, seam, dims));
|
|
17578
17561
|
labels.push(`[c${i}]`);
|
|
17579
17562
|
});
|
|
17580
17563
|
const graph = [...pre, `${labels.join("")}concat=n=${clips.length}:v=1:a=0[v]`].join(";");
|
|
@@ -17588,9 +17571,8 @@ function xfadeSpineArgs(clips, seam, dims) {
|
|
|
17588
17571
|
const inputs = [];
|
|
17589
17572
|
const filt = [];
|
|
17590
17573
|
for (let i = 0; i < n; i++) {
|
|
17591
|
-
inputs.push("-i", `{{in.c${i}}}`);
|
|
17592
|
-
|
|
17593
|
-
filt.push(`[${i}:v]${spineInputNormalize(dims)}${ops ? `,${ops}` : ""}[c${i}]`);
|
|
17574
|
+
inputs.push(...spineInputFlags(clips[i], clipInputLen(clips[i])), "-i", `{{in.c${i}}}`);
|
|
17575
|
+
filt.push(spineInputChain(clips, i, seam, dims));
|
|
17594
17576
|
}
|
|
17595
17577
|
let cur = "c0";
|
|
17596
17578
|
let accLen = clipInputLen(clips[0]);
|
|
@@ -17694,7 +17676,7 @@ function scaffoldVideoCanvas(input, elementsInput, opts) {
|
|
|
17694
17676
|
});
|
|
17695
17677
|
});
|
|
17696
17678
|
buildElementSheets(slots, nodes);
|
|
17697
|
-
const { clips, voTracks, vo_segments, talking_scenes } = buildTimeline(blueprint, slots, opts, nodes);
|
|
17679
|
+
const { clips, voTracks, vo_segments, talking_scenes, routes } = buildTimeline(blueprint, slots, opts, nodes);
|
|
17698
17680
|
const outAspect = resolveAspect(blueprint.source?.aspect_ratio, opts.aspect, genAspectsFor(opts.videoModel));
|
|
17699
17681
|
let videoRef = buildSpine(clips, opts.seamDedup ?? "head", canvasDims(outAspect.outAr), nodes);
|
|
17700
17682
|
let videoNode = "spine";
|
|
@@ -17793,14 +17775,39 @@ function scaffoldVideoCanvas(input, elementsInput, opts) {
|
|
|
17793
17775
|
// The timing plan `baker canvas validate` checks before any billed render:
|
|
17794
17776
|
// sequenced voiceover turns (no overlap), audio ≈ video length, and which
|
|
17795
17777
|
// scenes must be lip-synced.
|
|
17796
|
-
video: buildVideoMeta(
|
|
17778
|
+
video: buildVideoMeta(
|
|
17779
|
+
blueprint,
|
|
17780
|
+
clock,
|
|
17781
|
+
{ vo_segments, talking_scenes, routes },
|
|
17782
|
+
slots,
|
|
17783
|
+
nodes,
|
|
17784
|
+
Boolean(audioMixRef)
|
|
17785
|
+
)
|
|
17797
17786
|
},
|
|
17798
17787
|
nodes,
|
|
17799
17788
|
output: { node: videoNode, output: "video" }
|
|
17800
17789
|
};
|
|
17801
17790
|
}
|
|
17791
|
+
function buildGraphStats(blueprint, routes, nodes) {
|
|
17792
|
+
const histogram = {};
|
|
17793
|
+
for (const n of nodes) histogram[n.type] = (histogram[n.type] ?? 0) + 1;
|
|
17794
|
+
const billable = nodes.filter((n) => n.type === "image_generate" || n.type === "video_generate").length;
|
|
17795
|
+
return {
|
|
17796
|
+
nodes_total: nodes.length,
|
|
17797
|
+
nodes_billable: billable,
|
|
17798
|
+
node_types: histogram,
|
|
17799
|
+
scene_routes: blueprint.scenes.map((scene, i) => ({
|
|
17800
|
+
scene: i,
|
|
17801
|
+
route: routes.get(i) ?? "clip",
|
|
17802
|
+
window_s: Math.round(sceneDurationS(scene) * 100) / 100
|
|
17803
|
+
}))
|
|
17804
|
+
};
|
|
17805
|
+
}
|
|
17802
17806
|
function buildVideoMeta(blueprint, clock, meta, slots, nodes, hasAudioMix) {
|
|
17803
17807
|
return {
|
|
17808
|
+
// WHY the graph has the nodes it has: one route per scene (the dispatcher's own
|
|
17809
|
+
// record) + a node-type histogram. The first thing to read when a canvas looks big.
|
|
17810
|
+
graph_stats: buildGraphStats(blueprint, meta.routes, nodes),
|
|
17804
17811
|
// The SPINE length (Σ scene durations) — what the picture and the mix are pinned to.
|
|
17805
17812
|
duration_s: clock.totalS,
|
|
17806
17813
|
// The one-clock contract the validator enforces on the LIVE graph: the spine's
|
|
@@ -17996,7 +18003,7 @@ function buildVideoTodo(report, overlayCount, floatingCount, opts, blueprint) {
|
|
|
17996
18003
|
voice_description: d.voice_description,
|
|
17997
18004
|
line: d.line
|
|
17998
18005
|
})),
|
|
17999
|
-
talking_head_note: "SHOT-NATIVE: a presenter shot is ONE Seedance clip (its line quoted in s<anchor>_clip's prompt + generate_audio) so lips+voice are generated together \u2014 no tts, no veed-lipsync. Two adjacent presenter shots at a hard cut are SEPARATE clips; a cutaway phrase (the presenter on camera, cut to b-roll, back on camera) stays one clip
|
|
18006
|
+
talking_head_note: "SHOT-NATIVE: a presenter shot is ONE Seedance clip (its line quoted in s<anchor>_clip's prompt + generate_audio) so lips+voice are generated together \u2014 no tts, no veed-lipsync. Two adjacent presenter shots at a hard cut are SEPARATE clips; a cutaway phrase (the presenter on camera, cut to b-roll, back on camera) stays one clip whose on-camera windows are cut inside the spine's per-input chains (no extra nodes). Edit the line in the s<anchor>_clip prompt to re-author it. A pure-voiceover phrase (speaker never shown) is one ElevenLabs tts read instead.",
|
|
18000
18007
|
voice_note: "ONE voice per person: a single voice_select is reused across all that person's shots (on-camera AND off \u2014 the deconstruct's `voiceover` label folds into the sole presenter). Every presenter clip's native audio is extracted and re-voiced to that brand voice through a SINGLE merged audio_voice_convert per speaker (<voice>_conv, eleven_multilingual_sts_v2, timing preserved so lips stay matched) \u2014 so timbre stays consistent across the separate shot clips. Set voice_select.voice_id's gender/language to match the creator.",
|
|
18001
18008
|
native_timing: "Clips separate at COMPLETE BREAKS between shots, but the VOICE stays continuous where it should: a voiceover narration is ONE read across the b-roll it plays over, and a cutaway leaves the presenter's read continuous under the insert. Each clip is generated long enough for its estimated speech. `metadata.video.talking_scenes` carries each shot's scene_s vs est_speech_s. CAVEAT: a b-roll cutaway INSIDE a phrase lands at an approximate (proportional) time \u2014 Seedance exposes no word timing \u2014 so if a cutaway is off its beat, nudge the scene boundary (it's a starting point). NOTE: a native clip's voice is extracted for the SPOKEN window only (`s<i>_voextract`'s `-t`) \u2014 when the scene runs longer than the line, the picture tail is deliberately silent (extracting the full clip would put post-line breathing/babble on the voice bus); trim the scene or extend the line if the dead air reads wrong.",
|
|
18002
18009
|
craft: {
|
|
@@ -18135,8 +18142,8 @@ function renderStyleProjectionFromValue(blueprint) {
|
|
|
18135
18142
|
async function syncStyleProjection(canvas, log) {
|
|
18136
18143
|
const pair = findBlueprintProjection(canvas);
|
|
18137
18144
|
if (!pair) return "not_applicable";
|
|
18138
|
-
const rendered = renderStyleProjection(await
|
|
18139
|
-
const current = await
|
|
18145
|
+
const rendered = renderStyleProjection(await readFile4(pair.promptPath, "utf8"));
|
|
18146
|
+
const current = await readFile4(pair.stylePath, "utf8").catch(() => null);
|
|
18140
18147
|
if (current === rendered) return "up_to_date";
|
|
18141
18148
|
await writeFile(pair.stylePath, rendered, "utf8");
|
|
18142
18149
|
log(
|
|
@@ -18198,13 +18205,13 @@ ${body}` : header || body || compactJson(record);
|
|
|
18198
18205
|
}
|
|
18199
18206
|
|
|
18200
18207
|
// src/commands/canvas/run-record.ts
|
|
18201
|
-
import
|
|
18208
|
+
import path5 from "path";
|
|
18202
18209
|
var MAX_RUN_NODES = 200;
|
|
18203
18210
|
var MAX_OUTPUTS_PER_NODE = 10;
|
|
18204
18211
|
var MAX_FINAL_OUTPUTS = 10;
|
|
18205
18212
|
var MAX_CREATIVE_SLUG_LENGTH = 100;
|
|
18206
18213
|
function creativeSlugFromCanvasPath(filePath) {
|
|
18207
|
-
const normalized = filePath.split(
|
|
18214
|
+
const normalized = filePath.split(path5.sep).join("/");
|
|
18208
18215
|
const match = normalized.match(/(?:^|\/)src\/creatives\/([a-z0-9](?:[a-z0-9-]*[a-z0-9])?)\//);
|
|
18209
18216
|
const slug = match?.[1] ?? null;
|
|
18210
18217
|
return slug && slug.length <= MAX_CREATIVE_SLUG_LENGTH ? slug : null;
|
|
@@ -18489,43 +18496,59 @@ var RunRecordPoster = class {
|
|
|
18489
18496
|
|
|
18490
18497
|
// src/commands/canvas/run-retention.ts
|
|
18491
18498
|
import { rm } from "fs/promises";
|
|
18492
|
-
import
|
|
18499
|
+
import path6 from "path";
|
|
18493
18500
|
function runDirsToPrune(entries, keep, currentRunId) {
|
|
18494
18501
|
const runs = entries.filter((e) => /^r_[0-9A-Za-z]+$/.test(e) && e !== currentRunId).sort();
|
|
18495
18502
|
if (keep <= 0) return runs;
|
|
18496
18503
|
return runs.slice(0, Math.max(0, runs.length - keep));
|
|
18497
18504
|
}
|
|
18498
18505
|
async function pruneOldRuns(outputsDir, keep, currentRunId, log) {
|
|
18499
|
-
const { readdir:
|
|
18506
|
+
const { readdir: readdir6 } = await import("fs/promises");
|
|
18500
18507
|
let entries;
|
|
18501
18508
|
try {
|
|
18502
|
-
entries = await
|
|
18509
|
+
entries = await readdir6(outputsDir);
|
|
18503
18510
|
} catch {
|
|
18504
18511
|
return;
|
|
18505
18512
|
}
|
|
18506
18513
|
const toPrune = runDirsToPrune(entries, keep, currentRunId);
|
|
18507
18514
|
if (toPrune.length === 0) return;
|
|
18508
18515
|
for (const dir of toPrune) {
|
|
18509
|
-
await rm(
|
|
18516
|
+
await rm(path6.join(outputsDir, dir), { recursive: true, force: true }).catch(
|
|
18510
18517
|
(e) => log(`[prune ] could not remove ${dir}: ${e.message}`)
|
|
18511
18518
|
);
|
|
18512
18519
|
}
|
|
18513
18520
|
log(`[prune ] removed ${toPrune.length} old run dir(s), kept the ${keep} newest`);
|
|
18514
18521
|
}
|
|
18515
18522
|
|
|
18523
|
+
// src/commands/canvas/dirty-marker.ts
|
|
18524
|
+
import { mkdir, readdir as readdir2, rm as rm2, writeFile as writeFile2 } from "fs/promises";
|
|
18525
|
+
import path7 from "path";
|
|
18526
|
+
function creativeDirtyDir(base) {
|
|
18527
|
+
return base ?? path7.resolve("canvas", ".dirty");
|
|
18528
|
+
}
|
|
18529
|
+
function dirtyMarkerFile(slug, base) {
|
|
18530
|
+
return path7.join(creativeDirtyDir(base), `${slug}.json`);
|
|
18531
|
+
}
|
|
18532
|
+
async function clearCreativeDirty(slug, base) {
|
|
18533
|
+
try {
|
|
18534
|
+
await rm2(dirtyMarkerFile(slug, base), { force: true });
|
|
18535
|
+
} catch {
|
|
18536
|
+
}
|
|
18537
|
+
}
|
|
18538
|
+
|
|
18516
18539
|
// src/commands/canvas/run-resume.ts
|
|
18517
|
-
import { mkdir, readFile as
|
|
18518
|
-
import
|
|
18540
|
+
import { mkdir as mkdir2, readFile as readFile5, rm as rm3, writeFile as writeFile3 } from "fs/promises";
|
|
18541
|
+
import path8 from "path";
|
|
18519
18542
|
function markerKey(canvasPath) {
|
|
18520
18543
|
const slug = creativeSlugFromCanvasPath(canvasPath);
|
|
18521
|
-
const identity2 = slug ??
|
|
18544
|
+
const identity2 = slug ?? path8.relative(process.cwd(), path8.resolve(canvasPath));
|
|
18522
18545
|
return sha256Hex(Buffer.from(identity2)).slice(0, 32);
|
|
18523
18546
|
}
|
|
18524
18547
|
function legacyMarkerKey(canvasPath) {
|
|
18525
|
-
return sha256Hex(Buffer.from(
|
|
18548
|
+
return sha256Hex(Buffer.from(path8.resolve(canvasPath))).slice(0, 32);
|
|
18526
18549
|
}
|
|
18527
18550
|
function markerFile(outputsDir, key) {
|
|
18528
|
-
return
|
|
18551
|
+
return path8.join(outputsDir, ".inflight", `${key}.json`);
|
|
18529
18552
|
}
|
|
18530
18553
|
var REMOTE_ADOPT_STALE_MS = 12e4;
|
|
18531
18554
|
function classifyRemoteRun(run, now) {
|
|
@@ -18561,7 +18584,7 @@ async function resolveRunId(opts) {
|
|
|
18561
18584
|
async function readMarkerRunId(outputsDir, canvasPath) {
|
|
18562
18585
|
for (const key of [markerKey(canvasPath), legacyMarkerKey(canvasPath)]) {
|
|
18563
18586
|
try {
|
|
18564
|
-
const raw = await
|
|
18587
|
+
const raw = await readFile5(markerFile(outputsDir, key), "utf8");
|
|
18565
18588
|
const parsed = JSON.parse(raw);
|
|
18566
18589
|
if (typeof parsed.runId === "string" && parsed.runId.length > 0) return parsed.runId;
|
|
18567
18590
|
} catch {
|
|
@@ -18572,23 +18595,23 @@ async function readMarkerRunId(outputsDir, canvasPath) {
|
|
|
18572
18595
|
async function markRunInFlight(outputsDir, canvasPath, runId) {
|
|
18573
18596
|
try {
|
|
18574
18597
|
const file = markerFile(outputsDir, markerKey(canvasPath));
|
|
18575
|
-
await
|
|
18576
|
-
await
|
|
18598
|
+
await mkdir2(path8.dirname(file), { recursive: true });
|
|
18599
|
+
await writeFile3(file, JSON.stringify({ runId, canvasPath: path8.resolve(canvasPath), startedAt: Date.now() }));
|
|
18577
18600
|
} catch {
|
|
18578
18601
|
}
|
|
18579
18602
|
}
|
|
18580
18603
|
async function clearRunMarker(outputsDir, canvasPath) {
|
|
18581
18604
|
for (const key of [markerKey(canvasPath), legacyMarkerKey(canvasPath)]) {
|
|
18582
18605
|
try {
|
|
18583
|
-
await
|
|
18606
|
+
await rm3(markerFile(outputsDir, key), { force: true });
|
|
18584
18607
|
} catch {
|
|
18585
18608
|
}
|
|
18586
18609
|
}
|
|
18587
18610
|
}
|
|
18588
18611
|
|
|
18589
18612
|
// src/commands/canvas/run-snapshot.ts
|
|
18590
|
-
import { mkdir as
|
|
18591
|
-
import
|
|
18613
|
+
import { mkdir as mkdir3, readdir as readdir3, readFile as readFile6, stat as stat2, writeFile as writeFile4 } from "fs/promises";
|
|
18614
|
+
import path9 from "path";
|
|
18592
18615
|
var SNAPSHOT_SCHEMA = "baker-canvas-snapshot/1";
|
|
18593
18616
|
var MAX_SNAPSHOT_FILE_BYTES = 32 * 1024 * 1024;
|
|
18594
18617
|
var EXT_TO_MIME = {
|
|
@@ -18615,11 +18638,11 @@ var EXT_TO_MIME = {
|
|
|
18615
18638
|
woff2: "font/woff2"
|
|
18616
18639
|
};
|
|
18617
18640
|
function mimeForFile(filePath) {
|
|
18618
|
-
const ext =
|
|
18641
|
+
const ext = path9.extname(filePath).slice(1).toLowerCase();
|
|
18619
18642
|
return EXT_TO_MIME[ext] ?? "application/octet-stream";
|
|
18620
18643
|
}
|
|
18621
18644
|
function toPosix(p) {
|
|
18622
|
-
return p.split(
|
|
18645
|
+
return p.split(path9.sep).join("/");
|
|
18623
18646
|
}
|
|
18624
18647
|
function localPathRefsFromCanvas(parsed) {
|
|
18625
18648
|
const nodes = parsed?.nodes;
|
|
@@ -18643,30 +18666,30 @@ function isSnapshotablePath(value) {
|
|
|
18643
18666
|
}
|
|
18644
18667
|
async function uploadRunSnapshot(client, opts) {
|
|
18645
18668
|
try {
|
|
18646
|
-
const canvasDir =
|
|
18669
|
+
const canvasDir = path9.dirname(opts.canvasPath);
|
|
18647
18670
|
const put = (bytes, mime) => putContentAddressed(client, bytes, mime, opts.signal);
|
|
18648
18671
|
const canvasBytes = Buffer.from(opts.raw);
|
|
18649
18672
|
const canvasUpload = await put(canvasBytes, "application/json");
|
|
18650
18673
|
const files = [];
|
|
18651
18674
|
const skipped = [];
|
|
18652
18675
|
for (const refPath of localPathRefsFromCanvas(opts.parsed)) {
|
|
18653
|
-
const abs =
|
|
18676
|
+
const abs = path9.isAbsolute(refPath) ? refPath : path9.resolve(canvasDir, refPath);
|
|
18654
18677
|
let st;
|
|
18655
18678
|
try {
|
|
18656
18679
|
st = await stat2(abs);
|
|
18657
18680
|
} catch {
|
|
18658
|
-
skipped.push({ path: toPosix(
|
|
18681
|
+
skipped.push({ path: toPosix(path9.relative(canvasDir, abs)), reason: "missing" });
|
|
18659
18682
|
continue;
|
|
18660
18683
|
}
|
|
18661
18684
|
const fileList = st.isDirectory() ? await listFilesRecursive(abs) : [abs];
|
|
18662
18685
|
for (const file of fileList) {
|
|
18663
|
-
const rel = toPosix(
|
|
18686
|
+
const rel = toPosix(path9.relative(canvasDir, file));
|
|
18664
18687
|
const size = (await stat2(file)).size;
|
|
18665
18688
|
if (size > MAX_SNAPSHOT_FILE_BYTES) {
|
|
18666
18689
|
skipped.push({ path: rel, reason: `too large (${size} bytes)` });
|
|
18667
18690
|
continue;
|
|
18668
18691
|
}
|
|
18669
|
-
const bytes = await
|
|
18692
|
+
const bytes = await readFile6(file);
|
|
18670
18693
|
const upload = await put(bytes, mimeForFile(file));
|
|
18671
18694
|
files.push({ path: rel, sha256: upload.sha256, url: upload.url });
|
|
18672
18695
|
}
|
|
@@ -18675,7 +18698,7 @@ async function uploadRunSnapshot(client, opts) {
|
|
|
18675
18698
|
schema: SNAPSHOT_SCHEMA,
|
|
18676
18699
|
creativeSlug: opts.creativeSlug,
|
|
18677
18700
|
canvasSha: canvasUpload.sha256,
|
|
18678
|
-
canvas: { path:
|
|
18701
|
+
canvas: { path: path9.basename(opts.canvasPath), sha256: canvasUpload.sha256, url: canvasUpload.url },
|
|
18679
18702
|
files,
|
|
18680
18703
|
skipped: skipped.length > 0 ? skipped : void 0
|
|
18681
18704
|
};
|
|
@@ -18701,8 +18724,8 @@ async function putContentAddressed(client, bytes, mime, signal) {
|
|
|
18701
18724
|
return { sha256, url: publicUrl };
|
|
18702
18725
|
}
|
|
18703
18726
|
async function listFilesRecursive(dir) {
|
|
18704
|
-
const entries = await
|
|
18705
|
-
return entries.filter((d) => d.isFile()).map((d) =>
|
|
18727
|
+
const entries = await readdir3(dir, { recursive: true, withFileTypes: true });
|
|
18728
|
+
return entries.filter((d) => d.isFile()).map((d) => path9.join(d.parentPath, d.name));
|
|
18706
18729
|
}
|
|
18707
18730
|
var SnapshotConflictError = class extends Error {
|
|
18708
18731
|
conflicts;
|
|
@@ -18714,19 +18737,19 @@ var SnapshotConflictError = class extends Error {
|
|
|
18714
18737
|
};
|
|
18715
18738
|
async function restoreRunSnapshot(manifest, targetDir, opts = {}) {
|
|
18716
18739
|
const entries = [manifest.canvas, ...manifest.files];
|
|
18717
|
-
const resolvedTarget =
|
|
18740
|
+
const resolvedTarget = path9.resolve(targetDir);
|
|
18718
18741
|
const planned = [];
|
|
18719
18742
|
const conflicts = [];
|
|
18720
18743
|
const upToDate = [];
|
|
18721
18744
|
for (const entry of entries) {
|
|
18722
|
-
if (
|
|
18745
|
+
if (path9.isAbsolute(entry.path) || entry.path.split("/").includes("..")) {
|
|
18723
18746
|
throw new Error(`snapshot entry escapes the creative directory: ${entry.path}`);
|
|
18724
18747
|
}
|
|
18725
|
-
const target =
|
|
18726
|
-
if (target !== resolvedTarget && !target.startsWith(resolvedTarget +
|
|
18748
|
+
const target = path9.resolve(resolvedTarget, entry.path);
|
|
18749
|
+
if (target !== resolvedTarget && !target.startsWith(resolvedTarget + path9.sep)) {
|
|
18727
18750
|
throw new Error(`snapshot entry escapes the creative directory: ${entry.path}`);
|
|
18728
18751
|
}
|
|
18729
|
-
const existing = await
|
|
18752
|
+
const existing = await readFile6(target).catch(() => null);
|
|
18730
18753
|
if (existing) {
|
|
18731
18754
|
if (sha256Hex(existing) === entry.sha256) {
|
|
18732
18755
|
upToDate.push(entry.path);
|
|
@@ -18748,11 +18771,11 @@ async function restoreRunSnapshot(manifest, targetDir, opts = {}) {
|
|
|
18748
18771
|
if (sha256Hex(bytes) !== entry.sha256) {
|
|
18749
18772
|
throw new Error(`snapshot download for ${entry.path} does not match its recorded sha256`);
|
|
18750
18773
|
}
|
|
18751
|
-
await
|
|
18752
|
-
await
|
|
18774
|
+
await mkdir3(path9.dirname(target), { recursive: true });
|
|
18775
|
+
await writeFile4(target, bytes);
|
|
18753
18776
|
restored.push(entry.path);
|
|
18754
18777
|
}
|
|
18755
|
-
return { canvasPath:
|
|
18778
|
+
return { canvasPath: path9.resolve(resolvedTarget, manifest.canvas.path), restored, upToDate };
|
|
18756
18779
|
}
|
|
18757
18780
|
|
|
18758
18781
|
// src/commands/canvas/run.ts
|
|
@@ -18832,8 +18855,8 @@ function resolveMaxCredits(...candidates) {
|
|
|
18832
18855
|
return void 0;
|
|
18833
18856
|
}
|
|
18834
18857
|
async function executeCanvasRun(opts) {
|
|
18835
|
-
const filePath =
|
|
18836
|
-
const raw = await
|
|
18858
|
+
const filePath = path10.resolve(opts.file);
|
|
18859
|
+
const raw = await readFile7(filePath, "utf8");
|
|
18837
18860
|
let parsed;
|
|
18838
18861
|
try {
|
|
18839
18862
|
parsed = JSON.parse(raw);
|
|
@@ -18843,7 +18866,9 @@ async function executeCanvasRun(opts) {
|
|
|
18843
18866
|
`);
|
|
18844
18867
|
process.exit(2);
|
|
18845
18868
|
}
|
|
18846
|
-
|
|
18869
|
+
const attemptedSlug = creativeSlugFromCanvasPath(filePath);
|
|
18870
|
+
if (attemptedSlug) await clearCreativeDirty(attemptedSlug);
|
|
18871
|
+
parsed = resolveRelativeCanvasPaths(parsed, path10.dirname(filePath));
|
|
18847
18872
|
try {
|
|
18848
18873
|
await syncStyleProjection(parsed, (line) => process.stderr.write(`${line}
|
|
18849
18874
|
`));
|
|
@@ -18927,7 +18952,7 @@ async function executeCanvasRun(opts) {
|
|
|
18927
18952
|
const canvasSha = sha256Hex(Buffer.from(raw));
|
|
18928
18953
|
const creativeSlug = creativeSlugFromCanvasPath(filePath) ?? void 0;
|
|
18929
18954
|
const client = opts.record === false ? null : buildBackendClient();
|
|
18930
|
-
const outputsDir = opts.outputsDir ?
|
|
18955
|
+
const outputsDir = opts.outputsDir ? path10.resolve(opts.outputsDir) : path10.resolve("canvas");
|
|
18931
18956
|
const { runId, resumed, source, concurrentRunId } = await resolveRunId({
|
|
18932
18957
|
explicitRunId: opts.runId,
|
|
18933
18958
|
fresh: opts.fresh === true,
|
|
@@ -18961,8 +18986,12 @@ async function executeCanvasRun(opts) {
|
|
|
18961
18986
|
const canvasSnapshotUrl = client && creativeSlug ? await uploadRunSnapshot(client, { canvasPath: filePath, raw, creativeSlug, parsed }) ?? void 0 : void 0;
|
|
18962
18987
|
const recordMeta = {
|
|
18963
18988
|
creativeSlug,
|
|
18964
|
-
canvasPath:
|
|
18989
|
+
canvasPath: path10.relative(process.cwd(), filePath) || void 0,
|
|
18965
18990
|
canvasSha,
|
|
18991
|
+
// The fingerprint the dashboard compares against the current source to flag
|
|
18992
|
+
// "edited since last render". Computed from the on-disk canvas.json +
|
|
18993
|
+
// prompt.json — the same helper the edit-sync uses, so the two are comparable.
|
|
18994
|
+
sourceSha: await computeSourceSha(filePath),
|
|
18966
18995
|
chatId: getEnv().BAKER_CHAT_ID || void 0,
|
|
18967
18996
|
canvasSnapshotUrl
|
|
18968
18997
|
};
|
|
@@ -19144,7 +19173,7 @@ var rerunCommand = defineCommand90({
|
|
|
19144
19173
|
if (latest.canvasSha && manifest.canvasSha !== latest.canvasSha) {
|
|
19145
19174
|
fail("snapshot_mismatch", `snapshot manifest for run ${latest.runId} does not match its recorded canvas sha`);
|
|
19146
19175
|
}
|
|
19147
|
-
const targetDir =
|
|
19176
|
+
const targetDir = path11.resolve("src", "creatives", slug);
|
|
19148
19177
|
let restoredCanvasPath;
|
|
19149
19178
|
try {
|
|
19150
19179
|
const restore = await restoreRunSnapshot(manifest, targetDir, { force: args["force-remote"] === true });
|
|
@@ -19193,9 +19222,9 @@ async function fetchManifest(url) {
|
|
|
19193
19222
|
}
|
|
19194
19223
|
|
|
19195
19224
|
// src/commands/canvas/scaffold-static-ad.ts
|
|
19196
|
-
import { access, mkdir as
|
|
19197
|
-
import
|
|
19198
|
-
import { defineCommand as
|
|
19225
|
+
import { access, mkdir as mkdir4, readFile as readFile9, writeFile as writeFile5 } from "fs/promises";
|
|
19226
|
+
import path15 from "path";
|
|
19227
|
+
import { defineCommand as defineCommand92 } from "citty";
|
|
19199
19228
|
|
|
19200
19229
|
// src/engine/scaffold/staticAd.ts
|
|
19201
19230
|
import { z as z14 } from "zod";
|
|
@@ -19438,7 +19467,7 @@ function staticAdReport(input, elementsInput, opts) {
|
|
|
19438
19467
|
}
|
|
19439
19468
|
|
|
19440
19469
|
// src/commands/canvas/creative-definition.ts
|
|
19441
|
-
import
|
|
19470
|
+
import path12 from "path";
|
|
19442
19471
|
var PLATFORM_VALUES = ["meta", "google", "linkedin", "tiktok", "youtube", "x", "other"];
|
|
19443
19472
|
var FORMAT_VALUES = ["1:1", "4:5", "9:16", "16:9", "1.91:1"];
|
|
19444
19473
|
function titleFromSlug(slug) {
|
|
@@ -19480,16 +19509,16 @@ function buildCreativeDefinition(input) {
|
|
|
19480
19509
|
}
|
|
19481
19510
|
|
|
19482
19511
|
// src/commands/canvas/scaffold-static-ad-paths.ts
|
|
19483
|
-
import
|
|
19512
|
+
import path13 from "path";
|
|
19484
19513
|
function resolveScaffoldStaticAdPaths(rawFile, out, cwd = process.cwd(), slug) {
|
|
19485
19514
|
const file = rawFile.trim();
|
|
19486
19515
|
const imageIsUrl = /^https?:\/\//i.test(file);
|
|
19487
|
-
const imageSource = imageIsUrl ? file :
|
|
19488
|
-
const outPath = out ?
|
|
19489
|
-
const blueprintPath =
|
|
19490
|
-
const creativeDir = slug ?
|
|
19491
|
-
const definitionPath = creativeDir ?
|
|
19492
|
-
const referencesDir = creativeDir ?
|
|
19516
|
+
const imageSource = imageIsUrl ? file : path13.resolve(cwd, file);
|
|
19517
|
+
const outPath = out ? path13.resolve(cwd, out) : slug ? path13.join(cwd, "src", "creatives", slug, `${slug}.canvas.json`) : imageIsUrl ? path13.join(cwd, "static-ad.canvas.json") : path13.join(path13.dirname(imageSource), "static-ad.canvas.json");
|
|
19518
|
+
const blueprintPath = path13.join(path13.dirname(outPath), "prompt.json");
|
|
19519
|
+
const creativeDir = slug ? path13.dirname(outPath) : null;
|
|
19520
|
+
const definitionPath = creativeDir ? path13.join(creativeDir, "_definition.md") : null;
|
|
19521
|
+
const referencesDir = creativeDir ? path13.join(creativeDir, "references") : null;
|
|
19493
19522
|
return { imageIsUrl, imageSource, outPath, blueprintPath, creativeDir, definitionPath, referencesDir };
|
|
19494
19523
|
}
|
|
19495
19524
|
var SCAFFOLD_SLUG_PATTERN = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;
|
|
@@ -19498,6 +19527,11 @@ function isValidScaffoldSlug(slug) {
|
|
|
19498
19527
|
return slug.length <= SCAFFOLD_SLUG_MAX_LENGTH && SCAFFOLD_SLUG_PATTERN.test(slug);
|
|
19499
19528
|
}
|
|
19500
19529
|
|
|
19530
|
+
// src/commands/canvas/sync-definition.ts
|
|
19531
|
+
import { readdir as readdir4, readFile as readFile8, stat as stat3 } from "fs/promises";
|
|
19532
|
+
import path14 from "path";
|
|
19533
|
+
import { defineCommand as defineCommand91 } from "citty";
|
|
19534
|
+
|
|
19501
19535
|
// src/commands/canvas/definition-graph.ts
|
|
19502
19536
|
var MAX_NODES = 300;
|
|
19503
19537
|
function walkStrings(value, cb) {
|
|
@@ -19513,6 +19547,15 @@ function walkStrings(value, cb) {
|
|
|
19513
19547
|
for (const v of Object.values(value)) walkStrings(v, cb);
|
|
19514
19548
|
}
|
|
19515
19549
|
}
|
|
19550
|
+
var PREVIEWABLE_INGEST_EXPECTS = /* @__PURE__ */ new Set(["image"]);
|
|
19551
|
+
function nodeInputPreviewUrl(type, params) {
|
|
19552
|
+
if (type !== "ingest" || !params || typeof params !== "object") return void 0;
|
|
19553
|
+
const p = params;
|
|
19554
|
+
if (p.source !== "url" || typeof p.url !== "string") return void 0;
|
|
19555
|
+
if (!/^https?:\/\//i.test(p.url)) return void 0;
|
|
19556
|
+
if (typeof p.expect === "string" && !PREVIEWABLE_INGEST_EXPECTS.has(p.expect)) return void 0;
|
|
19557
|
+
return p.url;
|
|
19558
|
+
}
|
|
19516
19559
|
function canvasToDefinitionGraph(canvas) {
|
|
19517
19560
|
const rawNodes = canvas?.nodes;
|
|
19518
19561
|
if (!Array.isArray(rawNodes)) return null;
|
|
@@ -19540,6 +19583,8 @@ function canvasToDefinitionGraph(canvas) {
|
|
|
19540
19583
|
const base = { id, type };
|
|
19541
19584
|
if (depList.length > 0) base.deps = depList;
|
|
19542
19585
|
if (paramsPreview) base.paramsPreview = paramsPreview;
|
|
19586
|
+
const inputPreviewUrl = nodeInputPreviewUrl(type, params);
|
|
19587
|
+
if (inputPreviewUrl) base.inputPreviewUrl = inputPreviewUrl;
|
|
19543
19588
|
return base;
|
|
19544
19589
|
});
|
|
19545
19590
|
const rawOutput = canvas?.output;
|
|
@@ -19565,6 +19610,7 @@ async function syncCreativeDefinitionBestEffort(input) {
|
|
|
19565
19610
|
formats: input.formats,
|
|
19566
19611
|
sourceReferenceUrl: input.sourceReferenceUrl,
|
|
19567
19612
|
graph,
|
|
19613
|
+
sourceSha: input.sourceSha,
|
|
19568
19614
|
chatId
|
|
19569
19615
|
});
|
|
19570
19616
|
process.stdout.write(`[definition] synced workflow graph (${graph.nodes.length} nodes) \u2014 view it in the dashboard
|
|
@@ -19575,6 +19621,57 @@ async function syncCreativeDefinitionBestEffort(input) {
|
|
|
19575
19621
|
`);
|
|
19576
19622
|
}
|
|
19577
19623
|
}
|
|
19624
|
+
async function resolveCanvasPath(inputPath) {
|
|
19625
|
+
const resolved = path14.resolve(inputPath);
|
|
19626
|
+
let dir = resolved;
|
|
19627
|
+
try {
|
|
19628
|
+
if ((await stat3(resolved)).isFile()) {
|
|
19629
|
+
if (resolved.endsWith(".canvas.json")) return resolved;
|
|
19630
|
+
dir = path14.dirname(resolved);
|
|
19631
|
+
}
|
|
19632
|
+
} catch {
|
|
19633
|
+
dir = resolved.endsWith(".canvas.json") ? path14.dirname(resolved) : resolved;
|
|
19634
|
+
}
|
|
19635
|
+
let entries;
|
|
19636
|
+
try {
|
|
19637
|
+
entries = await readdir4(dir);
|
|
19638
|
+
} catch {
|
|
19639
|
+
return null;
|
|
19640
|
+
}
|
|
19641
|
+
const canvases = entries.filter((name) => name.endsWith(".canvas.json"));
|
|
19642
|
+
const slug = creativeSlugFromCanvasPath(`${dir}/x/`);
|
|
19643
|
+
const chosen = (slug ? canvases.find((name) => name === `${slug}.canvas.json`) : void 0) ?? canvases[0];
|
|
19644
|
+
return chosen ? path14.join(dir, chosen) : null;
|
|
19645
|
+
}
|
|
19646
|
+
var syncDefinitionCommand = defineCommand91({
|
|
19647
|
+
meta: {
|
|
19648
|
+
name: "sync-definition",
|
|
19649
|
+
description: "Push a creative's current node-graph + input thumbnails to the dashboard without rendering. Runs automatically when you edit a creative's canvas.json or prompt.json."
|
|
19650
|
+
},
|
|
19651
|
+
args: {
|
|
19652
|
+
file: {
|
|
19653
|
+
type: "positional",
|
|
19654
|
+
required: true,
|
|
19655
|
+
description: "A path under src/creatives/<slug>/ (the .canvas.json, its prompt.json, or the folder)"
|
|
19656
|
+
}
|
|
19657
|
+
},
|
|
19658
|
+
async run({ args }) {
|
|
19659
|
+
const canvasPath = await resolveCanvasPath(String(args.file));
|
|
19660
|
+
if (!canvasPath) {
|
|
19661
|
+
return;
|
|
19662
|
+
}
|
|
19663
|
+
const slug = creativeSlugFromCanvasPath(canvasPath);
|
|
19664
|
+
if (!slug) return;
|
|
19665
|
+
let canvas;
|
|
19666
|
+
try {
|
|
19667
|
+
canvas = JSON.parse(await readFile8(canvasPath, "utf8"));
|
|
19668
|
+
} catch {
|
|
19669
|
+
return;
|
|
19670
|
+
}
|
|
19671
|
+
const sourceSha = await computeSourceSha(canvasPath);
|
|
19672
|
+
await syncCreativeDefinitionBestEffort({ slug, canvas, sourceSha });
|
|
19673
|
+
}
|
|
19674
|
+
});
|
|
19578
19675
|
|
|
19579
19676
|
// src/commands/canvas/scaffold-static-ad.ts
|
|
19580
19677
|
async function fileExists(target) {
|
|
@@ -19592,7 +19689,7 @@ async function uploadSourceAsReference(source, isUrl, client) {
|
|
|
19592
19689
|
if (!res.ok) throw new Error(`failed to download source image (${res.status})`);
|
|
19593
19690
|
bytes = Buffer.from(await res.arrayBuffer());
|
|
19594
19691
|
} else {
|
|
19595
|
-
bytes = await
|
|
19692
|
+
bytes = await readFile9(source);
|
|
19596
19693
|
}
|
|
19597
19694
|
const safe = await toModelSafeImage(bytes);
|
|
19598
19695
|
const sha256 = sha256Hex(safe.bytes);
|
|
@@ -19647,7 +19744,7 @@ DROP background extras, decorative props, generic scenery, and anything small or
|
|
|
19647
19744
|
For each kept element return: { "type": one of logo|product|person|animal|badge, "label": a short UPPER_SNAKE_CASE name (e.g. LOGO, PRODUCT, HERO_DOG, TRUSTPILOT), "description": a concrete reusable description to source/shoot the real asset (include the exact expression for a living subject, and its castable attributes \u2014 breed/species for an animal, apparent age band, apparent origin/ethnicity, and wardrobe/setting for a person \u2014 so it can be recast to fit OUR audience/market), "expression": the facial expression for a living subject or null, "reason": why it is identity-critical, "locator": the blueprint entry this element came from as { "collection": one of "subjects" | "people" | "brands_logos", "index": its 0-based position in that array } (people -> people; logos/badges -> brands_logos; products/animals/objects -> subjects). Output ONLY the JSON object.`;
|
|
19648
19745
|
async function loadAssetText(ref, label) {
|
|
19649
19746
|
const r = ref;
|
|
19650
|
-
if (typeof r?.path === "string") return
|
|
19747
|
+
if (typeof r?.path === "string") return readFile9(r.path, "utf8");
|
|
19651
19748
|
if (typeof r?.url === "string") {
|
|
19652
19749
|
const res = await fetch(r.url);
|
|
19653
19750
|
if (!res.ok) throw new Error(`failed to fetch ${label} (${res.status})`);
|
|
@@ -19755,7 +19852,7 @@ async function runVisionPasses(canvas) {
|
|
|
19755
19852
|
return fail2("read_outputs", e instanceof Error ? e.message : String(e));
|
|
19756
19853
|
}
|
|
19757
19854
|
}
|
|
19758
|
-
var scaffoldStaticAdCommand =
|
|
19855
|
+
var scaffoldStaticAdCommand = defineCommand92({
|
|
19759
19856
|
meta: {
|
|
19760
19857
|
name: "scaffold-static-ad",
|
|
19761
19858
|
description: "Turn a source/inspiration image into a runnable static-ad canvas. Runs billed passes \u2014 image_describe (the blueprint, baked to prompt.json as the editable 'prompt'), an AI selection of the image's MAIN identity elements, and a structured global-layout pass (the column/row grid with per-region bounds and text sizes) \u2014 then scaffolds a canvas that wires one [TODO] ingest slot per element (logo/product/subject/badge + brand font) into image_generate. Edit prompt.json and drop the real assets, then `baker canvas run` it."
|
|
@@ -19800,7 +19897,7 @@ var scaffoldStaticAdCommand = defineCommand91({
|
|
|
19800
19897
|
process.cwd(),
|
|
19801
19898
|
slug
|
|
19802
19899
|
);
|
|
19803
|
-
await
|
|
19900
|
+
await mkdir4(path15.dirname(outPath), { recursive: true });
|
|
19804
19901
|
const { describeModel, selectModel, layoutModel, genModel } = resolveModels(args);
|
|
19805
19902
|
let durableSourceUrl;
|
|
19806
19903
|
if (referencesDir) {
|
|
@@ -19826,7 +19923,7 @@ var scaffoldStaticAdCommand = defineCommand91({
|
|
|
19826
19923
|
if (layout && annotated && typeof annotated === "object") {
|
|
19827
19924
|
annotated.layout = layout;
|
|
19828
19925
|
}
|
|
19829
|
-
await
|
|
19926
|
+
await writeFile5(blueprintPath, `${JSON.stringify(annotated, null, 2)}
|
|
19830
19927
|
`, "utf8");
|
|
19831
19928
|
let canvasImagePath = imageSource;
|
|
19832
19929
|
let canvasImageIsUrl = imageIsUrl;
|
|
@@ -19863,10 +19960,10 @@ var scaffoldStaticAdCommand = defineCommand91({
|
|
|
19863
19960
|
);
|
|
19864
19961
|
process.exit(2);
|
|
19865
19962
|
}
|
|
19866
|
-
await
|
|
19963
|
+
await writeFile5(outPath, `${JSON.stringify(canvas, null, 2)}
|
|
19867
19964
|
`, "utf8");
|
|
19868
19965
|
if (definitionPath && !await fileExists(definitionPath)) {
|
|
19869
|
-
await
|
|
19966
|
+
await writeFile5(
|
|
19870
19967
|
definitionPath,
|
|
19871
19968
|
buildCreativeDefinition({
|
|
19872
19969
|
title: args.title ? String(args.title) : titleFromSlug(slug ?? ""),
|
|
@@ -19888,7 +19985,8 @@ var scaffoldStaticAdCommand = defineCommand91({
|
|
|
19888
19985
|
platform: resolvePlatform(args.platform ? String(args.platform) : void 0),
|
|
19889
19986
|
formats: resolveFormats(args.aspect ? String(args.aspect) : report.aspect_ratio),
|
|
19890
19987
|
sourceReferenceUrl: durableSourceUrl ?? (imageIsUrl ? imageSource : void 0),
|
|
19891
|
-
canvas
|
|
19988
|
+
canvas,
|
|
19989
|
+
sourceSha: await computeSourceSha(outPath)
|
|
19892
19990
|
});
|
|
19893
19991
|
}
|
|
19894
19992
|
process.stdout.write(
|
|
@@ -19909,7 +20007,7 @@ var scaffoldStaticAdCommand = defineCommand91({
|
|
|
19909
20007
|
run_estimated_credits: validation.estimatedCredits
|
|
19910
20008
|
},
|
|
19911
20009
|
checklist: {
|
|
19912
|
-
edit_prompt: `Edit ${
|
|
20010
|
+
edit_prompt: `Edit ${path15.basename(blueprintPath)} \u2014 it is the blueprint generated from your image; rewrite it into the ad you want (palette, copy, claims, subjects). It feeds the generator directly.`,
|
|
19913
20011
|
assets_to_supply: report.elements,
|
|
19914
20012
|
font_slot: report.includes_font ? "Drop a brand font at the [TODO] brandfont path (the describe pass recorded the ad's typefaces under `fonts` in prompt.json \u2014 match those). The font is wired into the render as a TYPE SPECIMEN reference so generated text takes the brand letterforms. Delete the brandfont + type_ref nodes to skip it." : "skipped (--skip-font)",
|
|
19915
20013
|
actor_sheets: report.actor_sheets.length > 0 ? `Each living hero (${report.actor_sheets.join(", ")}) is fused into a generated multi-view reference sheet (image_reference_sheet) that the render grounds on \u2014 so drop ONE clean photo at that hero's ingest and the sheet builds the consistent turnaround. Pass --skip-actor-sheets to ground on the lone photo instead.` : "none (no person/animal heroes detected, or --skip-actor-sheets)",
|
|
@@ -19925,10 +20023,10 @@ var scaffoldStaticAdCommand = defineCommand91({
|
|
|
19925
20023
|
});
|
|
19926
20024
|
|
|
19927
20025
|
// src/commands/canvas/scaffold-video.ts
|
|
19928
|
-
import { access as access2, cp, mkdir as
|
|
20026
|
+
import { access as access2, cp, mkdir as mkdir5, readFile as readFile12, rm as rm5, writeFile as writeFile6 } from "fs/promises";
|
|
19929
20027
|
import { tmpdir as tmpdir2 } from "os";
|
|
19930
|
-
import
|
|
19931
|
-
import { defineCommand as
|
|
20028
|
+
import path18 from "path";
|
|
20029
|
+
import { defineCommand as defineCommand93 } from "citty";
|
|
19932
20030
|
|
|
19933
20031
|
// src/engine/scaffold/lib/model-router.ts
|
|
19934
20032
|
var SEEDANCE = "bytedance/seedance-2.0";
|
|
@@ -19966,7 +20064,7 @@ function routeVideoModel(input) {
|
|
|
19966
20064
|
|
|
19967
20065
|
// src/engine/nodes/local/lib/sceneDetect.ts
|
|
19968
20066
|
import { execFile as execFile2 } from "child_process";
|
|
19969
|
-
import { mkdtemp, readdir as
|
|
20067
|
+
import { mkdtemp, readdir as readdir5, readFile as readFile10, rm as rm4 } from "fs/promises";
|
|
19970
20068
|
import { tmpdir } from "os";
|
|
19971
20069
|
import { join as join2 } from "path";
|
|
19972
20070
|
import { promisify as promisify2 } from "util";
|
|
@@ -20040,11 +20138,11 @@ async function runSceneDetectOnce(filePath, threshold, minSceneLenS, timeoutMs)
|
|
|
20040
20138
|
],
|
|
20041
20139
|
{ encoding: "utf-8", maxBuffer: 32 * 1024 * 1024, timeout: timeoutMs }
|
|
20042
20140
|
);
|
|
20043
|
-
const csvName = (await
|
|
20141
|
+
const csvName = (await readdir5(outDir)).find((f) => f.toLowerCase().endsWith(".csv"));
|
|
20044
20142
|
if (!csvName) return [];
|
|
20045
|
-
return parsePySceneDetectCsvCuts(await
|
|
20143
|
+
return parsePySceneDetectCsvCuts(await readFile10(join2(outDir, csvName), "utf-8"));
|
|
20046
20144
|
} finally {
|
|
20047
|
-
await
|
|
20145
|
+
await rm4(outDir, { recursive: true, force: true });
|
|
20048
20146
|
}
|
|
20049
20147
|
}
|
|
20050
20148
|
async function detectSceneCutsPySceneDetect(filePath, opts = {}) {
|
|
@@ -20067,23 +20165,23 @@ async function detectSceneCutsPySceneDetect(filePath, opts = {}) {
|
|
|
20067
20165
|
|
|
20068
20166
|
// src/commands/canvas/composition-path.ts
|
|
20069
20167
|
import { existsSync as existsSync3 } from "fs";
|
|
20070
|
-
import
|
|
20168
|
+
import path16 from "path";
|
|
20071
20169
|
function resolveShippedCanvasDir(name, startDir, exists = existsSync3, maxDepth = 8) {
|
|
20072
|
-
const rel =
|
|
20170
|
+
const rel = path16.join("canvas", name);
|
|
20073
20171
|
let dir = startDir;
|
|
20074
20172
|
for (let i = 0; i < maxDepth; i++) {
|
|
20075
|
-
const candidate =
|
|
20076
|
-
if (exists(
|
|
20077
|
-
const parent =
|
|
20173
|
+
const candidate = path16.join(dir, rel);
|
|
20174
|
+
if (exists(path16.join(candidate, "meta.json"))) return candidate;
|
|
20175
|
+
const parent = path16.dirname(dir);
|
|
20078
20176
|
if (parent === dir) break;
|
|
20079
20177
|
dir = parent;
|
|
20080
20178
|
}
|
|
20081
|
-
return
|
|
20179
|
+
return path16.resolve(startDir, "../../../", rel);
|
|
20082
20180
|
}
|
|
20083
20181
|
|
|
20084
20182
|
// src/commands/canvas/gitignore.ts
|
|
20085
|
-
import { appendFile, readFile as
|
|
20086
|
-
import
|
|
20183
|
+
import { appendFile, readFile as readFile11 } from "fs/promises";
|
|
20184
|
+
import path17 from "path";
|
|
20087
20185
|
function missingGitignoreEntries(existing, entries) {
|
|
20088
20186
|
const present = new Set(
|
|
20089
20187
|
existing.split("\n").map((l) => l.trim().replace(/\/+$/, "")).filter((l) => l.length > 0 && !l.startsWith("#"))
|
|
@@ -20091,10 +20189,10 @@ function missingGitignoreEntries(existing, entries) {
|
|
|
20091
20189
|
return entries.filter((e) => !present.has(e.trim().replace(/\/+$/, "")));
|
|
20092
20190
|
}
|
|
20093
20191
|
async function ensureGitignore(dir, entries) {
|
|
20094
|
-
const file =
|
|
20192
|
+
const file = path17.join(dir, ".gitignore");
|
|
20095
20193
|
let existing;
|
|
20096
20194
|
try {
|
|
20097
|
-
existing = await
|
|
20195
|
+
existing = await readFile11(file, "utf8");
|
|
20098
20196
|
} catch {
|
|
20099
20197
|
return;
|
|
20100
20198
|
}
|
|
@@ -20133,7 +20231,7 @@ ONE PERSON, MULTIPLE LOOKS: if a single individual plays MULTIPLE personas or wa
|
|
|
20133
20231
|
For each kept element return: { "type": one of person|animal|product|logo|badge|location, "label": a short UPPER_SNAKE_CASE name (e.g. HERO, CREATOR_SKEPTIC, INSURANCE_CARD, LOGO), "description": a concrete reusable description to source/shoot the real asset \u2014 for a person/animal give a NEUTRAL castable role (e.g. "hero pet-owner, woman in her 30s" or "a small beagle"), NOT the original individual's literal face/identity: we RECAST with a FRESH person/animal, so never tell the agent to reuse the original. "expression": a living subject's typical expression or null, "cast_id": the global.cast id if it maps to one else null, "same_as": the label of another element this is the SAME individual as (different wardrobe/persona) else null, "scenes": the 0-based indices of ONLY the scenes where the element is ACTUALLY VISIBLE ON SCREEN \u2014 judged from that scene's start_frame_prompt / end_frame_prompt subjects and its action_detail, NOT from who is merely speaking. A narrator heard over b-roll is NOT present in that b-roll scene; a dog-running cutaway does NOT contain the couch creator just because she talks across it. Do NOT pad the list \u2014 an element wrongly listed in a scene makes the reproduction render the wrong subject there (e.g. the creator appearing in a pure-dog b-roll). When in doubt, leave a scene OUT. Output ONLY the JSON object.`;
|
|
20134
20232
|
async function loadAssetText2(ref, label) {
|
|
20135
20233
|
const r = ref;
|
|
20136
|
-
if (typeof r?.path === "string") return
|
|
20234
|
+
if (typeof r?.path === "string") return readFile12(r.path, "utf8");
|
|
20137
20235
|
if (typeof r?.url === "string") {
|
|
20138
20236
|
const res = await fetch(r.url);
|
|
20139
20237
|
if (!res.ok) throw new Error(`failed to fetch ${label} (${res.status})`);
|
|
@@ -20152,7 +20250,7 @@ async function loadTranscriptBestEffort(ref) {
|
|
|
20152
20250
|
async function stageCaptions(outDir, transcript) {
|
|
20153
20251
|
const text = transcript?.trim();
|
|
20154
20252
|
if (!text || text === "[]") return {};
|
|
20155
|
-
const compositionPath =
|
|
20253
|
+
const compositionPath = path18.join(outDir, "tiktok-captions-composition");
|
|
20156
20254
|
await cp(SHIPPED_CAPTIONS_DIR, compositionPath, { recursive: true });
|
|
20157
20255
|
return { compositionPath };
|
|
20158
20256
|
}
|
|
@@ -20170,12 +20268,12 @@ function patchCompositionHtml(html, dims) {
|
|
|
20170
20268
|
return html.replace(/(<meta\s+name="viewport"\s+content="width=)\d+(,\s*height=)\d+(")/i, `$1${dims.w}$2${dims.h}$3`).replace(/(width:\s*)\d+(px;\s*height:\s*)\d+(px;)/i, `$1${dims.w}$2${dims.h}$3`).replace(/(data-width=")\d+(")/i, `$1${dims.w}$2`).replace(/(data-height=")\d+(")/i, `$1${dims.h}$2`);
|
|
20171
20269
|
}
|
|
20172
20270
|
async function stampCompositionDims(compositionDir, dims) {
|
|
20173
|
-
const metaPath =
|
|
20174
|
-
const rawMeta = await
|
|
20175
|
-
await
|
|
20176
|
-
const htmlPath =
|
|
20177
|
-
const rawHtml = await
|
|
20178
|
-
await
|
|
20271
|
+
const metaPath = path18.join(compositionDir, "meta.json");
|
|
20272
|
+
const rawMeta = await readFile12(metaPath, "utf8");
|
|
20273
|
+
await writeFile6(metaPath, patchCompositionMeta(rawMeta, dims), "utf8");
|
|
20274
|
+
const htmlPath = path18.join(compositionDir, "index.html");
|
|
20275
|
+
const rawHtml = await readFile12(htmlPath, "utf8");
|
|
20276
|
+
await writeFile6(htmlPath, patchCompositionHtml(rawHtml, dims), "utf8");
|
|
20179
20277
|
}
|
|
20180
20278
|
function parseElements2(raw) {
|
|
20181
20279
|
const parsed = JSON.parse(raw);
|
|
@@ -20222,7 +20320,7 @@ var VIDEO_EXT_BY_MIME = {
|
|
|
20222
20320
|
"video/x-matroska": ".mkv"
|
|
20223
20321
|
};
|
|
20224
20322
|
function referenceVideoExt(url, contentType) {
|
|
20225
|
-
const fromPath =
|
|
20323
|
+
const fromPath = path18.extname(new URL(url).pathname).toLowerCase();
|
|
20226
20324
|
if (fromPath && fromPath.length <= 5) return fromPath;
|
|
20227
20325
|
const mime = (contentType ?? "").split(";")[0]?.trim().toLowerCase();
|
|
20228
20326
|
return mime && VIDEO_EXT_BY_MIME[mime] || ".mp4";
|
|
@@ -20248,7 +20346,7 @@ function videoDefinitionDescription(blueprint) {
|
|
|
20248
20346
|
return typeof product === "string" && product.trim() ? product.trim() : void 0;
|
|
20249
20347
|
}
|
|
20250
20348
|
async function materializeReferenceVideo(fileArg2) {
|
|
20251
|
-
if (!/^https?:\/\//i.test(fileArg2)) return
|
|
20349
|
+
if (!/^https?:\/\//i.test(fileArg2)) return path18.resolve(fileArg2);
|
|
20252
20350
|
let res;
|
|
20253
20351
|
try {
|
|
20254
20352
|
res = await fetch(fileArg2);
|
|
@@ -20258,11 +20356,11 @@ async function materializeReferenceVideo(fileArg2) {
|
|
|
20258
20356
|
if (!res.ok) throw new Error(`failed to download reference video (${res.status} ${res.statusText})`);
|
|
20259
20357
|
const bytes = Buffer.from(await res.arrayBuffer());
|
|
20260
20358
|
if (bytes.length === 0) throw new Error("reference video download was empty");
|
|
20261
|
-
const dest =
|
|
20359
|
+
const dest = path18.join(
|
|
20262
20360
|
tmpdir2(),
|
|
20263
20361
|
`baker-ref-${sha256Hex(bytes).slice(0, 16)}${referenceVideoExt(fileArg2, res.headers.get("content-type"))}`
|
|
20264
20362
|
);
|
|
20265
|
-
await
|
|
20363
|
+
await writeFile6(dest, bytes);
|
|
20266
20364
|
return dest;
|
|
20267
20365
|
}
|
|
20268
20366
|
function resolveSeamDedup(raw) {
|
|
@@ -20382,7 +20480,7 @@ async function runAnalysisPasses(deconstructCanvas, selectModel) {
|
|
|
20382
20480
|
return fail3("deconstruct", e instanceof Error ? e.message : String(e));
|
|
20383
20481
|
}
|
|
20384
20482
|
}
|
|
20385
|
-
var scaffoldVideoCommand =
|
|
20483
|
+
var scaffoldVideoCommand = defineCommand93({
|
|
20386
20484
|
meta: {
|
|
20387
20485
|
name: "scaffold-video",
|
|
20388
20486
|
description: "Turn a reference video into a runnable reproduction canvas in one command. Runs billed passes \u2014 video_deconstruct (the full scene-by-scene blueprint + transcript, baked to prompt.json as the editable 'prompt') and an AI selection of the video's RECURRING identity elements (person/animal/product/logo) \u2014 then scaffolds a pipeline where every scene boundary is a static-ad-grade frame (the blueprint as target_blueprint, a reference legend, the real frame as anchor) and each recurring element gets ONE shared [TODO] ingest slot wired into every frame it appears in. The clips feed Seedance an ultra-detailed motion brief (action, camera, dialogue, transcript). Edit prompt.json, drop the real source images, then `baker canvas run`."
|
|
@@ -20474,11 +20572,11 @@ var scaffoldVideoCommand = defineCommand92({
|
|
|
20474
20572
|
} catch (e) {
|
|
20475
20573
|
return fail3("download", e instanceof Error ? e.message : String(e));
|
|
20476
20574
|
}
|
|
20477
|
-
const base =
|
|
20478
|
-
const outPath = args.out ?
|
|
20479
|
-
const outDir =
|
|
20480
|
-
const blueprintPath =
|
|
20481
|
-
const blueprintStylePath =
|
|
20575
|
+
const base = path18.basename(videoPath, path18.extname(videoPath));
|
|
20576
|
+
const outPath = args.out ? path18.resolve(String(args.out)) : slug ? path18.join(process.cwd(), "src", "creatives", slug, `${slug}.canvas.json`) : path18.join(path18.dirname(videoPath), `${base}.video.canvas.json`);
|
|
20577
|
+
const outDir = path18.dirname(outPath);
|
|
20578
|
+
const blueprintPath = path18.join(outDir, "prompt.json");
|
|
20579
|
+
const blueprintStylePath = path18.join(outDir, "prompt.style.json");
|
|
20482
20580
|
const frames = args.frames === "reuse" ? "reuse" : "generate";
|
|
20483
20581
|
const maxScenes = args["max-scenes"] ? Number(args["max-scenes"]) : void 0;
|
|
20484
20582
|
if (Number.isFinite(maxScenes)) {
|
|
@@ -20497,11 +20595,11 @@ var scaffoldVideoCommand = defineCommand92({
|
|
|
20497
20595
|
shotCuts
|
|
20498
20596
|
});
|
|
20499
20597
|
const { blueprint, elements, transcript, creditsSpent } = await runAnalysisPasses(deconstructCanvas, selectModel);
|
|
20500
|
-
await
|
|
20598
|
+
await mkdir5(outDir, { recursive: true });
|
|
20501
20599
|
const annotated = annotateBlueprintWithElements(blueprint, elements);
|
|
20502
|
-
await
|
|
20600
|
+
await writeFile6(blueprintPath, `${JSON.stringify(annotated, null, 2)}
|
|
20503
20601
|
`, "utf8");
|
|
20504
|
-
await
|
|
20602
|
+
await writeFile6(blueprintStylePath, renderStyleProjectionFromValue(annotated), "utf8");
|
|
20505
20603
|
let aspect;
|
|
20506
20604
|
try {
|
|
20507
20605
|
aspect = resolveAspect(
|
|
@@ -20519,12 +20617,12 @@ var scaffoldVideoCommand = defineCommand92({
|
|
|
20519
20617
|
`
|
|
20520
20618
|
);
|
|
20521
20619
|
}
|
|
20522
|
-
const compositionDest =
|
|
20620
|
+
const compositionDest = path18.join(outDir, "video-overlay-composition");
|
|
20523
20621
|
await cp(SHIPPED_COMPOSITION_DIR, compositionDest, { recursive: true });
|
|
20524
20622
|
await stampCompositionDims(compositionDest, outDims);
|
|
20525
|
-
const indexPath =
|
|
20623
|
+
const indexPath = path18.join(compositionDest, "index.html");
|
|
20526
20624
|
const overlayHtml = buildOverlayHtml(blueprint, { captionsActive: Boolean(transcript) });
|
|
20527
|
-
const indexHtml = await
|
|
20625
|
+
const indexHtml = await readFile12(indexPath, "utf8");
|
|
20528
20626
|
const injected = indexHtml.replace("<!--OVERLAYS-->", () => overlayHtml);
|
|
20529
20627
|
if (injected === indexHtml && overlayHtml.trim()) {
|
|
20530
20628
|
fail3(
|
|
@@ -20532,16 +20630,16 @@ var scaffoldVideoCommand = defineCommand92({
|
|
|
20532
20630
|
`video-overlay-composition/index.html is missing the <!--OVERLAYS--> marker \u2014 cannot inject the overlay layer`
|
|
20533
20631
|
);
|
|
20534
20632
|
}
|
|
20535
|
-
await
|
|
20633
|
+
await writeFile6(indexPath, injected, "utf8");
|
|
20536
20634
|
const captions = await stageCaptions(outDir, transcript);
|
|
20537
20635
|
if (captions.compositionPath) await stampCompositionDims(captions.compositionPath, outDims);
|
|
20538
20636
|
const opts = {
|
|
20539
20637
|
imageModel,
|
|
20540
20638
|
videoModel,
|
|
20541
|
-
overlayCompositionPath:
|
|
20542
|
-
captionsCompositionPath: captions.compositionPath ?
|
|
20543
|
-
blueprintPath:
|
|
20544
|
-
blueprintStylePath:
|
|
20639
|
+
overlayCompositionPath: path18.relative(outDir, compositionDest),
|
|
20640
|
+
captionsCompositionPath: captions.compositionPath ? path18.relative(outDir, captions.compositionPath) : void 0,
|
|
20641
|
+
blueprintPath: path18.relative(outDir, blueprintPath),
|
|
20642
|
+
blueprintStylePath: path18.relative(outDir, blueprintStylePath),
|
|
20545
20643
|
frames,
|
|
20546
20644
|
ambient: Boolean(args.ambient),
|
|
20547
20645
|
seamDedup: resolveSeamDedup(args["seam-dedup"]),
|
|
@@ -20557,7 +20655,7 @@ var scaffoldVideoCommand = defineCommand92({
|
|
|
20557
20655
|
return fail3("scaffold", e instanceof Error ? e.message : String(e));
|
|
20558
20656
|
}
|
|
20559
20657
|
if (captions.compositionPath && !canvas.nodes.some((n) => n.id === "captions")) {
|
|
20560
|
-
await
|
|
20658
|
+
await rm5(captions.compositionPath, { recursive: true, force: true });
|
|
20561
20659
|
}
|
|
20562
20660
|
const validation = await validateCanvasDeep(resolveRelativeCanvasPaths(canvas, outDir), defaultRegistry());
|
|
20563
20661
|
if (!validation.ok) {
|
|
@@ -20566,7 +20664,7 @@ var scaffoldVideoCommand = defineCommand92({
|
|
|
20566
20664
|
todo.blocking_validation_issues = validation.issues;
|
|
20567
20665
|
meta.todo = todo;
|
|
20568
20666
|
}
|
|
20569
|
-
await
|
|
20667
|
+
await writeFile6(outPath, `${JSON.stringify(canvas, null, 2)}
|
|
20570
20668
|
`, "utf8");
|
|
20571
20669
|
if (!validation.ok) {
|
|
20572
20670
|
process.stderr.write(
|
|
@@ -20588,9 +20686,9 @@ var scaffoldVideoCommand = defineCommand92({
|
|
|
20588
20686
|
await ensureGitignore(process.cwd(), ["canvas/", ".context/"]);
|
|
20589
20687
|
const sourceRef = videoSourceReference(blueprint, fileArg2);
|
|
20590
20688
|
if (slug) {
|
|
20591
|
-
const definitionPath =
|
|
20689
|
+
const definitionPath = path18.join(outDir, "_definition.md");
|
|
20592
20690
|
if (!await fileExists2(definitionPath)) {
|
|
20593
|
-
await
|
|
20691
|
+
await writeFile6(
|
|
20594
20692
|
definitionPath,
|
|
20595
20693
|
buildCreativeDefinition({
|
|
20596
20694
|
title: titleFromSlug(slug),
|
|
@@ -20612,7 +20710,8 @@ var scaffoldVideoCommand = defineCommand92({
|
|
|
20612
20710
|
title: titleFromSlug(slug),
|
|
20613
20711
|
formats: [aspect.outAr],
|
|
20614
20712
|
canvas,
|
|
20615
|
-
sourceReferenceUrl: sourceRef.url
|
|
20713
|
+
sourceReferenceUrl: sourceRef.url,
|
|
20714
|
+
sourceSha: await computeSourceSha(outPath)
|
|
20616
20715
|
});
|
|
20617
20716
|
}
|
|
20618
20717
|
process.stdout.write(
|
|
@@ -20636,10 +20735,13 @@ var scaffoldVideoCommand = defineCommand92({
|
|
|
20636
20735
|
scene_count: report.scene_count,
|
|
20637
20736
|
total_nodes: canvas.nodes.length,
|
|
20638
20737
|
analysis_credits_spent: creditsSpent,
|
|
20639
|
-
run_estimated_credits: validation.estimatedCredits
|
|
20738
|
+
run_estimated_credits: validation.estimatedCredits,
|
|
20739
|
+
// WHY the graph has its nodes: per-scene routes + the node-type histogram
|
|
20740
|
+
// (mirrors metadata.video.graph_stats in the canvas).
|
|
20741
|
+
graph: canvas.metadata?.video?.graph_stats
|
|
20640
20742
|
},
|
|
20641
20743
|
checklist: {
|
|
20642
|
-
edit_prompt: `Edit ${
|
|
20744
|
+
edit_prompt: `Edit ${path18.basename(blueprintPath)} \u2014 the blueprint deconstructed from your video; rewrite it into the ad you want (cast, palette, copy, claims). Global cast/palette/brand edits flow into every frame automatically: \`baker canvas validate\`/\`run\` regenerate ${path18.basename(blueprintStylePath)} (the projection each frame's target_blueprint reads) from it \u2014 never edit that derived file by hand. Per-scene content is edited on each frame node's own prompt.`,
|
|
20643
20745
|
recurring_elements_to_supply: report.elements,
|
|
20644
20746
|
voices_to_confirm: report.dialogue.map((d) => ({
|
|
20645
20747
|
scene: d.scene,
|
|
@@ -20676,9 +20778,9 @@ var scaffoldVideoCommand = defineCommand92({
|
|
|
20676
20778
|
});
|
|
20677
20779
|
|
|
20678
20780
|
// src/commands/canvas/set-prompt.ts
|
|
20679
|
-
import { readFile as
|
|
20680
|
-
import
|
|
20681
|
-
import { defineCommand as
|
|
20781
|
+
import { readFile as readFile13, writeFile as writeFile7 } from "fs/promises";
|
|
20782
|
+
import path19 from "path";
|
|
20783
|
+
import { defineCommand as defineCommand94 } from "citty";
|
|
20682
20784
|
function setNodePrompt(canvas, nodeId, text) {
|
|
20683
20785
|
const nodes = canvas?.nodes;
|
|
20684
20786
|
if (!Array.isArray(nodes)) throw new Error("canvas has no nodes array");
|
|
@@ -20693,7 +20795,7 @@ function setNodePrompt(canvas, nodeId, text) {
|
|
|
20693
20795
|
newNodes[idx] = newNode;
|
|
20694
20796
|
return { ...canvas, nodes: newNodes };
|
|
20695
20797
|
}
|
|
20696
|
-
var setPromptCommand =
|
|
20798
|
+
var setPromptCommand = defineCommand94({
|
|
20697
20799
|
meta: {
|
|
20698
20800
|
name: "set-prompt",
|
|
20699
20801
|
description: "Safely set a node's params.prompt (a frame description, motion prompt, etc.) without hand-editing the JSON. Prefer --text-file for multi-line/accented copy \u2014 it preserves UTF-8 exactly, unlike shell-quoted jq."
|
|
@@ -20705,17 +20807,17 @@ var setPromptCommand = defineCommand93({
|
|
|
20705
20807
|
"text-file": { type: "string", description: "Read the new prompt from a UTF-8 file (preserves accents/newlines)" }
|
|
20706
20808
|
},
|
|
20707
20809
|
async run({ args }) {
|
|
20708
|
-
const filePath =
|
|
20810
|
+
const filePath = path19.resolve(String(args.file));
|
|
20709
20811
|
let canvas;
|
|
20710
20812
|
try {
|
|
20711
|
-
canvas = JSON.parse(await
|
|
20813
|
+
canvas = JSON.parse(await readFile13(filePath, "utf8"));
|
|
20712
20814
|
} catch (e) {
|
|
20713
20815
|
process.stderr.write(`${JSON.stringify({ ok: false, error: { code: "parse", message: String(e) } }, null, 2)}
|
|
20714
20816
|
`);
|
|
20715
20817
|
process.exit(2);
|
|
20716
20818
|
}
|
|
20717
20819
|
let text;
|
|
20718
|
-
if (args["text-file"]) text = await
|
|
20820
|
+
if (args["text-file"]) text = await readFile13(path19.resolve(String(args["text-file"])), "utf8");
|
|
20719
20821
|
else if (args.text !== void 0) text = String(args.text);
|
|
20720
20822
|
else {
|
|
20721
20823
|
process.stderr.write(
|
|
@@ -20736,14 +20838,14 @@ var setPromptCommand = defineCommand93({
|
|
|
20736
20838
|
process.exit(2);
|
|
20737
20839
|
return;
|
|
20738
20840
|
}
|
|
20739
|
-
const validation = await validateCanvasDeep(resolveRelativeCanvasPaths(updated,
|
|
20841
|
+
const validation = await validateCanvasDeep(resolveRelativeCanvasPaths(updated, path19.dirname(filePath)), defaultRegistry());
|
|
20740
20842
|
if (!validation.ok) {
|
|
20741
20843
|
process.stderr.write(`${JSON.stringify({ ok: false, error: { code: "validation", issues: validation.issues } }, null, 2)}
|
|
20742
20844
|
`);
|
|
20743
20845
|
process.exit(2);
|
|
20744
20846
|
return;
|
|
20745
20847
|
}
|
|
20746
|
-
await
|
|
20848
|
+
await writeFile7(filePath, `${JSON.stringify(updated, null, 2)}
|
|
20747
20849
|
`, "utf8");
|
|
20748
20850
|
process.stdout.write(`${JSON.stringify({ ok: true, node: String(args.node), bytes: text.length }, null, 2)}
|
|
20749
20851
|
`);
|
|
@@ -20751,18 +20853,18 @@ var setPromptCommand = defineCommand93({
|
|
|
20751
20853
|
});
|
|
20752
20854
|
|
|
20753
20855
|
// src/commands/canvas/validate.ts
|
|
20754
|
-
import { readFile as
|
|
20755
|
-
import
|
|
20756
|
-
import { defineCommand as
|
|
20757
|
-
var validateCommand =
|
|
20856
|
+
import { readFile as readFile14 } from "fs/promises";
|
|
20857
|
+
import path20 from "path";
|
|
20858
|
+
import { defineCommand as defineCommand95 } from "citty";
|
|
20859
|
+
var validateCommand = defineCommand95({
|
|
20758
20860
|
meta: {
|
|
20759
20861
|
name: "validate",
|
|
20760
20862
|
description: "Validate a canvas JSON file (no execution). Includes a per-node cost preview and runs each node's deep validators (composition meta checks for hyperframe_render/_snapshot)."
|
|
20761
20863
|
},
|
|
20762
20864
|
args: { file: { type: "positional", required: true, description: "Path to canvas JSON" } },
|
|
20763
20865
|
async run({ args }) {
|
|
20764
|
-
const filePath =
|
|
20765
|
-
const raw = await
|
|
20866
|
+
const filePath = path20.resolve(String(args.file));
|
|
20867
|
+
const raw = await readFile14(filePath, "utf8");
|
|
20766
20868
|
let parsed;
|
|
20767
20869
|
try {
|
|
20768
20870
|
parsed = JSON.parse(raw);
|
|
@@ -20772,7 +20874,7 @@ var validateCommand = defineCommand94({
|
|
|
20772
20874
|
`);
|
|
20773
20875
|
process.exit(2);
|
|
20774
20876
|
}
|
|
20775
|
-
parsed = resolveRelativeCanvasPaths(parsed,
|
|
20877
|
+
parsed = resolveRelativeCanvasPaths(parsed, path20.dirname(filePath));
|
|
20776
20878
|
let styleProjection = "not_applicable";
|
|
20777
20879
|
try {
|
|
20778
20880
|
styleProjection = await syncStyleProjection(parsed, (line) => process.stderr.write(`${line}
|
|
@@ -20811,7 +20913,7 @@ var validateCommand = defineCommand94({
|
|
|
20811
20913
|
});
|
|
20812
20914
|
|
|
20813
20915
|
// src/commands/canvas/index.ts
|
|
20814
|
-
var canvasCommand =
|
|
20916
|
+
var canvasCommand = defineCommand96({
|
|
20815
20917
|
meta: {
|
|
20816
20918
|
name: "canvas",
|
|
20817
20919
|
description: `Run Baker creative canvas JSON files locally. Local nodes execute in-process; remote nodes POST to the Convex backend gateway.
|
|
@@ -20823,6 +20925,7 @@ Subcommands:
|
|
|
20823
20925
|
baker canvas critique <file.json> \u2014 pre-spend creative critic (advisory): video hook/legibility/retention or static text/grounding/type scores, never blocks
|
|
20824
20926
|
baker canvas run <file.json> \u2014 execute the canvas, write outputs to ./canvas/<run_id>/
|
|
20825
20927
|
baker canvas rerun <slug> \u2014 restore a creative's latest recorded canvas from run history and run it (works in a fresh workspace)
|
|
20928
|
+
baker canvas sync-definition <path> \u2014 push a creative's current node-graph + input thumbnails to the dashboard without rendering (runs automatically on canvas/prompt edits)
|
|
20826
20929
|
baker canvas catalog \u2014 print the agent-facing node + composition catalog (JSON Schema)
|
|
20827
20930
|
baker canvas inspect <run_id> \u2014 one-page summary of a completed run
|
|
20828
20931
|
baker canvas scaffold-video <video> \u2014 turn a reference video into a runnable reproduction canvas (deconstruct + recurring-element detection)
|
|
@@ -20837,18 +20940,19 @@ Subcommands:
|
|
|
20837
20940
|
inspect: inspectCommand,
|
|
20838
20941
|
"scaffold-video": scaffoldVideoCommand,
|
|
20839
20942
|
"scaffold-static-ad": scaffoldStaticAdCommand,
|
|
20840
|
-
"set-prompt": setPromptCommand
|
|
20943
|
+
"set-prompt": setPromptCommand,
|
|
20944
|
+
"sync-definition": syncDefinitionCommand
|
|
20841
20945
|
}
|
|
20842
20946
|
});
|
|
20843
20947
|
|
|
20844
20948
|
// src/commands/creatives/index.ts
|
|
20845
|
-
import { defineCommand as
|
|
20949
|
+
import { defineCommand as defineCommand98 } from "citty";
|
|
20846
20950
|
|
|
20847
20951
|
// src/commands/creatives/publish.ts
|
|
20848
|
-
import { defineCommand as
|
|
20952
|
+
import { defineCommand as defineCommand97 } from "citty";
|
|
20849
20953
|
|
|
20850
20954
|
// src/commands/images/api.ts
|
|
20851
|
-
import { readFile as
|
|
20955
|
+
import { readFile as readFile15 } from "fs/promises";
|
|
20852
20956
|
import { extname } from "path";
|
|
20853
20957
|
var imageProcessingTimeoutMs = 18e4;
|
|
20854
20958
|
var imageReadyPollIntervalMs = 2e3;
|
|
@@ -20862,7 +20966,7 @@ var mimeMap = {
|
|
|
20862
20966
|
".avif": "image/avif"
|
|
20863
20967
|
};
|
|
20864
20968
|
var defaultImageApiDeps = {
|
|
20865
|
-
readFile:
|
|
20969
|
+
readFile: readFile15,
|
|
20866
20970
|
post: apiPost,
|
|
20867
20971
|
get: apiGet,
|
|
20868
20972
|
sleep: (ms) => new Promise((resolve5) => setTimeout(resolve5, ms))
|
|
@@ -20989,7 +21093,7 @@ async function publishCreative(args, deps = defaultImageApiDeps) {
|
|
|
20989
21093
|
chatId: chatIdFromEnv()
|
|
20990
21094
|
});
|
|
20991
21095
|
}
|
|
20992
|
-
var publishCommand =
|
|
21096
|
+
var publishCommand = defineCommand97({
|
|
20993
21097
|
meta: {
|
|
20994
21098
|
name: "publish",
|
|
20995
21099
|
description: "Publish a final static creative image to Baker Creatives and print the creative reference JSON."
|
|
@@ -21047,7 +21151,7 @@ var publishCommand = defineCommand96({
|
|
|
21047
21151
|
});
|
|
21048
21152
|
|
|
21049
21153
|
// src/commands/creatives/index.ts
|
|
21050
|
-
var creativesCommand3 =
|
|
21154
|
+
var creativesCommand3 = defineCommand98({
|
|
21051
21155
|
meta: {
|
|
21052
21156
|
name: "creatives",
|
|
21053
21157
|
description: `Publish static ad creatives as first-class Baker outputs.
|
|
@@ -21063,7 +21167,7 @@ Publishing uploads the image to the Company image library, applies the official
|
|
|
21063
21167
|
});
|
|
21064
21168
|
|
|
21065
21169
|
// src/commands/flows/index.ts
|
|
21066
|
-
import { defineCommand as
|
|
21170
|
+
import { defineCommand as defineCommand99 } from "citty";
|
|
21067
21171
|
|
|
21068
21172
|
// src/commands/flows/shared.ts
|
|
21069
21173
|
import { existsSync as existsSync4, readdirSync as readdirSync2, readFileSync as readFileSync9 } from "fs";
|
|
@@ -21096,12 +21200,12 @@ function listFlowSlugs() {
|
|
|
21096
21200
|
return readdirSync2(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith("_") && entry.name !== ".gitkeep").map((entry) => entry.name).sort();
|
|
21097
21201
|
}
|
|
21098
21202
|
function readFlowTree(slug) {
|
|
21099
|
-
const
|
|
21100
|
-
if (!existsSync4(
|
|
21203
|
+
const path21 = join3(flowsDir(), slug, "_data.json");
|
|
21204
|
+
if (!existsSync4(path21)) {
|
|
21101
21205
|
failLocal(`No form "${slug}". Run "baker flows list" to see the forms in this workspace.`);
|
|
21102
21206
|
}
|
|
21103
21207
|
try {
|
|
21104
|
-
return JSON.parse(readFileSync9(
|
|
21208
|
+
return JSON.parse(readFileSync9(path21, "utf-8"));
|
|
21105
21209
|
} catch (error) {
|
|
21106
21210
|
failLocal(`Could not read form "${slug}": ${error instanceof Error ? error.message : String(error)}`);
|
|
21107
21211
|
}
|
|
@@ -21218,7 +21322,7 @@ function displayName(slug) {
|
|
|
21218
21322
|
const name = tree.displayName;
|
|
21219
21323
|
return typeof name === "string" && name.trim() ? name.trim() : slug;
|
|
21220
21324
|
}
|
|
21221
|
-
var listCommand5 =
|
|
21325
|
+
var listCommand5 = defineCommand99({
|
|
21222
21326
|
meta: {
|
|
21223
21327
|
name: "list",
|
|
21224
21328
|
description: "List Forms in this workspace with the count of confidential fields still needing setup. Example: baker flows list"
|
|
@@ -21232,7 +21336,7 @@ var listCommand5 = defineCommand98({
|
|
|
21232
21336
|
writeJson({ ok: true, data: { flows } });
|
|
21233
21337
|
}
|
|
21234
21338
|
});
|
|
21235
|
-
var showCommand2 =
|
|
21339
|
+
var showCommand2 = defineCommand99({
|
|
21236
21340
|
meta: {
|
|
21237
21341
|
name: "show",
|
|
21238
21342
|
description: "Show a Form's confidential fields and their configuration status (never secret values). Example: baker flows show contact"
|
|
@@ -21253,7 +21357,7 @@ var showCommand2 = defineCommand98({
|
|
|
21253
21357
|
writeJson({ ok: true, data: response });
|
|
21254
21358
|
}
|
|
21255
21359
|
});
|
|
21256
|
-
var flowsCommand =
|
|
21360
|
+
var flowsCommand = defineCommand99({
|
|
21257
21361
|
meta: {
|
|
21258
21362
|
name: "flows",
|
|
21259
21363
|
description: `Read this workspace's Forms (flows) and the configuration status of their confidential fields \u2014 connection secrets, OAuth connections, and third-party field definitions (HubSpot, Calendly, HighLevel, SavvyCal).
|
|
@@ -21280,10 +21384,10 @@ Examples:
|
|
|
21280
21384
|
});
|
|
21281
21385
|
|
|
21282
21386
|
// src/commands/ga4/index.ts
|
|
21283
|
-
import { defineCommand as
|
|
21387
|
+
import { defineCommand as defineCommand103 } from "citty";
|
|
21284
21388
|
|
|
21285
21389
|
// src/commands/ga4/audit.ts
|
|
21286
|
-
import { defineCommand as
|
|
21390
|
+
import { defineCommand as defineCommand100 } from "citty";
|
|
21287
21391
|
|
|
21288
21392
|
// src/commands/ga4/resolve.ts
|
|
21289
21393
|
async function fetchProperties(useCache = true) {
|
|
@@ -21346,7 +21450,7 @@ registerSchema({
|
|
|
21346
21450
|
"no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
|
|
21347
21451
|
}
|
|
21348
21452
|
});
|
|
21349
|
-
var auditCommand2 =
|
|
21453
|
+
var auditCommand2 = defineCommand100({
|
|
21350
21454
|
meta: {
|
|
21351
21455
|
name: "audit",
|
|
21352
21456
|
description: `Run all GA4 admin health checks. Returns property config with playbook warnings.
|
|
@@ -21398,7 +21502,7 @@ Examples:
|
|
|
21398
21502
|
});
|
|
21399
21503
|
|
|
21400
21504
|
// src/commands/ga4/properties.ts
|
|
21401
|
-
import { defineCommand as
|
|
21505
|
+
import { defineCommand as defineCommand101 } from "citty";
|
|
21402
21506
|
registerSchema({
|
|
21403
21507
|
command: "ga4.properties",
|
|
21404
21508
|
description: "List all accessible GA4 properties. Returns property IDs needed for query and audit commands. Run this first to find property IDs.",
|
|
@@ -21406,7 +21510,7 @@ registerSchema({
|
|
|
21406
21510
|
"no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
|
|
21407
21511
|
}
|
|
21408
21512
|
});
|
|
21409
|
-
var propertiesCommand =
|
|
21513
|
+
var propertiesCommand = defineCommand101({
|
|
21410
21514
|
meta: {
|
|
21411
21515
|
name: "properties",
|
|
21412
21516
|
description: `List accessible GA4 properties.
|
|
@@ -21456,7 +21560,7 @@ Examples:
|
|
|
21456
21560
|
// src/commands/ga4/query.ts
|
|
21457
21561
|
import { appendFileSync as appendFileSync2, existsSync as existsSync5, readFileSync as readFileSync10, writeFileSync as writeFileSync3 } from "fs";
|
|
21458
21562
|
import { resolve as resolve2 } from "path";
|
|
21459
|
-
import { defineCommand as
|
|
21563
|
+
import { defineCommand as defineCommand102 } from "citty";
|
|
21460
21564
|
|
|
21461
21565
|
// src/commands/ga4/presets.ts
|
|
21462
21566
|
var GA4_PRESETS = [
|
|
@@ -21588,7 +21692,7 @@ function handleError(err) {
|
|
|
21588
21692
|
});
|
|
21589
21693
|
process.exit(1);
|
|
21590
21694
|
}
|
|
21591
|
-
var queryCommand2 =
|
|
21695
|
+
var queryCommand2 = defineCommand102({
|
|
21592
21696
|
meta: {
|
|
21593
21697
|
name: "query",
|
|
21594
21698
|
description: `Run GA4 Data API reports. Preset-first with free-form escape hatch.
|
|
@@ -21659,7 +21763,7 @@ Free-form (escape hatch):
|
|
|
21659
21763
|
});
|
|
21660
21764
|
|
|
21661
21765
|
// src/commands/ga4/index.ts
|
|
21662
|
-
var ga4Command =
|
|
21766
|
+
var ga4Command = defineCommand103({
|
|
21663
21767
|
meta: {
|
|
21664
21768
|
name: "ga4",
|
|
21665
21769
|
description: `Google Analytics 4 commands. Audit property config, run playbook-aligned reports.
|
|
@@ -21682,12 +21786,12 @@ Examples:
|
|
|
21682
21786
|
});
|
|
21683
21787
|
|
|
21684
21788
|
// src/commands/gsc/index.ts
|
|
21685
|
-
import { defineCommand as
|
|
21789
|
+
import { defineCommand as defineCommand107 } from "citty";
|
|
21686
21790
|
|
|
21687
21791
|
// src/commands/gsc/query.ts
|
|
21688
21792
|
import { appendFileSync as appendFileSync3, existsSync as existsSync6, readFileSync as readFileSync11, writeFileSync as writeFileSync4 } from "fs";
|
|
21689
21793
|
import { resolve as resolve3 } from "path";
|
|
21690
|
-
import { defineCommand as
|
|
21794
|
+
import { defineCommand as defineCommand104 } from "citty";
|
|
21691
21795
|
|
|
21692
21796
|
// src/commands/gsc/presets.ts
|
|
21693
21797
|
var GSC_PRESETS = [
|
|
@@ -21875,7 +21979,7 @@ function handleError2(err) {
|
|
|
21875
21979
|
});
|
|
21876
21980
|
process.exit(1);
|
|
21877
21981
|
}
|
|
21878
|
-
var queryCommand3 =
|
|
21982
|
+
var queryCommand3 = defineCommand104({
|
|
21879
21983
|
meta: {
|
|
21880
21984
|
name: "query",
|
|
21881
21985
|
description: `Run GSC Search Analytics queries. Preset-first with free-form escape hatch.
|
|
@@ -21953,7 +22057,7 @@ Free-form (escape hatch):
|
|
|
21953
22057
|
});
|
|
21954
22058
|
|
|
21955
22059
|
// src/commands/gsc/sitemaps.ts
|
|
21956
|
-
import { defineCommand as
|
|
22060
|
+
import { defineCommand as defineCommand105 } from "citty";
|
|
21957
22061
|
registerSchema({
|
|
21958
22062
|
command: "gsc.sitemaps",
|
|
21959
22063
|
description: "List sitemaps for a Search Console site. Check sitemap health and errors.",
|
|
@@ -21962,7 +22066,7 @@ registerSchema({
|
|
|
21962
22066
|
"no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
|
|
21963
22067
|
}
|
|
21964
22068
|
});
|
|
21965
|
-
var sitemapsCommand =
|
|
22069
|
+
var sitemapsCommand = defineCommand105({
|
|
21966
22070
|
meta: {
|
|
21967
22071
|
name: "sitemaps",
|
|
21968
22072
|
description: `List sitemaps for a site. Check health and errors.
|
|
@@ -22012,7 +22116,7 @@ Examples:
|
|
|
22012
22116
|
});
|
|
22013
22117
|
|
|
22014
22118
|
// src/commands/gsc/sites.ts
|
|
22015
|
-
import { defineCommand as
|
|
22119
|
+
import { defineCommand as defineCommand106 } from "citty";
|
|
22016
22120
|
registerSchema({
|
|
22017
22121
|
command: "gsc.sites",
|
|
22018
22122
|
description: "List all verified Google Search Console sites. Returns site URLs needed for query and sitemaps commands.",
|
|
@@ -22020,7 +22124,7 @@ registerSchema({
|
|
|
22020
22124
|
"no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
|
|
22021
22125
|
}
|
|
22022
22126
|
});
|
|
22023
|
-
var sitesCommand =
|
|
22127
|
+
var sitesCommand = defineCommand106({
|
|
22024
22128
|
meta: {
|
|
22025
22129
|
name: "sites",
|
|
22026
22130
|
description: `List verified Search Console sites.
|
|
@@ -22068,7 +22172,7 @@ Examples:
|
|
|
22068
22172
|
});
|
|
22069
22173
|
|
|
22070
22174
|
// src/commands/gsc/index.ts
|
|
22071
|
-
var gscCommand =
|
|
22175
|
+
var gscCommand = defineCommand107({
|
|
22072
22176
|
meta: {
|
|
22073
22177
|
name: "gsc",
|
|
22074
22178
|
description: `Google Search Console commands. PPC-SEO arbitrage, brand halo analysis, negative keyword discovery.
|
|
@@ -22091,10 +22195,10 @@ Examples:
|
|
|
22091
22195
|
});
|
|
22092
22196
|
|
|
22093
22197
|
// src/commands/images/index.ts
|
|
22094
|
-
import { defineCommand as
|
|
22198
|
+
import { defineCommand as defineCommand131 } from "citty";
|
|
22095
22199
|
|
|
22096
22200
|
// src/commands/images/crop.ts
|
|
22097
|
-
import { defineCommand as
|
|
22201
|
+
import { defineCommand as defineCommand108 } from "citty";
|
|
22098
22202
|
|
|
22099
22203
|
// src/lib/image/crop-sprite.ts
|
|
22100
22204
|
import sharp from "sharp";
|
|
@@ -22109,7 +22213,7 @@ function cropSprite(input, region) {
|
|
|
22109
22213
|
|
|
22110
22214
|
// src/lib/image/io.ts
|
|
22111
22215
|
import { randomBytes } from "crypto";
|
|
22112
|
-
import { glob as fsGlob, readFile as
|
|
22216
|
+
import { glob as fsGlob, readFile as readFile16, rename, stat as stat4, writeFile as writeFile8 } from "fs/promises";
|
|
22113
22217
|
import { dirname as dirname2, extname as extname2, join as join4, resolve as resolve4 } from "path";
|
|
22114
22218
|
var REMOTE_RE = /^https?:\/\//i;
|
|
22115
22219
|
var GLOB_RE = /[*?[\]{}]/;
|
|
@@ -22145,11 +22249,11 @@ async function readImageBuffer(pathOrUrl) {
|
|
|
22145
22249
|
}
|
|
22146
22250
|
return Buffer.from(await response.arrayBuffer());
|
|
22147
22251
|
}
|
|
22148
|
-
return
|
|
22252
|
+
return readFile16(pathOrUrl);
|
|
22149
22253
|
}
|
|
22150
|
-
async function isDirectory(
|
|
22254
|
+
async function isDirectory(path21) {
|
|
22151
22255
|
try {
|
|
22152
|
-
const s = await
|
|
22256
|
+
const s = await stat4(path21);
|
|
22153
22257
|
return s.isDirectory();
|
|
22154
22258
|
} catch {
|
|
22155
22259
|
return false;
|
|
@@ -22168,7 +22272,7 @@ async function atomicWrite(targetPath, data) {
|
|
|
22168
22272
|
const absolute = resolve4(targetPath);
|
|
22169
22273
|
const dir = dirname2(absolute);
|
|
22170
22274
|
const tmp = join4(dir, `.baker-image-${randomBytes(8).toString("hex")}.tmp`);
|
|
22171
|
-
await
|
|
22275
|
+
await writeFile8(tmp, data);
|
|
22172
22276
|
await rename(tmp, absolute);
|
|
22173
22277
|
}
|
|
22174
22278
|
|
|
@@ -22219,7 +22323,7 @@ function emitError2(err) {
|
|
|
22219
22323
|
}
|
|
22220
22324
|
process.exit(1);
|
|
22221
22325
|
}
|
|
22222
|
-
var cropCommand =
|
|
22326
|
+
var cropCommand = defineCommand108({
|
|
22223
22327
|
meta: {
|
|
22224
22328
|
name: "crop",
|
|
22225
22329
|
description: "Crop a rectangular region from an image.\n\nExample: baker images crop sprite.png --x 0 --y 0 --width 64 --height 64 --output icon.png"
|
|
@@ -22255,7 +22359,7 @@ var cropCommand = defineCommand107({
|
|
|
22255
22359
|
});
|
|
22256
22360
|
|
|
22257
22361
|
// src/commands/images/delete.ts
|
|
22258
|
-
import { defineCommand as
|
|
22362
|
+
import { defineCommand as defineCommand109 } from "citty";
|
|
22259
22363
|
registerSchema({
|
|
22260
22364
|
command: "images.delete",
|
|
22261
22365
|
description: "Delete an image by ID",
|
|
@@ -22269,7 +22373,7 @@ registerSchema({
|
|
|
22269
22373
|
}
|
|
22270
22374
|
}
|
|
22271
22375
|
});
|
|
22272
|
-
var deleteCommand =
|
|
22376
|
+
var deleteCommand = defineCommand109({
|
|
22273
22377
|
meta: {
|
|
22274
22378
|
name: "delete",
|
|
22275
22379
|
description: "Delete an image by ID. Use --dry-run to preview. Example: baker images delete j571abc123 --dry-run"
|
|
@@ -22310,7 +22414,7 @@ var deleteCommand = defineCommand108({
|
|
|
22310
22414
|
});
|
|
22311
22415
|
|
|
22312
22416
|
// src/commands/images/dimensions.ts
|
|
22313
|
-
import { defineCommand as
|
|
22417
|
+
import { defineCommand as defineCommand110 } from "citty";
|
|
22314
22418
|
|
|
22315
22419
|
// src/lib/image/dimensions.ts
|
|
22316
22420
|
import { imageSize } from "image-size";
|
|
@@ -22333,7 +22437,7 @@ registerSchema({
|
|
|
22333
22437
|
target: { type: "string", description: "Local file path or remote http(s) URL", required: true }
|
|
22334
22438
|
}
|
|
22335
22439
|
});
|
|
22336
|
-
var dimensionsCommand =
|
|
22440
|
+
var dimensionsCommand = defineCommand110({
|
|
22337
22441
|
meta: {
|
|
22338
22442
|
name: "dimensions",
|
|
22339
22443
|
description: "Read image dimensions without decoding the full file.\n\nExample: baker images dimensions ./logo.png\nExample: baker images dimensions https://acme.com/hero.png"
|
|
@@ -22377,7 +22481,7 @@ var dimensionsCommand = defineCommand109({
|
|
|
22377
22481
|
});
|
|
22378
22482
|
|
|
22379
22483
|
// src/commands/images/extract.ts
|
|
22380
|
-
import { defineCommand as
|
|
22484
|
+
import { defineCommand as defineCommand111 } from "citty";
|
|
22381
22485
|
registerSchema({
|
|
22382
22486
|
command: "images.extract",
|
|
22383
22487
|
description: "Extract images from a URL via Firecrawl (formats: images).",
|
|
@@ -22393,7 +22497,7 @@ registerSchema({
|
|
|
22393
22497
|
}
|
|
22394
22498
|
}
|
|
22395
22499
|
});
|
|
22396
|
-
var extractCommand =
|
|
22500
|
+
var extractCommand = defineCommand111({
|
|
22397
22501
|
meta: {
|
|
22398
22502
|
name: "extract",
|
|
22399
22503
|
description: "Pull every image from a single URL via Firecrawl. ~$0.001/scrape. Cap auto-ingest at 20.\n\nExample: baker images extract https://stripe.com --auto-ingest 5"
|
|
@@ -22431,7 +22535,7 @@ var extractCommand = defineCommand110({
|
|
|
22431
22535
|
});
|
|
22432
22536
|
|
|
22433
22537
|
// src/commands/images/find.ts
|
|
22434
|
-
import { defineCommand as
|
|
22538
|
+
import { defineCommand as defineCommand112 } from "citty";
|
|
22435
22539
|
registerSchema({
|
|
22436
22540
|
command: "images.find",
|
|
22437
22541
|
description: "Fanout image search: library first, then opted-in external providers.",
|
|
@@ -22463,7 +22567,7 @@ registerSchema({
|
|
|
22463
22567
|
}
|
|
22464
22568
|
}
|
|
22465
22569
|
});
|
|
22466
|
-
var findCommand =
|
|
22570
|
+
var findCommand = defineCommand112({
|
|
22467
22571
|
meta: {
|
|
22468
22572
|
name: "find",
|
|
22469
22573
|
description: "Library-first fanout image search. Opt in to providers with --sources. `--fallback` short-circuits to externals only when library is thin. With --auto-ingest, ingested external hits return Baker-owned URLs.\n\nExample: baker images find 'office' --sources library,magnific --limit 20"
|
|
@@ -22511,8 +22615,8 @@ var findCommand = defineCommand111({
|
|
|
22511
22615
|
});
|
|
22512
22616
|
|
|
22513
22617
|
// src/commands/images/generate.ts
|
|
22514
|
-
import { readFile as
|
|
22515
|
-
import { defineCommand as
|
|
22618
|
+
import { readFile as readFile17 } from "fs/promises";
|
|
22619
|
+
import { defineCommand as defineCommand113 } from "citty";
|
|
22516
22620
|
import sharp2 from "sharp";
|
|
22517
22621
|
var GENERATE_TIMEOUT_MS = 18e4;
|
|
22518
22622
|
var REFERENCE_MAX_EDGE = 1536;
|
|
@@ -22601,7 +22705,7 @@ async function resolveReferences(spec) {
|
|
|
22601
22705
|
}
|
|
22602
22706
|
let raw;
|
|
22603
22707
|
try {
|
|
22604
|
-
raw = await
|
|
22708
|
+
raw = await readFile17(entry);
|
|
22605
22709
|
} catch {
|
|
22606
22710
|
throw new ApiError("VALIDATION_ERROR", `Reference file not found: ${entry}`);
|
|
22607
22711
|
}
|
|
@@ -22615,7 +22719,7 @@ async function resolveReferences(spec) {
|
|
|
22615
22719
|
}
|
|
22616
22720
|
return out;
|
|
22617
22721
|
}
|
|
22618
|
-
var generateCommand =
|
|
22722
|
+
var generateCommand = defineCommand113({
|
|
22619
22723
|
meta: {
|
|
22620
22724
|
name: "generate",
|
|
22621
22725
|
description: "Generate an image with AI and store it in the library (cost-tracked per request via OpenRouter usage). Models mirror the canvas: openai/gpt-5.4-image-2 (default \u2014 photoreal, cleanest text, best for ad/landing reproduction), google/gemini-3-pro-image-preview (Nano Banana Pro), google/gemini-3.5-flash & google/gemini-3.1-flash-image-preview (fast, extreme aspect ratios), recraft/recraft-v4.1-pro-vector (vector/SVG-style with palette control). The result is auto-ingested (describe + embed), so the next `baker images library` query finds it. Pass --reference with image URLs and/or local file paths (Pinterest, stock, brand assets, sandbox files) to ground generation in reality.\n\nExamples:\n baker images generate 'a friendly golden retriever sitting in a bright modern living room' --aspect-ratio 16:9\n baker images generate 'hero shot of a matte black water bottle on marble' --model google/gemini-3-pro-image-preview --image-size 2K\n baker images generate 'lifestyle photo matching this mood' --reference 'https://\u2026/ref1.jpg,https://\u2026/ref2.jpg'\n baker images generate 'put this product on a marble countertop, soft daylight' --reference './src/brand/logos/product.png,./refs/kitchen-mood.jpg'\n baker images generate 'flat geometric mascot, brand palette' --model recraft/recraft-v4.1-pro-vector --rgb-colors '[[10,10,10],[255,80,0]]'"
|
|
@@ -22667,7 +22771,7 @@ var generateCommand = defineCommand112({
|
|
|
22667
22771
|
});
|
|
22668
22772
|
|
|
22669
22773
|
// src/commands/images/get.ts
|
|
22670
|
-
import { defineCommand as
|
|
22774
|
+
import { defineCommand as defineCommand114 } from "citty";
|
|
22671
22775
|
registerSchema({
|
|
22672
22776
|
command: "images.get",
|
|
22673
22777
|
description: "Get a single image by ID",
|
|
@@ -22675,7 +22779,7 @@ registerSchema({
|
|
|
22675
22779
|
id: { type: "string", description: "Image ID", required: true }
|
|
22676
22780
|
}
|
|
22677
22781
|
});
|
|
22678
|
-
var getCommand2 =
|
|
22782
|
+
var getCommand2 = defineCommand114({
|
|
22679
22783
|
meta: { name: "get", description: "Get a single image by ID. Example: baker images get j571abc123" },
|
|
22680
22784
|
args: {
|
|
22681
22785
|
id: { type: "positional", description: "Image ID", required: false },
|
|
@@ -22711,7 +22815,7 @@ var getCommand2 = defineCommand113({
|
|
|
22711
22815
|
});
|
|
22712
22816
|
|
|
22713
22817
|
// src/commands/images/gif.ts
|
|
22714
|
-
import { defineCommand as
|
|
22818
|
+
import { defineCommand as defineCommand115 } from "citty";
|
|
22715
22819
|
registerSchema({
|
|
22716
22820
|
command: "images.gif",
|
|
22717
22821
|
description: "Search Giphy for GIFs / reaction memes (paid social creative).",
|
|
@@ -22743,7 +22847,7 @@ registerSchema({
|
|
|
22743
22847
|
}
|
|
22744
22848
|
}
|
|
22745
22849
|
});
|
|
22746
|
-
var gifCommand =
|
|
22850
|
+
var gifCommand = defineCommand115({
|
|
22747
22851
|
meta: {
|
|
22748
22852
|
name: "gif",
|
|
22749
22853
|
description: "Search Giphy for GIFs / reaction memes \u2014 built for paid-social creative (Meta, TikTok, LinkedIn, X). Free API. Each hit carries WebP + GIF + MP4 URLs in providerMeta so you can pick the right format per platform.\n\nExample: baker images gif 'this is fine' --limit 10\nExample: baker images gif 'office reaction' --rating pg --auto-ingest 2\nExample: baker images gif --trending --limit 25"
|
|
@@ -22790,7 +22894,7 @@ var gifCommand = defineCommand114({
|
|
|
22790
22894
|
});
|
|
22791
22895
|
|
|
22792
22896
|
// src/commands/images/google.ts
|
|
22793
|
-
import { defineCommand as
|
|
22897
|
+
import { defineCommand as defineCommand116 } from "citty";
|
|
22794
22898
|
registerSchema({
|
|
22795
22899
|
command: "images.google",
|
|
22796
22900
|
description: "Google Images search via the official Custom Search JSON API. Unverified source \u2014 inspect before placing.",
|
|
@@ -22826,7 +22930,7 @@ registerSchema({
|
|
|
22826
22930
|
}
|
|
22827
22931
|
}
|
|
22828
22932
|
});
|
|
22829
|
-
var googleCommand2 =
|
|
22933
|
+
var googleCommand2 = defineCommand116({
|
|
22830
22934
|
meta: {
|
|
22831
22935
|
name: "google",
|
|
22832
22936
|
description: "Google Images via the official Custom Search JSON API ($0.005/query, free 100/day). \u26A0 Source unverified \u2014 watermarks, low-res, mislabeled results are common. Use as last resort. With --auto-ingest, ingested hits return Baker-owned URLs.\n\nExample: baker images google 'industrial workshop' --type photo --size large --limit 20"
|
|
@@ -22874,7 +22978,7 @@ var googleCommand2 = defineCommand115({
|
|
|
22874
22978
|
});
|
|
22875
22979
|
|
|
22876
22980
|
// src/commands/images/icon.ts
|
|
22877
|
-
import { defineCommand as
|
|
22981
|
+
import { defineCommand as defineCommand117 } from "citty";
|
|
22878
22982
|
registerSchema({
|
|
22879
22983
|
command: "images.icon",
|
|
22880
22984
|
description: "Icon lookup via Iconify (200+ icon sets, free CDN).",
|
|
@@ -22900,7 +23004,7 @@ registerSchema({
|
|
|
22900
23004
|
}
|
|
22901
23005
|
}
|
|
22902
23006
|
});
|
|
22903
|
-
var iconCommand =
|
|
23007
|
+
var iconCommand = defineCommand117({
|
|
22904
23008
|
meta: {
|
|
22905
23009
|
name: "icon",
|
|
22906
23010
|
description: "Icon via Iconify (simple-icons, logos, lucide, devicon, heroicons, tabler, phosphor, material-symbols, \u2026). Free CDN, no API key.\n\nExample: baker images icon react --set devicon\nExample: baker images icon lucide:check --color '#0a0a0a'"
|
|
@@ -22940,7 +23044,7 @@ var iconCommand = defineCommand116({
|
|
|
22940
23044
|
});
|
|
22941
23045
|
|
|
22942
23046
|
// src/commands/images/ingest.ts
|
|
22943
|
-
import { defineCommand as
|
|
23047
|
+
import { defineCommand as defineCommand118 } from "citty";
|
|
22944
23048
|
registerSchema({
|
|
22945
23049
|
command: "images.ingest",
|
|
22946
23050
|
description: "Ingest a remote image URL into the library (full describe + embed).",
|
|
@@ -22952,7 +23056,7 @@ registerSchema({
|
|
|
22952
23056
|
context: { type: "string", description: "Description context hint", required: false }
|
|
22953
23057
|
}
|
|
22954
23058
|
});
|
|
22955
|
-
var ingestCommand =
|
|
23059
|
+
var ingestCommand = defineCommand118({
|
|
22956
23060
|
meta: {
|
|
22957
23061
|
name: "ingest",
|
|
22958
23062
|
description: "Download a remote URL and store it in the library. Hash-deduped on bytes + externalId.\n\nExample: baker images ingest https://img.freepik.com/free-photo/xyz.jpg --source magnific --external-id 12345"
|
|
@@ -22994,7 +23098,7 @@ var ingestCommand = defineCommand117({
|
|
|
22994
23098
|
});
|
|
22995
23099
|
|
|
22996
23100
|
// src/commands/images/library.ts
|
|
22997
|
-
import { defineCommand as
|
|
23101
|
+
import { defineCommand as defineCommand119 } from "citty";
|
|
22998
23102
|
registerSchema({
|
|
22999
23103
|
command: "images.library",
|
|
23000
23104
|
description: "Search the company image library. Returns only ready images.",
|
|
@@ -23020,7 +23124,7 @@ registerSchema({
|
|
|
23020
23124
|
}
|
|
23021
23125
|
}
|
|
23022
23126
|
});
|
|
23023
|
-
var libraryCommand =
|
|
23127
|
+
var libraryCommand = defineCommand119({
|
|
23024
23128
|
meta: {
|
|
23025
23129
|
name: "library",
|
|
23026
23130
|
description: "Search the company image library (hybrid BM25 + vector + Cohere rerank). Use this BEFORE any external provider.\n\nExample: baker images library 'hero banner' --aspect-ratio 16:9 --source magnific"
|
|
@@ -23077,7 +23181,7 @@ var libraryCommand = defineCommand118({
|
|
|
23077
23181
|
});
|
|
23078
23182
|
|
|
23079
23183
|
// src/commands/images/logo.ts
|
|
23080
|
-
import { defineCommand as
|
|
23184
|
+
import { defineCommand as defineCommand120 } from "citty";
|
|
23081
23185
|
registerSchema({
|
|
23082
23186
|
command: "images.logo",
|
|
23083
23187
|
description: "Brand logo lookup via Brandfetch CDN (fallback/404). Auto-ingests by default.",
|
|
@@ -23102,7 +23206,7 @@ registerSchema({
|
|
|
23102
23206
|
}
|
|
23103
23207
|
}
|
|
23104
23208
|
});
|
|
23105
|
-
var logoCommand =
|
|
23209
|
+
var logoCommand = defineCommand120({
|
|
23106
23210
|
meta: {
|
|
23107
23211
|
name: "logo",
|
|
23108
23212
|
description: "Brand logo via Brandfetch CDN. Returns up to 5 variants (icon, light/dark logo, light/dark symbol). Auto-ingests the first variant.\n\nExample: baker images logo stripe.com --variant logo"
|
|
@@ -23140,7 +23244,7 @@ var logoCommand = defineCommand119({
|
|
|
23140
23244
|
});
|
|
23141
23245
|
|
|
23142
23246
|
// src/commands/images/normalize.ts
|
|
23143
|
-
import { defineCommand as
|
|
23247
|
+
import { defineCommand as defineCommand121 } from "citty";
|
|
23144
23248
|
|
|
23145
23249
|
// src/lib/image/color-changer.ts
|
|
23146
23250
|
import quantize from "quantize";
|
|
@@ -23872,7 +23976,7 @@ function coerceRawArgs(args) {
|
|
|
23872
23976
|
"dry-run": bool(args["dry-run"])
|
|
23873
23977
|
};
|
|
23874
23978
|
}
|
|
23875
|
-
var normalizeCommand =
|
|
23979
|
+
var normalizeCommand = defineCommand121({
|
|
23876
23980
|
meta: {
|
|
23877
23981
|
name: "normalize",
|
|
23878
23982
|
description: `Normalize logos / images: declarative recolor + bg removal + trim + resize. Operates on local files; writes in-place by default.
|
|
@@ -23927,7 +24031,7 @@ Examples:
|
|
|
23927
24031
|
});
|
|
23928
24032
|
|
|
23929
24033
|
// src/commands/images/pinterest.ts
|
|
23930
|
-
import { defineCommand as
|
|
24034
|
+
import { defineCommand as defineCommand122 } from "citty";
|
|
23931
24035
|
registerSchema({
|
|
23932
24036
|
command: "images.pinterest",
|
|
23933
24037
|
description: "Pinterest image search via ScrapeCreators. Reference-grade real-world photography, product styling, interiors, fashion, food, and aesthetic mood boards. Inspect before placing \u2014 Pinterest is unverified, trademark-bearing web content.",
|
|
@@ -23947,7 +24051,7 @@ registerSchema({
|
|
|
23947
24051
|
}
|
|
23948
24052
|
}
|
|
23949
24053
|
});
|
|
23950
|
-
var pinterestCommand =
|
|
24054
|
+
var pinterestCommand = defineCommand122({
|
|
23951
24055
|
meta: {
|
|
23952
24056
|
name: "pinterest",
|
|
23953
24057
|
description: "Pinterest image search via ScrapeCreators ($0.00188/request). Best for photo-realistic reference imagery \u2014 lifestyle, interiors, fashion, food, product styling, and mood boards to brief AI generation against. \u26A0 Unverified, trademark-bearing web content \u2014 inspect and respect rights before placing on a customer page. Browse first; auto-ingest only the pins you commit to.\n\nExamples:\n baker images pinterest 'scandinavian living room'\n baker images pinterest 'minimalist skincare product photography' --limit 20\n baker images pinterest 'cozy coffee shop interior' --auto-ingest 2 --context 'Mood reference for hero photography'"
|
|
@@ -23987,7 +24091,7 @@ var pinterestCommand = defineCommand121({
|
|
|
23987
24091
|
});
|
|
23988
24092
|
|
|
23989
24093
|
// src/commands/images/screenshot.ts
|
|
23990
|
-
import { defineCommand as
|
|
24094
|
+
import { defineCommand as defineCommand123 } from "citty";
|
|
23991
24095
|
registerSchema({
|
|
23992
24096
|
command: "images.screenshot",
|
|
23993
24097
|
description: "Capture a website screenshot via ScreenshotOne. Auto-ingests on success.",
|
|
@@ -24003,7 +24107,7 @@ registerSchema({
|
|
|
24003
24107
|
}
|
|
24004
24108
|
}
|
|
24005
24109
|
});
|
|
24006
|
-
var screenshotCommand =
|
|
24110
|
+
var screenshotCommand = defineCommand123({
|
|
24007
24111
|
meta: {
|
|
24008
24112
|
name: "screenshot",
|
|
24009
24113
|
description: "Screenshot a URL via ScreenshotOne. $0.009/capture. Auto-ingests to library.\n\nExample: baker images screenshot https://stripe.com --full-page"
|
|
@@ -24066,7 +24170,7 @@ var screenshotCommand = defineCommand122({
|
|
|
24066
24170
|
});
|
|
24067
24171
|
|
|
24068
24172
|
// src/commands/images/search.ts
|
|
24069
|
-
import { defineCommand as
|
|
24173
|
+
import { defineCommand as defineCommand124 } from "citty";
|
|
24070
24174
|
registerSchema({
|
|
24071
24175
|
command: "images.search",
|
|
24072
24176
|
description: "Search images by text query. Only returns ready images.",
|
|
@@ -24082,7 +24186,7 @@ registerSchema({
|
|
|
24082
24186
|
tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
|
|
24083
24187
|
}
|
|
24084
24188
|
});
|
|
24085
|
-
var searchCommand =
|
|
24189
|
+
var searchCommand = defineCommand124({
|
|
24086
24190
|
meta: {
|
|
24087
24191
|
name: "search",
|
|
24088
24192
|
description: "Semantic search images by text query. Uses hybrid BM25 + vector + reranking. Example: baker images search 'hero banner' --aspect-ratio 16:9 --tags logo"
|
|
@@ -24142,7 +24246,7 @@ var searchCommand = defineCommand123({
|
|
|
24142
24246
|
});
|
|
24143
24247
|
|
|
24144
24248
|
// src/commands/images/sticker.ts
|
|
24145
|
-
import { defineCommand as
|
|
24249
|
+
import { defineCommand as defineCommand125 } from "citty";
|
|
24146
24250
|
registerSchema({
|
|
24147
24251
|
command: "images.sticker",
|
|
24148
24252
|
description: "Search Giphy stickers \u2014 transparent-background overlays for ad creative.",
|
|
@@ -24174,7 +24278,7 @@ registerSchema({
|
|
|
24174
24278
|
}
|
|
24175
24279
|
}
|
|
24176
24280
|
});
|
|
24177
|
-
var stickerCommand =
|
|
24281
|
+
var stickerCommand = defineCommand125({
|
|
24178
24282
|
meta: {
|
|
24179
24283
|
name: "sticker",
|
|
24180
24284
|
description: "Search Giphy's sticker corpus \u2014 transparent-background WebPs / GIFs ideal for overlaying on ad creative (Meta, TikTok, Stories). Same Giphy free API as `baker images gif`; results carry WebP + GIF + MP4 URLs in providerMeta.\n\nExample: baker images sticker 'thumbs up' --limit 10\nExample: baker images sticker celebration --rating g --auto-ingest 3\nExample: baker images sticker --trending --limit 25"
|
|
@@ -24221,7 +24325,7 @@ var stickerCommand = defineCommand124({
|
|
|
24221
24325
|
});
|
|
24222
24326
|
|
|
24223
24327
|
// src/commands/images/stock.ts
|
|
24224
|
-
import { defineCommand as
|
|
24328
|
+
import { defineCommand as defineCommand126 } from "citty";
|
|
24225
24329
|
registerSchema({
|
|
24226
24330
|
command: "images.stock",
|
|
24227
24331
|
description: "Stock photo, vector illustration, icon-set, and PSD search via Magnific (Freepik's developer API).",
|
|
@@ -24279,7 +24383,7 @@ registerSchema({
|
|
|
24279
24383
|
}
|
|
24280
24384
|
}
|
|
24281
24385
|
});
|
|
24282
|
-
var stockCommand =
|
|
24386
|
+
var stockCommand = defineCommand126({
|
|
24283
24387
|
meta: {
|
|
24284
24388
|
name: "stock",
|
|
24285
24389
|
description: "Stock search via Magnific \u2014 Freepik's developer API (~250M assets: photos, vectors, illustrations, icons, PSDs). $0.002/req. With --auto-ingest, ingested hits return Baker-owned URLs.\n\nExamples:\n baker images stock 'minimalist office'\n baker images stock 'flat office workers' --type vector\n baker images stock 'hero photo of a kitchen' --type photo --orientation landscape --ai exclude\n baker images stock 'brand pattern' --color '#0a0a0a' --license freemium --auto-ingest 2"
|
|
@@ -24335,7 +24439,7 @@ var stockCommand = defineCommand125({
|
|
|
24335
24439
|
});
|
|
24336
24440
|
|
|
24337
24441
|
// src/lib/tags-command.ts
|
|
24338
|
-
import { defineCommand as
|
|
24442
|
+
import { defineCommand as defineCommand127 } from "citty";
|
|
24339
24443
|
function makeTagsCommand(command, label, endpoint) {
|
|
24340
24444
|
registerSchema({
|
|
24341
24445
|
command: `${command}.tags`,
|
|
@@ -24344,7 +24448,7 @@ function makeTagsCommand(command, label, endpoint) {
|
|
|
24344
24448
|
output: { type: "string", description: "Output format: md|json", required: false, default: "md" }
|
|
24345
24449
|
}
|
|
24346
24450
|
});
|
|
24347
|
-
return
|
|
24451
|
+
return defineCommand127({
|
|
24348
24452
|
meta: {
|
|
24349
24453
|
name: "tags",
|
|
24350
24454
|
description: `List the available ${label} tag names (defaults + company custom tags). Use before filtering with --tags. Example: baker ${command} tags`
|
|
@@ -24380,7 +24484,7 @@ function makeTagsCommand(command, label, endpoint) {
|
|
|
24380
24484
|
var tagsCommand2 = makeTagsCommand("images", "image", "/api/images/tags");
|
|
24381
24485
|
|
|
24382
24486
|
// src/commands/images/upload.ts
|
|
24383
|
-
import { defineCommand as
|
|
24487
|
+
import { defineCommand as defineCommand128 } from "citty";
|
|
24384
24488
|
registerSchema({
|
|
24385
24489
|
command: "images.upload",
|
|
24386
24490
|
description: "Upload an image to the library \u2014 local file path or remote http(s) URL.",
|
|
@@ -24418,7 +24522,7 @@ registerSchema({
|
|
|
24418
24522
|
function isRemoteUrl2(value) {
|
|
24419
24523
|
return /^https?:\/\//i.test(value);
|
|
24420
24524
|
}
|
|
24421
|
-
var uploadCommand =
|
|
24525
|
+
var uploadCommand = defineCommand128({
|
|
24422
24526
|
meta: {
|
|
24423
24527
|
name: "upload",
|
|
24424
24528
|
description: "Upload an image to the library \u2014 accepts a local file path OR a remote http(s) URL.\n\nLocal: reads bytes, sends to /api/images/upload, content-type auto-detected from extension.\nRemote: dispatches to /api/images/ingest with hash-dedup on bytes + externalId.\n\nExamples:\n baker images upload ./logo.png --source uploaded\n baker images upload ./cert.png --context 'ISO 27001 badge \u2014 enterprise tier'\n baker images upload https://acme.com/hero.png --source firecrawl --context 'Acme competitor pricing hero'"
|
|
@@ -24511,7 +24615,7 @@ async function uploadLocal(target, args) {
|
|
|
24511
24615
|
}
|
|
24512
24616
|
|
|
24513
24617
|
// src/commands/images/upscale.ts
|
|
24514
|
-
import { defineCommand as
|
|
24618
|
+
import { defineCommand as defineCommand129 } from "citty";
|
|
24515
24619
|
registerSchema({
|
|
24516
24620
|
command: "images.upscale",
|
|
24517
24621
|
description: "Upscale a library image via the backend (Replicate, cost-tracked). Waits for completion by default. The image must be status 'ready' and raster (not SVG/AVIF).",
|
|
@@ -24526,7 +24630,7 @@ registerSchema({
|
|
|
24526
24630
|
}
|
|
24527
24631
|
});
|
|
24528
24632
|
var POLL_INTERVAL_MS3 = 1500;
|
|
24529
|
-
var upscaleCommand =
|
|
24633
|
+
var upscaleCommand = defineCommand129({
|
|
24530
24634
|
meta: {
|
|
24531
24635
|
name: "upscale",
|
|
24532
24636
|
description: "Upscale a library image via the Convex backend (Replicate, cost-tracked at $0.05/image). Waits for completion by default.\n\nExample: baker images upscale j571abc123def\nExample: baker images upscale j571abc123def --max-wait 0 # fire-and-forget"
|
|
@@ -24581,7 +24685,7 @@ var upscaleCommand = defineCommand128({
|
|
|
24581
24685
|
});
|
|
24582
24686
|
|
|
24583
24687
|
// src/commands/images/use.ts
|
|
24584
|
-
import { defineCommand as
|
|
24688
|
+
import { defineCommand as defineCommand130 } from "citty";
|
|
24585
24689
|
registerSchema({
|
|
24586
24690
|
command: "images.use",
|
|
24587
24691
|
description: "Ingest a URL and wait for the library record to be ready.",
|
|
@@ -24597,7 +24701,7 @@ registerSchema({
|
|
|
24597
24701
|
}
|
|
24598
24702
|
});
|
|
24599
24703
|
var POLL_INTERVAL_MS4 = 1500;
|
|
24600
|
-
var useCommand =
|
|
24704
|
+
var useCommand = defineCommand130({
|
|
24601
24705
|
meta: {
|
|
24602
24706
|
name: "use",
|
|
24603
24707
|
description: "Sugar over `ingest`: download \u2192 store \u2192 wait until describe + embed complete \u2192 return ready library record.\n\nExample: baker images use https://cdn.example.com/hero.png --source uploaded"
|
|
@@ -24643,7 +24747,7 @@ var useCommand = defineCommand129({
|
|
|
24643
24747
|
});
|
|
24644
24748
|
|
|
24645
24749
|
// src/commands/images/index.ts
|
|
24646
|
-
var imagesCommand =
|
|
24750
|
+
var imagesCommand = defineCommand131({
|
|
24647
24751
|
meta: {
|
|
24648
24752
|
name: "images",
|
|
24649
24753
|
description: `Find, source, and normalize images. Subcommands route by provider so cost + license are explicit.
|
|
@@ -24713,7 +24817,7 @@ Paid transforms (run on the Convex backend, cost-tracked):
|
|
|
24713
24817
|
});
|
|
24714
24818
|
|
|
24715
24819
|
// src/commands/mcp/index.ts
|
|
24716
|
-
import { defineCommand as
|
|
24820
|
+
import { defineCommand as defineCommand132 } from "citty";
|
|
24717
24821
|
var SCOPES = ["user", "user_org", "company", "org"];
|
|
24718
24822
|
function parseScope(raw) {
|
|
24719
24823
|
const scope = raw === void 0 ? "company" : String(raw);
|
|
@@ -24752,7 +24856,7 @@ registerSchema({
|
|
|
24752
24856
|
description: "List the custom MCP servers this company's chats see (org + company + your own user scope).",
|
|
24753
24857
|
args: {}
|
|
24754
24858
|
});
|
|
24755
|
-
var listCommand6 =
|
|
24859
|
+
var listCommand6 = defineCommand132({
|
|
24756
24860
|
meta: { name: "list", description: "List custom MCP servers visible to this company's chats." },
|
|
24757
24861
|
run: async () => {
|
|
24758
24862
|
try {
|
|
@@ -24777,7 +24881,7 @@ registerSchema({
|
|
|
24777
24881
|
header: { type: "string", description: 'Auth header "Key: Value" (repeatable)', required: false }
|
|
24778
24882
|
}
|
|
24779
24883
|
});
|
|
24780
|
-
var addCommand =
|
|
24884
|
+
var addCommand = defineCommand132({
|
|
24781
24885
|
meta: {
|
|
24782
24886
|
name: "add",
|
|
24783
24887
|
description: `Register a custom MCP server. Tools appear as mcp__<name>__* on the NEXT message.
|
|
@@ -24818,7 +24922,7 @@ registerSchema({
|
|
|
24818
24922
|
description: "Remove a company custom MCP server by name.",
|
|
24819
24923
|
args: { name: { type: "string", description: "Server name to remove", required: true } }
|
|
24820
24924
|
});
|
|
24821
|
-
var removeCommand4 =
|
|
24925
|
+
var removeCommand4 = defineCommand132({
|
|
24822
24926
|
meta: {
|
|
24823
24927
|
name: "remove",
|
|
24824
24928
|
description: `Remove a company custom MCP server by name.
|
|
@@ -24840,7 +24944,7 @@ Example:
|
|
|
24840
24944
|
}
|
|
24841
24945
|
}
|
|
24842
24946
|
});
|
|
24843
|
-
var mcpCommand =
|
|
24947
|
+
var mcpCommand = defineCommand132({
|
|
24844
24948
|
meta: {
|
|
24845
24949
|
name: "mcp",
|
|
24846
24950
|
description: `Custom MCP servers for this company \u2014 point the agent at any HTTPS MCP endpoint.
|
|
@@ -24864,10 +24968,10 @@ Examples:
|
|
|
24864
24968
|
});
|
|
24865
24969
|
|
|
24866
24970
|
// src/commands/research/index.ts
|
|
24867
|
-
import { defineCommand as
|
|
24971
|
+
import { defineCommand as defineCommand143 } from "citty";
|
|
24868
24972
|
|
|
24869
24973
|
// src/commands/research/advertisers.ts
|
|
24870
|
-
import { defineCommand as
|
|
24974
|
+
import { defineCommand as defineCommand133 } from "citty";
|
|
24871
24975
|
|
|
24872
24976
|
// src/commands/research/output.ts
|
|
24873
24977
|
var RESEARCH_DATA_NOTE = "Estimates based on third-party SERP data \u2014 not exact figures. Use for directional insights, not precise measurement.";
|
|
@@ -24980,7 +25084,7 @@ var FIELDS3 = {
|
|
|
24980
25084
|
etv: "Estimated traffic value (USD)",
|
|
24981
25085
|
visibility: "SERP visibility score (0-1)"
|
|
24982
25086
|
};
|
|
24983
|
-
var advertisersCommand =
|
|
25087
|
+
var advertisersCommand = defineCommand133({
|
|
24984
25088
|
meta: {
|
|
24985
25089
|
name: "advertisers",
|
|
24986
25090
|
description: `Find domains competing for a keyword in Google SERPs.
|
|
@@ -25027,7 +25131,7 @@ Examples:
|
|
|
25027
25131
|
});
|
|
25028
25132
|
|
|
25029
25133
|
// src/commands/research/autocomplete.ts
|
|
25030
|
-
import { defineCommand as
|
|
25134
|
+
import { defineCommand as defineCommand134 } from "citty";
|
|
25031
25135
|
registerSchema({
|
|
25032
25136
|
command: "research.autocomplete",
|
|
25033
25137
|
description: "Get Google Autocomplete suggestions for a seed keyword. Useful for keyword expansion and discovering what people actually search for. IMPORTANT: If --location and --language are omitted, defaults to United States (us) and English (en).",
|
|
@@ -25050,7 +25154,7 @@ registerSchema({
|
|
|
25050
25154
|
var FIELDS4 = {
|
|
25051
25155
|
suggestion: "Autocomplete suggestion from Google"
|
|
25052
25156
|
};
|
|
25053
|
-
var autocompleteCommand =
|
|
25157
|
+
var autocompleteCommand = defineCommand134({
|
|
25054
25158
|
meta: {
|
|
25055
25159
|
name: "autocomplete",
|
|
25056
25160
|
description: `Get Google Autocomplete suggestions for keyword expansion.
|
|
@@ -25096,7 +25200,7 @@ Examples:
|
|
|
25096
25200
|
});
|
|
25097
25201
|
|
|
25098
25202
|
// src/commands/research/countries.ts
|
|
25099
|
-
import { defineCommand as
|
|
25203
|
+
import { defineCommand as defineCommand135 } from "citty";
|
|
25100
25204
|
registerSchema({
|
|
25101
25205
|
command: "research.countries",
|
|
25102
25206
|
description: "List all supported country codes for --location flag in research commands.",
|
|
@@ -25153,7 +25257,7 @@ var FIELDS5 = {
|
|
|
25153
25257
|
code: "Country code to pass as --location",
|
|
25154
25258
|
name: "Country name"
|
|
25155
25259
|
};
|
|
25156
|
-
var countriesCommand =
|
|
25260
|
+
var countriesCommand = defineCommand135({
|
|
25157
25261
|
meta: {
|
|
25158
25262
|
name: "countries",
|
|
25159
25263
|
description: "List all supported country codes for --location flag."
|
|
@@ -25164,7 +25268,7 @@ var countriesCommand = defineCommand134({
|
|
|
25164
25268
|
});
|
|
25165
25269
|
|
|
25166
25270
|
// src/commands/research/intent.ts
|
|
25167
|
-
import { defineCommand as
|
|
25271
|
+
import { defineCommand as defineCommand136 } from "citty";
|
|
25168
25272
|
registerSchema({
|
|
25169
25273
|
command: "research.intent",
|
|
25170
25274
|
description: "Classify Google Search intent for keywords. Determines if someone searching is looking to buy, research, or navigate. IMPORTANT: If --language is omitted, defaults to English (en). The response includes a query_context object showing which language was used.",
|
|
@@ -25187,7 +25291,7 @@ var FIELDS6 = {
|
|
|
25187
25291
|
intent: "Primary Google Search intent: informational, navigational, commercial, transactional",
|
|
25188
25292
|
probability: "Confidence score 0.0-1.0"
|
|
25189
25293
|
};
|
|
25190
|
-
var intentCommand =
|
|
25294
|
+
var intentCommand = defineCommand136({
|
|
25191
25295
|
meta: {
|
|
25192
25296
|
name: "intent",
|
|
25193
25297
|
description: `Classify Google Search intent for keywords. Returns intent type and confidence.
|
|
@@ -25235,7 +25339,7 @@ Examples:
|
|
|
25235
25339
|
});
|
|
25236
25340
|
|
|
25237
25341
|
// src/commands/research/keyword-gap.ts
|
|
25238
|
-
import { defineCommand as
|
|
25342
|
+
import { defineCommand as defineCommand137 } from "citty";
|
|
25239
25343
|
registerSchema({
|
|
25240
25344
|
command: "research.keyword-gap",
|
|
25241
25345
|
description: "Find keywords a competitor ranks for (organic or paid) that you don't. Discovers expansion opportunities. IMPORTANT: If --location and --language are omitted, defaults to United States (us) and English (en). The response includes a query_context object showing which location/language were used.",
|
|
@@ -25264,7 +25368,7 @@ var FIELDS7 = {
|
|
|
25264
25368
|
cpc: "Cost per click USD",
|
|
25265
25369
|
their_position: "Competitor's ranking position"
|
|
25266
25370
|
};
|
|
25267
|
-
var keywordGapCommand =
|
|
25371
|
+
var keywordGapCommand = defineCommand137({
|
|
25268
25372
|
meta: {
|
|
25269
25373
|
name: "keyword-gap",
|
|
25270
25374
|
description: `Find keywords a competitor has that you don't. Supports pagination via --offset.
|
|
@@ -25338,7 +25442,7 @@ Examples:
|
|
|
25338
25442
|
});
|
|
25339
25443
|
|
|
25340
25444
|
// src/commands/research/keywords-for-site.ts
|
|
25341
|
-
import { defineCommand as
|
|
25445
|
+
import { defineCommand as defineCommand138 } from "citty";
|
|
25342
25446
|
registerSchema({
|
|
25343
25447
|
command: "research.keywords-for-site",
|
|
25344
25448
|
description: "Get keywords a competitor targets in Google. Use --type paid to see only paid keywords, --type organic for organic only. IMPORTANT: If --location and --language are omitted, defaults to United States (us) and English (en). The response includes a query_context object showing which location/language were used.",
|
|
@@ -25371,7 +25475,7 @@ var FIELDS8 = {
|
|
|
25371
25475
|
competition: "LOW, MEDIUM, or HIGH",
|
|
25372
25476
|
competition_index: "Competition score 0-100"
|
|
25373
25477
|
};
|
|
25374
|
-
var keywordsForSiteCommand =
|
|
25478
|
+
var keywordsForSiteCommand = defineCommand138({
|
|
25375
25479
|
meta: {
|
|
25376
25480
|
name: "keywords-for-site",
|
|
25377
25481
|
description: `Get keywords a competitor targets in Google. Use --type to filter paid/organic.
|
|
@@ -25424,7 +25528,7 @@ Examples:
|
|
|
25424
25528
|
});
|
|
25425
25529
|
|
|
25426
25530
|
// src/commands/research/languages.ts
|
|
25427
|
-
import { defineCommand as
|
|
25531
|
+
import { defineCommand as defineCommand139 } from "citty";
|
|
25428
25532
|
registerSchema({
|
|
25429
25533
|
command: "research.languages",
|
|
25430
25534
|
description: "List all supported language codes for --language flag in research commands.",
|
|
@@ -25454,7 +25558,7 @@ var FIELDS9 = {
|
|
|
25454
25558
|
code: "Language code to pass as --language",
|
|
25455
25559
|
name: "Language name (also accepted by --language)"
|
|
25456
25560
|
};
|
|
25457
|
-
var languagesCommand2 =
|
|
25561
|
+
var languagesCommand2 = defineCommand139({
|
|
25458
25562
|
meta: {
|
|
25459
25563
|
name: "languages",
|
|
25460
25564
|
description: "List all supported language codes for --language flag."
|
|
@@ -25465,7 +25569,7 @@ var languagesCommand2 = defineCommand138({
|
|
|
25465
25569
|
});
|
|
25466
25570
|
|
|
25467
25571
|
// src/commands/research/lighthouse.ts
|
|
25468
|
-
import { defineCommand as
|
|
25572
|
+
import { defineCommand as defineCommand140 } from "citty";
|
|
25469
25573
|
registerSchema({
|
|
25470
25574
|
command: "research.lighthouse",
|
|
25471
25575
|
description: "Landing page performance audit. Returns metrics that affect Google Ads Quality Score and CPC.",
|
|
@@ -25484,7 +25588,7 @@ var FIELDS10 = {
|
|
|
25484
25588
|
speed_index_ms: "Speed Index in ms (good: < 3400)",
|
|
25485
25589
|
interactive_ms: "Time to Interactive in ms (good: < 3800)"
|
|
25486
25590
|
};
|
|
25487
|
-
var lighthouseCommand =
|
|
25591
|
+
var lighthouseCommand = defineCommand140({
|
|
25488
25592
|
meta: {
|
|
25489
25593
|
name: "lighthouse",
|
|
25490
25594
|
description: `Landing page performance audit. Metrics affecting Google Ads Quality Score.
|
|
@@ -25522,7 +25626,7 @@ Examples:
|
|
|
25522
25626
|
});
|
|
25523
25627
|
|
|
25524
25628
|
// src/commands/research/relevant-pages.ts
|
|
25525
|
-
import { defineCommand as
|
|
25629
|
+
import { defineCommand as defineCommand141 } from "citty";
|
|
25526
25630
|
registerSchema({
|
|
25527
25631
|
command: "research.relevant-pages",
|
|
25528
25632
|
description: "Get the top pages of a competitor domain with organic traffic and ranking data. Shows which pages drive the most traffic. IMPORTANT: If --location and --language are omitted, defaults to United States (us) and English (en).",
|
|
@@ -25548,7 +25652,7 @@ var FIELDS11 = {
|
|
|
25548
25652
|
keywords: "Total organic keywords the page ranks for",
|
|
25549
25653
|
top_10: "Keywords in positions 1-10"
|
|
25550
25654
|
};
|
|
25551
|
-
var relevantPagesCommand =
|
|
25655
|
+
var relevantPagesCommand = defineCommand141({
|
|
25552
25656
|
meta: {
|
|
25553
25657
|
name: "relevant-pages",
|
|
25554
25658
|
description: `Get the top pages of a competitor domain with traffic data.
|
|
@@ -25594,7 +25698,7 @@ Examples:
|
|
|
25594
25698
|
});
|
|
25595
25699
|
|
|
25596
25700
|
// src/commands/research/web.ts
|
|
25597
|
-
import { defineCommand as
|
|
25701
|
+
import { defineCommand as defineCommand142 } from "citty";
|
|
25598
25702
|
registerSchema({
|
|
25599
25703
|
command: "research.web",
|
|
25600
25704
|
description: "Search the web with AI to answer marketing questions \u2014 competitors, ICP, pricing, pain points, market trends. Three depth levels: medium (quick, default), high (thorough), xhigh (exhaustive deep research).",
|
|
@@ -25645,7 +25749,7 @@ async function runDeepResearch(question) {
|
|
|
25645
25749
|
}
|
|
25646
25750
|
throw new Error("Deep research timed out");
|
|
25647
25751
|
}
|
|
25648
|
-
var webCommand =
|
|
25752
|
+
var webCommand = defineCommand142({
|
|
25649
25753
|
meta: {
|
|
25650
25754
|
name: "web",
|
|
25651
25755
|
description: `Search the web with AI to answer any open-ended marketing question. Uses live internet data via Google Search.
|
|
@@ -25705,7 +25809,7 @@ Examples:
|
|
|
25705
25809
|
});
|
|
25706
25810
|
|
|
25707
25811
|
// src/commands/research/index.ts
|
|
25708
|
-
var researchCommand =
|
|
25812
|
+
var researchCommand = defineCommand143({
|
|
25709
25813
|
meta: {
|
|
25710
25814
|
name: "research",
|
|
25711
25815
|
description: `Competitive intelligence and AI-powered research commands.
|
|
@@ -25745,10 +25849,10 @@ Examples:
|
|
|
25745
25849
|
});
|
|
25746
25850
|
|
|
25747
25851
|
// src/commands/scheduled-actions/index.ts
|
|
25748
|
-
import { defineCommand as
|
|
25852
|
+
import { defineCommand as defineCommand150 } from "citty";
|
|
25749
25853
|
|
|
25750
25854
|
// src/commands/scheduled-actions/create.ts
|
|
25751
|
-
import { defineCommand as
|
|
25855
|
+
import { defineCommand as defineCommand144 } from "citty";
|
|
25752
25856
|
|
|
25753
25857
|
// src/commands/scheduled-actions/shared.ts
|
|
25754
25858
|
var TEMP_SCHEDULED_ACTION_PREFIX = "temp_sched_";
|
|
@@ -25863,7 +25967,7 @@ registerSchema({
|
|
|
25863
25967
|
prompt: { type: "string", description: "Additional prompt instructions for the spawned agent", required: false }
|
|
25864
25968
|
}
|
|
25865
25969
|
});
|
|
25866
|
-
var createCommand2 =
|
|
25970
|
+
var createCommand2 = defineCommand144({
|
|
25867
25971
|
meta: {
|
|
25868
25972
|
name: "create",
|
|
25869
25973
|
description: 'Stage a scheduled action. Example: baker scheduled-actions create --name "Weekly report" --description "..." --cron "0 9 * * MON"'
|
|
@@ -25912,7 +26016,7 @@ var createCommand2 = defineCommand143({
|
|
|
25912
26016
|
});
|
|
25913
26017
|
|
|
25914
26018
|
// src/commands/scheduled-actions/delete.ts
|
|
25915
|
-
import { defineCommand as
|
|
26019
|
+
import { defineCommand as defineCommand145 } from "citty";
|
|
25916
26020
|
registerSchema({
|
|
25917
26021
|
command: "scheduled-actions.delete",
|
|
25918
26022
|
description: "Stage deletion of a published scheduled action or cancellation of a temp_sched_* draft creation.",
|
|
@@ -25920,7 +26024,7 @@ registerSchema({
|
|
|
25920
26024
|
id: { type: "string", description: "Published scheduled action ID or temp_sched_* draft ID", required: true }
|
|
25921
26025
|
}
|
|
25922
26026
|
});
|
|
25923
|
-
var deleteCommand2 =
|
|
26027
|
+
var deleteCommand2 = defineCommand145({
|
|
25924
26028
|
meta: {
|
|
25925
26029
|
name: "delete",
|
|
25926
26030
|
description: "Stage scheduled action deletion. Example: baker scheduled-actions delete <id-or-temp_sched_id>"
|
|
@@ -25949,7 +26053,7 @@ var deleteCommand2 = defineCommand144({
|
|
|
25949
26053
|
});
|
|
25950
26054
|
|
|
25951
26055
|
// src/commands/scheduled-actions/get.ts
|
|
25952
|
-
import { defineCommand as
|
|
26056
|
+
import { defineCommand as defineCommand146 } from "citty";
|
|
25953
26057
|
registerSchema({
|
|
25954
26058
|
command: "scheduled-actions.get",
|
|
25955
26059
|
description: "Get a published scheduled action or a temp_sched_* draft-created scheduled action.",
|
|
@@ -25957,7 +26061,7 @@ registerSchema({
|
|
|
25957
26061
|
id: { type: "string", description: "Published scheduled action ID or temp_sched_* draft ID", required: true }
|
|
25958
26062
|
}
|
|
25959
26063
|
});
|
|
25960
|
-
var getCommand3 =
|
|
26064
|
+
var getCommand3 = defineCommand146({
|
|
25961
26065
|
meta: {
|
|
25962
26066
|
name: "get",
|
|
25963
26067
|
description: "Get a scheduled action. Example: baker scheduled-actions get <id-or-temp_sched_id>"
|
|
@@ -25994,13 +26098,13 @@ var getCommand3 = defineCommand145({
|
|
|
25994
26098
|
});
|
|
25995
26099
|
|
|
25996
26100
|
// src/commands/scheduled-actions/list.ts
|
|
25997
|
-
import { defineCommand as
|
|
26101
|
+
import { defineCommand as defineCommand147 } from "citty";
|
|
25998
26102
|
registerSchema({
|
|
25999
26103
|
command: "scheduled-actions.list",
|
|
26000
26104
|
description: "List published scheduled actions. Includes draft state when BAKER_CHAT_ID is set.",
|
|
26001
26105
|
args: {}
|
|
26002
26106
|
});
|
|
26003
|
-
var listCommand7 =
|
|
26107
|
+
var listCommand7 = defineCommand147({
|
|
26004
26108
|
meta: {
|
|
26005
26109
|
name: "list",
|
|
26006
26110
|
description: "List scheduled actions. Includes staged draft ops when BAKER_CHAT_ID is set."
|
|
@@ -26021,7 +26125,7 @@ var listCommand7 = defineCommand146({
|
|
|
26021
26125
|
});
|
|
26022
26126
|
|
|
26023
26127
|
// src/commands/scheduled-actions/trigger.ts
|
|
26024
|
-
import { defineCommand as
|
|
26128
|
+
import { defineCommand as defineCommand148 } from "citty";
|
|
26025
26129
|
registerSchema({
|
|
26026
26130
|
command: "scheduled-actions.trigger",
|
|
26027
26131
|
description: "Immediately trigger a published scheduled action. Does not require BAKER_CHAT_ID and rejects temp_sched_* IDs.",
|
|
@@ -26029,7 +26133,7 @@ registerSchema({
|
|
|
26029
26133
|
id: { type: "string", description: "Published scheduled action ID", required: true }
|
|
26030
26134
|
}
|
|
26031
26135
|
});
|
|
26032
|
-
var triggerCommand =
|
|
26136
|
+
var triggerCommand = defineCommand148({
|
|
26033
26137
|
meta: {
|
|
26034
26138
|
name: "trigger",
|
|
26035
26139
|
description: "Immediately trigger a published scheduled action. Example: baker scheduled-actions trigger <id>"
|
|
@@ -26066,7 +26170,7 @@ var triggerCommand = defineCommand147({
|
|
|
26066
26170
|
});
|
|
26067
26171
|
|
|
26068
26172
|
// src/commands/scheduled-actions/update.ts
|
|
26069
|
-
import { defineCommand as
|
|
26173
|
+
import { defineCommand as defineCommand149 } from "citty";
|
|
26070
26174
|
registerSchema({
|
|
26071
26175
|
command: "scheduled-actions.update",
|
|
26072
26176
|
description: "Stage an update to a published scheduled action or temp_sched_* draft-created scheduled action.",
|
|
@@ -26091,7 +26195,7 @@ registerSchema({
|
|
|
26091
26195
|
prompt: { type: "string", description: "Replacement additional spawned-agent instructions", required: false }
|
|
26092
26196
|
}
|
|
26093
26197
|
});
|
|
26094
|
-
var updateCommand2 =
|
|
26198
|
+
var updateCommand2 = defineCommand149({
|
|
26095
26199
|
meta: {
|
|
26096
26200
|
name: "update",
|
|
26097
26201
|
description: "Stage a scheduled action update. Example: baker scheduled-actions update <id> --enabled false"
|
|
@@ -26162,7 +26266,7 @@ var updateCommand2 = defineCommand148({
|
|
|
26162
26266
|
});
|
|
26163
26267
|
|
|
26164
26268
|
// src/commands/scheduled-actions/index.ts
|
|
26165
|
-
var scheduledActionsCommand =
|
|
26269
|
+
var scheduledActionsCommand = defineCommand150({
|
|
26166
26270
|
meta: {
|
|
26167
26271
|
name: "scheduled-actions",
|
|
26168
26272
|
description: `Manage Scheduled Actions. Subcommands: list, get, create, update, delete, trigger.
|
|
@@ -26188,8 +26292,8 @@ Examples:
|
|
|
26188
26292
|
});
|
|
26189
26293
|
|
|
26190
26294
|
// src/commands/schema.ts
|
|
26191
|
-
import { defineCommand as
|
|
26192
|
-
var schemaCommand =
|
|
26295
|
+
import { defineCommand as defineCommand151 } from "citty";
|
|
26296
|
+
var schemaCommand = defineCommand151({
|
|
26193
26297
|
meta: {
|
|
26194
26298
|
name: "schema",
|
|
26195
26299
|
description: "Inspect command argument schemas (for AI agent introspection). Lists all commands if no argument given. Example: baker schema images.search"
|
|
@@ -26225,7 +26329,7 @@ var schemaCommand = defineCommand150({
|
|
|
26225
26329
|
});
|
|
26226
26330
|
|
|
26227
26331
|
// src/commands/tags/index.ts
|
|
26228
|
-
import { defineCommand as
|
|
26332
|
+
import { defineCommand as defineCommand152 } from "citty";
|
|
26229
26333
|
|
|
26230
26334
|
// src/commands/tags/shared.ts
|
|
26231
26335
|
function failApi3(err) {
|
|
@@ -26291,7 +26395,7 @@ async function listTags(json) {
|
|
|
26291
26395
|
failApi3(err);
|
|
26292
26396
|
}
|
|
26293
26397
|
}
|
|
26294
|
-
var listCommand8 =
|
|
26398
|
+
var listCommand8 = defineCommand152({
|
|
26295
26399
|
meta: {
|
|
26296
26400
|
name: "list",
|
|
26297
26401
|
description: "Effective tags for this chat (production + staged), with each tag's full readable config (secrets excluded) \u2014 reuse a stored value to pre-fill a change rather than asking the user. Refs printed here are what flow side-effect tagIds should use. Example: baker tags list"
|
|
@@ -26310,7 +26414,7 @@ async function listDraft3() {
|
|
|
26310
26414
|
failApi3(err);
|
|
26311
26415
|
}
|
|
26312
26416
|
}
|
|
26313
|
-
var draftCommand3 =
|
|
26417
|
+
var draftCommand3 = defineCommand152({
|
|
26314
26418
|
meta: {
|
|
26315
26419
|
name: "draft",
|
|
26316
26420
|
description: "Review the tag changes staged in this chat (read-only). Staged changes were approved via request_tag_input and apply when the chat is published; to amend or drop one, propose a follow-up change through the same tool (a delete on a tag_temp_* ref drops the staged create)."
|
|
@@ -26319,7 +26423,7 @@ var draftCommand3 = defineCommand151({
|
|
|
26319
26423
|
await listDraft3();
|
|
26320
26424
|
}
|
|
26321
26425
|
});
|
|
26322
|
-
var tagsCommand3 =
|
|
26426
|
+
var tagsCommand3 = defineCommand152({
|
|
26323
26427
|
meta: {
|
|
26324
26428
|
name: "tags",
|
|
26325
26429
|
description: `Read the client's marketing/analytics tags (Meta pixel, GA4, Google Ads, GTM, Clarity, Hotjar, \u2026) \u2014 production tags plus the changes staged in this chat.
|
|
@@ -26344,10 +26448,10 @@ Examples:
|
|
|
26344
26448
|
});
|
|
26345
26449
|
|
|
26346
26450
|
// src/commands/testimonials/index.ts
|
|
26347
|
-
import { defineCommand as
|
|
26451
|
+
import { defineCommand as defineCommand156 } from "citty";
|
|
26348
26452
|
|
|
26349
26453
|
// src/commands/testimonials/get.ts
|
|
26350
|
-
import { defineCommand as
|
|
26454
|
+
import { defineCommand as defineCommand153 } from "citty";
|
|
26351
26455
|
registerSchema({
|
|
26352
26456
|
command: "testimonials.get",
|
|
26353
26457
|
description: "Get a single testimonial by ID",
|
|
@@ -26355,7 +26459,7 @@ registerSchema({
|
|
|
26355
26459
|
id: { type: "string", description: "Testimonial ID", required: true }
|
|
26356
26460
|
}
|
|
26357
26461
|
});
|
|
26358
|
-
var getCommand4 =
|
|
26462
|
+
var getCommand4 = defineCommand153({
|
|
26359
26463
|
meta: { name: "get", description: "Get a single testimonial by ID. Example: baker testimonials get j571abc123" },
|
|
26360
26464
|
args: {
|
|
26361
26465
|
id: { type: "positional", description: "Testimonial ID", required: false },
|
|
@@ -26392,7 +26496,7 @@ var getCommand4 = defineCommand152({
|
|
|
26392
26496
|
});
|
|
26393
26497
|
|
|
26394
26498
|
// src/commands/testimonials/list.ts
|
|
26395
|
-
import { defineCommand as
|
|
26499
|
+
import { defineCommand as defineCommand154 } from "citty";
|
|
26396
26500
|
registerSchema({
|
|
26397
26501
|
command: "testimonials.list",
|
|
26398
26502
|
description: "List testimonials with optional filters.",
|
|
@@ -26422,7 +26526,7 @@ registerSchema({
|
|
|
26422
26526
|
limit: { type: "number", description: "Max results (default 50)", required: false, default: 50 }
|
|
26423
26527
|
}
|
|
26424
26528
|
});
|
|
26425
|
-
var listCommand9 =
|
|
26529
|
+
var listCommand9 = defineCommand154({
|
|
26426
26530
|
meta: {
|
|
26427
26531
|
name: "list",
|
|
26428
26532
|
description: "List testimonials with optional filters. Example: baker testimonials list --source google --sentiment positive"
|
|
@@ -26471,7 +26575,7 @@ var listCommand9 = defineCommand153({
|
|
|
26471
26575
|
});
|
|
26472
26576
|
|
|
26473
26577
|
// src/commands/testimonials/search.ts
|
|
26474
|
-
import { defineCommand as
|
|
26578
|
+
import { defineCommand as defineCommand155 } from "citty";
|
|
26475
26579
|
registerSchema({
|
|
26476
26580
|
command: "testimonials.search",
|
|
26477
26581
|
description: "Search testimonials by text query. Uses hybrid BM25 + vector + reranking.",
|
|
@@ -26502,7 +26606,7 @@ registerSchema({
|
|
|
26502
26606
|
tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
|
|
26503
26607
|
}
|
|
26504
26608
|
});
|
|
26505
|
-
var searchCommand2 =
|
|
26609
|
+
var searchCommand2 = defineCommand155({
|
|
26506
26610
|
meta: {
|
|
26507
26611
|
name: "search",
|
|
26508
26612
|
description: "Semantic search testimonials by text query. Uses hybrid BM25 + vector + reranking. Example: baker testimonials search 'great service' --rating-min 4"
|
|
@@ -26576,7 +26680,7 @@ var searchCommand2 = defineCommand154({
|
|
|
26576
26680
|
var tagsCommand4 = makeTagsCommand("testimonials", "testimonial", "/api/testimonials/tags");
|
|
26577
26681
|
|
|
26578
26682
|
// src/commands/testimonials/index.ts
|
|
26579
|
-
var testimonialsCommand =
|
|
26683
|
+
var testimonialsCommand = defineCommand156({
|
|
26580
26684
|
meta: {
|
|
26581
26685
|
name: "testimonials",
|
|
26582
26686
|
description: `Find and browse testimonials in Baker. Subcommands: search, get, list, tags.
|
|
@@ -26597,10 +26701,10 @@ Examples:
|
|
|
26597
26701
|
});
|
|
26598
26702
|
|
|
26599
26703
|
// src/commands/videos/index.ts
|
|
26600
|
-
import { defineCommand as
|
|
26704
|
+
import { defineCommand as defineCommand161 } from "citty";
|
|
26601
26705
|
|
|
26602
26706
|
// src/commands/videos/delete.ts
|
|
26603
|
-
import { defineCommand as
|
|
26707
|
+
import { defineCommand as defineCommand157 } from "citty";
|
|
26604
26708
|
registerSchema({
|
|
26605
26709
|
command: "videos.delete",
|
|
26606
26710
|
description: "Delete a video by ID",
|
|
@@ -26614,7 +26718,7 @@ registerSchema({
|
|
|
26614
26718
|
}
|
|
26615
26719
|
}
|
|
26616
26720
|
});
|
|
26617
|
-
var deleteCommand3 =
|
|
26721
|
+
var deleteCommand3 = defineCommand157({
|
|
26618
26722
|
meta: {
|
|
26619
26723
|
name: "delete",
|
|
26620
26724
|
description: "Delete a video by ID. Use --dry-run to preview. Example: baker videos delete j571abc123 --dry-run"
|
|
@@ -26655,7 +26759,7 @@ var deleteCommand3 = defineCommand156({
|
|
|
26655
26759
|
});
|
|
26656
26760
|
|
|
26657
26761
|
// src/commands/videos/get.ts
|
|
26658
|
-
import { defineCommand as
|
|
26762
|
+
import { defineCommand as defineCommand158 } from "citty";
|
|
26659
26763
|
registerSchema({
|
|
26660
26764
|
command: "videos.get",
|
|
26661
26765
|
description: "Get a single video by ID",
|
|
@@ -26663,7 +26767,7 @@ registerSchema({
|
|
|
26663
26767
|
id: { type: "string", description: "Video ID", required: true }
|
|
26664
26768
|
}
|
|
26665
26769
|
});
|
|
26666
|
-
var getCommand5 =
|
|
26770
|
+
var getCommand5 = defineCommand158({
|
|
26667
26771
|
meta: { name: "get", description: "Get a single video by ID. Example: baker videos get j571abc123" },
|
|
26668
26772
|
args: {
|
|
26669
26773
|
id: { type: "positional", description: "Video ID", required: false },
|
|
@@ -26700,7 +26804,7 @@ var getCommand5 = defineCommand157({
|
|
|
26700
26804
|
});
|
|
26701
26805
|
|
|
26702
26806
|
// src/commands/videos/search.ts
|
|
26703
|
-
import { defineCommand as
|
|
26807
|
+
import { defineCommand as defineCommand159 } from "citty";
|
|
26704
26808
|
registerSchema({
|
|
26705
26809
|
command: "videos.search",
|
|
26706
26810
|
description: "Search videos by text query. Only returns ready videos.",
|
|
@@ -26710,7 +26814,7 @@ registerSchema({
|
|
|
26710
26814
|
tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
|
|
26711
26815
|
}
|
|
26712
26816
|
});
|
|
26713
|
-
var searchCommand3 =
|
|
26817
|
+
var searchCommand3 = defineCommand159({
|
|
26714
26818
|
meta: {
|
|
26715
26819
|
name: "search",
|
|
26716
26820
|
description: "Semantic search videos by text query. Uses hybrid BM25 + vector + reranking. Example: baker videos search 'product demo' --tags tutorial"
|
|
@@ -26760,9 +26864,9 @@ var searchCommand3 = defineCommand158({
|
|
|
26760
26864
|
var tagsCommand5 = makeTagsCommand("videos", "video", "/api/videos/tags");
|
|
26761
26865
|
|
|
26762
26866
|
// src/commands/videos/upload.ts
|
|
26763
|
-
import { readFile as
|
|
26867
|
+
import { readFile as readFile18, stat as stat5 } from "fs/promises";
|
|
26764
26868
|
import { extname as extname3 } from "path";
|
|
26765
|
-
import { defineCommand as
|
|
26869
|
+
import { defineCommand as defineCommand160 } from "citty";
|
|
26766
26870
|
var MIME_MAP = {
|
|
26767
26871
|
".mp4": "video/mp4",
|
|
26768
26872
|
".mov": "video/quicktime",
|
|
@@ -26796,7 +26900,7 @@ function detectContentType(filePath) {
|
|
|
26796
26900
|
}
|
|
26797
26901
|
return mime;
|
|
26798
26902
|
}
|
|
26799
|
-
var uploadCommand2 =
|
|
26903
|
+
var uploadCommand2 = defineCommand160({
|
|
26800
26904
|
meta: {
|
|
26801
26905
|
name: "upload",
|
|
26802
26906
|
description: "Upload a video file to Baker via Mux direct upload. Auto-detects content type. Example: baker videos upload ./demo.mp4"
|
|
@@ -26815,7 +26919,7 @@ var uploadCommand2 = defineCommand159({
|
|
|
26815
26919
|
}
|
|
26816
26920
|
const contentType = args["content-type"] || detectContentType(filePath);
|
|
26817
26921
|
if (args["dry-run"]) {
|
|
26818
|
-
const fileStats = await
|
|
26922
|
+
const fileStats = await stat5(filePath);
|
|
26819
26923
|
writeJson({
|
|
26820
26924
|
ok: true,
|
|
26821
26925
|
dryRun: true,
|
|
@@ -26825,7 +26929,7 @@ var uploadCommand2 = defineCommand159({
|
|
|
26825
26929
|
return;
|
|
26826
26930
|
}
|
|
26827
26931
|
const { uploadUrl, videoId } = await apiPost("/api/videos/upload", {});
|
|
26828
|
-
const fileBuffer = await
|
|
26932
|
+
const fileBuffer = await readFile18(filePath);
|
|
26829
26933
|
const uploadResponse = await fetch(uploadUrl, {
|
|
26830
26934
|
method: "PUT",
|
|
26831
26935
|
headers: { "Content-Type": contentType },
|
|
@@ -26850,7 +26954,7 @@ var uploadCommand2 = defineCommand159({
|
|
|
26850
26954
|
});
|
|
26851
26955
|
|
|
26852
26956
|
// src/commands/videos/index.ts
|
|
26853
|
-
var videosCommand =
|
|
26957
|
+
var videosCommand = defineCommand161({
|
|
26854
26958
|
meta: {
|
|
26855
26959
|
name: "videos",
|
|
26856
26960
|
description: `Find and manage videos in Baker. Subcommands: search, get, upload, delete, tags.
|
|
@@ -26873,10 +26977,10 @@ Examples:
|
|
|
26873
26977
|
});
|
|
26874
26978
|
|
|
26875
26979
|
// src/commands/winning-ads/index.ts
|
|
26876
|
-
import { defineCommand as
|
|
26980
|
+
import { defineCommand as defineCommand165 } from "citty";
|
|
26877
26981
|
|
|
26878
26982
|
// src/commands/winning-ads/advertisers.ts
|
|
26879
|
-
import { defineCommand as
|
|
26983
|
+
import { defineCommand as defineCommand162 } from "citty";
|
|
26880
26984
|
registerSchema({
|
|
26881
26985
|
command: "winning-ads.advertisers",
|
|
26882
26986
|
description: "Resolve a brand name to advertiser_id(s) in the ad-dna corpus \u2014 to find your OWN advertiser (to --exclude-advertiser) or a competitor (to --advertiser-id).",
|
|
@@ -26889,7 +26993,7 @@ registerSchema({
|
|
|
26889
26993
|
function identity(record) {
|
|
26890
26994
|
return record;
|
|
26891
26995
|
}
|
|
26892
|
-
var advertisersCommand2 =
|
|
26996
|
+
var advertisersCommand2 = defineCommand162({
|
|
26893
26997
|
meta: {
|
|
26894
26998
|
name: "advertisers",
|
|
26895
26999
|
description: 'Resolve a brand name to advertiser_id(s). Use it to find your own advertiser for --exclude-advertiser, or a competitor for --advertiser-id. Example: baker winning-ads advertisers "Deel" --output md'
|
|
@@ -26940,7 +27044,7 @@ var advertisersCommand2 = defineCommand161({
|
|
|
26940
27044
|
});
|
|
26941
27045
|
|
|
26942
27046
|
// src/commands/winning-ads/patterns.ts
|
|
26943
|
-
import { defineCommand as
|
|
27047
|
+
import { defineCommand as defineCommand163 } from "citty";
|
|
26944
27048
|
function leanRow(r) {
|
|
26945
27049
|
return {
|
|
26946
27050
|
key: r.key,
|
|
@@ -26960,7 +27064,7 @@ function makePatternsCommand(opts) {
|
|
|
26960
27064
|
limit: { type: "number", description: "Max keys 1-100 (default 20)", required: false, default: 20 }
|
|
26961
27065
|
}
|
|
26962
27066
|
});
|
|
26963
|
-
return
|
|
27067
|
+
return defineCommand163({
|
|
26964
27068
|
meta: { name: opts.name, description: opts.description },
|
|
26965
27069
|
args: {
|
|
26966
27070
|
platform: { type: "string", description: "Single platform to segment on", required: false },
|
|
@@ -27015,7 +27119,7 @@ var patternsCommand = makePatternsCommand({
|
|
|
27015
27119
|
});
|
|
27016
27120
|
|
|
27017
27121
|
// src/commands/winning-ads/search.ts
|
|
27018
|
-
import { defineCommand as
|
|
27122
|
+
import { defineCommand as defineCommand164 } from "citty";
|
|
27019
27123
|
registerSchema({
|
|
27020
27124
|
command: "winning-ads.search",
|
|
27021
27125
|
description: "Search the ad-dna corpus of scored winning ads. Returns a lean shortlist (advertiser, summary, scores, media_url) to pick a reference to reproduce.",
|
|
@@ -27129,7 +27233,7 @@ function buildSearchBody(args) {
|
|
|
27129
27233
|
}
|
|
27130
27234
|
return body;
|
|
27131
27235
|
}
|
|
27132
|
-
var searchCommand4 =
|
|
27236
|
+
var searchCommand4 = defineCommand164({
|
|
27133
27237
|
meta: {
|
|
27134
27238
|
name: "search",
|
|
27135
27239
|
description: "Search winning reference ads. Example: baker winning-ads search 'B2B SaaS before/after AI automation' --platform meta --format static --winner-category winner --exclude-advertiser adv_123 --output md"
|
|
@@ -27247,7 +27351,7 @@ var searchCommand4 = defineCommand163({
|
|
|
27247
27351
|
});
|
|
27248
27352
|
|
|
27249
27353
|
// src/commands/winning-ads/index.ts
|
|
27250
|
-
var winningAdsCommand =
|
|
27354
|
+
var winningAdsCommand = defineCommand165({
|
|
27251
27355
|
meta: {
|
|
27252
27356
|
name: "winning-ads",
|
|
27253
27357
|
description: `Search the ad-dna corpus of scored "winning" ads for reference creatives to reproduce. Proxied through the Baker backend (BAKER_API_KEY) \u2014 no separate token needed.
|
|
@@ -27294,7 +27398,7 @@ function getCliVersion() {
|
|
|
27294
27398
|
}
|
|
27295
27399
|
|
|
27296
27400
|
// src/cli.ts
|
|
27297
|
-
var main =
|
|
27401
|
+
var main = defineCommand166({
|
|
27298
27402
|
meta: {
|
|
27299
27403
|
name: "baker",
|
|
27300
27404
|
version: getCliVersion(),
|