@koda-sl/baker-cli 0.98.0-dev.62be5b016 → 0.99.0-dev.40c99be71
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 +12 -0
- package/canvas/tiktok-captions-composition/index.html +7 -2
- package/canvas/video-overlay-composition/index.html +18 -25
- package/dist/{chunk-IKMDQQ4M.js → chunk-FOK2JPRW.js} +130 -24
- package/dist/chunk-FOK2JPRW.js.map +1 -0
- package/dist/cli.js +529 -206
- package/dist/cli.js.map +1 -1
- package/dist/engine/index.d.ts +7 -0
- package/dist/engine/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-IKMDQQ4M.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -11,10 +11,10 @@ import {
|
|
|
11
11
|
extForMime,
|
|
12
12
|
generateCatalog,
|
|
13
13
|
validateCanvasDeep
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-FOK2JPRW.js";
|
|
15
15
|
|
|
16
16
|
// src/cli.ts
|
|
17
|
-
import { defineCommand as
|
|
17
|
+
import { defineCommand as defineCommand150, runMain } from "citty";
|
|
18
18
|
|
|
19
19
|
// src/commands/actions/index.ts
|
|
20
20
|
import { defineCommand as defineCommand17 } from "citty";
|
|
@@ -45,6 +45,9 @@ function getEnv() {
|
|
|
45
45
|
}
|
|
46
46
|
return cached;
|
|
47
47
|
}
|
|
48
|
+
function runtimeEnvVar(name) {
|
|
49
|
+
return process.env[name];
|
|
50
|
+
}
|
|
48
51
|
function requireChatId() {
|
|
49
52
|
const env = getEnv();
|
|
50
53
|
if (!env.BAKER_CHAT_ID) {
|
|
@@ -149,9 +152,9 @@ async function handleResponse(response) {
|
|
|
149
152
|
throw new ApiError("INTERNAL_ERROR", "Failed to parse API response as JSON");
|
|
150
153
|
}
|
|
151
154
|
}
|
|
152
|
-
async function apiGet(
|
|
155
|
+
async function apiGet(path12, params) {
|
|
153
156
|
const env = getEnv();
|
|
154
|
-
const url = new URL(
|
|
157
|
+
const url = new URL(path12, env.BAKER_API_URL);
|
|
155
158
|
if (params) {
|
|
156
159
|
const clean = sanitizeParams(params);
|
|
157
160
|
for (const [key, value] of Object.entries(clean)) {
|
|
@@ -176,12 +179,12 @@ async function apiGet(path8, params) {
|
|
|
176
179
|
}
|
|
177
180
|
return handleResponse(response);
|
|
178
181
|
}
|
|
179
|
-
async function apiPost(
|
|
182
|
+
async function apiPost(path12, body, opts) {
|
|
180
183
|
const env = getEnv();
|
|
181
184
|
const timeoutMs = opts?.timeoutMs ?? 6e4;
|
|
182
185
|
let response;
|
|
183
186
|
try {
|
|
184
|
-
response = await fetchWithRateLimitRetry(new URL(
|
|
187
|
+
response = await fetchWithRateLimitRetry(new URL(path12, env.BAKER_API_URL).toString(), {
|
|
185
188
|
method: "POST",
|
|
186
189
|
headers: {
|
|
187
190
|
Authorization: `Bearer ${env.BAKER_API_KEY}`,
|
|
@@ -1329,31 +1332,31 @@ function cachePath(category, key) {
|
|
|
1329
1332
|
return join(dir, `${hashKey(key)}.json`);
|
|
1330
1333
|
}
|
|
1331
1334
|
function cacheGet(category, key) {
|
|
1332
|
-
const
|
|
1333
|
-
if (!existsSync(
|
|
1335
|
+
const path12 = cachePath(category, key);
|
|
1336
|
+
if (!existsSync(path12)) {
|
|
1334
1337
|
return null;
|
|
1335
1338
|
}
|
|
1336
1339
|
try {
|
|
1337
|
-
const raw = readFileSync(
|
|
1340
|
+
const raw = readFileSync(path12, "utf-8");
|
|
1338
1341
|
const entry = JSON.parse(raw);
|
|
1339
1342
|
if (entry.expiresAt < Date.now()) {
|
|
1340
|
-
rmSync(
|
|
1343
|
+
rmSync(path12, { force: true });
|
|
1341
1344
|
return null;
|
|
1342
1345
|
}
|
|
1343
1346
|
return entry;
|
|
1344
1347
|
} catch {
|
|
1345
|
-
rmSync(
|
|
1348
|
+
rmSync(path12, { force: true });
|
|
1346
1349
|
return null;
|
|
1347
1350
|
}
|
|
1348
1351
|
}
|
|
1349
1352
|
function cacheSet(category, key, data, ttlMs, fields) {
|
|
1350
|
-
const
|
|
1353
|
+
const path12 = cachePath(category, key);
|
|
1351
1354
|
const entry = {
|
|
1352
1355
|
expiresAt: Date.now() + ttlMs,
|
|
1353
1356
|
data,
|
|
1354
1357
|
fields
|
|
1355
1358
|
};
|
|
1356
|
-
writeFileSync(
|
|
1359
|
+
writeFileSync(path12, JSON.stringify(entry), "utf-8");
|
|
1357
1360
|
}
|
|
1358
1361
|
var HOUR = 60 * 60 * 1e3;
|
|
1359
1362
|
var MINUTE = 60 * 1e3;
|
|
@@ -8047,7 +8050,7 @@ Examples:
|
|
|
8047
8050
|
});
|
|
8048
8051
|
|
|
8049
8052
|
// src/commands/canvas/index.ts
|
|
8050
|
-
import { defineCommand as
|
|
8053
|
+
import { defineCommand as defineCommand86 } from "citty";
|
|
8051
8054
|
|
|
8052
8055
|
// src/commands/canvas/catalog.ts
|
|
8053
8056
|
import { defineCommand as defineCommand78 } from "citty";
|
|
@@ -8255,9 +8258,8 @@ var galleryCommand = defineCommand79({
|
|
|
8255
8258
|
const slug = path.basename(creativeDir);
|
|
8256
8259
|
const workspaceDir = path.resolve(String(args["workspace-dir"] ?? ".creatives-workspace"));
|
|
8257
8260
|
const runsDir = path.join(workspaceDir, slug, "runs");
|
|
8258
|
-
const
|
|
8259
|
-
const
|
|
8260
|
-
const companyId = String(args["company-id"] ?? runtimeEnv.BAKER_COMPANY_ID ?? "");
|
|
8261
|
+
const publicUrl = (args["public-url"] ?? runtimeEnvVar("R2_PUBLIC_URL") ?? "").replace(/\/+$/, "");
|
|
8262
|
+
const companyId = String(args["company-id"] ?? runtimeEnvVar("BAKER_COMPANY_ID") ?? "");
|
|
8261
8263
|
const definitionPath = path.join(creativeDir, "_definition.md");
|
|
8262
8264
|
let definitionMd = "";
|
|
8263
8265
|
try {
|
|
@@ -8396,7 +8398,7 @@ async function probeDuration(filePath) {
|
|
|
8396
8398
|
|
|
8397
8399
|
// src/commands/canvas/run.ts
|
|
8398
8400
|
import { readFile as readFile3 } from "fs/promises";
|
|
8399
|
-
import
|
|
8401
|
+
import path5 from "path";
|
|
8400
8402
|
import { defineCommand as defineCommand81 } from "citty";
|
|
8401
8403
|
|
|
8402
8404
|
// src/commands/canvas/placeholders.ts
|
|
@@ -8415,6 +8417,57 @@ function unsuppliedPlaceholderAssets(canvas) {
|
|
|
8415
8417
|
return out;
|
|
8416
8418
|
}
|
|
8417
8419
|
|
|
8420
|
+
// src/commands/canvas/resolve-paths.ts
|
|
8421
|
+
import path3 from "path";
|
|
8422
|
+
function resolveRelativeCanvasPaths(canvas, baseDir) {
|
|
8423
|
+
if (!canvas || typeof canvas !== "object") return canvas;
|
|
8424
|
+
const c = canvas;
|
|
8425
|
+
if (!Array.isArray(c.nodes)) return canvas;
|
|
8426
|
+
return { ...canvas, nodes: c.nodes.map((n) => resolveNode(n, baseDir)) };
|
|
8427
|
+
}
|
|
8428
|
+
function resolveNode(node, baseDir) {
|
|
8429
|
+
if (!node || typeof node !== "object") return node;
|
|
8430
|
+
const n = node;
|
|
8431
|
+
const params = n.params;
|
|
8432
|
+
if (!params || typeof params !== "object") return node;
|
|
8433
|
+
if (n.type === "ingest" && params.source === "path" && isResolvableRelative(params.path)) {
|
|
8434
|
+
return { ...node, params: { ...params, path: path3.resolve(baseDir, params.path) } };
|
|
8435
|
+
}
|
|
8436
|
+
if (n.type === "hyperframe_render" && isResolvableRelative(params.composition)) {
|
|
8437
|
+
return { ...node, params: { ...params, composition: path3.resolve(baseDir, params.composition) } };
|
|
8438
|
+
}
|
|
8439
|
+
return node;
|
|
8440
|
+
}
|
|
8441
|
+
function isResolvableRelative(value) {
|
|
8442
|
+
return typeof value === "string" && value.length > 0 && !value.includes("[TODO") && !path3.isAbsolute(value);
|
|
8443
|
+
}
|
|
8444
|
+
|
|
8445
|
+
// src/commands/canvas/run-retention.ts
|
|
8446
|
+
import { rm } from "fs/promises";
|
|
8447
|
+
import path4 from "path";
|
|
8448
|
+
function runDirsToPrune(entries, keep, currentRunId) {
|
|
8449
|
+
const runs = entries.filter((e) => /^r_[0-9A-Za-z]+$/.test(e) && e !== currentRunId).sort();
|
|
8450
|
+
if (keep <= 0) return runs;
|
|
8451
|
+
return runs.slice(0, Math.max(0, runs.length - keep));
|
|
8452
|
+
}
|
|
8453
|
+
async function pruneOldRuns(outputsDir, keep, currentRunId, log) {
|
|
8454
|
+
const { readdir: readdir4 } = await import("fs/promises");
|
|
8455
|
+
let entries;
|
|
8456
|
+
try {
|
|
8457
|
+
entries = await readdir4(outputsDir);
|
|
8458
|
+
} catch {
|
|
8459
|
+
return;
|
|
8460
|
+
}
|
|
8461
|
+
const toPrune = runDirsToPrune(entries, keep, currentRunId);
|
|
8462
|
+
if (toPrune.length === 0) return;
|
|
8463
|
+
for (const dir of toPrune) {
|
|
8464
|
+
await rm(path4.join(outputsDir, dir), { recursive: true, force: true }).catch(
|
|
8465
|
+
(e) => log(`[prune ] could not remove ${dir}: ${e.message}`)
|
|
8466
|
+
);
|
|
8467
|
+
}
|
|
8468
|
+
log(`[prune ] removed ${toPrune.length} old run dir(s), kept the ${keep} newest`);
|
|
8469
|
+
}
|
|
8470
|
+
|
|
8418
8471
|
// src/commands/canvas/run.ts
|
|
8419
8472
|
var runCommand = defineCommand81({
|
|
8420
8473
|
meta: { name: "run", description: "Validate and execute a canvas JSON file." },
|
|
@@ -8423,10 +8476,14 @@ var runCommand = defineCommand81({
|
|
|
8423
8476
|
"cache-dir": { type: "string", description: "Cache root (default ./canvas/.cache)" },
|
|
8424
8477
|
"outputs-dir": { type: "string", description: "Per-run outputs root (default ./canvas)" },
|
|
8425
8478
|
"run-id": { type: "string", description: "Override run id" },
|
|
8426
|
-
"cache-policy": { type: "string", description: "read_write | bypass | read_only" }
|
|
8479
|
+
"cache-policy": { type: "string", description: "read_write | bypass | read_only" },
|
|
8480
|
+
"keep-runs": {
|
|
8481
|
+
type: "string",
|
|
8482
|
+
description: "After the run, prune old r_* run dirs, keeping the N newest (off by default)"
|
|
8483
|
+
}
|
|
8427
8484
|
},
|
|
8428
8485
|
async run({ args }) {
|
|
8429
|
-
const filePath =
|
|
8486
|
+
const filePath = path5.resolve(String(args.file));
|
|
8430
8487
|
const raw = await readFile3(filePath, "utf8");
|
|
8431
8488
|
let parsed;
|
|
8432
8489
|
try {
|
|
@@ -8437,6 +8494,7 @@ var runCommand = defineCommand81({
|
|
|
8437
8494
|
`);
|
|
8438
8495
|
process.exit(2);
|
|
8439
8496
|
}
|
|
8497
|
+
parsed = resolveRelativeCanvasPaths(parsed, path5.dirname(filePath));
|
|
8440
8498
|
const pending = unsuppliedPlaceholderAssets(parsed);
|
|
8441
8499
|
if (pending.length > 0) {
|
|
8442
8500
|
process.stderr.write(
|
|
@@ -8468,6 +8526,12 @@ var runCommand = defineCommand81({
|
|
|
8468
8526
|
run_id: args["run-id"] ? String(args["run-id"]) : void 0,
|
|
8469
8527
|
cache_policy: policy
|
|
8470
8528
|
});
|
|
8529
|
+
const keepRuns = args["keep-runs"] !== void 0 ? Number(args["keep-runs"]) : void 0;
|
|
8530
|
+
if (keepRuns !== void 0 && Number.isFinite(keepRuns)) {
|
|
8531
|
+
const outputsDir = args["outputs-dir"] ? path5.resolve(String(args["outputs-dir"])) : path5.resolve("canvas");
|
|
8532
|
+
await pruneOldRuns(outputsDir, keepRuns, result.run_id, (line) => process.stdout.write(`${line}
|
|
8533
|
+
`));
|
|
8534
|
+
}
|
|
8471
8535
|
process.stdout.write(
|
|
8472
8536
|
`${JSON.stringify(
|
|
8473
8537
|
{
|
|
@@ -8500,7 +8564,7 @@ var runCommand = defineCommand81({
|
|
|
8500
8564
|
|
|
8501
8565
|
// src/commands/canvas/scaffold-static-ad.ts
|
|
8502
8566
|
import { readFile as readFile4, writeFile } from "fs/promises";
|
|
8503
|
-
import
|
|
8567
|
+
import path6 from "path";
|
|
8504
8568
|
import { defineCommand as defineCommand82 } from "citty";
|
|
8505
8569
|
|
|
8506
8570
|
// src/engine/scaffold/staticAd.ts
|
|
@@ -8837,10 +8901,10 @@ var scaffoldStaticAdCommand = defineCommand82({
|
|
|
8837
8901
|
"skip-font": { type: "boolean", description: "Skip the brand-font \u2192 type-specimen slot" }
|
|
8838
8902
|
},
|
|
8839
8903
|
async run({ args }) {
|
|
8840
|
-
const imagePath =
|
|
8841
|
-
const outPath = args.out ?
|
|
8842
|
-
const outDir =
|
|
8843
|
-
const blueprintPath =
|
|
8904
|
+
const imagePath = path6.resolve(String(args.file));
|
|
8905
|
+
const outPath = args.out ? path6.resolve(String(args.out)) : path6.join(path6.dirname(imagePath), "static-ad.canvas.json");
|
|
8906
|
+
const outDir = path6.dirname(outPath);
|
|
8907
|
+
const blueprintPath = path6.join(outDir, "prompt.json");
|
|
8844
8908
|
const { describeModel, selectModel, layoutModel, genModel } = resolveModels(args);
|
|
8845
8909
|
const describeCanvas = buildDescribeCanvas(
|
|
8846
8910
|
imagePath,
|
|
@@ -8897,7 +8961,7 @@ var scaffoldStaticAdCommand = defineCommand82({
|
|
|
8897
8961
|
run_estimated_credits: validation.estimatedCredits
|
|
8898
8962
|
},
|
|
8899
8963
|
checklist: {
|
|
8900
|
-
edit_prompt: `Edit ${
|
|
8964
|
+
edit_prompt: `Edit ${path6.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.`,
|
|
8901
8965
|
assets_to_supply: report.elements,
|
|
8902
8966
|
font_slot: report.includes_font ? "Drop a brand font at the [TODO] brandfont path, or delete the brandfont + type_ref nodes to skip it." : "skipped (--skip-font)",
|
|
8903
8967
|
note: "Replace every [TODO] ingest path with a real file, then `baker canvas validate` and `baker canvas run`. Running generates a billed image \u2014 it is not free."
|
|
@@ -8912,13 +8976,13 @@ var scaffoldStaticAdCommand = defineCommand82({
|
|
|
8912
8976
|
});
|
|
8913
8977
|
|
|
8914
8978
|
// src/commands/canvas/scaffold-video.ts
|
|
8915
|
-
import { cp, mkdir, readFile as
|
|
8916
|
-
import
|
|
8979
|
+
import { cp, mkdir, readFile as readFile7, writeFile as writeFile2 } from "fs/promises";
|
|
8980
|
+
import path9 from "path";
|
|
8917
8981
|
import { defineCommand as defineCommand83 } from "citty";
|
|
8918
8982
|
|
|
8919
8983
|
// src/engine/nodes/local/lib/sceneDetect.ts
|
|
8920
8984
|
import { execFile as execFile2 } from "child_process";
|
|
8921
|
-
import { mkdtemp, readdir as readdir3, readFile as readFile5, rm } from "fs/promises";
|
|
8985
|
+
import { mkdtemp, readdir as readdir3, readFile as readFile5, rm as rm2 } from "fs/promises";
|
|
8922
8986
|
import { tmpdir } from "os";
|
|
8923
8987
|
import { join as join2 } from "path";
|
|
8924
8988
|
import { promisify as promisify2 } from "util";
|
|
@@ -8986,7 +9050,7 @@ async function runSceneDetectOnce(filePath, threshold, minSceneLenS, timeoutMs)
|
|
|
8986
9050
|
if (!csvName) return [];
|
|
8987
9051
|
return parsePySceneDetectCsvCuts(await readFile5(join2(outDir, csvName), "utf-8"));
|
|
8988
9052
|
} finally {
|
|
8989
|
-
await
|
|
9053
|
+
await rm2(outDir, { recursive: true, force: true });
|
|
8990
9054
|
}
|
|
8991
9055
|
}
|
|
8992
9056
|
async function detectSceneCutsPySceneDetect(filePath, opts = {}) {
|
|
@@ -9242,6 +9306,13 @@ function stillHoldArgs(durationS, dims) {
|
|
|
9242
9306
|
`scale=${dims.w}:${dims.h}:force_original_aspect_ratio=increase,crop=${dims.w}:${dims.h},setsar=1,format=yuv420p`,
|
|
9243
9307
|
"-c:v",
|
|
9244
9308
|
"libx264",
|
|
9309
|
+
// Near-visually-lossless re-encode. libx264 DEFAULTS (crf 23, preset medium)
|
|
9310
|
+
// roughly halve the source bitrate and add banding on smooth surfaces; the
|
|
9311
|
+
// spine concats these by stream-copy, so any loss here ships to the final cut.
|
|
9312
|
+
"-crf",
|
|
9313
|
+
"18",
|
|
9314
|
+
"-preset",
|
|
9315
|
+
"slow",
|
|
9245
9316
|
"-pix_fmt",
|
|
9246
9317
|
"yuv420p",
|
|
9247
9318
|
"{{out.video}}"
|
|
@@ -9257,6 +9328,13 @@ function trimArgs(durationS, offsetS = 0) {
|
|
|
9257
9328
|
"-an",
|
|
9258
9329
|
"-c:v",
|
|
9259
9330
|
"libx264",
|
|
9331
|
+
// Preserve the seedance source quality through the trim. libx264 DEFAULTS
|
|
9332
|
+
// (crf 23) halve the bitrate (measured 9.57→4.40 Mbps) and band on motion;
|
|
9333
|
+
// the spine stream-copies the result, so the loss is permanent without this.
|
|
9334
|
+
"-crf",
|
|
9335
|
+
"18",
|
|
9336
|
+
"-preset",
|
|
9337
|
+
"slow",
|
|
9260
9338
|
"-pix_fmt",
|
|
9261
9339
|
"yuv420p",
|
|
9262
9340
|
"{{out.video}}"
|
|
@@ -9323,6 +9401,13 @@ var Scene = z3.object({
|
|
|
9323
9401
|
// The scene's role in the ad's persuasion arc (DECON-supplied); drives the
|
|
9324
9402
|
// script re-craft checklist. Inferred from position when absent.
|
|
9325
9403
|
narrative_role: z3.string().optional(),
|
|
9404
|
+
// DECON-supplied on the HOOK scene: the engineered physical/emotional state that
|
|
9405
|
+
// makes the first frame stop the scroll (sweaty/breathless/urgent …). Injected
|
|
9406
|
+
// into the hook's start-frame description so the generator renders that state,
|
|
9407
|
+
// not a calm influencer (CCA-11).
|
|
9408
|
+
hook_mechanic: z3.object({ mechanic: z3.string().optional(), why_it_stops_scroll: z3.string().optional() }).loose().optional(),
|
|
9409
|
+
// DECON-supplied per-scene location (so a gym hook isn't flattened to "home").
|
|
9410
|
+
scene_setting: z3.string().optional(),
|
|
9326
9411
|
// How this scene cuts to the next (DECON-supplied). A recognized non-cut type
|
|
9327
9412
|
// (fade/whip/zoom/dissolve/swipe) is reproduced as an ffmpeg xfade at the
|
|
9328
9413
|
// boundary; cut/match_cut/none/other stay hard cuts. The last scene's value is
|
|
@@ -9370,10 +9455,21 @@ var VideoBlueprint = z3.object({
|
|
|
9370
9455
|
mode: z3.string().optional(),
|
|
9371
9456
|
voice_description: z3.string().optional(),
|
|
9372
9457
|
persona: z3.string().optional()
|
|
9373
|
-
}).loose().optional()
|
|
9458
|
+
}).loose().optional(),
|
|
9459
|
+
// Visual palette — read only to colour a clean brand-card/CTA plate (the
|
|
9460
|
+
// first hex is the dominant brand colour); never to drive frame generation.
|
|
9461
|
+
style: z3.object({ palette: z3.array(z3.object({ hex: z3.string().optional() }).loose()).optional() }).loose().optional()
|
|
9374
9462
|
}).loose().optional(),
|
|
9375
9463
|
scenes: z3.array(Scene).min(1)
|
|
9376
9464
|
}).loose();
|
|
9465
|
+
function injectHookPhysicality(blueprint) {
|
|
9466
|
+
for (const scene of blueprint.scenes) {
|
|
9467
|
+
const why = scene.hook_mechanic?.why_it_stops_scroll?.trim();
|
|
9468
|
+
const prompt = scene.start_frame_prompt?.trim();
|
|
9469
|
+
if (!why || !prompt || prompt.includes(why)) continue;
|
|
9470
|
+
scene.start_frame_prompt = `${prompt} The subject's physical state IS the scroll-stopper \u2014 render it explicitly, not a calm pose: ${why}.`;
|
|
9471
|
+
}
|
|
9472
|
+
}
|
|
9377
9473
|
var AppearsItem = z3.union([z3.number(), z3.object({ scene: z3.number(), edge: z3.string().optional() }).loose()]);
|
|
9378
9474
|
var RecurringElement = z3.object({
|
|
9379
9475
|
// person | animal | product | logo | badge | other
|
|
@@ -9399,7 +9495,8 @@ function sanitizeId2(raw, fallback) {
|
|
|
9399
9495
|
return /^[a-z]/.test(id) ? id : `${fallback}_${id}`.replace(/_+$/g, "") || fallback;
|
|
9400
9496
|
}
|
|
9401
9497
|
function labelFor2(el, used) {
|
|
9402
|
-
const
|
|
9498
|
+
const raw = el.type?.toLowerCase() === "logo" ? "BRAND_LOGO" : el.label ?? el.type ?? "ELEMENT";
|
|
9499
|
+
const base = raw.toUpperCase().replace(/[^A-Z0-9]+/g, "_").replace(/^_+|_+$/g, "") || "ELEMENT";
|
|
9403
9500
|
let label = base;
|
|
9404
9501
|
let n = 2;
|
|
9405
9502
|
while (used.has(label)) label = `${base}_${n++}`;
|
|
@@ -9566,6 +9663,8 @@ function buildElementSheets(slots, nodes) {
|
|
|
9566
9663
|
if (slot.sameAs) continue;
|
|
9567
9664
|
if (slot.presence.size < 1) continue;
|
|
9568
9665
|
const sheetId = `${slot.id}_sheet`;
|
|
9666
|
+
const slotType = slot.type.toLowerCase();
|
|
9667
|
+
const isCast = slotType === "person" || slotType === "animal";
|
|
9569
9668
|
nodes.push({
|
|
9570
9669
|
id: sheetId,
|
|
9571
9670
|
type: "image_reference_sheet",
|
|
@@ -9578,7 +9677,14 @@ function buildElementSheets(slots, nodes) {
|
|
|
9578
9677
|
// 4K: the sheet packs up to 8 cells (angles + tight face/detail close-ups), and
|
|
9579
9678
|
// it's the ONE reference every frame grounds on — per-cell sharpness here
|
|
9580
9679
|
// propagates to every clip, so it's worth the highest tier on this single asset.
|
|
9581
|
-
image_size: "4K"
|
|
9680
|
+
image_size: "4K",
|
|
9681
|
+
// The sheet is the look that propagates to EVERY grounded frame, so a glossy
|
|
9682
|
+
// studio turnaround makes the whole UGC ad read as "produced" (the #1 AI tell).
|
|
9683
|
+
// Force a flat, real, front-camera look on the cast sheet so the actor stays
|
|
9684
|
+
// authentic, not an airbrushed influencer (CCA-02).
|
|
9685
|
+
...isCast ? {
|
|
9686
|
+
style: "authentic UGC look: flat, even, natural front-camera lighting \u2014 no studio key/rim light, no seamless backdrop, no shallow depth of field; real skin texture and pores, no airbrushing or beauty retouch; true-to-life everyday styling"
|
|
9687
|
+
} : {}
|
|
9582
9688
|
}
|
|
9583
9689
|
});
|
|
9584
9690
|
slot.ref = `$ref:${sheetId}.sheet`;
|
|
@@ -9686,8 +9792,7 @@ function buildFrameRef(edge, url, framePrompt, present, ctx, nodes) {
|
|
|
9686
9792
|
const t = s.type.toLowerCase();
|
|
9687
9793
|
return t === "person" || t === "animal";
|
|
9688
9794
|
});
|
|
9689
|
-
const
|
|
9690
|
-
const useOriginalAnchor = Boolean(url) && (castSlots.length === 0 || castIdentityLocked);
|
|
9795
|
+
const useOriginalAnchor = Boolean(url) && castSlots.length === 0;
|
|
9691
9796
|
const hasOriginal = useOriginalAnchor;
|
|
9692
9797
|
const originalRef = useOriginalAnchor && url ? ingestFrameRef(url, edge, ctx, nodes) : void 0;
|
|
9693
9798
|
const reference = [...present.map((s) => s.ref), ...originalRef ? [originalRef] : []];
|
|
@@ -9898,6 +10003,39 @@ function isUiOnlyComposite(regions) {
|
|
|
9898
10003
|
const ui = regions.filter(regionIsUiSurface).length;
|
|
9899
10004
|
return ui >= 1 && regions.length - ui <= 1;
|
|
9900
10005
|
}
|
|
10006
|
+
function sceneIsFullScreenUi(scene, present) {
|
|
10007
|
+
if (scene.narrative_role?.trim() === "cta") return false;
|
|
10008
|
+
const hasCast = present.some((s) => {
|
|
10009
|
+
const t = s.type.toLowerCase();
|
|
10010
|
+
return t === "person" || t === "animal";
|
|
10011
|
+
});
|
|
10012
|
+
if (hasCast) return false;
|
|
10013
|
+
const hay = `${scene.summary ?? ""} ${scene.start_frame_prompt ?? ""} ${scene.end_frame_prompt ?? ""} ${scene.action_detail ?? ""}`;
|
|
10014
|
+
return UI_SURFACE_RE.test(hay);
|
|
10015
|
+
}
|
|
10016
|
+
function screenStillArgs(durationS, dims) {
|
|
10017
|
+
return [
|
|
10018
|
+
"-loop",
|
|
10019
|
+
"1",
|
|
10020
|
+
"-i",
|
|
10021
|
+
"{{in.frame}}",
|
|
10022
|
+
"-t",
|
|
10023
|
+
durationS.toFixed(3),
|
|
10024
|
+
"-r",
|
|
10025
|
+
"30",
|
|
10026
|
+
"-vf",
|
|
10027
|
+
`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`,
|
|
10028
|
+
"-c:v",
|
|
10029
|
+
"libx264",
|
|
10030
|
+
"-crf",
|
|
10031
|
+
"18",
|
|
10032
|
+
"-preset",
|
|
10033
|
+
"slow",
|
|
10034
|
+
"-pix_fmt",
|
|
10035
|
+
"yuv420p",
|
|
10036
|
+
"{{out.video}}"
|
|
10037
|
+
];
|
|
10038
|
+
}
|
|
9901
10039
|
function layeredComposition(scene) {
|
|
9902
10040
|
const comp = scene.composition;
|
|
9903
10041
|
const layout = (comp?.layout ?? "").toLowerCase();
|
|
@@ -10068,6 +10206,77 @@ function emitFlashHold(i, scene, slots, ctx, lengths, out, ar, nodes, clips) {
|
|
|
10068
10206
|
});
|
|
10069
10207
|
clips.push({ ref: `$ref:s${i}_clip.video`, scene_s: lengths.dur, out });
|
|
10070
10208
|
}
|
|
10209
|
+
function emitScreenScene(i, scene, lengths, out, ar, nodes, clips) {
|
|
10210
|
+
const label = commentSafe((scene.summary || scene.start_frame_prompt || "the app screen").slice(0, 120));
|
|
10211
|
+
const refId = `s${i}_screen_ref`;
|
|
10212
|
+
nodes.push({
|
|
10213
|
+
id: refId,
|
|
10214
|
+
type: "ingest",
|
|
10215
|
+
params: {
|
|
10216
|
+
source: "path",
|
|
10217
|
+
path: `[TODO: supply the REAL screen for "${label}" \u2014 NEVER AI-generate a UI. Capture a clean, text-free screenshot with \`baker images screenshot https://<brand-domain>/<path>\` (image-library skill); spoken/overlay text rides the overlay layer, not the screenshot]`,
|
|
10218
|
+
expect: "image"
|
|
10219
|
+
}
|
|
10220
|
+
});
|
|
10221
|
+
nodes.push({
|
|
10222
|
+
id: `s${i}_clip`,
|
|
10223
|
+
type: "ffmpeg",
|
|
10224
|
+
inputs: { frame: `$ref:${refId}.asset` },
|
|
10225
|
+
params: {
|
|
10226
|
+
args: screenStillArgs(lengths.trimTarget, canvasDims(ar)),
|
|
10227
|
+
outputs: { video: { kind: "video", ext: "mp4" } }
|
|
10228
|
+
}
|
|
10229
|
+
});
|
|
10230
|
+
clips.push({ ref: `$ref:s${i}_clip.video`, scene_s: lengths.dur, out });
|
|
10231
|
+
}
|
|
10232
|
+
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;
|
|
10233
|
+
function sceneIsBrandCard(scene, present, isCta) {
|
|
10234
|
+
if (!isCta) return false;
|
|
10235
|
+
const hasCast = present.some((s) => {
|
|
10236
|
+
const t = s.type.toLowerCase();
|
|
10237
|
+
return t === "person" || t === "animal";
|
|
10238
|
+
});
|
|
10239
|
+
if (hasCast) return false;
|
|
10240
|
+
const hay = `${scene.summary ?? ""} ${scene.start_frame_prompt ?? ""} ${scene.end_frame_prompt ?? ""}`;
|
|
10241
|
+
return BRAND_CARD_RE.test(hay);
|
|
10242
|
+
}
|
|
10243
|
+
var HEX6_RE = /^#?[0-9a-fA-F]{6}$/;
|
|
10244
|
+
function brandPlateColor(blueprint) {
|
|
10245
|
+
const palette = blueprint.global?.style?.palette;
|
|
10246
|
+
const hex = palette?.map((p) => p?.hex).find((h) => typeof h === "string" && HEX6_RE.test(h));
|
|
10247
|
+
return hex ? `0x${hex.replace(/^#/, "").toUpperCase()}` : "0x000000";
|
|
10248
|
+
}
|
|
10249
|
+
function colorPlateArgs(durationS, dims, color) {
|
|
10250
|
+
return [
|
|
10251
|
+
"-f",
|
|
10252
|
+
"lavfi",
|
|
10253
|
+
"-i",
|
|
10254
|
+
`color=c=${color}:s=${dims.w}x${dims.h}:r=30`,
|
|
10255
|
+
"-t",
|
|
10256
|
+
durationS.toFixed(3),
|
|
10257
|
+
"-c:v",
|
|
10258
|
+
"libx264",
|
|
10259
|
+
"-crf",
|
|
10260
|
+
"18",
|
|
10261
|
+
"-preset",
|
|
10262
|
+
"slow",
|
|
10263
|
+
"-pix_fmt",
|
|
10264
|
+
"yuv420p",
|
|
10265
|
+
"{{out.video}}"
|
|
10266
|
+
];
|
|
10267
|
+
}
|
|
10268
|
+
function emitBrandCardScene(i, lengths, out, ar, color, nodes, clips) {
|
|
10269
|
+
nodes.push({
|
|
10270
|
+
id: `s${i}_clip`,
|
|
10271
|
+
type: "ffmpeg",
|
|
10272
|
+
inputs: {},
|
|
10273
|
+
params: {
|
|
10274
|
+
args: colorPlateArgs(lengths.trimTarget, canvasDims(ar), color),
|
|
10275
|
+
outputs: { video: { kind: "video", ext: "mp4" } }
|
|
10276
|
+
}
|
|
10277
|
+
});
|
|
10278
|
+
clips.push({ ref: `$ref:s${i}_clip.video`, scene_s: lengths.dur, out });
|
|
10279
|
+
}
|
|
10071
10280
|
function musicArcDigest(blueprint) {
|
|
10072
10281
|
const roles = blueprint.scenes.map((s) => s.narrative_role).filter((r) => Boolean(r));
|
|
10073
10282
|
const arc = roles.length > 0 ? roles.join(" \u2192 ") : "";
|
|
@@ -10187,7 +10396,7 @@ function makePresenterPresent(slots, canonical, opts = {}) {
|
|
|
10187
10396
|
const solePerson = !opts.strict && personSlots.length === 1 ? personSlots[0].presence : null;
|
|
10188
10397
|
return (speaker, sceneIndex) => {
|
|
10189
10398
|
const presence = bySpeaker.get(speaker) ?? solePerson;
|
|
10190
|
-
if (!presence) return opts.strict
|
|
10399
|
+
if (!presence) return !opts.strict;
|
|
10191
10400
|
return presence.has(sceneIndex);
|
|
10192
10401
|
};
|
|
10193
10402
|
}
|
|
@@ -10552,6 +10761,15 @@ function emitBrollScene(scene, i, isLast, env, nodes, out, prevEndFrame) {
|
|
|
10552
10761
|
shootMode: mode,
|
|
10553
10762
|
ingestCache: env.ingestCache
|
|
10554
10763
|
};
|
|
10764
|
+
if (!env.reuse && sceneIsFullScreenUi(scene, present)) {
|
|
10765
|
+
emitScreenScene(i, scene, lengths, lengths.out, env.ar, nodes, out.clips);
|
|
10766
|
+
return void 0;
|
|
10767
|
+
}
|
|
10768
|
+
const isCta = scene.narrative_role?.trim() === "cta" || isLast;
|
|
10769
|
+
if (!env.reuse && sceneIsBrandCard(scene, present, isCta)) {
|
|
10770
|
+
emitBrandCardScene(i, lengths, lengths.out, env.ar, brandPlateColor(env.blueprint), nodes, out.clips);
|
|
10771
|
+
return void 0;
|
|
10772
|
+
}
|
|
10555
10773
|
if (!ambientBroll && lengths.dur <= FLASH_HOLD_MAX_S) {
|
|
10556
10774
|
emitFlashHold(i, scene, env.slots, ctx, lengths, lengths.out, env.ar, nodes, out.clips);
|
|
10557
10775
|
return void 0;
|
|
@@ -10817,7 +11035,7 @@ function overlayElement(ov, at, dur) {
|
|
|
10817
11035
|
const normAnim = normalizeAnim(ov.animation);
|
|
10818
11036
|
const anim = normAnim ? ` data-anim="${normAnim}"` : "";
|
|
10819
11037
|
const detail = ov.animation_detail ? ` data-anim-detail="${escapeHtml(ov.animation_detail)}"` : "";
|
|
10820
|
-
return `<div class="ov ${positionClass(ov.position)}" data-start="${at}" data-dur="${dur}"${role}${anim}${detail}>${escapeHtml(ov.text.trim())}</div>`;
|
|
11038
|
+
return `<div class="ov clip ${positionClass(ov.position)}" data-start="${at}" data-dur="${dur}"${role}${anim}${detail}>${escapeHtml(ov.text.trim())}</div>`;
|
|
10821
11039
|
}
|
|
10822
11040
|
var RICH_OVERLAY_RE = /notif|tweet|\bx post\b|post\b|comment|message|chat|bubble|card|review|rating|stat|counter|toast|popup/;
|
|
10823
11041
|
function sourceHint(fe) {
|
|
@@ -10847,7 +11065,7 @@ function floatingStub(fe, sceneStart) {
|
|
|
10847
11065
|
const slug = (fe.kind ?? "element").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "element";
|
|
10848
11066
|
return [
|
|
10849
11067
|
`<!-- ${kind}: ${label} @ ${at}s for ${dur}s (${positionClass(fe.position)}). Source a real asset: ${hint} \u2014 drop it in this dir and uncomment:`,
|
|
10850
|
-
`<img class="ov ${positionClass(fe.position)}" src="your-${slug}.png" data-start="${at}" data-dur="${dur}" alt="" /> -->`
|
|
11068
|
+
`<img class="ov clip ${positionClass(fe.position)}" src="your-${slug}.png" data-start="${at}" data-dur="${dur}" alt="" /> -->`
|
|
10851
11069
|
].join("\n");
|
|
10852
11070
|
}
|
|
10853
11071
|
function uiPipStub(scene) {
|
|
@@ -10867,7 +11085,7 @@ function uiPipStub(scene) {
|
|
|
10867
11085
|
" \u2014 OR hand-build a brand-accurate HTML screen; then frame it in a phone mockup:",
|
|
10868
11086
|
" npx hyperframes add phone-scroll (writes compositions/phone-scroll.html)",
|
|
10869
11087
|
" drop the screenshot as screenshot.png in this dir and nest it as a PIP clip:",
|
|
10870
|
-
` <div data-composition-src="compositions/phone-scroll.html" data-start="${at}" data-duration="${dur}" data-track-index="2" data-width="1080" data-height="1920"></div> -->`
|
|
11088
|
+
` <div class="clip" data-composition-src="compositions/phone-scroll.html" data-start="${at}" data-duration="${dur}" data-track-index="2" data-width="1080" data-height="1920"></div> -->`
|
|
10871
11089
|
].join("\n");
|
|
10872
11090
|
}
|
|
10873
11091
|
function buildOverlayHtml(input) {
|
|
@@ -10963,6 +11181,7 @@ function buildSpine(clips, nodes) {
|
|
|
10963
11181
|
}
|
|
10964
11182
|
function scaffoldVideoCanvas(input, elementsInput, opts) {
|
|
10965
11183
|
const blueprint = VideoBlueprint.parse(input);
|
|
11184
|
+
injectHookPhysicality(blueprint);
|
|
10966
11185
|
const elements = RecurringElements.parse(elementsInput);
|
|
10967
11186
|
const nodes = [];
|
|
10968
11187
|
nodes.push({
|
|
@@ -11374,18 +11593,44 @@ function videoReport(input, elementsInput) {
|
|
|
11374
11593
|
|
|
11375
11594
|
// src/commands/canvas/composition-path.ts
|
|
11376
11595
|
import { existsSync as existsSync3 } from "fs";
|
|
11377
|
-
import
|
|
11596
|
+
import path7 from "path";
|
|
11378
11597
|
function resolveShippedCanvasDir(name, startDir, exists = existsSync3, maxDepth = 8) {
|
|
11379
|
-
const rel =
|
|
11598
|
+
const rel = path7.join("canvas", name);
|
|
11380
11599
|
let dir = startDir;
|
|
11381
11600
|
for (let i = 0; i < maxDepth; i++) {
|
|
11382
|
-
const candidate =
|
|
11383
|
-
if (exists(
|
|
11384
|
-
const parent =
|
|
11601
|
+
const candidate = path7.join(dir, rel);
|
|
11602
|
+
if (exists(path7.join(candidate, "meta.json"))) return candidate;
|
|
11603
|
+
const parent = path7.dirname(dir);
|
|
11385
11604
|
if (parent === dir) break;
|
|
11386
11605
|
dir = parent;
|
|
11387
11606
|
}
|
|
11388
|
-
return
|
|
11607
|
+
return path7.resolve(startDir, "../../../", rel);
|
|
11608
|
+
}
|
|
11609
|
+
|
|
11610
|
+
// src/commands/canvas/gitignore.ts
|
|
11611
|
+
import { appendFile, readFile as readFile6 } from "fs/promises";
|
|
11612
|
+
import path8 from "path";
|
|
11613
|
+
function missingGitignoreEntries(existing, entries) {
|
|
11614
|
+
const present = new Set(
|
|
11615
|
+
existing.split("\n").map((l) => l.trim().replace(/\/+$/, "")).filter((l) => l.length > 0 && !l.startsWith("#"))
|
|
11616
|
+
);
|
|
11617
|
+
return entries.filter((e) => !present.has(e.trim().replace(/\/+$/, "")));
|
|
11618
|
+
}
|
|
11619
|
+
async function ensureGitignore(dir, entries) {
|
|
11620
|
+
const file = path8.join(dir, ".gitignore");
|
|
11621
|
+
let existing;
|
|
11622
|
+
try {
|
|
11623
|
+
existing = await readFile6(file, "utf8");
|
|
11624
|
+
} catch {
|
|
11625
|
+
return;
|
|
11626
|
+
}
|
|
11627
|
+
const missing = missingGitignoreEntries(existing, entries);
|
|
11628
|
+
if (missing.length === 0) return;
|
|
11629
|
+
const prefix = existing.endsWith("\n") || existing.length === 0 ? "" : "\n";
|
|
11630
|
+
await appendFile(file, `${prefix}
|
|
11631
|
+
# Baker canvas (engine cache + scaffold working files)
|
|
11632
|
+
${missing.join("\n")}
|
|
11633
|
+
`);
|
|
11389
11634
|
}
|
|
11390
11635
|
|
|
11391
11636
|
// src/commands/canvas/scaffold-video.ts
|
|
@@ -11414,7 +11659,7 @@ ONE PERSON, MULTIPLE LOOKS: if a single individual plays MULTIPLE personas or wa
|
|
|
11414
11659
|
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.`;
|
|
11415
11660
|
async function loadAssetText2(ref, label) {
|
|
11416
11661
|
const r = ref;
|
|
11417
|
-
if (typeof r?.path === "string") return
|
|
11662
|
+
if (typeof r?.path === "string") return readFile7(r.path, "utf8");
|
|
11418
11663
|
if (typeof r?.url === "string") {
|
|
11419
11664
|
const res = await fetch(r.url);
|
|
11420
11665
|
if (!res.ok) throw new Error(`failed to fetch ${label} (${res.status})`);
|
|
@@ -11433,7 +11678,7 @@ async function loadTranscriptBestEffort(ref) {
|
|
|
11433
11678
|
async function stageCaptions(outDir, transcript) {
|
|
11434
11679
|
const text = transcript?.trim();
|
|
11435
11680
|
if (!text || text === "[]") return {};
|
|
11436
|
-
const compositionPath =
|
|
11681
|
+
const compositionPath = path9.join(outDir, "tiktok-captions-composition");
|
|
11437
11682
|
await cp(SHIPPED_CAPTIONS_DIR, compositionPath, { recursive: true });
|
|
11438
11683
|
return { compositionPath };
|
|
11439
11684
|
}
|
|
@@ -11595,11 +11840,11 @@ var scaffoldVideoCommand = defineCommand83({
|
|
|
11595
11840
|
}
|
|
11596
11841
|
},
|
|
11597
11842
|
async run({ args }) {
|
|
11598
|
-
const videoPath =
|
|
11599
|
-
const base =
|
|
11600
|
-
const outPath = args.out ?
|
|
11601
|
-
const outDir =
|
|
11602
|
-
const blueprintPath =
|
|
11843
|
+
const videoPath = path9.resolve(String(args.file));
|
|
11844
|
+
const base = path9.basename(videoPath, path9.extname(videoPath));
|
|
11845
|
+
const outPath = args.out ? path9.resolve(String(args.out)) : path9.join(path9.dirname(videoPath), `${base}.video.canvas.json`);
|
|
11846
|
+
const outDir = path9.dirname(outPath);
|
|
11847
|
+
const blueprintPath = path9.join(outDir, "prompt.json");
|
|
11603
11848
|
const frames = args.frames === "reuse" ? "reuse" : "generate";
|
|
11604
11849
|
const maxScenes = args["max-scenes"] ? Number(args["max-scenes"]) : void 0;
|
|
11605
11850
|
if (Number.isFinite(maxScenes)) {
|
|
@@ -11622,11 +11867,11 @@ var scaffoldVideoCommand = defineCommand83({
|
|
|
11622
11867
|
const annotated = annotateBlueprintWithElements(blueprint, elements);
|
|
11623
11868
|
await writeFile2(blueprintPath, `${JSON.stringify(annotated, null, 2)}
|
|
11624
11869
|
`, "utf8");
|
|
11625
|
-
const compositionDest =
|
|
11870
|
+
const compositionDest = path9.join(outDir, "video-overlay-composition");
|
|
11626
11871
|
await cp(SHIPPED_COMPOSITION_DIR, compositionDest, { recursive: true });
|
|
11627
|
-
const indexPath =
|
|
11872
|
+
const indexPath = path9.join(compositionDest, "index.html");
|
|
11628
11873
|
const overlayHtml = buildOverlayHtml(blueprint);
|
|
11629
|
-
const indexHtml = await
|
|
11874
|
+
const indexHtml = await readFile7(indexPath, "utf8");
|
|
11630
11875
|
const injected = indexHtml.replace("<!--OVERLAYS-->", () => overlayHtml);
|
|
11631
11876
|
if (injected === indexHtml && overlayHtml.trim()) {
|
|
11632
11877
|
fail2(
|
|
@@ -11639,9 +11884,9 @@ var scaffoldVideoCommand = defineCommand83({
|
|
|
11639
11884
|
const opts = {
|
|
11640
11885
|
imageModel,
|
|
11641
11886
|
videoModel,
|
|
11642
|
-
overlayCompositionPath: compositionDest,
|
|
11643
|
-
captionsCompositionPath: captions.compositionPath,
|
|
11644
|
-
blueprintPath,
|
|
11887
|
+
overlayCompositionPath: path9.relative(outDir, compositionDest),
|
|
11888
|
+
captionsCompositionPath: captions.compositionPath ? path9.relative(outDir, captions.compositionPath) : void 0,
|
|
11889
|
+
blueprintPath: path9.relative(outDir, blueprintPath),
|
|
11645
11890
|
frames,
|
|
11646
11891
|
ambient: Boolean(args.ambient),
|
|
11647
11892
|
...args.resolution ? { resolution: String(args.resolution) } : {}
|
|
@@ -11654,7 +11899,7 @@ var scaffoldVideoCommand = defineCommand83({
|
|
|
11654
11899
|
} catch (e) {
|
|
11655
11900
|
return fail2("scaffold", e instanceof Error ? e.message : String(e));
|
|
11656
11901
|
}
|
|
11657
|
-
const validation = await validateCanvasDeep(canvas, defaultRegistry());
|
|
11902
|
+
const validation = await validateCanvasDeep(resolveRelativeCanvasPaths(canvas, outDir), defaultRegistry());
|
|
11658
11903
|
if (!validation.ok) {
|
|
11659
11904
|
process.stderr.write(
|
|
11660
11905
|
`${JSON.stringify({ ok: false, error: { code: "validation", issues: validation.issues } }, null, 2)}
|
|
@@ -11664,6 +11909,7 @@ var scaffoldVideoCommand = defineCommand83({
|
|
|
11664
11909
|
}
|
|
11665
11910
|
await writeFile2(outPath, `${JSON.stringify(canvas, null, 2)}
|
|
11666
11911
|
`, "utf8");
|
|
11912
|
+
await ensureGitignore(process.cwd(), ["canvas/", ".context/"]);
|
|
11667
11913
|
process.stdout.write(
|
|
11668
11914
|
`${JSON.stringify(
|
|
11669
11915
|
{
|
|
@@ -11681,7 +11927,7 @@ var scaffoldVideoCommand = defineCommand83({
|
|
|
11681
11927
|
run_estimated_credits: validation.estimatedCredits
|
|
11682
11928
|
},
|
|
11683
11929
|
checklist: {
|
|
11684
|
-
edit_prompt: `Edit ${
|
|
11930
|
+
edit_prompt: `Edit ${path9.basename(blueprintPath)} \u2014 the blueprint deconstructed from your video; rewrite it into the ad you want (cast, palette, copy, claims). Every scene frame reads it via target_blueprint.`,
|
|
11685
11931
|
recurring_elements_to_supply: report.elements,
|
|
11686
11932
|
voices_to_confirm: report.dialogue.map((d) => ({
|
|
11687
11933
|
scene: d.scene,
|
|
@@ -11706,19 +11952,94 @@ var scaffoldVideoCommand = defineCommand83({
|
|
|
11706
11952
|
}
|
|
11707
11953
|
});
|
|
11708
11954
|
|
|
11709
|
-
// src/commands/canvas/
|
|
11710
|
-
import { readFile as
|
|
11711
|
-
import
|
|
11955
|
+
// src/commands/canvas/set-prompt.ts
|
|
11956
|
+
import { readFile as readFile8, writeFile as writeFile3 } from "fs/promises";
|
|
11957
|
+
import path10 from "path";
|
|
11712
11958
|
import { defineCommand as defineCommand84 } from "citty";
|
|
11713
|
-
|
|
11959
|
+
function setNodePrompt(canvas, nodeId, text) {
|
|
11960
|
+
const nodes = canvas?.nodes;
|
|
11961
|
+
if (!Array.isArray(nodes)) throw new Error("canvas has no nodes array");
|
|
11962
|
+
const idx = nodes.findIndex((n) => n?.id === nodeId);
|
|
11963
|
+
if (idx < 0) {
|
|
11964
|
+
const ids = nodes.map((n) => n?.id).filter((id) => typeof id === "string");
|
|
11965
|
+
throw new Error(`node "${nodeId}" not found. Known nodes: ${ids.join(", ")}`);
|
|
11966
|
+
}
|
|
11967
|
+
const node = nodes[idx];
|
|
11968
|
+
const newNode = { ...node, params: { ...node.params ?? {}, prompt: text } };
|
|
11969
|
+
const newNodes = [...nodes];
|
|
11970
|
+
newNodes[idx] = newNode;
|
|
11971
|
+
return { ...canvas, nodes: newNodes };
|
|
11972
|
+
}
|
|
11973
|
+
var setPromptCommand = defineCommand84({
|
|
11974
|
+
meta: {
|
|
11975
|
+
name: "set-prompt",
|
|
11976
|
+
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."
|
|
11977
|
+
},
|
|
11978
|
+
args: {
|
|
11979
|
+
file: { type: "positional", required: true, description: "Path to canvas JSON" },
|
|
11980
|
+
node: { type: "positional", required: true, description: "Node id to edit (e.g. s0_start)" },
|
|
11981
|
+
text: { type: "string", description: "New prompt text (inline)" },
|
|
11982
|
+
"text-file": { type: "string", description: "Read the new prompt from a UTF-8 file (preserves accents/newlines)" }
|
|
11983
|
+
},
|
|
11984
|
+
async run({ args }) {
|
|
11985
|
+
const filePath = path10.resolve(String(args.file));
|
|
11986
|
+
let canvas;
|
|
11987
|
+
try {
|
|
11988
|
+
canvas = JSON.parse(await readFile8(filePath, "utf8"));
|
|
11989
|
+
} catch (e) {
|
|
11990
|
+
process.stderr.write(`${JSON.stringify({ ok: false, error: { code: "parse", message: String(e) } }, null, 2)}
|
|
11991
|
+
`);
|
|
11992
|
+
process.exit(2);
|
|
11993
|
+
}
|
|
11994
|
+
let text;
|
|
11995
|
+
if (args["text-file"]) text = await readFile8(path10.resolve(String(args["text-file"])), "utf8");
|
|
11996
|
+
else if (args.text !== void 0) text = String(args.text);
|
|
11997
|
+
else {
|
|
11998
|
+
process.stderr.write(
|
|
11999
|
+
`${JSON.stringify({ ok: false, error: { code: "no_text", message: "pass --text or --text-file" } }, null, 2)}
|
|
12000
|
+
`
|
|
12001
|
+
);
|
|
12002
|
+
process.exit(2);
|
|
12003
|
+
return;
|
|
12004
|
+
}
|
|
12005
|
+
let updated;
|
|
12006
|
+
try {
|
|
12007
|
+
updated = setNodePrompt(canvas, String(args.node), text);
|
|
12008
|
+
} catch (e) {
|
|
12009
|
+
process.stderr.write(
|
|
12010
|
+
`${JSON.stringify({ ok: false, error: { code: "node_not_found", message: String(e.message) } }, null, 2)}
|
|
12011
|
+
`
|
|
12012
|
+
);
|
|
12013
|
+
process.exit(2);
|
|
12014
|
+
return;
|
|
12015
|
+
}
|
|
12016
|
+
const validation = await validateCanvasDeep(resolveRelativeCanvasPaths(updated, path10.dirname(filePath)), defaultRegistry());
|
|
12017
|
+
if (!validation.ok) {
|
|
12018
|
+
process.stderr.write(`${JSON.stringify({ ok: false, error: { code: "validation", issues: validation.issues } }, null, 2)}
|
|
12019
|
+
`);
|
|
12020
|
+
process.exit(2);
|
|
12021
|
+
return;
|
|
12022
|
+
}
|
|
12023
|
+
await writeFile3(filePath, `${JSON.stringify(updated, null, 2)}
|
|
12024
|
+
`, "utf8");
|
|
12025
|
+
process.stdout.write(`${JSON.stringify({ ok: true, node: String(args.node), bytes: text.length }, null, 2)}
|
|
12026
|
+
`);
|
|
12027
|
+
}
|
|
12028
|
+
});
|
|
12029
|
+
|
|
12030
|
+
// src/commands/canvas/validate.ts
|
|
12031
|
+
import { readFile as readFile9 } from "fs/promises";
|
|
12032
|
+
import path11 from "path";
|
|
12033
|
+
import { defineCommand as defineCommand85 } from "citty";
|
|
12034
|
+
var validateCommand = defineCommand85({
|
|
11714
12035
|
meta: {
|
|
11715
12036
|
name: "validate",
|
|
11716
12037
|
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)."
|
|
11717
12038
|
},
|
|
11718
12039
|
args: { file: { type: "positional", required: true, description: "Path to canvas JSON" } },
|
|
11719
12040
|
async run({ args }) {
|
|
11720
|
-
const filePath =
|
|
11721
|
-
const raw = await
|
|
12041
|
+
const filePath = path11.resolve(String(args.file));
|
|
12042
|
+
const raw = await readFile9(filePath, "utf8");
|
|
11722
12043
|
let parsed;
|
|
11723
12044
|
try {
|
|
11724
12045
|
parsed = JSON.parse(raw);
|
|
@@ -11728,6 +12049,7 @@ var validateCommand = defineCommand84({
|
|
|
11728
12049
|
`);
|
|
11729
12050
|
process.exit(2);
|
|
11730
12051
|
}
|
|
12052
|
+
parsed = resolveRelativeCanvasPaths(parsed, path11.dirname(filePath));
|
|
11731
12053
|
const result = await validateCanvasDeep(parsed, defaultRegistry());
|
|
11732
12054
|
if (!result.ok) {
|
|
11733
12055
|
process.stderr.write(`${JSON.stringify({ ok: false, issues: result.issues }, null, 2)}
|
|
@@ -11752,7 +12074,7 @@ var validateCommand = defineCommand84({
|
|
|
11752
12074
|
});
|
|
11753
12075
|
|
|
11754
12076
|
// src/commands/canvas/index.ts
|
|
11755
|
-
var canvasCommand =
|
|
12077
|
+
var canvasCommand = defineCommand86({
|
|
11756
12078
|
meta: {
|
|
11757
12079
|
name: "canvas",
|
|
11758
12080
|
description: `Run Baker creative canvas JSON files locally. Local nodes execute in-process; remote nodes POST to the Convex backend gateway.
|
|
@@ -11775,15 +12097,16 @@ Subcommands:
|
|
|
11775
12097
|
inspect: inspectCommand,
|
|
11776
12098
|
gallery: galleryCommand,
|
|
11777
12099
|
"scaffold-video": scaffoldVideoCommand,
|
|
11778
|
-
"scaffold-static-ad": scaffoldStaticAdCommand
|
|
12100
|
+
"scaffold-static-ad": scaffoldStaticAdCommand,
|
|
12101
|
+
"set-prompt": setPromptCommand
|
|
11779
12102
|
}
|
|
11780
12103
|
});
|
|
11781
12104
|
|
|
11782
12105
|
// src/commands/ga4/index.ts
|
|
11783
|
-
import { defineCommand as
|
|
12106
|
+
import { defineCommand as defineCommand90 } from "citty";
|
|
11784
12107
|
|
|
11785
12108
|
// src/commands/ga4/audit.ts
|
|
11786
|
-
import { defineCommand as
|
|
12109
|
+
import { defineCommand as defineCommand87 } from "citty";
|
|
11787
12110
|
|
|
11788
12111
|
// src/commands/ga4/resolve.ts
|
|
11789
12112
|
async function fetchProperties(useCache = true) {
|
|
@@ -11846,7 +12169,7 @@ registerSchema({
|
|
|
11846
12169
|
"no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
|
|
11847
12170
|
}
|
|
11848
12171
|
});
|
|
11849
|
-
var auditCommand2 =
|
|
12172
|
+
var auditCommand2 = defineCommand87({
|
|
11850
12173
|
meta: {
|
|
11851
12174
|
name: "audit",
|
|
11852
12175
|
description: `Run all GA4 admin health checks. Returns property config with playbook warnings.
|
|
@@ -11898,7 +12221,7 @@ Examples:
|
|
|
11898
12221
|
});
|
|
11899
12222
|
|
|
11900
12223
|
// src/commands/ga4/properties.ts
|
|
11901
|
-
import { defineCommand as
|
|
12224
|
+
import { defineCommand as defineCommand88 } from "citty";
|
|
11902
12225
|
registerSchema({
|
|
11903
12226
|
command: "ga4.properties",
|
|
11904
12227
|
description: "List all accessible GA4 properties. Returns property IDs needed for query and audit commands. Run this first to find property IDs.",
|
|
@@ -11906,7 +12229,7 @@ registerSchema({
|
|
|
11906
12229
|
"no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
|
|
11907
12230
|
}
|
|
11908
12231
|
});
|
|
11909
|
-
var propertiesCommand =
|
|
12232
|
+
var propertiesCommand = defineCommand88({
|
|
11910
12233
|
meta: {
|
|
11911
12234
|
name: "properties",
|
|
11912
12235
|
description: `List accessible GA4 properties.
|
|
@@ -11956,7 +12279,7 @@ Examples:
|
|
|
11956
12279
|
// src/commands/ga4/query.ts
|
|
11957
12280
|
import { appendFileSync as appendFileSync2, existsSync as existsSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
|
|
11958
12281
|
import { resolve as resolve2 } from "path";
|
|
11959
|
-
import { defineCommand as
|
|
12282
|
+
import { defineCommand as defineCommand89 } from "citty";
|
|
11960
12283
|
|
|
11961
12284
|
// src/commands/ga4/presets.ts
|
|
11962
12285
|
var GA4_PRESETS = [
|
|
@@ -12088,7 +12411,7 @@ function handleError(err) {
|
|
|
12088
12411
|
});
|
|
12089
12412
|
process.exit(1);
|
|
12090
12413
|
}
|
|
12091
|
-
var queryCommand2 =
|
|
12414
|
+
var queryCommand2 = defineCommand89({
|
|
12092
12415
|
meta: {
|
|
12093
12416
|
name: "query",
|
|
12094
12417
|
description: `Run GA4 Data API reports. Preset-first with free-form escape hatch.
|
|
@@ -12159,7 +12482,7 @@ Free-form (escape hatch):
|
|
|
12159
12482
|
});
|
|
12160
12483
|
|
|
12161
12484
|
// src/commands/ga4/index.ts
|
|
12162
|
-
var ga4Command =
|
|
12485
|
+
var ga4Command = defineCommand90({
|
|
12163
12486
|
meta: {
|
|
12164
12487
|
name: "ga4",
|
|
12165
12488
|
description: `Google Analytics 4 commands. Audit property config, run playbook-aligned reports.
|
|
@@ -12182,12 +12505,12 @@ Examples:
|
|
|
12182
12505
|
});
|
|
12183
12506
|
|
|
12184
12507
|
// src/commands/gsc/index.ts
|
|
12185
|
-
import { defineCommand as
|
|
12508
|
+
import { defineCommand as defineCommand94 } from "citty";
|
|
12186
12509
|
|
|
12187
12510
|
// src/commands/gsc/query.ts
|
|
12188
12511
|
import { appendFileSync as appendFileSync3, existsSync as existsSync5, readFileSync as readFileSync7, writeFileSync as writeFileSync5 } from "fs";
|
|
12189
12512
|
import { resolve as resolve3 } from "path";
|
|
12190
|
-
import { defineCommand as
|
|
12513
|
+
import { defineCommand as defineCommand91 } from "citty";
|
|
12191
12514
|
|
|
12192
12515
|
// src/commands/gsc/presets.ts
|
|
12193
12516
|
var GSC_PRESETS = [
|
|
@@ -12375,7 +12698,7 @@ function handleError2(err) {
|
|
|
12375
12698
|
});
|
|
12376
12699
|
process.exit(1);
|
|
12377
12700
|
}
|
|
12378
|
-
var queryCommand3 =
|
|
12701
|
+
var queryCommand3 = defineCommand91({
|
|
12379
12702
|
meta: {
|
|
12380
12703
|
name: "query",
|
|
12381
12704
|
description: `Run GSC Search Analytics queries. Preset-first with free-form escape hatch.
|
|
@@ -12453,7 +12776,7 @@ Free-form (escape hatch):
|
|
|
12453
12776
|
});
|
|
12454
12777
|
|
|
12455
12778
|
// src/commands/gsc/sitemaps.ts
|
|
12456
|
-
import { defineCommand as
|
|
12779
|
+
import { defineCommand as defineCommand92 } from "citty";
|
|
12457
12780
|
registerSchema({
|
|
12458
12781
|
command: "gsc.sitemaps",
|
|
12459
12782
|
description: "List sitemaps for a Search Console site. Check sitemap health and errors.",
|
|
@@ -12462,7 +12785,7 @@ registerSchema({
|
|
|
12462
12785
|
"no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
|
|
12463
12786
|
}
|
|
12464
12787
|
});
|
|
12465
|
-
var sitemapsCommand =
|
|
12788
|
+
var sitemapsCommand = defineCommand92({
|
|
12466
12789
|
meta: {
|
|
12467
12790
|
name: "sitemaps",
|
|
12468
12791
|
description: `List sitemaps for a site. Check health and errors.
|
|
@@ -12512,7 +12835,7 @@ Examples:
|
|
|
12512
12835
|
});
|
|
12513
12836
|
|
|
12514
12837
|
// src/commands/gsc/sites.ts
|
|
12515
|
-
import { defineCommand as
|
|
12838
|
+
import { defineCommand as defineCommand93 } from "citty";
|
|
12516
12839
|
registerSchema({
|
|
12517
12840
|
command: "gsc.sites",
|
|
12518
12841
|
description: "List all verified Google Search Console sites. Returns site URLs needed for query and sitemaps commands.",
|
|
@@ -12520,7 +12843,7 @@ registerSchema({
|
|
|
12520
12843
|
"no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
|
|
12521
12844
|
}
|
|
12522
12845
|
});
|
|
12523
|
-
var sitesCommand =
|
|
12846
|
+
var sitesCommand = defineCommand93({
|
|
12524
12847
|
meta: {
|
|
12525
12848
|
name: "sites",
|
|
12526
12849
|
description: `List verified Search Console sites.
|
|
@@ -12568,7 +12891,7 @@ Examples:
|
|
|
12568
12891
|
});
|
|
12569
12892
|
|
|
12570
12893
|
// src/commands/gsc/index.ts
|
|
12571
|
-
var gscCommand =
|
|
12894
|
+
var gscCommand = defineCommand94({
|
|
12572
12895
|
meta: {
|
|
12573
12896
|
name: "gsc",
|
|
12574
12897
|
description: `Google Search Console commands. PPC-SEO arbitrage, brand halo analysis, negative keyword discovery.
|
|
@@ -12591,10 +12914,10 @@ Examples:
|
|
|
12591
12914
|
});
|
|
12592
12915
|
|
|
12593
12916
|
// src/commands/images/index.ts
|
|
12594
|
-
import { defineCommand as
|
|
12917
|
+
import { defineCommand as defineCommand118 } from "citty";
|
|
12595
12918
|
|
|
12596
12919
|
// src/commands/images/crop.ts
|
|
12597
|
-
import { defineCommand as
|
|
12920
|
+
import { defineCommand as defineCommand95 } from "citty";
|
|
12598
12921
|
|
|
12599
12922
|
// src/lib/image/crop-sprite.ts
|
|
12600
12923
|
import sharp from "sharp";
|
|
@@ -12609,7 +12932,7 @@ function cropSprite(input, region) {
|
|
|
12609
12932
|
|
|
12610
12933
|
// src/lib/image/io.ts
|
|
12611
12934
|
import { randomBytes } from "crypto";
|
|
12612
|
-
import { glob as fsGlob, readFile as
|
|
12935
|
+
import { glob as fsGlob, readFile as readFile10, rename, stat as stat2, writeFile as writeFile4 } from "fs/promises";
|
|
12613
12936
|
import { dirname, extname, join as join3, resolve as resolve4 } from "path";
|
|
12614
12937
|
var REMOTE_RE = /^https?:\/\//i;
|
|
12615
12938
|
var GLOB_RE = /[*?[\]{}]/;
|
|
@@ -12645,11 +12968,11 @@ async function readImageBuffer(pathOrUrl) {
|
|
|
12645
12968
|
}
|
|
12646
12969
|
return Buffer.from(await response.arrayBuffer());
|
|
12647
12970
|
}
|
|
12648
|
-
return
|
|
12971
|
+
return readFile10(pathOrUrl);
|
|
12649
12972
|
}
|
|
12650
|
-
async function isDirectory(
|
|
12973
|
+
async function isDirectory(path12) {
|
|
12651
12974
|
try {
|
|
12652
|
-
const s = await stat2(
|
|
12975
|
+
const s = await stat2(path12);
|
|
12653
12976
|
return s.isDirectory();
|
|
12654
12977
|
} catch {
|
|
12655
12978
|
return false;
|
|
@@ -12668,7 +12991,7 @@ async function atomicWrite(targetPath, data) {
|
|
|
12668
12991
|
const absolute = resolve4(targetPath);
|
|
12669
12992
|
const dir = dirname(absolute);
|
|
12670
12993
|
const tmp = join3(dir, `.baker-image-${randomBytes(8).toString("hex")}.tmp`);
|
|
12671
|
-
await
|
|
12994
|
+
await writeFile4(tmp, data);
|
|
12672
12995
|
await rename(tmp, absolute);
|
|
12673
12996
|
}
|
|
12674
12997
|
|
|
@@ -12719,7 +13042,7 @@ function emitError2(err) {
|
|
|
12719
13042
|
}
|
|
12720
13043
|
process.exit(1);
|
|
12721
13044
|
}
|
|
12722
|
-
var cropCommand =
|
|
13045
|
+
var cropCommand = defineCommand95({
|
|
12723
13046
|
meta: {
|
|
12724
13047
|
name: "crop",
|
|
12725
13048
|
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"
|
|
@@ -12755,7 +13078,7 @@ var cropCommand = defineCommand94({
|
|
|
12755
13078
|
});
|
|
12756
13079
|
|
|
12757
13080
|
// src/commands/images/delete.ts
|
|
12758
|
-
import { defineCommand as
|
|
13081
|
+
import { defineCommand as defineCommand96 } from "citty";
|
|
12759
13082
|
registerSchema({
|
|
12760
13083
|
command: "images.delete",
|
|
12761
13084
|
description: "Delete an image by ID",
|
|
@@ -12769,7 +13092,7 @@ registerSchema({
|
|
|
12769
13092
|
}
|
|
12770
13093
|
}
|
|
12771
13094
|
});
|
|
12772
|
-
var deleteCommand =
|
|
13095
|
+
var deleteCommand = defineCommand96({
|
|
12773
13096
|
meta: {
|
|
12774
13097
|
name: "delete",
|
|
12775
13098
|
description: "Delete an image by ID. Use --dry-run to preview. Example: baker images delete j571abc123 --dry-run"
|
|
@@ -12810,7 +13133,7 @@ var deleteCommand = defineCommand95({
|
|
|
12810
13133
|
});
|
|
12811
13134
|
|
|
12812
13135
|
// src/commands/images/dimensions.ts
|
|
12813
|
-
import { defineCommand as
|
|
13136
|
+
import { defineCommand as defineCommand97 } from "citty";
|
|
12814
13137
|
|
|
12815
13138
|
// src/lib/image/dimensions.ts
|
|
12816
13139
|
import { imageSize } from "image-size";
|
|
@@ -12833,7 +13156,7 @@ registerSchema({
|
|
|
12833
13156
|
target: { type: "string", description: "Local file path or remote http(s) URL", required: true }
|
|
12834
13157
|
}
|
|
12835
13158
|
});
|
|
12836
|
-
var dimensionsCommand =
|
|
13159
|
+
var dimensionsCommand = defineCommand97({
|
|
12837
13160
|
meta: {
|
|
12838
13161
|
name: "dimensions",
|
|
12839
13162
|
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"
|
|
@@ -12877,7 +13200,7 @@ var dimensionsCommand = defineCommand96({
|
|
|
12877
13200
|
});
|
|
12878
13201
|
|
|
12879
13202
|
// src/commands/images/extract.ts
|
|
12880
|
-
import { defineCommand as
|
|
13203
|
+
import { defineCommand as defineCommand98 } from "citty";
|
|
12881
13204
|
registerSchema({
|
|
12882
13205
|
command: "images.extract",
|
|
12883
13206
|
description: "Extract images from a URL via Firecrawl (formats: images).",
|
|
@@ -12893,7 +13216,7 @@ registerSchema({
|
|
|
12893
13216
|
}
|
|
12894
13217
|
}
|
|
12895
13218
|
});
|
|
12896
|
-
var extractCommand =
|
|
13219
|
+
var extractCommand = defineCommand98({
|
|
12897
13220
|
meta: {
|
|
12898
13221
|
name: "extract",
|
|
12899
13222
|
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"
|
|
@@ -12931,7 +13254,7 @@ var extractCommand = defineCommand97({
|
|
|
12931
13254
|
});
|
|
12932
13255
|
|
|
12933
13256
|
// src/commands/images/find.ts
|
|
12934
|
-
import { defineCommand as
|
|
13257
|
+
import { defineCommand as defineCommand99 } from "citty";
|
|
12935
13258
|
registerSchema({
|
|
12936
13259
|
command: "images.find",
|
|
12937
13260
|
description: "Fanout image search: library first, then opted-in external providers.",
|
|
@@ -12963,7 +13286,7 @@ registerSchema({
|
|
|
12963
13286
|
}
|
|
12964
13287
|
}
|
|
12965
13288
|
});
|
|
12966
|
-
var findCommand =
|
|
13289
|
+
var findCommand = defineCommand99({
|
|
12967
13290
|
meta: {
|
|
12968
13291
|
name: "find",
|
|
12969
13292
|
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"
|
|
@@ -13009,8 +13332,8 @@ var findCommand = defineCommand98({
|
|
|
13009
13332
|
});
|
|
13010
13333
|
|
|
13011
13334
|
// src/commands/images/generate.ts
|
|
13012
|
-
import { readFile as
|
|
13013
|
-
import { defineCommand as
|
|
13335
|
+
import { readFile as readFile11 } from "fs/promises";
|
|
13336
|
+
import { defineCommand as defineCommand100 } from "citty";
|
|
13014
13337
|
import sharp2 from "sharp";
|
|
13015
13338
|
var GENERATE_TIMEOUT_MS = 18e4;
|
|
13016
13339
|
var REFERENCE_MAX_EDGE = 1536;
|
|
@@ -13092,7 +13415,7 @@ async function resolveReferences(spec) {
|
|
|
13092
13415
|
}
|
|
13093
13416
|
let raw;
|
|
13094
13417
|
try {
|
|
13095
|
-
raw = await
|
|
13418
|
+
raw = await readFile11(entry);
|
|
13096
13419
|
} catch {
|
|
13097
13420
|
throw new ApiError("VALIDATION_ERROR", `Reference file not found: ${entry}`);
|
|
13098
13421
|
}
|
|
@@ -13106,7 +13429,7 @@ async function resolveReferences(spec) {
|
|
|
13106
13429
|
}
|
|
13107
13430
|
return out;
|
|
13108
13431
|
}
|
|
13109
|
-
var generateCommand =
|
|
13432
|
+
var generateCommand = defineCommand100({
|
|
13110
13433
|
meta: {
|
|
13111
13434
|
name: "generate",
|
|
13112
13435
|
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]]'"
|
|
@@ -13158,7 +13481,7 @@ var generateCommand = defineCommand99({
|
|
|
13158
13481
|
});
|
|
13159
13482
|
|
|
13160
13483
|
// src/commands/images/get.ts
|
|
13161
|
-
import { defineCommand as
|
|
13484
|
+
import { defineCommand as defineCommand101 } from "citty";
|
|
13162
13485
|
registerSchema({
|
|
13163
13486
|
command: "images.get",
|
|
13164
13487
|
description: "Get a single image by ID",
|
|
@@ -13166,7 +13489,7 @@ registerSchema({
|
|
|
13166
13489
|
id: { type: "string", description: "Image ID", required: true }
|
|
13167
13490
|
}
|
|
13168
13491
|
});
|
|
13169
|
-
var getCommand2 =
|
|
13492
|
+
var getCommand2 = defineCommand101({
|
|
13170
13493
|
meta: { name: "get", description: "Get a single image by ID. Example: baker images get j571abc123" },
|
|
13171
13494
|
args: {
|
|
13172
13495
|
id: { type: "positional", description: "Image ID", required: false },
|
|
@@ -13202,7 +13525,7 @@ var getCommand2 = defineCommand100({
|
|
|
13202
13525
|
});
|
|
13203
13526
|
|
|
13204
13527
|
// src/commands/images/gif.ts
|
|
13205
|
-
import { defineCommand as
|
|
13528
|
+
import { defineCommand as defineCommand102 } from "citty";
|
|
13206
13529
|
registerSchema({
|
|
13207
13530
|
command: "images.gif",
|
|
13208
13531
|
description: "Search Giphy for GIFs / reaction memes (paid social creative).",
|
|
@@ -13234,7 +13557,7 @@ registerSchema({
|
|
|
13234
13557
|
}
|
|
13235
13558
|
}
|
|
13236
13559
|
});
|
|
13237
|
-
var gifCommand =
|
|
13560
|
+
var gifCommand = defineCommand102({
|
|
13238
13561
|
meta: {
|
|
13239
13562
|
name: "gif",
|
|
13240
13563
|
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"
|
|
@@ -13281,7 +13604,7 @@ var gifCommand = defineCommand101({
|
|
|
13281
13604
|
});
|
|
13282
13605
|
|
|
13283
13606
|
// src/commands/images/google.ts
|
|
13284
|
-
import { defineCommand as
|
|
13607
|
+
import { defineCommand as defineCommand103 } from "citty";
|
|
13285
13608
|
registerSchema({
|
|
13286
13609
|
command: "images.google",
|
|
13287
13610
|
description: "Google Images search via the official Custom Search JSON API. Unverified source \u2014 inspect before placing.",
|
|
@@ -13317,7 +13640,7 @@ registerSchema({
|
|
|
13317
13640
|
}
|
|
13318
13641
|
}
|
|
13319
13642
|
});
|
|
13320
|
-
var googleCommand2 =
|
|
13643
|
+
var googleCommand2 = defineCommand103({
|
|
13321
13644
|
meta: {
|
|
13322
13645
|
name: "google",
|
|
13323
13646
|
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"
|
|
@@ -13365,7 +13688,7 @@ var googleCommand2 = defineCommand102({
|
|
|
13365
13688
|
});
|
|
13366
13689
|
|
|
13367
13690
|
// src/commands/images/icon.ts
|
|
13368
|
-
import { defineCommand as
|
|
13691
|
+
import { defineCommand as defineCommand104 } from "citty";
|
|
13369
13692
|
registerSchema({
|
|
13370
13693
|
command: "images.icon",
|
|
13371
13694
|
description: "Icon lookup via Iconify (200+ icon sets, free CDN).",
|
|
@@ -13391,7 +13714,7 @@ registerSchema({
|
|
|
13391
13714
|
}
|
|
13392
13715
|
}
|
|
13393
13716
|
});
|
|
13394
|
-
var iconCommand =
|
|
13717
|
+
var iconCommand = defineCommand104({
|
|
13395
13718
|
meta: {
|
|
13396
13719
|
name: "icon",
|
|
13397
13720
|
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'"
|
|
@@ -13431,7 +13754,7 @@ var iconCommand = defineCommand103({
|
|
|
13431
13754
|
});
|
|
13432
13755
|
|
|
13433
13756
|
// src/commands/images/ingest.ts
|
|
13434
|
-
import { defineCommand as
|
|
13757
|
+
import { defineCommand as defineCommand105 } from "citty";
|
|
13435
13758
|
registerSchema({
|
|
13436
13759
|
command: "images.ingest",
|
|
13437
13760
|
description: "Ingest a remote image URL into the library (full describe + embed).",
|
|
@@ -13443,7 +13766,7 @@ registerSchema({
|
|
|
13443
13766
|
context: { type: "string", description: "Description context hint", required: false }
|
|
13444
13767
|
}
|
|
13445
13768
|
});
|
|
13446
|
-
var ingestCommand =
|
|
13769
|
+
var ingestCommand = defineCommand105({
|
|
13447
13770
|
meta: {
|
|
13448
13771
|
name: "ingest",
|
|
13449
13772
|
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"
|
|
@@ -13485,7 +13808,7 @@ var ingestCommand = defineCommand104({
|
|
|
13485
13808
|
});
|
|
13486
13809
|
|
|
13487
13810
|
// src/commands/images/library.ts
|
|
13488
|
-
import { defineCommand as
|
|
13811
|
+
import { defineCommand as defineCommand106 } from "citty";
|
|
13489
13812
|
registerSchema({
|
|
13490
13813
|
command: "images.library",
|
|
13491
13814
|
description: "Search the company image library. Returns only ready images.",
|
|
@@ -13511,7 +13834,7 @@ registerSchema({
|
|
|
13511
13834
|
}
|
|
13512
13835
|
}
|
|
13513
13836
|
});
|
|
13514
|
-
var libraryCommand =
|
|
13837
|
+
var libraryCommand = defineCommand106({
|
|
13515
13838
|
meta: {
|
|
13516
13839
|
name: "library",
|
|
13517
13840
|
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"
|
|
@@ -13568,7 +13891,7 @@ var libraryCommand = defineCommand105({
|
|
|
13568
13891
|
});
|
|
13569
13892
|
|
|
13570
13893
|
// src/commands/images/logo.ts
|
|
13571
|
-
import { defineCommand as
|
|
13894
|
+
import { defineCommand as defineCommand107 } from "citty";
|
|
13572
13895
|
registerSchema({
|
|
13573
13896
|
command: "images.logo",
|
|
13574
13897
|
description: "Brand logo lookup via Brandfetch CDN (fallback/404). Auto-ingests by default.",
|
|
@@ -13593,7 +13916,7 @@ registerSchema({
|
|
|
13593
13916
|
}
|
|
13594
13917
|
}
|
|
13595
13918
|
});
|
|
13596
|
-
var logoCommand =
|
|
13919
|
+
var logoCommand = defineCommand107({
|
|
13597
13920
|
meta: {
|
|
13598
13921
|
name: "logo",
|
|
13599
13922
|
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"
|
|
@@ -13631,7 +13954,7 @@ var logoCommand = defineCommand106({
|
|
|
13631
13954
|
});
|
|
13632
13955
|
|
|
13633
13956
|
// src/commands/images/normalize.ts
|
|
13634
|
-
import { defineCommand as
|
|
13957
|
+
import { defineCommand as defineCommand108 } from "citty";
|
|
13635
13958
|
|
|
13636
13959
|
// src/lib/image/color-changer.ts
|
|
13637
13960
|
import quantize from "quantize";
|
|
@@ -14363,7 +14686,7 @@ function coerceRawArgs(args) {
|
|
|
14363
14686
|
"dry-run": bool(args["dry-run"])
|
|
14364
14687
|
};
|
|
14365
14688
|
}
|
|
14366
|
-
var normalizeCommand =
|
|
14689
|
+
var normalizeCommand = defineCommand108({
|
|
14367
14690
|
meta: {
|
|
14368
14691
|
name: "normalize",
|
|
14369
14692
|
description: `Normalize logos / images: declarative recolor + bg removal + trim + resize. Operates on local files; writes in-place by default.
|
|
@@ -14418,7 +14741,7 @@ Examples:
|
|
|
14418
14741
|
});
|
|
14419
14742
|
|
|
14420
14743
|
// src/commands/images/pinterest.ts
|
|
14421
|
-
import { defineCommand as
|
|
14744
|
+
import { defineCommand as defineCommand109 } from "citty";
|
|
14422
14745
|
registerSchema({
|
|
14423
14746
|
command: "images.pinterest",
|
|
14424
14747
|
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.",
|
|
@@ -14438,7 +14761,7 @@ registerSchema({
|
|
|
14438
14761
|
}
|
|
14439
14762
|
}
|
|
14440
14763
|
});
|
|
14441
|
-
var pinterestCommand =
|
|
14764
|
+
var pinterestCommand = defineCommand109({
|
|
14442
14765
|
meta: {
|
|
14443
14766
|
name: "pinterest",
|
|
14444
14767
|
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'"
|
|
@@ -14478,7 +14801,7 @@ var pinterestCommand = defineCommand108({
|
|
|
14478
14801
|
});
|
|
14479
14802
|
|
|
14480
14803
|
// src/commands/images/screenshot.ts
|
|
14481
|
-
import { defineCommand as
|
|
14804
|
+
import { defineCommand as defineCommand110 } from "citty";
|
|
14482
14805
|
registerSchema({
|
|
14483
14806
|
command: "images.screenshot",
|
|
14484
14807
|
description: "Capture a website screenshot via ScreenshotOne. Auto-ingests on success.",
|
|
@@ -14494,7 +14817,7 @@ registerSchema({
|
|
|
14494
14817
|
}
|
|
14495
14818
|
}
|
|
14496
14819
|
});
|
|
14497
|
-
var screenshotCommand =
|
|
14820
|
+
var screenshotCommand = defineCommand110({
|
|
14498
14821
|
meta: {
|
|
14499
14822
|
name: "screenshot",
|
|
14500
14823
|
description: "Screenshot a URL via ScreenshotOne. $0.009/capture. Auto-ingests to library.\n\nExample: baker images screenshot https://stripe.com --full-page"
|
|
@@ -14544,7 +14867,7 @@ var screenshotCommand = defineCommand109({
|
|
|
14544
14867
|
});
|
|
14545
14868
|
|
|
14546
14869
|
// src/commands/images/search.ts
|
|
14547
|
-
import { defineCommand as
|
|
14870
|
+
import { defineCommand as defineCommand111 } from "citty";
|
|
14548
14871
|
registerSchema({
|
|
14549
14872
|
command: "images.search",
|
|
14550
14873
|
description: "Search images by text query. Only returns ready images.",
|
|
@@ -14560,7 +14883,7 @@ registerSchema({
|
|
|
14560
14883
|
tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
|
|
14561
14884
|
}
|
|
14562
14885
|
});
|
|
14563
|
-
var searchCommand =
|
|
14886
|
+
var searchCommand = defineCommand111({
|
|
14564
14887
|
meta: {
|
|
14565
14888
|
name: "search",
|
|
14566
14889
|
description: "Semantic search images by text query. Uses hybrid BM25 + vector + reranking. Example: baker images search 'hero banner' --aspect-ratio 16:9 --tags logo"
|
|
@@ -14620,7 +14943,7 @@ var searchCommand = defineCommand110({
|
|
|
14620
14943
|
});
|
|
14621
14944
|
|
|
14622
14945
|
// src/commands/images/sticker.ts
|
|
14623
|
-
import { defineCommand as
|
|
14946
|
+
import { defineCommand as defineCommand112 } from "citty";
|
|
14624
14947
|
registerSchema({
|
|
14625
14948
|
command: "images.sticker",
|
|
14626
14949
|
description: "Search Giphy stickers \u2014 transparent-background overlays for ad creative.",
|
|
@@ -14652,7 +14975,7 @@ registerSchema({
|
|
|
14652
14975
|
}
|
|
14653
14976
|
}
|
|
14654
14977
|
});
|
|
14655
|
-
var stickerCommand =
|
|
14978
|
+
var stickerCommand = defineCommand112({
|
|
14656
14979
|
meta: {
|
|
14657
14980
|
name: "sticker",
|
|
14658
14981
|
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"
|
|
@@ -14699,7 +15022,7 @@ var stickerCommand = defineCommand111({
|
|
|
14699
15022
|
});
|
|
14700
15023
|
|
|
14701
15024
|
// src/commands/images/stock.ts
|
|
14702
|
-
import { defineCommand as
|
|
15025
|
+
import { defineCommand as defineCommand113 } from "citty";
|
|
14703
15026
|
registerSchema({
|
|
14704
15027
|
command: "images.stock",
|
|
14705
15028
|
description: "Stock photo, vector illustration, icon-set, and PSD search via Magnific (Freepik's developer API).",
|
|
@@ -14757,7 +15080,7 @@ registerSchema({
|
|
|
14757
15080
|
}
|
|
14758
15081
|
}
|
|
14759
15082
|
});
|
|
14760
|
-
var stockCommand =
|
|
15083
|
+
var stockCommand = defineCommand113({
|
|
14761
15084
|
meta: {
|
|
14762
15085
|
name: "stock",
|
|
14763
15086
|
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"
|
|
@@ -14813,7 +15136,7 @@ var stockCommand = defineCommand112({
|
|
|
14813
15136
|
});
|
|
14814
15137
|
|
|
14815
15138
|
// src/lib/tags-command.ts
|
|
14816
|
-
import { defineCommand as
|
|
15139
|
+
import { defineCommand as defineCommand114 } from "citty";
|
|
14817
15140
|
function makeTagsCommand(command, label, endpoint) {
|
|
14818
15141
|
registerSchema({
|
|
14819
15142
|
command: `${command}.tags`,
|
|
@@ -14822,7 +15145,7 @@ function makeTagsCommand(command, label, endpoint) {
|
|
|
14822
15145
|
output: { type: "string", description: "Output format: md|json", required: false, default: "md" }
|
|
14823
15146
|
}
|
|
14824
15147
|
});
|
|
14825
|
-
return
|
|
15148
|
+
return defineCommand114({
|
|
14826
15149
|
meta: {
|
|
14827
15150
|
name: "tags",
|
|
14828
15151
|
description: `List the available ${label} tag names (defaults + company custom tags). Use before filtering with --tags. Example: baker ${command} tags`
|
|
@@ -14858,9 +15181,9 @@ function makeTagsCommand(command, label, endpoint) {
|
|
|
14858
15181
|
var tagsCommand2 = makeTagsCommand("images", "image", "/api/images/tags");
|
|
14859
15182
|
|
|
14860
15183
|
// src/commands/images/upload.ts
|
|
14861
|
-
import { readFile as
|
|
15184
|
+
import { readFile as readFile12 } from "fs/promises";
|
|
14862
15185
|
import { extname as extname2 } from "path";
|
|
14863
|
-
import { defineCommand as
|
|
15186
|
+
import { defineCommand as defineCommand115 } from "citty";
|
|
14864
15187
|
var MIME_MAP = {
|
|
14865
15188
|
".png": "image/png",
|
|
14866
15189
|
".jpg": "image/jpeg",
|
|
@@ -14915,7 +15238,7 @@ function detectContentType(filePath) {
|
|
|
14915
15238
|
}
|
|
14916
15239
|
return mime;
|
|
14917
15240
|
}
|
|
14918
|
-
var uploadCommand =
|
|
15241
|
+
var uploadCommand = defineCommand115({
|
|
14919
15242
|
meta: {
|
|
14920
15243
|
name: "upload",
|
|
14921
15244
|
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'"
|
|
@@ -14998,7 +15321,7 @@ async function uploadLocal(target, args) {
|
|
|
14998
15321
|
});
|
|
14999
15322
|
return;
|
|
15000
15323
|
}
|
|
15001
|
-
const fileBuffer = await
|
|
15324
|
+
const fileBuffer = await readFile12(target);
|
|
15002
15325
|
const base64 = fileBuffer.toString("base64");
|
|
15003
15326
|
const body = { base64, contentType };
|
|
15004
15327
|
if (args.source) body.source = args.source;
|
|
@@ -15008,7 +15331,7 @@ async function uploadLocal(target, args) {
|
|
|
15008
15331
|
}
|
|
15009
15332
|
|
|
15010
15333
|
// src/commands/images/upscale.ts
|
|
15011
|
-
import { defineCommand as
|
|
15334
|
+
import { defineCommand as defineCommand116 } from "citty";
|
|
15012
15335
|
registerSchema({
|
|
15013
15336
|
command: "images.upscale",
|
|
15014
15337
|
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).",
|
|
@@ -15023,7 +15346,7 @@ registerSchema({
|
|
|
15023
15346
|
}
|
|
15024
15347
|
});
|
|
15025
15348
|
var POLL_INTERVAL_MS3 = 1500;
|
|
15026
|
-
var upscaleCommand =
|
|
15349
|
+
var upscaleCommand = defineCommand116({
|
|
15027
15350
|
meta: {
|
|
15028
15351
|
name: "upscale",
|
|
15029
15352
|
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"
|
|
@@ -15078,7 +15401,7 @@ var upscaleCommand = defineCommand115({
|
|
|
15078
15401
|
});
|
|
15079
15402
|
|
|
15080
15403
|
// src/commands/images/use.ts
|
|
15081
|
-
import { defineCommand as
|
|
15404
|
+
import { defineCommand as defineCommand117 } from "citty";
|
|
15082
15405
|
registerSchema({
|
|
15083
15406
|
command: "images.use",
|
|
15084
15407
|
description: "Ingest a URL and wait for the library record to be ready.",
|
|
@@ -15094,7 +15417,7 @@ registerSchema({
|
|
|
15094
15417
|
}
|
|
15095
15418
|
});
|
|
15096
15419
|
var POLL_INTERVAL_MS4 = 1500;
|
|
15097
|
-
var useCommand =
|
|
15420
|
+
var useCommand = defineCommand117({
|
|
15098
15421
|
meta: {
|
|
15099
15422
|
name: "use",
|
|
15100
15423
|
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"
|
|
@@ -15140,7 +15463,7 @@ var useCommand = defineCommand116({
|
|
|
15140
15463
|
});
|
|
15141
15464
|
|
|
15142
15465
|
// src/commands/images/index.ts
|
|
15143
|
-
var imagesCommand =
|
|
15466
|
+
var imagesCommand = defineCommand118({
|
|
15144
15467
|
meta: {
|
|
15145
15468
|
name: "images",
|
|
15146
15469
|
description: `Find, source, and normalize images. Subcommands route by provider so cost + license are explicit.
|
|
@@ -15210,10 +15533,10 @@ Paid transforms (run on the Convex backend, cost-tracked):
|
|
|
15210
15533
|
});
|
|
15211
15534
|
|
|
15212
15535
|
// src/commands/research/index.ts
|
|
15213
|
-
import { defineCommand as
|
|
15536
|
+
import { defineCommand as defineCommand129 } from "citty";
|
|
15214
15537
|
|
|
15215
15538
|
// src/commands/research/advertisers.ts
|
|
15216
|
-
import { defineCommand as
|
|
15539
|
+
import { defineCommand as defineCommand119 } from "citty";
|
|
15217
15540
|
|
|
15218
15541
|
// src/commands/research/output.ts
|
|
15219
15542
|
var RESEARCH_DATA_NOTE = "Estimates based on third-party SERP data \u2014 not exact figures. Use for directional insights, not precise measurement.";
|
|
@@ -15326,7 +15649,7 @@ var FIELDS3 = {
|
|
|
15326
15649
|
etv: "Estimated traffic value (USD)",
|
|
15327
15650
|
visibility: "SERP visibility score (0-1)"
|
|
15328
15651
|
};
|
|
15329
|
-
var advertisersCommand =
|
|
15652
|
+
var advertisersCommand = defineCommand119({
|
|
15330
15653
|
meta: {
|
|
15331
15654
|
name: "advertisers",
|
|
15332
15655
|
description: `Find domains competing for a keyword in Google SERPs.
|
|
@@ -15373,7 +15696,7 @@ Examples:
|
|
|
15373
15696
|
});
|
|
15374
15697
|
|
|
15375
15698
|
// src/commands/research/autocomplete.ts
|
|
15376
|
-
import { defineCommand as
|
|
15699
|
+
import { defineCommand as defineCommand120 } from "citty";
|
|
15377
15700
|
registerSchema({
|
|
15378
15701
|
command: "research.autocomplete",
|
|
15379
15702
|
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).",
|
|
@@ -15396,7 +15719,7 @@ registerSchema({
|
|
|
15396
15719
|
var FIELDS4 = {
|
|
15397
15720
|
suggestion: "Autocomplete suggestion from Google"
|
|
15398
15721
|
};
|
|
15399
|
-
var autocompleteCommand =
|
|
15722
|
+
var autocompleteCommand = defineCommand120({
|
|
15400
15723
|
meta: {
|
|
15401
15724
|
name: "autocomplete",
|
|
15402
15725
|
description: `Get Google Autocomplete suggestions for keyword expansion.
|
|
@@ -15442,7 +15765,7 @@ Examples:
|
|
|
15442
15765
|
});
|
|
15443
15766
|
|
|
15444
15767
|
// src/commands/research/countries.ts
|
|
15445
|
-
import { defineCommand as
|
|
15768
|
+
import { defineCommand as defineCommand121 } from "citty";
|
|
15446
15769
|
registerSchema({
|
|
15447
15770
|
command: "research.countries",
|
|
15448
15771
|
description: "List all supported country codes for --location flag in research commands.",
|
|
@@ -15499,7 +15822,7 @@ var FIELDS5 = {
|
|
|
15499
15822
|
code: "Country code to pass as --location",
|
|
15500
15823
|
name: "Country name"
|
|
15501
15824
|
};
|
|
15502
|
-
var countriesCommand =
|
|
15825
|
+
var countriesCommand = defineCommand121({
|
|
15503
15826
|
meta: {
|
|
15504
15827
|
name: "countries",
|
|
15505
15828
|
description: "List all supported country codes for --location flag."
|
|
@@ -15510,7 +15833,7 @@ var countriesCommand = defineCommand120({
|
|
|
15510
15833
|
});
|
|
15511
15834
|
|
|
15512
15835
|
// src/commands/research/intent.ts
|
|
15513
|
-
import { defineCommand as
|
|
15836
|
+
import { defineCommand as defineCommand122 } from "citty";
|
|
15514
15837
|
registerSchema({
|
|
15515
15838
|
command: "research.intent",
|
|
15516
15839
|
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.",
|
|
@@ -15533,7 +15856,7 @@ var FIELDS6 = {
|
|
|
15533
15856
|
intent: "Primary Google Search intent: informational, navigational, commercial, transactional",
|
|
15534
15857
|
probability: "Confidence score 0.0-1.0"
|
|
15535
15858
|
};
|
|
15536
|
-
var intentCommand =
|
|
15859
|
+
var intentCommand = defineCommand122({
|
|
15537
15860
|
meta: {
|
|
15538
15861
|
name: "intent",
|
|
15539
15862
|
description: `Classify Google Search intent for keywords. Returns intent type and confidence.
|
|
@@ -15581,7 +15904,7 @@ Examples:
|
|
|
15581
15904
|
});
|
|
15582
15905
|
|
|
15583
15906
|
// src/commands/research/keyword-gap.ts
|
|
15584
|
-
import { defineCommand as
|
|
15907
|
+
import { defineCommand as defineCommand123 } from "citty";
|
|
15585
15908
|
registerSchema({
|
|
15586
15909
|
command: "research.keyword-gap",
|
|
15587
15910
|
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.",
|
|
@@ -15610,7 +15933,7 @@ var FIELDS7 = {
|
|
|
15610
15933
|
cpc: "Cost per click USD",
|
|
15611
15934
|
their_position: "Competitor's ranking position"
|
|
15612
15935
|
};
|
|
15613
|
-
var keywordGapCommand =
|
|
15936
|
+
var keywordGapCommand = defineCommand123({
|
|
15614
15937
|
meta: {
|
|
15615
15938
|
name: "keyword-gap",
|
|
15616
15939
|
description: `Find keywords a competitor has that you don't. Supports pagination via --offset.
|
|
@@ -15684,7 +16007,7 @@ Examples:
|
|
|
15684
16007
|
});
|
|
15685
16008
|
|
|
15686
16009
|
// src/commands/research/keywords-for-site.ts
|
|
15687
|
-
import { defineCommand as
|
|
16010
|
+
import { defineCommand as defineCommand124 } from "citty";
|
|
15688
16011
|
registerSchema({
|
|
15689
16012
|
command: "research.keywords-for-site",
|
|
15690
16013
|
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.",
|
|
@@ -15717,7 +16040,7 @@ var FIELDS8 = {
|
|
|
15717
16040
|
competition: "LOW, MEDIUM, or HIGH",
|
|
15718
16041
|
competition_index: "Competition score 0-100"
|
|
15719
16042
|
};
|
|
15720
|
-
var keywordsForSiteCommand =
|
|
16043
|
+
var keywordsForSiteCommand = defineCommand124({
|
|
15721
16044
|
meta: {
|
|
15722
16045
|
name: "keywords-for-site",
|
|
15723
16046
|
description: `Get keywords a competitor targets in Google. Use --type to filter paid/organic.
|
|
@@ -15770,7 +16093,7 @@ Examples:
|
|
|
15770
16093
|
});
|
|
15771
16094
|
|
|
15772
16095
|
// src/commands/research/languages.ts
|
|
15773
|
-
import { defineCommand as
|
|
16096
|
+
import { defineCommand as defineCommand125 } from "citty";
|
|
15774
16097
|
registerSchema({
|
|
15775
16098
|
command: "research.languages",
|
|
15776
16099
|
description: "List all supported language codes for --language flag in research commands.",
|
|
@@ -15800,7 +16123,7 @@ var FIELDS9 = {
|
|
|
15800
16123
|
code: "Language code to pass as --language",
|
|
15801
16124
|
name: "Language name (also accepted by --language)"
|
|
15802
16125
|
};
|
|
15803
|
-
var languagesCommand2 =
|
|
16126
|
+
var languagesCommand2 = defineCommand125({
|
|
15804
16127
|
meta: {
|
|
15805
16128
|
name: "languages",
|
|
15806
16129
|
description: "List all supported language codes for --language flag."
|
|
@@ -15811,7 +16134,7 @@ var languagesCommand2 = defineCommand124({
|
|
|
15811
16134
|
});
|
|
15812
16135
|
|
|
15813
16136
|
// src/commands/research/lighthouse.ts
|
|
15814
|
-
import { defineCommand as
|
|
16137
|
+
import { defineCommand as defineCommand126 } from "citty";
|
|
15815
16138
|
registerSchema({
|
|
15816
16139
|
command: "research.lighthouse",
|
|
15817
16140
|
description: "Landing page performance audit. Returns metrics that affect Google Ads Quality Score and CPC.",
|
|
@@ -15830,7 +16153,7 @@ var FIELDS10 = {
|
|
|
15830
16153
|
speed_index_ms: "Speed Index in ms (good: < 3400)",
|
|
15831
16154
|
interactive_ms: "Time to Interactive in ms (good: < 3800)"
|
|
15832
16155
|
};
|
|
15833
|
-
var lighthouseCommand =
|
|
16156
|
+
var lighthouseCommand = defineCommand126({
|
|
15834
16157
|
meta: {
|
|
15835
16158
|
name: "lighthouse",
|
|
15836
16159
|
description: `Landing page performance audit. Metrics affecting Google Ads Quality Score.
|
|
@@ -15868,7 +16191,7 @@ Examples:
|
|
|
15868
16191
|
});
|
|
15869
16192
|
|
|
15870
16193
|
// src/commands/research/relevant-pages.ts
|
|
15871
|
-
import { defineCommand as
|
|
16194
|
+
import { defineCommand as defineCommand127 } from "citty";
|
|
15872
16195
|
registerSchema({
|
|
15873
16196
|
command: "research.relevant-pages",
|
|
15874
16197
|
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).",
|
|
@@ -15894,7 +16217,7 @@ var FIELDS11 = {
|
|
|
15894
16217
|
keywords: "Total organic keywords the page ranks for",
|
|
15895
16218
|
top_10: "Keywords in positions 1-10"
|
|
15896
16219
|
};
|
|
15897
|
-
var relevantPagesCommand =
|
|
16220
|
+
var relevantPagesCommand = defineCommand127({
|
|
15898
16221
|
meta: {
|
|
15899
16222
|
name: "relevant-pages",
|
|
15900
16223
|
description: `Get the top pages of a competitor domain with traffic data.
|
|
@@ -15940,7 +16263,7 @@ Examples:
|
|
|
15940
16263
|
});
|
|
15941
16264
|
|
|
15942
16265
|
// src/commands/research/web.ts
|
|
15943
|
-
import { defineCommand as
|
|
16266
|
+
import { defineCommand as defineCommand128 } from "citty";
|
|
15944
16267
|
registerSchema({
|
|
15945
16268
|
command: "research.web",
|
|
15946
16269
|
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).",
|
|
@@ -15991,7 +16314,7 @@ async function runDeepResearch(question) {
|
|
|
15991
16314
|
}
|
|
15992
16315
|
throw new Error("Deep research timed out");
|
|
15993
16316
|
}
|
|
15994
|
-
var webCommand =
|
|
16317
|
+
var webCommand = defineCommand128({
|
|
15995
16318
|
meta: {
|
|
15996
16319
|
name: "web",
|
|
15997
16320
|
description: `Search the web with AI to answer any open-ended marketing question. Uses live internet data via Google Search.
|
|
@@ -16051,7 +16374,7 @@ Examples:
|
|
|
16051
16374
|
});
|
|
16052
16375
|
|
|
16053
16376
|
// src/commands/research/index.ts
|
|
16054
|
-
var researchCommand =
|
|
16377
|
+
var researchCommand = defineCommand129({
|
|
16055
16378
|
meta: {
|
|
16056
16379
|
name: "research",
|
|
16057
16380
|
description: `Competitive intelligence and AI-powered research commands.
|
|
@@ -16091,10 +16414,10 @@ Examples:
|
|
|
16091
16414
|
});
|
|
16092
16415
|
|
|
16093
16416
|
// src/commands/scheduled-actions/index.ts
|
|
16094
|
-
import { defineCommand as
|
|
16417
|
+
import { defineCommand as defineCommand136 } from "citty";
|
|
16095
16418
|
|
|
16096
16419
|
// src/commands/scheduled-actions/create.ts
|
|
16097
|
-
import { defineCommand as
|
|
16420
|
+
import { defineCommand as defineCommand130 } from "citty";
|
|
16098
16421
|
|
|
16099
16422
|
// src/commands/scheduled-actions/shared.ts
|
|
16100
16423
|
var TEMP_SCHEDULED_ACTION_PREFIX = "temp_sched_";
|
|
@@ -16199,7 +16522,7 @@ registerSchema({
|
|
|
16199
16522
|
prompt: { type: "string", description: "Additional prompt instructions for the spawned agent", required: false }
|
|
16200
16523
|
}
|
|
16201
16524
|
});
|
|
16202
|
-
var createCommand2 =
|
|
16525
|
+
var createCommand2 = defineCommand130({
|
|
16203
16526
|
meta: {
|
|
16204
16527
|
name: "create",
|
|
16205
16528
|
description: 'Stage a scheduled action. Example: baker scheduled-actions create --name "Weekly report" --description "..." --cron "0 9 * * MON"'
|
|
@@ -16247,7 +16570,7 @@ var createCommand2 = defineCommand129({
|
|
|
16247
16570
|
});
|
|
16248
16571
|
|
|
16249
16572
|
// src/commands/scheduled-actions/delete.ts
|
|
16250
|
-
import { defineCommand as
|
|
16573
|
+
import { defineCommand as defineCommand131 } from "citty";
|
|
16251
16574
|
registerSchema({
|
|
16252
16575
|
command: "scheduled-actions.delete",
|
|
16253
16576
|
description: "Stage deletion of a published scheduled action or cancellation of a temp_sched_* draft creation.",
|
|
@@ -16255,7 +16578,7 @@ registerSchema({
|
|
|
16255
16578
|
id: { type: "string", description: "Published scheduled action ID or temp_sched_* draft ID", required: true }
|
|
16256
16579
|
}
|
|
16257
16580
|
});
|
|
16258
|
-
var deleteCommand2 =
|
|
16581
|
+
var deleteCommand2 = defineCommand131({
|
|
16259
16582
|
meta: {
|
|
16260
16583
|
name: "delete",
|
|
16261
16584
|
description: "Stage scheduled action deletion. Example: baker scheduled-actions delete <id-or-temp_sched_id>"
|
|
@@ -16284,7 +16607,7 @@ var deleteCommand2 = defineCommand130({
|
|
|
16284
16607
|
});
|
|
16285
16608
|
|
|
16286
16609
|
// src/commands/scheduled-actions/get.ts
|
|
16287
|
-
import { defineCommand as
|
|
16610
|
+
import { defineCommand as defineCommand132 } from "citty";
|
|
16288
16611
|
registerSchema({
|
|
16289
16612
|
command: "scheduled-actions.get",
|
|
16290
16613
|
description: "Get a published scheduled action or a temp_sched_* draft-created scheduled action.",
|
|
@@ -16292,7 +16615,7 @@ registerSchema({
|
|
|
16292
16615
|
id: { type: "string", description: "Published scheduled action ID or temp_sched_* draft ID", required: true }
|
|
16293
16616
|
}
|
|
16294
16617
|
});
|
|
16295
|
-
var getCommand3 =
|
|
16618
|
+
var getCommand3 = defineCommand132({
|
|
16296
16619
|
meta: {
|
|
16297
16620
|
name: "get",
|
|
16298
16621
|
description: "Get a scheduled action. Example: baker scheduled-actions get <id-or-temp_sched_id>"
|
|
@@ -16329,13 +16652,13 @@ var getCommand3 = defineCommand131({
|
|
|
16329
16652
|
});
|
|
16330
16653
|
|
|
16331
16654
|
// src/commands/scheduled-actions/list.ts
|
|
16332
|
-
import { defineCommand as
|
|
16655
|
+
import { defineCommand as defineCommand133 } from "citty";
|
|
16333
16656
|
registerSchema({
|
|
16334
16657
|
command: "scheduled-actions.list",
|
|
16335
16658
|
description: "List published scheduled actions. Includes draft state when BAKER_CHAT_ID is set.",
|
|
16336
16659
|
args: {}
|
|
16337
16660
|
});
|
|
16338
|
-
var listCommand3 =
|
|
16661
|
+
var listCommand3 = defineCommand133({
|
|
16339
16662
|
meta: {
|
|
16340
16663
|
name: "list",
|
|
16341
16664
|
description: "List scheduled actions. Includes staged draft ops when BAKER_CHAT_ID is set."
|
|
@@ -16356,7 +16679,7 @@ var listCommand3 = defineCommand132({
|
|
|
16356
16679
|
});
|
|
16357
16680
|
|
|
16358
16681
|
// src/commands/scheduled-actions/trigger.ts
|
|
16359
|
-
import { defineCommand as
|
|
16682
|
+
import { defineCommand as defineCommand134 } from "citty";
|
|
16360
16683
|
registerSchema({
|
|
16361
16684
|
command: "scheduled-actions.trigger",
|
|
16362
16685
|
description: "Immediately trigger a published scheduled action. Does not require BAKER_CHAT_ID and rejects temp_sched_* IDs.",
|
|
@@ -16364,7 +16687,7 @@ registerSchema({
|
|
|
16364
16687
|
id: { type: "string", description: "Published scheduled action ID", required: true }
|
|
16365
16688
|
}
|
|
16366
16689
|
});
|
|
16367
|
-
var triggerCommand =
|
|
16690
|
+
var triggerCommand = defineCommand134({
|
|
16368
16691
|
meta: {
|
|
16369
16692
|
name: "trigger",
|
|
16370
16693
|
description: "Immediately trigger a published scheduled action. Example: baker scheduled-actions trigger <id>"
|
|
@@ -16401,7 +16724,7 @@ var triggerCommand = defineCommand133({
|
|
|
16401
16724
|
});
|
|
16402
16725
|
|
|
16403
16726
|
// src/commands/scheduled-actions/update.ts
|
|
16404
|
-
import { defineCommand as
|
|
16727
|
+
import { defineCommand as defineCommand135 } from "citty";
|
|
16405
16728
|
registerSchema({
|
|
16406
16729
|
command: "scheduled-actions.update",
|
|
16407
16730
|
description: "Stage an update to a published scheduled action or temp_sched_* draft-created scheduled action.",
|
|
@@ -16426,7 +16749,7 @@ registerSchema({
|
|
|
16426
16749
|
prompt: { type: "string", description: "Replacement additional spawned-agent instructions", required: false }
|
|
16427
16750
|
}
|
|
16428
16751
|
});
|
|
16429
|
-
var updateCommand2 =
|
|
16752
|
+
var updateCommand2 = defineCommand135({
|
|
16430
16753
|
meta: {
|
|
16431
16754
|
name: "update",
|
|
16432
16755
|
description: "Stage a scheduled action update. Example: baker scheduled-actions update <id> --enabled false"
|
|
@@ -16496,7 +16819,7 @@ var updateCommand2 = defineCommand134({
|
|
|
16496
16819
|
});
|
|
16497
16820
|
|
|
16498
16821
|
// src/commands/scheduled-actions/index.ts
|
|
16499
|
-
var scheduledActionsCommand =
|
|
16822
|
+
var scheduledActionsCommand = defineCommand136({
|
|
16500
16823
|
meta: {
|
|
16501
16824
|
name: "scheduled-actions",
|
|
16502
16825
|
description: `Manage Scheduled Actions. Subcommands: list, get, create, update, delete, trigger.
|
|
@@ -16522,8 +16845,8 @@ Examples:
|
|
|
16522
16845
|
});
|
|
16523
16846
|
|
|
16524
16847
|
// src/commands/schema.ts
|
|
16525
|
-
import { defineCommand as
|
|
16526
|
-
var schemaCommand =
|
|
16848
|
+
import { defineCommand as defineCommand137 } from "citty";
|
|
16849
|
+
var schemaCommand = defineCommand137({
|
|
16527
16850
|
meta: {
|
|
16528
16851
|
name: "schema",
|
|
16529
16852
|
description: "Inspect command argument schemas (for AI agent introspection). Lists all commands if no argument given. Example: baker schema images.search"
|
|
@@ -16559,10 +16882,10 @@ var schemaCommand = defineCommand136({
|
|
|
16559
16882
|
});
|
|
16560
16883
|
|
|
16561
16884
|
// src/commands/testimonials/index.ts
|
|
16562
|
-
import { defineCommand as
|
|
16885
|
+
import { defineCommand as defineCommand141 } from "citty";
|
|
16563
16886
|
|
|
16564
16887
|
// src/commands/testimonials/get.ts
|
|
16565
|
-
import { defineCommand as
|
|
16888
|
+
import { defineCommand as defineCommand138 } from "citty";
|
|
16566
16889
|
registerSchema({
|
|
16567
16890
|
command: "testimonials.get",
|
|
16568
16891
|
description: "Get a single testimonial by ID",
|
|
@@ -16570,7 +16893,7 @@ registerSchema({
|
|
|
16570
16893
|
id: { type: "string", description: "Testimonial ID", required: true }
|
|
16571
16894
|
}
|
|
16572
16895
|
});
|
|
16573
|
-
var getCommand4 =
|
|
16896
|
+
var getCommand4 = defineCommand138({
|
|
16574
16897
|
meta: { name: "get", description: "Get a single testimonial by ID. Example: baker testimonials get j571abc123" },
|
|
16575
16898
|
args: {
|
|
16576
16899
|
id: { type: "positional", description: "Testimonial ID", required: false },
|
|
@@ -16607,7 +16930,7 @@ var getCommand4 = defineCommand137({
|
|
|
16607
16930
|
});
|
|
16608
16931
|
|
|
16609
16932
|
// src/commands/testimonials/list.ts
|
|
16610
|
-
import { defineCommand as
|
|
16933
|
+
import { defineCommand as defineCommand139 } from "citty";
|
|
16611
16934
|
registerSchema({
|
|
16612
16935
|
command: "testimonials.list",
|
|
16613
16936
|
description: "List testimonials with optional filters.",
|
|
@@ -16637,7 +16960,7 @@ registerSchema({
|
|
|
16637
16960
|
limit: { type: "number", description: "Max results (default 50)", required: false, default: 50 }
|
|
16638
16961
|
}
|
|
16639
16962
|
});
|
|
16640
|
-
var listCommand4 =
|
|
16963
|
+
var listCommand4 = defineCommand139({
|
|
16641
16964
|
meta: {
|
|
16642
16965
|
name: "list",
|
|
16643
16966
|
description: "List testimonials with optional filters. Example: baker testimonials list --source google --sentiment positive"
|
|
@@ -16686,7 +17009,7 @@ var listCommand4 = defineCommand138({
|
|
|
16686
17009
|
});
|
|
16687
17010
|
|
|
16688
17011
|
// src/commands/testimonials/search.ts
|
|
16689
|
-
import { defineCommand as
|
|
17012
|
+
import { defineCommand as defineCommand140 } from "citty";
|
|
16690
17013
|
registerSchema({
|
|
16691
17014
|
command: "testimonials.search",
|
|
16692
17015
|
description: "Search testimonials by text query. Uses hybrid BM25 + vector + reranking.",
|
|
@@ -16717,7 +17040,7 @@ registerSchema({
|
|
|
16717
17040
|
tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
|
|
16718
17041
|
}
|
|
16719
17042
|
});
|
|
16720
|
-
var searchCommand2 =
|
|
17043
|
+
var searchCommand2 = defineCommand140({
|
|
16721
17044
|
meta: {
|
|
16722
17045
|
name: "search",
|
|
16723
17046
|
description: "Semantic search testimonials by text query. Uses hybrid BM25 + vector + reranking. Example: baker testimonials search 'great service' --rating-min 4"
|
|
@@ -16791,7 +17114,7 @@ var searchCommand2 = defineCommand139({
|
|
|
16791
17114
|
var tagsCommand3 = makeTagsCommand("testimonials", "testimonial", "/api/testimonials/tags");
|
|
16792
17115
|
|
|
16793
17116
|
// src/commands/testimonials/index.ts
|
|
16794
|
-
var testimonialsCommand =
|
|
17117
|
+
var testimonialsCommand = defineCommand141({
|
|
16795
17118
|
meta: {
|
|
16796
17119
|
name: "testimonials",
|
|
16797
17120
|
description: `Find and browse testimonials in Baker. Subcommands: search, get, list, tags.
|
|
@@ -16812,10 +17135,10 @@ Examples:
|
|
|
16812
17135
|
});
|
|
16813
17136
|
|
|
16814
17137
|
// src/commands/videos/index.ts
|
|
16815
|
-
import { defineCommand as
|
|
17138
|
+
import { defineCommand as defineCommand146 } from "citty";
|
|
16816
17139
|
|
|
16817
17140
|
// src/commands/videos/delete.ts
|
|
16818
|
-
import { defineCommand as
|
|
17141
|
+
import { defineCommand as defineCommand142 } from "citty";
|
|
16819
17142
|
registerSchema({
|
|
16820
17143
|
command: "videos.delete",
|
|
16821
17144
|
description: "Delete a video by ID",
|
|
@@ -16829,7 +17152,7 @@ registerSchema({
|
|
|
16829
17152
|
}
|
|
16830
17153
|
}
|
|
16831
17154
|
});
|
|
16832
|
-
var deleteCommand3 =
|
|
17155
|
+
var deleteCommand3 = defineCommand142({
|
|
16833
17156
|
meta: {
|
|
16834
17157
|
name: "delete",
|
|
16835
17158
|
description: "Delete a video by ID. Use --dry-run to preview. Example: baker videos delete j571abc123 --dry-run"
|
|
@@ -16870,7 +17193,7 @@ var deleteCommand3 = defineCommand141({
|
|
|
16870
17193
|
});
|
|
16871
17194
|
|
|
16872
17195
|
// src/commands/videos/get.ts
|
|
16873
|
-
import { defineCommand as
|
|
17196
|
+
import { defineCommand as defineCommand143 } from "citty";
|
|
16874
17197
|
registerSchema({
|
|
16875
17198
|
command: "videos.get",
|
|
16876
17199
|
description: "Get a single video by ID",
|
|
@@ -16878,7 +17201,7 @@ registerSchema({
|
|
|
16878
17201
|
id: { type: "string", description: "Video ID", required: true }
|
|
16879
17202
|
}
|
|
16880
17203
|
});
|
|
16881
|
-
var getCommand5 =
|
|
17204
|
+
var getCommand5 = defineCommand143({
|
|
16882
17205
|
meta: { name: "get", description: "Get a single video by ID. Example: baker videos get j571abc123" },
|
|
16883
17206
|
args: {
|
|
16884
17207
|
id: { type: "positional", description: "Video ID", required: false },
|
|
@@ -16915,7 +17238,7 @@ var getCommand5 = defineCommand142({
|
|
|
16915
17238
|
});
|
|
16916
17239
|
|
|
16917
17240
|
// src/commands/videos/search.ts
|
|
16918
|
-
import { defineCommand as
|
|
17241
|
+
import { defineCommand as defineCommand144 } from "citty";
|
|
16919
17242
|
registerSchema({
|
|
16920
17243
|
command: "videos.search",
|
|
16921
17244
|
description: "Search videos by text query. Only returns ready videos.",
|
|
@@ -16925,7 +17248,7 @@ registerSchema({
|
|
|
16925
17248
|
tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
|
|
16926
17249
|
}
|
|
16927
17250
|
});
|
|
16928
|
-
var searchCommand3 =
|
|
17251
|
+
var searchCommand3 = defineCommand144({
|
|
16929
17252
|
meta: {
|
|
16930
17253
|
name: "search",
|
|
16931
17254
|
description: "Semantic search videos by text query. Uses hybrid BM25 + vector + reranking. Example: baker videos search 'product demo' --tags tutorial"
|
|
@@ -16975,9 +17298,9 @@ var searchCommand3 = defineCommand143({
|
|
|
16975
17298
|
var tagsCommand4 = makeTagsCommand("videos", "video", "/api/videos/tags");
|
|
16976
17299
|
|
|
16977
17300
|
// src/commands/videos/upload.ts
|
|
16978
|
-
import { readFile as
|
|
17301
|
+
import { readFile as readFile13, stat as stat3 } from "fs/promises";
|
|
16979
17302
|
import { extname as extname3 } from "path";
|
|
16980
|
-
import { defineCommand as
|
|
17303
|
+
import { defineCommand as defineCommand145 } from "citty";
|
|
16981
17304
|
var MIME_MAP2 = {
|
|
16982
17305
|
".mp4": "video/mp4",
|
|
16983
17306
|
".mov": "video/quicktime",
|
|
@@ -17011,7 +17334,7 @@ function detectContentType2(filePath) {
|
|
|
17011
17334
|
}
|
|
17012
17335
|
return mime;
|
|
17013
17336
|
}
|
|
17014
|
-
var uploadCommand2 =
|
|
17337
|
+
var uploadCommand2 = defineCommand145({
|
|
17015
17338
|
meta: {
|
|
17016
17339
|
name: "upload",
|
|
17017
17340
|
description: "Upload a video file to Baker via Mux direct upload. Auto-detects content type. Example: baker videos upload ./demo.mp4"
|
|
@@ -17040,7 +17363,7 @@ var uploadCommand2 = defineCommand144({
|
|
|
17040
17363
|
return;
|
|
17041
17364
|
}
|
|
17042
17365
|
const { uploadUrl, videoId } = await apiPost("/api/videos/upload", {});
|
|
17043
|
-
const fileBuffer = await
|
|
17366
|
+
const fileBuffer = await readFile13(filePath);
|
|
17044
17367
|
const uploadResponse = await fetch(uploadUrl, {
|
|
17045
17368
|
method: "PUT",
|
|
17046
17369
|
headers: { "Content-Type": contentType },
|
|
@@ -17065,7 +17388,7 @@ var uploadCommand2 = defineCommand144({
|
|
|
17065
17388
|
});
|
|
17066
17389
|
|
|
17067
17390
|
// src/commands/videos/index.ts
|
|
17068
|
-
var videosCommand =
|
|
17391
|
+
var videosCommand = defineCommand146({
|
|
17069
17392
|
meta: {
|
|
17070
17393
|
name: "videos",
|
|
17071
17394
|
description: `Find and manage videos in Baker. Subcommands: search, get, upload, delete, tags.
|
|
@@ -17088,10 +17411,10 @@ Examples:
|
|
|
17088
17411
|
});
|
|
17089
17412
|
|
|
17090
17413
|
// src/commands/winning-ads/index.ts
|
|
17091
|
-
import { defineCommand as
|
|
17414
|
+
import { defineCommand as defineCommand149 } from "citty";
|
|
17092
17415
|
|
|
17093
17416
|
// src/commands/winning-ads/advertisers.ts
|
|
17094
|
-
import { defineCommand as
|
|
17417
|
+
import { defineCommand as defineCommand147 } from "citty";
|
|
17095
17418
|
registerSchema({
|
|
17096
17419
|
command: "winning-ads.advertisers",
|
|
17097
17420
|
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).",
|
|
@@ -17104,7 +17427,7 @@ registerSchema({
|
|
|
17104
17427
|
function identity(record) {
|
|
17105
17428
|
return record;
|
|
17106
17429
|
}
|
|
17107
|
-
var advertisersCommand2 =
|
|
17430
|
+
var advertisersCommand2 = defineCommand147({
|
|
17108
17431
|
meta: {
|
|
17109
17432
|
name: "advertisers",
|
|
17110
17433
|
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'
|
|
@@ -17155,7 +17478,7 @@ var advertisersCommand2 = defineCommand146({
|
|
|
17155
17478
|
});
|
|
17156
17479
|
|
|
17157
17480
|
// src/commands/winning-ads/search.ts
|
|
17158
|
-
import { defineCommand as
|
|
17481
|
+
import { defineCommand as defineCommand148 } from "citty";
|
|
17159
17482
|
registerSchema({
|
|
17160
17483
|
command: "winning-ads.search",
|
|
17161
17484
|
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.",
|
|
@@ -17263,7 +17586,7 @@ function buildSearchBody(args) {
|
|
|
17263
17586
|
}
|
|
17264
17587
|
return body;
|
|
17265
17588
|
}
|
|
17266
|
-
var searchCommand4 =
|
|
17589
|
+
var searchCommand4 = defineCommand148({
|
|
17267
17590
|
meta: {
|
|
17268
17591
|
name: "search",
|
|
17269
17592
|
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"
|
|
@@ -17375,7 +17698,7 @@ var searchCommand4 = defineCommand147({
|
|
|
17375
17698
|
});
|
|
17376
17699
|
|
|
17377
17700
|
// src/commands/winning-ads/index.ts
|
|
17378
|
-
var winningAdsCommand =
|
|
17701
|
+
var winningAdsCommand = defineCommand149({
|
|
17379
17702
|
meta: {
|
|
17380
17703
|
name: "winning-ads",
|
|
17381
17704
|
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.
|
|
@@ -17415,7 +17738,7 @@ function getCliVersion() {
|
|
|
17415
17738
|
}
|
|
17416
17739
|
|
|
17417
17740
|
// src/cli.ts
|
|
17418
|
-
var main =
|
|
17741
|
+
var main = defineCommand150({
|
|
17419
17742
|
meta: {
|
|
17420
17743
|
name: "baker",
|
|
17421
17744
|
version: getCliVersion(),
|