@koda-sl/baker-cli 0.97.0 → 0.98.1
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-RCPMJKI7.js → chunk-3JVYU72O.js} +130 -24
- package/dist/chunk-3JVYU72O.js.map +1 -0
- package/dist/cli.js +524 -203
- 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-RCPMJKI7.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -9,10 +9,10 @@ import {
|
|
|
9
9
|
defaultRegistry,
|
|
10
10
|
generateCatalog,
|
|
11
11
|
validateCanvasDeep
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-3JVYU72O.js";
|
|
13
13
|
|
|
14
14
|
// src/cli.ts
|
|
15
|
-
import { defineCommand as
|
|
15
|
+
import { defineCommand as defineCommand149, runMain } from "citty";
|
|
16
16
|
|
|
17
17
|
// src/commands/actions/index.ts
|
|
18
18
|
import { defineCommand as defineCommand17 } from "citty";
|
|
@@ -147,9 +147,9 @@ async function handleResponse(response) {
|
|
|
147
147
|
throw new ApiError("INTERNAL_ERROR", "Failed to parse API response as JSON");
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
|
-
async function apiGet(
|
|
150
|
+
async function apiGet(path11, params) {
|
|
151
151
|
const env = getEnv();
|
|
152
|
-
const url = new URL(
|
|
152
|
+
const url = new URL(path11, env.BAKER_API_URL);
|
|
153
153
|
if (params) {
|
|
154
154
|
const clean = sanitizeParams(params);
|
|
155
155
|
for (const [key, value] of Object.entries(clean)) {
|
|
@@ -174,12 +174,12 @@ async function apiGet(path7, params) {
|
|
|
174
174
|
}
|
|
175
175
|
return handleResponse(response);
|
|
176
176
|
}
|
|
177
|
-
async function apiPost(
|
|
177
|
+
async function apiPost(path11, body, opts) {
|
|
178
178
|
const env = getEnv();
|
|
179
179
|
const timeoutMs = opts?.timeoutMs ?? 6e4;
|
|
180
180
|
let response;
|
|
181
181
|
try {
|
|
182
|
-
response = await fetchWithRateLimitRetry(new URL(
|
|
182
|
+
response = await fetchWithRateLimitRetry(new URL(path11, env.BAKER_API_URL).toString(), {
|
|
183
183
|
method: "POST",
|
|
184
184
|
headers: {
|
|
185
185
|
Authorization: `Bearer ${env.BAKER_API_KEY}`,
|
|
@@ -1327,31 +1327,31 @@ function cachePath(category, key) {
|
|
|
1327
1327
|
return join(dir, `${hashKey(key)}.json`);
|
|
1328
1328
|
}
|
|
1329
1329
|
function cacheGet(category, key) {
|
|
1330
|
-
const
|
|
1331
|
-
if (!existsSync(
|
|
1330
|
+
const path11 = cachePath(category, key);
|
|
1331
|
+
if (!existsSync(path11)) {
|
|
1332
1332
|
return null;
|
|
1333
1333
|
}
|
|
1334
1334
|
try {
|
|
1335
|
-
const raw = readFileSync(
|
|
1335
|
+
const raw = readFileSync(path11, "utf-8");
|
|
1336
1336
|
const entry = JSON.parse(raw);
|
|
1337
1337
|
if (entry.expiresAt < Date.now()) {
|
|
1338
|
-
rmSync(
|
|
1338
|
+
rmSync(path11, { force: true });
|
|
1339
1339
|
return null;
|
|
1340
1340
|
}
|
|
1341
1341
|
return entry;
|
|
1342
1342
|
} catch {
|
|
1343
|
-
rmSync(
|
|
1343
|
+
rmSync(path11, { force: true });
|
|
1344
1344
|
return null;
|
|
1345
1345
|
}
|
|
1346
1346
|
}
|
|
1347
1347
|
function cacheSet(category, key, data, ttlMs, fields) {
|
|
1348
|
-
const
|
|
1348
|
+
const path11 = cachePath(category, key);
|
|
1349
1349
|
const entry = {
|
|
1350
1350
|
expiresAt: Date.now() + ttlMs,
|
|
1351
1351
|
data,
|
|
1352
1352
|
fields
|
|
1353
1353
|
};
|
|
1354
|
-
writeFileSync(
|
|
1354
|
+
writeFileSync(path11, JSON.stringify(entry), "utf-8");
|
|
1355
1355
|
}
|
|
1356
1356
|
var HOUR = 60 * 60 * 1e3;
|
|
1357
1357
|
var MINUTE = 60 * 1e3;
|
|
@@ -8045,7 +8045,7 @@ Examples:
|
|
|
8045
8045
|
});
|
|
8046
8046
|
|
|
8047
8047
|
// src/commands/canvas/index.ts
|
|
8048
|
-
import { defineCommand as
|
|
8048
|
+
import { defineCommand as defineCommand85 } from "citty";
|
|
8049
8049
|
|
|
8050
8050
|
// src/commands/canvas/catalog.ts
|
|
8051
8051
|
import { defineCommand as defineCommand78 } from "citty";
|
|
@@ -8176,7 +8176,7 @@ async function probeDuration(filePath) {
|
|
|
8176
8176
|
|
|
8177
8177
|
// src/commands/canvas/run.ts
|
|
8178
8178
|
import { readFile as readFile2 } from "fs/promises";
|
|
8179
|
-
import
|
|
8179
|
+
import path4 from "path";
|
|
8180
8180
|
import { defineCommand as defineCommand80 } from "citty";
|
|
8181
8181
|
|
|
8182
8182
|
// src/commands/canvas/placeholders.ts
|
|
@@ -8195,6 +8195,57 @@ function unsuppliedPlaceholderAssets(canvas) {
|
|
|
8195
8195
|
return out;
|
|
8196
8196
|
}
|
|
8197
8197
|
|
|
8198
|
+
// src/commands/canvas/resolve-paths.ts
|
|
8199
|
+
import path2 from "path";
|
|
8200
|
+
function resolveRelativeCanvasPaths(canvas, baseDir) {
|
|
8201
|
+
if (!canvas || typeof canvas !== "object") return canvas;
|
|
8202
|
+
const c = canvas;
|
|
8203
|
+
if (!Array.isArray(c.nodes)) return canvas;
|
|
8204
|
+
return { ...canvas, nodes: c.nodes.map((n) => resolveNode(n, baseDir)) };
|
|
8205
|
+
}
|
|
8206
|
+
function resolveNode(node, baseDir) {
|
|
8207
|
+
if (!node || typeof node !== "object") return node;
|
|
8208
|
+
const n = node;
|
|
8209
|
+
const params = n.params;
|
|
8210
|
+
if (!params || typeof params !== "object") return node;
|
|
8211
|
+
if (n.type === "ingest" && params.source === "path" && isResolvableRelative(params.path)) {
|
|
8212
|
+
return { ...node, params: { ...params, path: path2.resolve(baseDir, params.path) } };
|
|
8213
|
+
}
|
|
8214
|
+
if (n.type === "hyperframe_render" && isResolvableRelative(params.composition)) {
|
|
8215
|
+
return { ...node, params: { ...params, composition: path2.resolve(baseDir, params.composition) } };
|
|
8216
|
+
}
|
|
8217
|
+
return node;
|
|
8218
|
+
}
|
|
8219
|
+
function isResolvableRelative(value) {
|
|
8220
|
+
return typeof value === "string" && value.length > 0 && !value.includes("[TODO") && !path2.isAbsolute(value);
|
|
8221
|
+
}
|
|
8222
|
+
|
|
8223
|
+
// src/commands/canvas/run-retention.ts
|
|
8224
|
+
import { rm } from "fs/promises";
|
|
8225
|
+
import path3 from "path";
|
|
8226
|
+
function runDirsToPrune(entries, keep, currentRunId) {
|
|
8227
|
+
const runs = entries.filter((e) => /^r_[0-9A-Za-z]+$/.test(e) && e !== currentRunId).sort();
|
|
8228
|
+
if (keep <= 0) return runs;
|
|
8229
|
+
return runs.slice(0, Math.max(0, runs.length - keep));
|
|
8230
|
+
}
|
|
8231
|
+
async function pruneOldRuns(outputsDir, keep, currentRunId, log) {
|
|
8232
|
+
const { readdir: readdir3 } = await import("fs/promises");
|
|
8233
|
+
let entries;
|
|
8234
|
+
try {
|
|
8235
|
+
entries = await readdir3(outputsDir);
|
|
8236
|
+
} catch {
|
|
8237
|
+
return;
|
|
8238
|
+
}
|
|
8239
|
+
const toPrune = runDirsToPrune(entries, keep, currentRunId);
|
|
8240
|
+
if (toPrune.length === 0) return;
|
|
8241
|
+
for (const dir of toPrune) {
|
|
8242
|
+
await rm(path3.join(outputsDir, dir), { recursive: true, force: true }).catch(
|
|
8243
|
+
(e) => log(`[prune ] could not remove ${dir}: ${e.message}`)
|
|
8244
|
+
);
|
|
8245
|
+
}
|
|
8246
|
+
log(`[prune ] removed ${toPrune.length} old run dir(s), kept the ${keep} newest`);
|
|
8247
|
+
}
|
|
8248
|
+
|
|
8198
8249
|
// src/commands/canvas/run.ts
|
|
8199
8250
|
var runCommand = defineCommand80({
|
|
8200
8251
|
meta: { name: "run", description: "Validate and execute a canvas JSON file." },
|
|
@@ -8203,10 +8254,14 @@ var runCommand = defineCommand80({
|
|
|
8203
8254
|
"cache-dir": { type: "string", description: "Cache root (default ./canvas/.cache)" },
|
|
8204
8255
|
"outputs-dir": { type: "string", description: "Per-run outputs root (default ./canvas)" },
|
|
8205
8256
|
"run-id": { type: "string", description: "Override run id" },
|
|
8206
|
-
"cache-policy": { type: "string", description: "read_write | bypass | read_only" }
|
|
8257
|
+
"cache-policy": { type: "string", description: "read_write | bypass | read_only" },
|
|
8258
|
+
"keep-runs": {
|
|
8259
|
+
type: "string",
|
|
8260
|
+
description: "After the run, prune old r_* run dirs, keeping the N newest (off by default)"
|
|
8261
|
+
}
|
|
8207
8262
|
},
|
|
8208
8263
|
async run({ args }) {
|
|
8209
|
-
const filePath =
|
|
8264
|
+
const filePath = path4.resolve(String(args.file));
|
|
8210
8265
|
const raw = await readFile2(filePath, "utf8");
|
|
8211
8266
|
let parsed;
|
|
8212
8267
|
try {
|
|
@@ -8217,6 +8272,7 @@ var runCommand = defineCommand80({
|
|
|
8217
8272
|
`);
|
|
8218
8273
|
process.exit(2);
|
|
8219
8274
|
}
|
|
8275
|
+
parsed = resolveRelativeCanvasPaths(parsed, path4.dirname(filePath));
|
|
8220
8276
|
const pending = unsuppliedPlaceholderAssets(parsed);
|
|
8221
8277
|
if (pending.length > 0) {
|
|
8222
8278
|
process.stderr.write(
|
|
@@ -8248,6 +8304,12 @@ var runCommand = defineCommand80({
|
|
|
8248
8304
|
run_id: args["run-id"] ? String(args["run-id"]) : void 0,
|
|
8249
8305
|
cache_policy: policy
|
|
8250
8306
|
});
|
|
8307
|
+
const keepRuns = args["keep-runs"] !== void 0 ? Number(args["keep-runs"]) : void 0;
|
|
8308
|
+
if (keepRuns !== void 0 && Number.isFinite(keepRuns)) {
|
|
8309
|
+
const outputsDir = args["outputs-dir"] ? path4.resolve(String(args["outputs-dir"])) : path4.resolve("canvas");
|
|
8310
|
+
await pruneOldRuns(outputsDir, keepRuns, result.run_id, (line) => process.stdout.write(`${line}
|
|
8311
|
+
`));
|
|
8312
|
+
}
|
|
8251
8313
|
process.stdout.write(
|
|
8252
8314
|
`${JSON.stringify(
|
|
8253
8315
|
{
|
|
@@ -8280,7 +8342,7 @@ var runCommand = defineCommand80({
|
|
|
8280
8342
|
|
|
8281
8343
|
// src/commands/canvas/scaffold-static-ad.ts
|
|
8282
8344
|
import { readFile as readFile3, writeFile } from "fs/promises";
|
|
8283
|
-
import
|
|
8345
|
+
import path5 from "path";
|
|
8284
8346
|
import { defineCommand as defineCommand81 } from "citty";
|
|
8285
8347
|
|
|
8286
8348
|
// src/engine/scaffold/staticAd.ts
|
|
@@ -8617,10 +8679,10 @@ var scaffoldStaticAdCommand = defineCommand81({
|
|
|
8617
8679
|
"skip-font": { type: "boolean", description: "Skip the brand-font \u2192 type-specimen slot" }
|
|
8618
8680
|
},
|
|
8619
8681
|
async run({ args }) {
|
|
8620
|
-
const imagePath =
|
|
8621
|
-
const outPath = args.out ?
|
|
8622
|
-
const outDir =
|
|
8623
|
-
const blueprintPath =
|
|
8682
|
+
const imagePath = path5.resolve(String(args.file));
|
|
8683
|
+
const outPath = args.out ? path5.resolve(String(args.out)) : path5.join(path5.dirname(imagePath), "static-ad.canvas.json");
|
|
8684
|
+
const outDir = path5.dirname(outPath);
|
|
8685
|
+
const blueprintPath = path5.join(outDir, "prompt.json");
|
|
8624
8686
|
const { describeModel, selectModel, layoutModel, genModel } = resolveModels(args);
|
|
8625
8687
|
const describeCanvas = buildDescribeCanvas(
|
|
8626
8688
|
imagePath,
|
|
@@ -8677,7 +8739,7 @@ var scaffoldStaticAdCommand = defineCommand81({
|
|
|
8677
8739
|
run_estimated_credits: validation.estimatedCredits
|
|
8678
8740
|
},
|
|
8679
8741
|
checklist: {
|
|
8680
|
-
edit_prompt: `Edit ${
|
|
8742
|
+
edit_prompt: `Edit ${path5.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.`,
|
|
8681
8743
|
assets_to_supply: report.elements,
|
|
8682
8744
|
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)",
|
|
8683
8745
|
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."
|
|
@@ -8692,13 +8754,13 @@ var scaffoldStaticAdCommand = defineCommand81({
|
|
|
8692
8754
|
});
|
|
8693
8755
|
|
|
8694
8756
|
// src/commands/canvas/scaffold-video.ts
|
|
8695
|
-
import { cp, mkdir, readFile as
|
|
8696
|
-
import
|
|
8757
|
+
import { cp, mkdir, readFile as readFile6, writeFile as writeFile2 } from "fs/promises";
|
|
8758
|
+
import path8 from "path";
|
|
8697
8759
|
import { defineCommand as defineCommand82 } from "citty";
|
|
8698
8760
|
|
|
8699
8761
|
// src/engine/nodes/local/lib/sceneDetect.ts
|
|
8700
8762
|
import { execFile as execFile2 } from "child_process";
|
|
8701
|
-
import { mkdtemp, readdir as readdir2, readFile as readFile4, rm } from "fs/promises";
|
|
8763
|
+
import { mkdtemp, readdir as readdir2, readFile as readFile4, rm as rm2 } from "fs/promises";
|
|
8702
8764
|
import { tmpdir } from "os";
|
|
8703
8765
|
import { join as join2 } from "path";
|
|
8704
8766
|
import { promisify as promisify2 } from "util";
|
|
@@ -8766,7 +8828,7 @@ async function runSceneDetectOnce(filePath, threshold, minSceneLenS, timeoutMs)
|
|
|
8766
8828
|
if (!csvName) return [];
|
|
8767
8829
|
return parsePySceneDetectCsvCuts(await readFile4(join2(outDir, csvName), "utf-8"));
|
|
8768
8830
|
} finally {
|
|
8769
|
-
await
|
|
8831
|
+
await rm2(outDir, { recursive: true, force: true });
|
|
8770
8832
|
}
|
|
8771
8833
|
}
|
|
8772
8834
|
async function detectSceneCutsPySceneDetect(filePath, opts = {}) {
|
|
@@ -9022,6 +9084,13 @@ function stillHoldArgs(durationS, dims) {
|
|
|
9022
9084
|
`scale=${dims.w}:${dims.h}:force_original_aspect_ratio=increase,crop=${dims.w}:${dims.h},setsar=1,format=yuv420p`,
|
|
9023
9085
|
"-c:v",
|
|
9024
9086
|
"libx264",
|
|
9087
|
+
// Near-visually-lossless re-encode. libx264 DEFAULTS (crf 23, preset medium)
|
|
9088
|
+
// roughly halve the source bitrate and add banding on smooth surfaces; the
|
|
9089
|
+
// spine concats these by stream-copy, so any loss here ships to the final cut.
|
|
9090
|
+
"-crf",
|
|
9091
|
+
"18",
|
|
9092
|
+
"-preset",
|
|
9093
|
+
"slow",
|
|
9025
9094
|
"-pix_fmt",
|
|
9026
9095
|
"yuv420p",
|
|
9027
9096
|
"{{out.video}}"
|
|
@@ -9037,6 +9106,13 @@ function trimArgs(durationS, offsetS = 0) {
|
|
|
9037
9106
|
"-an",
|
|
9038
9107
|
"-c:v",
|
|
9039
9108
|
"libx264",
|
|
9109
|
+
// Preserve the seedance source quality through the trim. libx264 DEFAULTS
|
|
9110
|
+
// (crf 23) halve the bitrate (measured 9.57→4.40 Mbps) and band on motion;
|
|
9111
|
+
// the spine stream-copies the result, so the loss is permanent without this.
|
|
9112
|
+
"-crf",
|
|
9113
|
+
"18",
|
|
9114
|
+
"-preset",
|
|
9115
|
+
"slow",
|
|
9040
9116
|
"-pix_fmt",
|
|
9041
9117
|
"yuv420p",
|
|
9042
9118
|
"{{out.video}}"
|
|
@@ -9103,6 +9179,13 @@ var Scene = z3.object({
|
|
|
9103
9179
|
// The scene's role in the ad's persuasion arc (DECON-supplied); drives the
|
|
9104
9180
|
// script re-craft checklist. Inferred from position when absent.
|
|
9105
9181
|
narrative_role: z3.string().optional(),
|
|
9182
|
+
// DECON-supplied on the HOOK scene: the engineered physical/emotional state that
|
|
9183
|
+
// makes the first frame stop the scroll (sweaty/breathless/urgent …). Injected
|
|
9184
|
+
// into the hook's start-frame description so the generator renders that state,
|
|
9185
|
+
// not a calm influencer (CCA-11).
|
|
9186
|
+
hook_mechanic: z3.object({ mechanic: z3.string().optional(), why_it_stops_scroll: z3.string().optional() }).loose().optional(),
|
|
9187
|
+
// DECON-supplied per-scene location (so a gym hook isn't flattened to "home").
|
|
9188
|
+
scene_setting: z3.string().optional(),
|
|
9106
9189
|
// How this scene cuts to the next (DECON-supplied). A recognized non-cut type
|
|
9107
9190
|
// (fade/whip/zoom/dissolve/swipe) is reproduced as an ffmpeg xfade at the
|
|
9108
9191
|
// boundary; cut/match_cut/none/other stay hard cuts. The last scene's value is
|
|
@@ -9150,10 +9233,21 @@ var VideoBlueprint = z3.object({
|
|
|
9150
9233
|
mode: z3.string().optional(),
|
|
9151
9234
|
voice_description: z3.string().optional(),
|
|
9152
9235
|
persona: z3.string().optional()
|
|
9153
|
-
}).loose().optional()
|
|
9236
|
+
}).loose().optional(),
|
|
9237
|
+
// Visual palette — read only to colour a clean brand-card/CTA plate (the
|
|
9238
|
+
// first hex is the dominant brand colour); never to drive frame generation.
|
|
9239
|
+
style: z3.object({ palette: z3.array(z3.object({ hex: z3.string().optional() }).loose()).optional() }).loose().optional()
|
|
9154
9240
|
}).loose().optional(),
|
|
9155
9241
|
scenes: z3.array(Scene).min(1)
|
|
9156
9242
|
}).loose();
|
|
9243
|
+
function injectHookPhysicality(blueprint) {
|
|
9244
|
+
for (const scene of blueprint.scenes) {
|
|
9245
|
+
const why = scene.hook_mechanic?.why_it_stops_scroll?.trim();
|
|
9246
|
+
const prompt = scene.start_frame_prompt?.trim();
|
|
9247
|
+
if (!why || !prompt || prompt.includes(why)) continue;
|
|
9248
|
+
scene.start_frame_prompt = `${prompt} The subject's physical state IS the scroll-stopper \u2014 render it explicitly, not a calm pose: ${why}.`;
|
|
9249
|
+
}
|
|
9250
|
+
}
|
|
9157
9251
|
var AppearsItem = z3.union([z3.number(), z3.object({ scene: z3.number(), edge: z3.string().optional() }).loose()]);
|
|
9158
9252
|
var RecurringElement = z3.object({
|
|
9159
9253
|
// person | animal | product | logo | badge | other
|
|
@@ -9179,7 +9273,8 @@ function sanitizeId2(raw, fallback) {
|
|
|
9179
9273
|
return /^[a-z]/.test(id) ? id : `${fallback}_${id}`.replace(/_+$/g, "") || fallback;
|
|
9180
9274
|
}
|
|
9181
9275
|
function labelFor2(el, used) {
|
|
9182
|
-
const
|
|
9276
|
+
const raw = el.type?.toLowerCase() === "logo" ? "BRAND_LOGO" : el.label ?? el.type ?? "ELEMENT";
|
|
9277
|
+
const base = raw.toUpperCase().replace(/[^A-Z0-9]+/g, "_").replace(/^_+|_+$/g, "") || "ELEMENT";
|
|
9183
9278
|
let label = base;
|
|
9184
9279
|
let n = 2;
|
|
9185
9280
|
while (used.has(label)) label = `${base}_${n++}`;
|
|
@@ -9346,6 +9441,8 @@ function buildElementSheets(slots, nodes) {
|
|
|
9346
9441
|
if (slot.sameAs) continue;
|
|
9347
9442
|
if (slot.presence.size < 1) continue;
|
|
9348
9443
|
const sheetId = `${slot.id}_sheet`;
|
|
9444
|
+
const slotType = slot.type.toLowerCase();
|
|
9445
|
+
const isCast = slotType === "person" || slotType === "animal";
|
|
9349
9446
|
nodes.push({
|
|
9350
9447
|
id: sheetId,
|
|
9351
9448
|
type: "image_reference_sheet",
|
|
@@ -9358,7 +9455,14 @@ function buildElementSheets(slots, nodes) {
|
|
|
9358
9455
|
// 4K: the sheet packs up to 8 cells (angles + tight face/detail close-ups), and
|
|
9359
9456
|
// it's the ONE reference every frame grounds on — per-cell sharpness here
|
|
9360
9457
|
// propagates to every clip, so it's worth the highest tier on this single asset.
|
|
9361
|
-
image_size: "4K"
|
|
9458
|
+
image_size: "4K",
|
|
9459
|
+
// The sheet is the look that propagates to EVERY grounded frame, so a glossy
|
|
9460
|
+
// studio turnaround makes the whole UGC ad read as "produced" (the #1 AI tell).
|
|
9461
|
+
// Force a flat, real, front-camera look on the cast sheet so the actor stays
|
|
9462
|
+
// authentic, not an airbrushed influencer (CCA-02).
|
|
9463
|
+
...isCast ? {
|
|
9464
|
+
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"
|
|
9465
|
+
} : {}
|
|
9362
9466
|
}
|
|
9363
9467
|
});
|
|
9364
9468
|
slot.ref = `$ref:${sheetId}.sheet`;
|
|
@@ -9466,8 +9570,7 @@ function buildFrameRef(edge, url, framePrompt, present, ctx, nodes) {
|
|
|
9466
9570
|
const t = s.type.toLowerCase();
|
|
9467
9571
|
return t === "person" || t === "animal";
|
|
9468
9572
|
});
|
|
9469
|
-
const
|
|
9470
|
-
const useOriginalAnchor = Boolean(url) && (castSlots.length === 0 || castIdentityLocked);
|
|
9573
|
+
const useOriginalAnchor = Boolean(url) && castSlots.length === 0;
|
|
9471
9574
|
const hasOriginal = useOriginalAnchor;
|
|
9472
9575
|
const originalRef = useOriginalAnchor && url ? ingestFrameRef(url, edge, ctx, nodes) : void 0;
|
|
9473
9576
|
const reference = [...present.map((s) => s.ref), ...originalRef ? [originalRef] : []];
|
|
@@ -9678,6 +9781,39 @@ function isUiOnlyComposite(regions) {
|
|
|
9678
9781
|
const ui = regions.filter(regionIsUiSurface).length;
|
|
9679
9782
|
return ui >= 1 && regions.length - ui <= 1;
|
|
9680
9783
|
}
|
|
9784
|
+
function sceneIsFullScreenUi(scene, present) {
|
|
9785
|
+
if (scene.narrative_role?.trim() === "cta") return false;
|
|
9786
|
+
const hasCast = present.some((s) => {
|
|
9787
|
+
const t = s.type.toLowerCase();
|
|
9788
|
+
return t === "person" || t === "animal";
|
|
9789
|
+
});
|
|
9790
|
+
if (hasCast) return false;
|
|
9791
|
+
const hay = `${scene.summary ?? ""} ${scene.start_frame_prompt ?? ""} ${scene.end_frame_prompt ?? ""} ${scene.action_detail ?? ""}`;
|
|
9792
|
+
return UI_SURFACE_RE.test(hay);
|
|
9793
|
+
}
|
|
9794
|
+
function screenStillArgs(durationS, dims) {
|
|
9795
|
+
return [
|
|
9796
|
+
"-loop",
|
|
9797
|
+
"1",
|
|
9798
|
+
"-i",
|
|
9799
|
+
"{{in.frame}}",
|
|
9800
|
+
"-t",
|
|
9801
|
+
durationS.toFixed(3),
|
|
9802
|
+
"-r",
|
|
9803
|
+
"30",
|
|
9804
|
+
"-vf",
|
|
9805
|
+
`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`,
|
|
9806
|
+
"-c:v",
|
|
9807
|
+
"libx264",
|
|
9808
|
+
"-crf",
|
|
9809
|
+
"18",
|
|
9810
|
+
"-preset",
|
|
9811
|
+
"slow",
|
|
9812
|
+
"-pix_fmt",
|
|
9813
|
+
"yuv420p",
|
|
9814
|
+
"{{out.video}}"
|
|
9815
|
+
];
|
|
9816
|
+
}
|
|
9681
9817
|
function layeredComposition(scene) {
|
|
9682
9818
|
const comp = scene.composition;
|
|
9683
9819
|
const layout = (comp?.layout ?? "").toLowerCase();
|
|
@@ -9848,6 +9984,77 @@ function emitFlashHold(i, scene, slots, ctx, lengths, out, ar, nodes, clips) {
|
|
|
9848
9984
|
});
|
|
9849
9985
|
clips.push({ ref: `$ref:s${i}_clip.video`, scene_s: lengths.dur, out });
|
|
9850
9986
|
}
|
|
9987
|
+
function emitScreenScene(i, scene, lengths, out, ar, nodes, clips) {
|
|
9988
|
+
const label = commentSafe((scene.summary || scene.start_frame_prompt || "the app screen").slice(0, 120));
|
|
9989
|
+
const refId = `s${i}_screen_ref`;
|
|
9990
|
+
nodes.push({
|
|
9991
|
+
id: refId,
|
|
9992
|
+
type: "ingest",
|
|
9993
|
+
params: {
|
|
9994
|
+
source: "path",
|
|
9995
|
+
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]`,
|
|
9996
|
+
expect: "image"
|
|
9997
|
+
}
|
|
9998
|
+
});
|
|
9999
|
+
nodes.push({
|
|
10000
|
+
id: `s${i}_clip`,
|
|
10001
|
+
type: "ffmpeg",
|
|
10002
|
+
inputs: { frame: `$ref:${refId}.asset` },
|
|
10003
|
+
params: {
|
|
10004
|
+
args: screenStillArgs(lengths.trimTarget, canvasDims(ar)),
|
|
10005
|
+
outputs: { video: { kind: "video", ext: "mp4" } }
|
|
10006
|
+
}
|
|
10007
|
+
});
|
|
10008
|
+
clips.push({ ref: `$ref:s${i}_clip.video`, scene_s: lengths.dur, out });
|
|
10009
|
+
}
|
|
10010
|
+
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;
|
|
10011
|
+
function sceneIsBrandCard(scene, present, isCta) {
|
|
10012
|
+
if (!isCta) return false;
|
|
10013
|
+
const hasCast = present.some((s) => {
|
|
10014
|
+
const t = s.type.toLowerCase();
|
|
10015
|
+
return t === "person" || t === "animal";
|
|
10016
|
+
});
|
|
10017
|
+
if (hasCast) return false;
|
|
10018
|
+
const hay = `${scene.summary ?? ""} ${scene.start_frame_prompt ?? ""} ${scene.end_frame_prompt ?? ""}`;
|
|
10019
|
+
return BRAND_CARD_RE.test(hay);
|
|
10020
|
+
}
|
|
10021
|
+
var HEX6_RE = /^#?[0-9a-fA-F]{6}$/;
|
|
10022
|
+
function brandPlateColor(blueprint) {
|
|
10023
|
+
const palette = blueprint.global?.style?.palette;
|
|
10024
|
+
const hex = palette?.map((p) => p?.hex).find((h) => typeof h === "string" && HEX6_RE.test(h));
|
|
10025
|
+
return hex ? `0x${hex.replace(/^#/, "").toUpperCase()}` : "0x000000";
|
|
10026
|
+
}
|
|
10027
|
+
function colorPlateArgs(durationS, dims, color) {
|
|
10028
|
+
return [
|
|
10029
|
+
"-f",
|
|
10030
|
+
"lavfi",
|
|
10031
|
+
"-i",
|
|
10032
|
+
`color=c=${color}:s=${dims.w}x${dims.h}:r=30`,
|
|
10033
|
+
"-t",
|
|
10034
|
+
durationS.toFixed(3),
|
|
10035
|
+
"-c:v",
|
|
10036
|
+
"libx264",
|
|
10037
|
+
"-crf",
|
|
10038
|
+
"18",
|
|
10039
|
+
"-preset",
|
|
10040
|
+
"slow",
|
|
10041
|
+
"-pix_fmt",
|
|
10042
|
+
"yuv420p",
|
|
10043
|
+
"{{out.video}}"
|
|
10044
|
+
];
|
|
10045
|
+
}
|
|
10046
|
+
function emitBrandCardScene(i, lengths, out, ar, color, nodes, clips) {
|
|
10047
|
+
nodes.push({
|
|
10048
|
+
id: `s${i}_clip`,
|
|
10049
|
+
type: "ffmpeg",
|
|
10050
|
+
inputs: {},
|
|
10051
|
+
params: {
|
|
10052
|
+
args: colorPlateArgs(lengths.trimTarget, canvasDims(ar), color),
|
|
10053
|
+
outputs: { video: { kind: "video", ext: "mp4" } }
|
|
10054
|
+
}
|
|
10055
|
+
});
|
|
10056
|
+
clips.push({ ref: `$ref:s${i}_clip.video`, scene_s: lengths.dur, out });
|
|
10057
|
+
}
|
|
9851
10058
|
function musicArcDigest(blueprint) {
|
|
9852
10059
|
const roles = blueprint.scenes.map((s) => s.narrative_role).filter((r) => Boolean(r));
|
|
9853
10060
|
const arc = roles.length > 0 ? roles.join(" \u2192 ") : "";
|
|
@@ -9967,7 +10174,7 @@ function makePresenterPresent(slots, canonical, opts = {}) {
|
|
|
9967
10174
|
const solePerson = !opts.strict && personSlots.length === 1 ? personSlots[0].presence : null;
|
|
9968
10175
|
return (speaker, sceneIndex) => {
|
|
9969
10176
|
const presence = bySpeaker.get(speaker) ?? solePerson;
|
|
9970
|
-
if (!presence) return opts.strict
|
|
10177
|
+
if (!presence) return !opts.strict;
|
|
9971
10178
|
return presence.has(sceneIndex);
|
|
9972
10179
|
};
|
|
9973
10180
|
}
|
|
@@ -10332,6 +10539,15 @@ function emitBrollScene(scene, i, isLast, env, nodes, out, prevEndFrame) {
|
|
|
10332
10539
|
shootMode: mode,
|
|
10333
10540
|
ingestCache: env.ingestCache
|
|
10334
10541
|
};
|
|
10542
|
+
if (!env.reuse && sceneIsFullScreenUi(scene, present)) {
|
|
10543
|
+
emitScreenScene(i, scene, lengths, lengths.out, env.ar, nodes, out.clips);
|
|
10544
|
+
return void 0;
|
|
10545
|
+
}
|
|
10546
|
+
const isCta = scene.narrative_role?.trim() === "cta" || isLast;
|
|
10547
|
+
if (!env.reuse && sceneIsBrandCard(scene, present, isCta)) {
|
|
10548
|
+
emitBrandCardScene(i, lengths, lengths.out, env.ar, brandPlateColor(env.blueprint), nodes, out.clips);
|
|
10549
|
+
return void 0;
|
|
10550
|
+
}
|
|
10335
10551
|
if (!ambientBroll && lengths.dur <= FLASH_HOLD_MAX_S) {
|
|
10336
10552
|
emitFlashHold(i, scene, env.slots, ctx, lengths, lengths.out, env.ar, nodes, out.clips);
|
|
10337
10553
|
return void 0;
|
|
@@ -10597,7 +10813,7 @@ function overlayElement(ov, at, dur) {
|
|
|
10597
10813
|
const normAnim = normalizeAnim(ov.animation);
|
|
10598
10814
|
const anim = normAnim ? ` data-anim="${normAnim}"` : "";
|
|
10599
10815
|
const detail = ov.animation_detail ? ` data-anim-detail="${escapeHtml(ov.animation_detail)}"` : "";
|
|
10600
|
-
return `<div class="ov ${positionClass(ov.position)}" data-start="${at}" data-dur="${dur}"${role}${anim}${detail}>${escapeHtml(ov.text.trim())}</div>`;
|
|
10816
|
+
return `<div class="ov clip ${positionClass(ov.position)}" data-start="${at}" data-dur="${dur}"${role}${anim}${detail}>${escapeHtml(ov.text.trim())}</div>`;
|
|
10601
10817
|
}
|
|
10602
10818
|
var RICH_OVERLAY_RE = /notif|tweet|\bx post\b|post\b|comment|message|chat|bubble|card|review|rating|stat|counter|toast|popup/;
|
|
10603
10819
|
function sourceHint(fe) {
|
|
@@ -10627,7 +10843,7 @@ function floatingStub(fe, sceneStart) {
|
|
|
10627
10843
|
const slug = (fe.kind ?? "element").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "element";
|
|
10628
10844
|
return [
|
|
10629
10845
|
`<!-- ${kind}: ${label} @ ${at}s for ${dur}s (${positionClass(fe.position)}). Source a real asset: ${hint} \u2014 drop it in this dir and uncomment:`,
|
|
10630
|
-
`<img class="ov ${positionClass(fe.position)}" src="your-${slug}.png" data-start="${at}" data-dur="${dur}" alt="" /> -->`
|
|
10846
|
+
`<img class="ov clip ${positionClass(fe.position)}" src="your-${slug}.png" data-start="${at}" data-dur="${dur}" alt="" /> -->`
|
|
10631
10847
|
].join("\n");
|
|
10632
10848
|
}
|
|
10633
10849
|
function uiPipStub(scene) {
|
|
@@ -10647,7 +10863,7 @@ function uiPipStub(scene) {
|
|
|
10647
10863
|
" \u2014 OR hand-build a brand-accurate HTML screen; then frame it in a phone mockup:",
|
|
10648
10864
|
" npx hyperframes add phone-scroll (writes compositions/phone-scroll.html)",
|
|
10649
10865
|
" drop the screenshot as screenshot.png in this dir and nest it as a PIP clip:",
|
|
10650
|
-
` <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> -->`
|
|
10866
|
+
` <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> -->`
|
|
10651
10867
|
].join("\n");
|
|
10652
10868
|
}
|
|
10653
10869
|
function buildOverlayHtml(input) {
|
|
@@ -10743,6 +10959,7 @@ function buildSpine(clips, nodes) {
|
|
|
10743
10959
|
}
|
|
10744
10960
|
function scaffoldVideoCanvas(input, elementsInput, opts) {
|
|
10745
10961
|
const blueprint = VideoBlueprint.parse(input);
|
|
10962
|
+
injectHookPhysicality(blueprint);
|
|
10746
10963
|
const elements = RecurringElements.parse(elementsInput);
|
|
10747
10964
|
const nodes = [];
|
|
10748
10965
|
nodes.push({
|
|
@@ -11154,18 +11371,44 @@ function videoReport(input, elementsInput) {
|
|
|
11154
11371
|
|
|
11155
11372
|
// src/commands/canvas/composition-path.ts
|
|
11156
11373
|
import { existsSync as existsSync3 } from "fs";
|
|
11157
|
-
import
|
|
11374
|
+
import path6 from "path";
|
|
11158
11375
|
function resolveShippedCanvasDir(name, startDir, exists = existsSync3, maxDepth = 8) {
|
|
11159
|
-
const rel =
|
|
11376
|
+
const rel = path6.join("canvas", name);
|
|
11160
11377
|
let dir = startDir;
|
|
11161
11378
|
for (let i = 0; i < maxDepth; i++) {
|
|
11162
|
-
const candidate =
|
|
11163
|
-
if (exists(
|
|
11164
|
-
const parent =
|
|
11379
|
+
const candidate = path6.join(dir, rel);
|
|
11380
|
+
if (exists(path6.join(candidate, "meta.json"))) return candidate;
|
|
11381
|
+
const parent = path6.dirname(dir);
|
|
11165
11382
|
if (parent === dir) break;
|
|
11166
11383
|
dir = parent;
|
|
11167
11384
|
}
|
|
11168
|
-
return
|
|
11385
|
+
return path6.resolve(startDir, "../../../", rel);
|
|
11386
|
+
}
|
|
11387
|
+
|
|
11388
|
+
// src/commands/canvas/gitignore.ts
|
|
11389
|
+
import { appendFile, readFile as readFile5 } from "fs/promises";
|
|
11390
|
+
import path7 from "path";
|
|
11391
|
+
function missingGitignoreEntries(existing, entries) {
|
|
11392
|
+
const present = new Set(
|
|
11393
|
+
existing.split("\n").map((l) => l.trim().replace(/\/+$/, "")).filter((l) => l.length > 0 && !l.startsWith("#"))
|
|
11394
|
+
);
|
|
11395
|
+
return entries.filter((e) => !present.has(e.trim().replace(/\/+$/, "")));
|
|
11396
|
+
}
|
|
11397
|
+
async function ensureGitignore(dir, entries) {
|
|
11398
|
+
const file = path7.join(dir, ".gitignore");
|
|
11399
|
+
let existing;
|
|
11400
|
+
try {
|
|
11401
|
+
existing = await readFile5(file, "utf8");
|
|
11402
|
+
} catch {
|
|
11403
|
+
return;
|
|
11404
|
+
}
|
|
11405
|
+
const missing = missingGitignoreEntries(existing, entries);
|
|
11406
|
+
if (missing.length === 0) return;
|
|
11407
|
+
const prefix = existing.endsWith("\n") || existing.length === 0 ? "" : "\n";
|
|
11408
|
+
await appendFile(file, `${prefix}
|
|
11409
|
+
# Baker canvas (engine cache + scaffold working files)
|
|
11410
|
+
${missing.join("\n")}
|
|
11411
|
+
`);
|
|
11169
11412
|
}
|
|
11170
11413
|
|
|
11171
11414
|
// src/commands/canvas/scaffold-video.ts
|
|
@@ -11194,7 +11437,7 @@ ONE PERSON, MULTIPLE LOOKS: if a single individual plays MULTIPLE personas or wa
|
|
|
11194
11437
|
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.`;
|
|
11195
11438
|
async function loadAssetText2(ref, label) {
|
|
11196
11439
|
const r = ref;
|
|
11197
|
-
if (typeof r?.path === "string") return
|
|
11440
|
+
if (typeof r?.path === "string") return readFile6(r.path, "utf8");
|
|
11198
11441
|
if (typeof r?.url === "string") {
|
|
11199
11442
|
const res = await fetch(r.url);
|
|
11200
11443
|
if (!res.ok) throw new Error(`failed to fetch ${label} (${res.status})`);
|
|
@@ -11213,7 +11456,7 @@ async function loadTranscriptBestEffort(ref) {
|
|
|
11213
11456
|
async function stageCaptions(outDir, transcript) {
|
|
11214
11457
|
const text = transcript?.trim();
|
|
11215
11458
|
if (!text || text === "[]") return {};
|
|
11216
|
-
const compositionPath =
|
|
11459
|
+
const compositionPath = path8.join(outDir, "tiktok-captions-composition");
|
|
11217
11460
|
await cp(SHIPPED_CAPTIONS_DIR, compositionPath, { recursive: true });
|
|
11218
11461
|
return { compositionPath };
|
|
11219
11462
|
}
|
|
@@ -11375,11 +11618,11 @@ var scaffoldVideoCommand = defineCommand82({
|
|
|
11375
11618
|
}
|
|
11376
11619
|
},
|
|
11377
11620
|
async run({ args }) {
|
|
11378
|
-
const videoPath =
|
|
11379
|
-
const base =
|
|
11380
|
-
const outPath = args.out ?
|
|
11381
|
-
const outDir =
|
|
11382
|
-
const blueprintPath =
|
|
11621
|
+
const videoPath = path8.resolve(String(args.file));
|
|
11622
|
+
const base = path8.basename(videoPath, path8.extname(videoPath));
|
|
11623
|
+
const outPath = args.out ? path8.resolve(String(args.out)) : path8.join(path8.dirname(videoPath), `${base}.video.canvas.json`);
|
|
11624
|
+
const outDir = path8.dirname(outPath);
|
|
11625
|
+
const blueprintPath = path8.join(outDir, "prompt.json");
|
|
11383
11626
|
const frames = args.frames === "reuse" ? "reuse" : "generate";
|
|
11384
11627
|
const maxScenes = args["max-scenes"] ? Number(args["max-scenes"]) : void 0;
|
|
11385
11628
|
if (Number.isFinite(maxScenes)) {
|
|
@@ -11402,11 +11645,11 @@ var scaffoldVideoCommand = defineCommand82({
|
|
|
11402
11645
|
const annotated = annotateBlueprintWithElements(blueprint, elements);
|
|
11403
11646
|
await writeFile2(blueprintPath, `${JSON.stringify(annotated, null, 2)}
|
|
11404
11647
|
`, "utf8");
|
|
11405
|
-
const compositionDest =
|
|
11648
|
+
const compositionDest = path8.join(outDir, "video-overlay-composition");
|
|
11406
11649
|
await cp(SHIPPED_COMPOSITION_DIR, compositionDest, { recursive: true });
|
|
11407
|
-
const indexPath =
|
|
11650
|
+
const indexPath = path8.join(compositionDest, "index.html");
|
|
11408
11651
|
const overlayHtml = buildOverlayHtml(blueprint);
|
|
11409
|
-
const indexHtml = await
|
|
11652
|
+
const indexHtml = await readFile6(indexPath, "utf8");
|
|
11410
11653
|
const injected = indexHtml.replace("<!--OVERLAYS-->", () => overlayHtml);
|
|
11411
11654
|
if (injected === indexHtml && overlayHtml.trim()) {
|
|
11412
11655
|
fail2(
|
|
@@ -11419,9 +11662,9 @@ var scaffoldVideoCommand = defineCommand82({
|
|
|
11419
11662
|
const opts = {
|
|
11420
11663
|
imageModel,
|
|
11421
11664
|
videoModel,
|
|
11422
|
-
overlayCompositionPath: compositionDest,
|
|
11423
|
-
captionsCompositionPath: captions.compositionPath,
|
|
11424
|
-
blueprintPath,
|
|
11665
|
+
overlayCompositionPath: path8.relative(outDir, compositionDest),
|
|
11666
|
+
captionsCompositionPath: captions.compositionPath ? path8.relative(outDir, captions.compositionPath) : void 0,
|
|
11667
|
+
blueprintPath: path8.relative(outDir, blueprintPath),
|
|
11425
11668
|
frames,
|
|
11426
11669
|
ambient: Boolean(args.ambient),
|
|
11427
11670
|
...args.resolution ? { resolution: String(args.resolution) } : {}
|
|
@@ -11434,7 +11677,7 @@ var scaffoldVideoCommand = defineCommand82({
|
|
|
11434
11677
|
} catch (e) {
|
|
11435
11678
|
return fail2("scaffold", e instanceof Error ? e.message : String(e));
|
|
11436
11679
|
}
|
|
11437
|
-
const validation = await validateCanvasDeep(canvas, defaultRegistry());
|
|
11680
|
+
const validation = await validateCanvasDeep(resolveRelativeCanvasPaths(canvas, outDir), defaultRegistry());
|
|
11438
11681
|
if (!validation.ok) {
|
|
11439
11682
|
process.stderr.write(
|
|
11440
11683
|
`${JSON.stringify({ ok: false, error: { code: "validation", issues: validation.issues } }, null, 2)}
|
|
@@ -11444,6 +11687,7 @@ var scaffoldVideoCommand = defineCommand82({
|
|
|
11444
11687
|
}
|
|
11445
11688
|
await writeFile2(outPath, `${JSON.stringify(canvas, null, 2)}
|
|
11446
11689
|
`, "utf8");
|
|
11690
|
+
await ensureGitignore(process.cwd(), ["canvas/", ".context/"]);
|
|
11447
11691
|
process.stdout.write(
|
|
11448
11692
|
`${JSON.stringify(
|
|
11449
11693
|
{
|
|
@@ -11461,7 +11705,7 @@ var scaffoldVideoCommand = defineCommand82({
|
|
|
11461
11705
|
run_estimated_credits: validation.estimatedCredits
|
|
11462
11706
|
},
|
|
11463
11707
|
checklist: {
|
|
11464
|
-
edit_prompt: `Edit ${
|
|
11708
|
+
edit_prompt: `Edit ${path8.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.`,
|
|
11465
11709
|
recurring_elements_to_supply: report.elements,
|
|
11466
11710
|
voices_to_confirm: report.dialogue.map((d) => ({
|
|
11467
11711
|
scene: d.scene,
|
|
@@ -11486,19 +11730,94 @@ var scaffoldVideoCommand = defineCommand82({
|
|
|
11486
11730
|
}
|
|
11487
11731
|
});
|
|
11488
11732
|
|
|
11489
|
-
// src/commands/canvas/
|
|
11490
|
-
import { readFile as
|
|
11491
|
-
import
|
|
11733
|
+
// src/commands/canvas/set-prompt.ts
|
|
11734
|
+
import { readFile as readFile7, writeFile as writeFile3 } from "fs/promises";
|
|
11735
|
+
import path9 from "path";
|
|
11492
11736
|
import { defineCommand as defineCommand83 } from "citty";
|
|
11493
|
-
|
|
11737
|
+
function setNodePrompt(canvas, nodeId, text) {
|
|
11738
|
+
const nodes = canvas?.nodes;
|
|
11739
|
+
if (!Array.isArray(nodes)) throw new Error("canvas has no nodes array");
|
|
11740
|
+
const idx = nodes.findIndex((n) => n?.id === nodeId);
|
|
11741
|
+
if (idx < 0) {
|
|
11742
|
+
const ids = nodes.map((n) => n?.id).filter((id) => typeof id === "string");
|
|
11743
|
+
throw new Error(`node "${nodeId}" not found. Known nodes: ${ids.join(", ")}`);
|
|
11744
|
+
}
|
|
11745
|
+
const node = nodes[idx];
|
|
11746
|
+
const newNode = { ...node, params: { ...node.params ?? {}, prompt: text } };
|
|
11747
|
+
const newNodes = [...nodes];
|
|
11748
|
+
newNodes[idx] = newNode;
|
|
11749
|
+
return { ...canvas, nodes: newNodes };
|
|
11750
|
+
}
|
|
11751
|
+
var setPromptCommand = defineCommand83({
|
|
11752
|
+
meta: {
|
|
11753
|
+
name: "set-prompt",
|
|
11754
|
+
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."
|
|
11755
|
+
},
|
|
11756
|
+
args: {
|
|
11757
|
+
file: { type: "positional", required: true, description: "Path to canvas JSON" },
|
|
11758
|
+
node: { type: "positional", required: true, description: "Node id to edit (e.g. s0_start)" },
|
|
11759
|
+
text: { type: "string", description: "New prompt text (inline)" },
|
|
11760
|
+
"text-file": { type: "string", description: "Read the new prompt from a UTF-8 file (preserves accents/newlines)" }
|
|
11761
|
+
},
|
|
11762
|
+
async run({ args }) {
|
|
11763
|
+
const filePath = path9.resolve(String(args.file));
|
|
11764
|
+
let canvas;
|
|
11765
|
+
try {
|
|
11766
|
+
canvas = JSON.parse(await readFile7(filePath, "utf8"));
|
|
11767
|
+
} catch (e) {
|
|
11768
|
+
process.stderr.write(`${JSON.stringify({ ok: false, error: { code: "parse", message: String(e) } }, null, 2)}
|
|
11769
|
+
`);
|
|
11770
|
+
process.exit(2);
|
|
11771
|
+
}
|
|
11772
|
+
let text;
|
|
11773
|
+
if (args["text-file"]) text = await readFile7(path9.resolve(String(args["text-file"])), "utf8");
|
|
11774
|
+
else if (args.text !== void 0) text = String(args.text);
|
|
11775
|
+
else {
|
|
11776
|
+
process.stderr.write(
|
|
11777
|
+
`${JSON.stringify({ ok: false, error: { code: "no_text", message: "pass --text or --text-file" } }, null, 2)}
|
|
11778
|
+
`
|
|
11779
|
+
);
|
|
11780
|
+
process.exit(2);
|
|
11781
|
+
return;
|
|
11782
|
+
}
|
|
11783
|
+
let updated;
|
|
11784
|
+
try {
|
|
11785
|
+
updated = setNodePrompt(canvas, String(args.node), text);
|
|
11786
|
+
} catch (e) {
|
|
11787
|
+
process.stderr.write(
|
|
11788
|
+
`${JSON.stringify({ ok: false, error: { code: "node_not_found", message: String(e.message) } }, null, 2)}
|
|
11789
|
+
`
|
|
11790
|
+
);
|
|
11791
|
+
process.exit(2);
|
|
11792
|
+
return;
|
|
11793
|
+
}
|
|
11794
|
+
const validation = await validateCanvasDeep(resolveRelativeCanvasPaths(updated, path9.dirname(filePath)), defaultRegistry());
|
|
11795
|
+
if (!validation.ok) {
|
|
11796
|
+
process.stderr.write(`${JSON.stringify({ ok: false, error: { code: "validation", issues: validation.issues } }, null, 2)}
|
|
11797
|
+
`);
|
|
11798
|
+
process.exit(2);
|
|
11799
|
+
return;
|
|
11800
|
+
}
|
|
11801
|
+
await writeFile3(filePath, `${JSON.stringify(updated, null, 2)}
|
|
11802
|
+
`, "utf8");
|
|
11803
|
+
process.stdout.write(`${JSON.stringify({ ok: true, node: String(args.node), bytes: text.length }, null, 2)}
|
|
11804
|
+
`);
|
|
11805
|
+
}
|
|
11806
|
+
});
|
|
11807
|
+
|
|
11808
|
+
// src/commands/canvas/validate.ts
|
|
11809
|
+
import { readFile as readFile8 } from "fs/promises";
|
|
11810
|
+
import path10 from "path";
|
|
11811
|
+
import { defineCommand as defineCommand84 } from "citty";
|
|
11812
|
+
var validateCommand = defineCommand84({
|
|
11494
11813
|
meta: {
|
|
11495
11814
|
name: "validate",
|
|
11496
11815
|
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)."
|
|
11497
11816
|
},
|
|
11498
11817
|
args: { file: { type: "positional", required: true, description: "Path to canvas JSON" } },
|
|
11499
11818
|
async run({ args }) {
|
|
11500
|
-
const filePath =
|
|
11501
|
-
const raw = await
|
|
11819
|
+
const filePath = path10.resolve(String(args.file));
|
|
11820
|
+
const raw = await readFile8(filePath, "utf8");
|
|
11502
11821
|
let parsed;
|
|
11503
11822
|
try {
|
|
11504
11823
|
parsed = JSON.parse(raw);
|
|
@@ -11508,6 +11827,7 @@ var validateCommand = defineCommand83({
|
|
|
11508
11827
|
`);
|
|
11509
11828
|
process.exit(2);
|
|
11510
11829
|
}
|
|
11830
|
+
parsed = resolveRelativeCanvasPaths(parsed, path10.dirname(filePath));
|
|
11511
11831
|
const result = await validateCanvasDeep(parsed, defaultRegistry());
|
|
11512
11832
|
if (!result.ok) {
|
|
11513
11833
|
process.stderr.write(`${JSON.stringify({ ok: false, issues: result.issues }, null, 2)}
|
|
@@ -11532,7 +11852,7 @@ var validateCommand = defineCommand83({
|
|
|
11532
11852
|
});
|
|
11533
11853
|
|
|
11534
11854
|
// src/commands/canvas/index.ts
|
|
11535
|
-
var canvasCommand =
|
|
11855
|
+
var canvasCommand = defineCommand85({
|
|
11536
11856
|
meta: {
|
|
11537
11857
|
name: "canvas",
|
|
11538
11858
|
description: `Run Baker creative canvas JSON files locally. Local nodes execute in-process; remote nodes POST to the Convex backend gateway.
|
|
@@ -11553,15 +11873,16 @@ Subcommands:
|
|
|
11553
11873
|
catalog: catalogCommand,
|
|
11554
11874
|
inspect: inspectCommand,
|
|
11555
11875
|
"scaffold-video": scaffoldVideoCommand,
|
|
11556
|
-
"scaffold-static-ad": scaffoldStaticAdCommand
|
|
11876
|
+
"scaffold-static-ad": scaffoldStaticAdCommand,
|
|
11877
|
+
"set-prompt": setPromptCommand
|
|
11557
11878
|
}
|
|
11558
11879
|
});
|
|
11559
11880
|
|
|
11560
11881
|
// src/commands/ga4/index.ts
|
|
11561
|
-
import { defineCommand as
|
|
11882
|
+
import { defineCommand as defineCommand89 } from "citty";
|
|
11562
11883
|
|
|
11563
11884
|
// src/commands/ga4/audit.ts
|
|
11564
|
-
import { defineCommand as
|
|
11885
|
+
import { defineCommand as defineCommand86 } from "citty";
|
|
11565
11886
|
|
|
11566
11887
|
// src/commands/ga4/resolve.ts
|
|
11567
11888
|
async function fetchProperties(useCache = true) {
|
|
@@ -11624,7 +11945,7 @@ registerSchema({
|
|
|
11624
11945
|
"no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
|
|
11625
11946
|
}
|
|
11626
11947
|
});
|
|
11627
|
-
var auditCommand2 =
|
|
11948
|
+
var auditCommand2 = defineCommand86({
|
|
11628
11949
|
meta: {
|
|
11629
11950
|
name: "audit",
|
|
11630
11951
|
description: `Run all GA4 admin health checks. Returns property config with playbook warnings.
|
|
@@ -11676,7 +11997,7 @@ Examples:
|
|
|
11676
11997
|
});
|
|
11677
11998
|
|
|
11678
11999
|
// src/commands/ga4/properties.ts
|
|
11679
|
-
import { defineCommand as
|
|
12000
|
+
import { defineCommand as defineCommand87 } from "citty";
|
|
11680
12001
|
registerSchema({
|
|
11681
12002
|
command: "ga4.properties",
|
|
11682
12003
|
description: "List all accessible GA4 properties. Returns property IDs needed for query and audit commands. Run this first to find property IDs.",
|
|
@@ -11684,7 +12005,7 @@ registerSchema({
|
|
|
11684
12005
|
"no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
|
|
11685
12006
|
}
|
|
11686
12007
|
});
|
|
11687
|
-
var propertiesCommand =
|
|
12008
|
+
var propertiesCommand = defineCommand87({
|
|
11688
12009
|
meta: {
|
|
11689
12010
|
name: "properties",
|
|
11690
12011
|
description: `List accessible GA4 properties.
|
|
@@ -11734,7 +12055,7 @@ Examples:
|
|
|
11734
12055
|
// src/commands/ga4/query.ts
|
|
11735
12056
|
import { appendFileSync as appendFileSync2, existsSync as existsSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
|
|
11736
12057
|
import { resolve as resolve2 } from "path";
|
|
11737
|
-
import { defineCommand as
|
|
12058
|
+
import { defineCommand as defineCommand88 } from "citty";
|
|
11738
12059
|
|
|
11739
12060
|
// src/commands/ga4/presets.ts
|
|
11740
12061
|
var GA4_PRESETS = [
|
|
@@ -11866,7 +12187,7 @@ function handleError(err) {
|
|
|
11866
12187
|
});
|
|
11867
12188
|
process.exit(1);
|
|
11868
12189
|
}
|
|
11869
|
-
var queryCommand2 =
|
|
12190
|
+
var queryCommand2 = defineCommand88({
|
|
11870
12191
|
meta: {
|
|
11871
12192
|
name: "query",
|
|
11872
12193
|
description: `Run GA4 Data API reports. Preset-first with free-form escape hatch.
|
|
@@ -11937,7 +12258,7 @@ Free-form (escape hatch):
|
|
|
11937
12258
|
});
|
|
11938
12259
|
|
|
11939
12260
|
// src/commands/ga4/index.ts
|
|
11940
|
-
var ga4Command =
|
|
12261
|
+
var ga4Command = defineCommand89({
|
|
11941
12262
|
meta: {
|
|
11942
12263
|
name: "ga4",
|
|
11943
12264
|
description: `Google Analytics 4 commands. Audit property config, run playbook-aligned reports.
|
|
@@ -11960,12 +12281,12 @@ Examples:
|
|
|
11960
12281
|
});
|
|
11961
12282
|
|
|
11962
12283
|
// src/commands/gsc/index.ts
|
|
11963
|
-
import { defineCommand as
|
|
12284
|
+
import { defineCommand as defineCommand93 } from "citty";
|
|
11964
12285
|
|
|
11965
12286
|
// src/commands/gsc/query.ts
|
|
11966
12287
|
import { appendFileSync as appendFileSync3, existsSync as existsSync5, readFileSync as readFileSync7, writeFileSync as writeFileSync5 } from "fs";
|
|
11967
12288
|
import { resolve as resolve3 } from "path";
|
|
11968
|
-
import { defineCommand as
|
|
12289
|
+
import { defineCommand as defineCommand90 } from "citty";
|
|
11969
12290
|
|
|
11970
12291
|
// src/commands/gsc/presets.ts
|
|
11971
12292
|
var GSC_PRESETS = [
|
|
@@ -12153,7 +12474,7 @@ function handleError2(err) {
|
|
|
12153
12474
|
});
|
|
12154
12475
|
process.exit(1);
|
|
12155
12476
|
}
|
|
12156
|
-
var queryCommand3 =
|
|
12477
|
+
var queryCommand3 = defineCommand90({
|
|
12157
12478
|
meta: {
|
|
12158
12479
|
name: "query",
|
|
12159
12480
|
description: `Run GSC Search Analytics queries. Preset-first with free-form escape hatch.
|
|
@@ -12231,7 +12552,7 @@ Free-form (escape hatch):
|
|
|
12231
12552
|
});
|
|
12232
12553
|
|
|
12233
12554
|
// src/commands/gsc/sitemaps.ts
|
|
12234
|
-
import { defineCommand as
|
|
12555
|
+
import { defineCommand as defineCommand91 } from "citty";
|
|
12235
12556
|
registerSchema({
|
|
12236
12557
|
command: "gsc.sitemaps",
|
|
12237
12558
|
description: "List sitemaps for a Search Console site. Check sitemap health and errors.",
|
|
@@ -12240,7 +12561,7 @@ registerSchema({
|
|
|
12240
12561
|
"no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
|
|
12241
12562
|
}
|
|
12242
12563
|
});
|
|
12243
|
-
var sitemapsCommand =
|
|
12564
|
+
var sitemapsCommand = defineCommand91({
|
|
12244
12565
|
meta: {
|
|
12245
12566
|
name: "sitemaps",
|
|
12246
12567
|
description: `List sitemaps for a site. Check health and errors.
|
|
@@ -12290,7 +12611,7 @@ Examples:
|
|
|
12290
12611
|
});
|
|
12291
12612
|
|
|
12292
12613
|
// src/commands/gsc/sites.ts
|
|
12293
|
-
import { defineCommand as
|
|
12614
|
+
import { defineCommand as defineCommand92 } from "citty";
|
|
12294
12615
|
registerSchema({
|
|
12295
12616
|
command: "gsc.sites",
|
|
12296
12617
|
description: "List all verified Google Search Console sites. Returns site URLs needed for query and sitemaps commands.",
|
|
@@ -12298,7 +12619,7 @@ registerSchema({
|
|
|
12298
12619
|
"no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
|
|
12299
12620
|
}
|
|
12300
12621
|
});
|
|
12301
|
-
var sitesCommand =
|
|
12622
|
+
var sitesCommand = defineCommand92({
|
|
12302
12623
|
meta: {
|
|
12303
12624
|
name: "sites",
|
|
12304
12625
|
description: `List verified Search Console sites.
|
|
@@ -12346,7 +12667,7 @@ Examples:
|
|
|
12346
12667
|
});
|
|
12347
12668
|
|
|
12348
12669
|
// src/commands/gsc/index.ts
|
|
12349
|
-
var gscCommand =
|
|
12670
|
+
var gscCommand = defineCommand93({
|
|
12350
12671
|
meta: {
|
|
12351
12672
|
name: "gsc",
|
|
12352
12673
|
description: `Google Search Console commands. PPC-SEO arbitrage, brand halo analysis, negative keyword discovery.
|
|
@@ -12369,10 +12690,10 @@ Examples:
|
|
|
12369
12690
|
});
|
|
12370
12691
|
|
|
12371
12692
|
// src/commands/images/index.ts
|
|
12372
|
-
import { defineCommand as
|
|
12693
|
+
import { defineCommand as defineCommand117 } from "citty";
|
|
12373
12694
|
|
|
12374
12695
|
// src/commands/images/crop.ts
|
|
12375
|
-
import { defineCommand as
|
|
12696
|
+
import { defineCommand as defineCommand94 } from "citty";
|
|
12376
12697
|
|
|
12377
12698
|
// src/lib/image/crop-sprite.ts
|
|
12378
12699
|
import sharp from "sharp";
|
|
@@ -12387,7 +12708,7 @@ function cropSprite(input, region) {
|
|
|
12387
12708
|
|
|
12388
12709
|
// src/lib/image/io.ts
|
|
12389
12710
|
import { randomBytes } from "crypto";
|
|
12390
|
-
import { glob as fsGlob, readFile as
|
|
12711
|
+
import { glob as fsGlob, readFile as readFile9, rename, stat as stat2, writeFile as writeFile4 } from "fs/promises";
|
|
12391
12712
|
import { dirname, extname, join as join3, resolve as resolve4 } from "path";
|
|
12392
12713
|
var REMOTE_RE = /^https?:\/\//i;
|
|
12393
12714
|
var GLOB_RE = /[*?[\]{}]/;
|
|
@@ -12423,11 +12744,11 @@ async function readImageBuffer(pathOrUrl) {
|
|
|
12423
12744
|
}
|
|
12424
12745
|
return Buffer.from(await response.arrayBuffer());
|
|
12425
12746
|
}
|
|
12426
|
-
return
|
|
12747
|
+
return readFile9(pathOrUrl);
|
|
12427
12748
|
}
|
|
12428
|
-
async function isDirectory(
|
|
12749
|
+
async function isDirectory(path11) {
|
|
12429
12750
|
try {
|
|
12430
|
-
const s = await stat2(
|
|
12751
|
+
const s = await stat2(path11);
|
|
12431
12752
|
return s.isDirectory();
|
|
12432
12753
|
} catch {
|
|
12433
12754
|
return false;
|
|
@@ -12446,7 +12767,7 @@ async function atomicWrite(targetPath, data) {
|
|
|
12446
12767
|
const absolute = resolve4(targetPath);
|
|
12447
12768
|
const dir = dirname(absolute);
|
|
12448
12769
|
const tmp = join3(dir, `.baker-image-${randomBytes(8).toString("hex")}.tmp`);
|
|
12449
|
-
await
|
|
12770
|
+
await writeFile4(tmp, data);
|
|
12450
12771
|
await rename(tmp, absolute);
|
|
12451
12772
|
}
|
|
12452
12773
|
|
|
@@ -12497,7 +12818,7 @@ function emitError2(err) {
|
|
|
12497
12818
|
}
|
|
12498
12819
|
process.exit(1);
|
|
12499
12820
|
}
|
|
12500
|
-
var cropCommand =
|
|
12821
|
+
var cropCommand = defineCommand94({
|
|
12501
12822
|
meta: {
|
|
12502
12823
|
name: "crop",
|
|
12503
12824
|
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"
|
|
@@ -12533,7 +12854,7 @@ var cropCommand = defineCommand93({
|
|
|
12533
12854
|
});
|
|
12534
12855
|
|
|
12535
12856
|
// src/commands/images/delete.ts
|
|
12536
|
-
import { defineCommand as
|
|
12857
|
+
import { defineCommand as defineCommand95 } from "citty";
|
|
12537
12858
|
registerSchema({
|
|
12538
12859
|
command: "images.delete",
|
|
12539
12860
|
description: "Delete an image by ID",
|
|
@@ -12547,7 +12868,7 @@ registerSchema({
|
|
|
12547
12868
|
}
|
|
12548
12869
|
}
|
|
12549
12870
|
});
|
|
12550
|
-
var deleteCommand =
|
|
12871
|
+
var deleteCommand = defineCommand95({
|
|
12551
12872
|
meta: {
|
|
12552
12873
|
name: "delete",
|
|
12553
12874
|
description: "Delete an image by ID. Use --dry-run to preview. Example: baker images delete j571abc123 --dry-run"
|
|
@@ -12588,7 +12909,7 @@ var deleteCommand = defineCommand94({
|
|
|
12588
12909
|
});
|
|
12589
12910
|
|
|
12590
12911
|
// src/commands/images/dimensions.ts
|
|
12591
|
-
import { defineCommand as
|
|
12912
|
+
import { defineCommand as defineCommand96 } from "citty";
|
|
12592
12913
|
|
|
12593
12914
|
// src/lib/image/dimensions.ts
|
|
12594
12915
|
import { imageSize } from "image-size";
|
|
@@ -12611,7 +12932,7 @@ registerSchema({
|
|
|
12611
12932
|
target: { type: "string", description: "Local file path or remote http(s) URL", required: true }
|
|
12612
12933
|
}
|
|
12613
12934
|
});
|
|
12614
|
-
var dimensionsCommand =
|
|
12935
|
+
var dimensionsCommand = defineCommand96({
|
|
12615
12936
|
meta: {
|
|
12616
12937
|
name: "dimensions",
|
|
12617
12938
|
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"
|
|
@@ -12655,7 +12976,7 @@ var dimensionsCommand = defineCommand95({
|
|
|
12655
12976
|
});
|
|
12656
12977
|
|
|
12657
12978
|
// src/commands/images/extract.ts
|
|
12658
|
-
import { defineCommand as
|
|
12979
|
+
import { defineCommand as defineCommand97 } from "citty";
|
|
12659
12980
|
registerSchema({
|
|
12660
12981
|
command: "images.extract",
|
|
12661
12982
|
description: "Extract images from a URL via Firecrawl (formats: images).",
|
|
@@ -12671,7 +12992,7 @@ registerSchema({
|
|
|
12671
12992
|
}
|
|
12672
12993
|
}
|
|
12673
12994
|
});
|
|
12674
|
-
var extractCommand =
|
|
12995
|
+
var extractCommand = defineCommand97({
|
|
12675
12996
|
meta: {
|
|
12676
12997
|
name: "extract",
|
|
12677
12998
|
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"
|
|
@@ -12709,7 +13030,7 @@ var extractCommand = defineCommand96({
|
|
|
12709
13030
|
});
|
|
12710
13031
|
|
|
12711
13032
|
// src/commands/images/find.ts
|
|
12712
|
-
import { defineCommand as
|
|
13033
|
+
import { defineCommand as defineCommand98 } from "citty";
|
|
12713
13034
|
registerSchema({
|
|
12714
13035
|
command: "images.find",
|
|
12715
13036
|
description: "Fanout image search: library first, then opted-in external providers.",
|
|
@@ -12741,7 +13062,7 @@ registerSchema({
|
|
|
12741
13062
|
}
|
|
12742
13063
|
}
|
|
12743
13064
|
});
|
|
12744
|
-
var findCommand =
|
|
13065
|
+
var findCommand = defineCommand98({
|
|
12745
13066
|
meta: {
|
|
12746
13067
|
name: "find",
|
|
12747
13068
|
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"
|
|
@@ -12787,8 +13108,8 @@ var findCommand = defineCommand97({
|
|
|
12787
13108
|
});
|
|
12788
13109
|
|
|
12789
13110
|
// src/commands/images/generate.ts
|
|
12790
|
-
import { readFile as
|
|
12791
|
-
import { defineCommand as
|
|
13111
|
+
import { readFile as readFile10 } from "fs/promises";
|
|
13112
|
+
import { defineCommand as defineCommand99 } from "citty";
|
|
12792
13113
|
import sharp2 from "sharp";
|
|
12793
13114
|
var GENERATE_TIMEOUT_MS = 18e4;
|
|
12794
13115
|
var REFERENCE_MAX_EDGE = 1536;
|
|
@@ -12870,7 +13191,7 @@ async function resolveReferences(spec) {
|
|
|
12870
13191
|
}
|
|
12871
13192
|
let raw;
|
|
12872
13193
|
try {
|
|
12873
|
-
raw = await
|
|
13194
|
+
raw = await readFile10(entry);
|
|
12874
13195
|
} catch {
|
|
12875
13196
|
throw new ApiError("VALIDATION_ERROR", `Reference file not found: ${entry}`);
|
|
12876
13197
|
}
|
|
@@ -12884,7 +13205,7 @@ async function resolveReferences(spec) {
|
|
|
12884
13205
|
}
|
|
12885
13206
|
return out;
|
|
12886
13207
|
}
|
|
12887
|
-
var generateCommand =
|
|
13208
|
+
var generateCommand = defineCommand99({
|
|
12888
13209
|
meta: {
|
|
12889
13210
|
name: "generate",
|
|
12890
13211
|
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]]'"
|
|
@@ -12936,7 +13257,7 @@ var generateCommand = defineCommand98({
|
|
|
12936
13257
|
});
|
|
12937
13258
|
|
|
12938
13259
|
// src/commands/images/get.ts
|
|
12939
|
-
import { defineCommand as
|
|
13260
|
+
import { defineCommand as defineCommand100 } from "citty";
|
|
12940
13261
|
registerSchema({
|
|
12941
13262
|
command: "images.get",
|
|
12942
13263
|
description: "Get a single image by ID",
|
|
@@ -12944,7 +13265,7 @@ registerSchema({
|
|
|
12944
13265
|
id: { type: "string", description: "Image ID", required: true }
|
|
12945
13266
|
}
|
|
12946
13267
|
});
|
|
12947
|
-
var getCommand2 =
|
|
13268
|
+
var getCommand2 = defineCommand100({
|
|
12948
13269
|
meta: { name: "get", description: "Get a single image by ID. Example: baker images get j571abc123" },
|
|
12949
13270
|
args: {
|
|
12950
13271
|
id: { type: "positional", description: "Image ID", required: false },
|
|
@@ -12980,7 +13301,7 @@ var getCommand2 = defineCommand99({
|
|
|
12980
13301
|
});
|
|
12981
13302
|
|
|
12982
13303
|
// src/commands/images/gif.ts
|
|
12983
|
-
import { defineCommand as
|
|
13304
|
+
import { defineCommand as defineCommand101 } from "citty";
|
|
12984
13305
|
registerSchema({
|
|
12985
13306
|
command: "images.gif",
|
|
12986
13307
|
description: "Search Giphy for GIFs / reaction memes (paid social creative).",
|
|
@@ -13012,7 +13333,7 @@ registerSchema({
|
|
|
13012
13333
|
}
|
|
13013
13334
|
}
|
|
13014
13335
|
});
|
|
13015
|
-
var gifCommand =
|
|
13336
|
+
var gifCommand = defineCommand101({
|
|
13016
13337
|
meta: {
|
|
13017
13338
|
name: "gif",
|
|
13018
13339
|
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"
|
|
@@ -13059,7 +13380,7 @@ var gifCommand = defineCommand100({
|
|
|
13059
13380
|
});
|
|
13060
13381
|
|
|
13061
13382
|
// src/commands/images/google.ts
|
|
13062
|
-
import { defineCommand as
|
|
13383
|
+
import { defineCommand as defineCommand102 } from "citty";
|
|
13063
13384
|
registerSchema({
|
|
13064
13385
|
command: "images.google",
|
|
13065
13386
|
description: "Google Images search via the official Custom Search JSON API. Unverified source \u2014 inspect before placing.",
|
|
@@ -13095,7 +13416,7 @@ registerSchema({
|
|
|
13095
13416
|
}
|
|
13096
13417
|
}
|
|
13097
13418
|
});
|
|
13098
|
-
var googleCommand2 =
|
|
13419
|
+
var googleCommand2 = defineCommand102({
|
|
13099
13420
|
meta: {
|
|
13100
13421
|
name: "google",
|
|
13101
13422
|
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"
|
|
@@ -13143,7 +13464,7 @@ var googleCommand2 = defineCommand101({
|
|
|
13143
13464
|
});
|
|
13144
13465
|
|
|
13145
13466
|
// src/commands/images/icon.ts
|
|
13146
|
-
import { defineCommand as
|
|
13467
|
+
import { defineCommand as defineCommand103 } from "citty";
|
|
13147
13468
|
registerSchema({
|
|
13148
13469
|
command: "images.icon",
|
|
13149
13470
|
description: "Icon lookup via Iconify (200+ icon sets, free CDN).",
|
|
@@ -13169,7 +13490,7 @@ registerSchema({
|
|
|
13169
13490
|
}
|
|
13170
13491
|
}
|
|
13171
13492
|
});
|
|
13172
|
-
var iconCommand =
|
|
13493
|
+
var iconCommand = defineCommand103({
|
|
13173
13494
|
meta: {
|
|
13174
13495
|
name: "icon",
|
|
13175
13496
|
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'"
|
|
@@ -13209,7 +13530,7 @@ var iconCommand = defineCommand102({
|
|
|
13209
13530
|
});
|
|
13210
13531
|
|
|
13211
13532
|
// src/commands/images/ingest.ts
|
|
13212
|
-
import { defineCommand as
|
|
13533
|
+
import { defineCommand as defineCommand104 } from "citty";
|
|
13213
13534
|
registerSchema({
|
|
13214
13535
|
command: "images.ingest",
|
|
13215
13536
|
description: "Ingest a remote image URL into the library (full describe + embed).",
|
|
@@ -13221,7 +13542,7 @@ registerSchema({
|
|
|
13221
13542
|
context: { type: "string", description: "Description context hint", required: false }
|
|
13222
13543
|
}
|
|
13223
13544
|
});
|
|
13224
|
-
var ingestCommand =
|
|
13545
|
+
var ingestCommand = defineCommand104({
|
|
13225
13546
|
meta: {
|
|
13226
13547
|
name: "ingest",
|
|
13227
13548
|
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"
|
|
@@ -13263,7 +13584,7 @@ var ingestCommand = defineCommand103({
|
|
|
13263
13584
|
});
|
|
13264
13585
|
|
|
13265
13586
|
// src/commands/images/library.ts
|
|
13266
|
-
import { defineCommand as
|
|
13587
|
+
import { defineCommand as defineCommand105 } from "citty";
|
|
13267
13588
|
registerSchema({
|
|
13268
13589
|
command: "images.library",
|
|
13269
13590
|
description: "Search the company image library. Returns only ready images.",
|
|
@@ -13289,7 +13610,7 @@ registerSchema({
|
|
|
13289
13610
|
}
|
|
13290
13611
|
}
|
|
13291
13612
|
});
|
|
13292
|
-
var libraryCommand =
|
|
13613
|
+
var libraryCommand = defineCommand105({
|
|
13293
13614
|
meta: {
|
|
13294
13615
|
name: "library",
|
|
13295
13616
|
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"
|
|
@@ -13346,7 +13667,7 @@ var libraryCommand = defineCommand104({
|
|
|
13346
13667
|
});
|
|
13347
13668
|
|
|
13348
13669
|
// src/commands/images/logo.ts
|
|
13349
|
-
import { defineCommand as
|
|
13670
|
+
import { defineCommand as defineCommand106 } from "citty";
|
|
13350
13671
|
registerSchema({
|
|
13351
13672
|
command: "images.logo",
|
|
13352
13673
|
description: "Brand logo lookup via Brandfetch CDN (fallback/404). Auto-ingests by default.",
|
|
@@ -13371,7 +13692,7 @@ registerSchema({
|
|
|
13371
13692
|
}
|
|
13372
13693
|
}
|
|
13373
13694
|
});
|
|
13374
|
-
var logoCommand =
|
|
13695
|
+
var logoCommand = defineCommand106({
|
|
13375
13696
|
meta: {
|
|
13376
13697
|
name: "logo",
|
|
13377
13698
|
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"
|
|
@@ -13409,7 +13730,7 @@ var logoCommand = defineCommand105({
|
|
|
13409
13730
|
});
|
|
13410
13731
|
|
|
13411
13732
|
// src/commands/images/normalize.ts
|
|
13412
|
-
import { defineCommand as
|
|
13733
|
+
import { defineCommand as defineCommand107 } from "citty";
|
|
13413
13734
|
|
|
13414
13735
|
// src/lib/image/color-changer.ts
|
|
13415
13736
|
import quantize from "quantize";
|
|
@@ -14141,7 +14462,7 @@ function coerceRawArgs(args) {
|
|
|
14141
14462
|
"dry-run": bool(args["dry-run"])
|
|
14142
14463
|
};
|
|
14143
14464
|
}
|
|
14144
|
-
var normalizeCommand =
|
|
14465
|
+
var normalizeCommand = defineCommand107({
|
|
14145
14466
|
meta: {
|
|
14146
14467
|
name: "normalize",
|
|
14147
14468
|
description: `Normalize logos / images: declarative recolor + bg removal + trim + resize. Operates on local files; writes in-place by default.
|
|
@@ -14196,7 +14517,7 @@ Examples:
|
|
|
14196
14517
|
});
|
|
14197
14518
|
|
|
14198
14519
|
// src/commands/images/pinterest.ts
|
|
14199
|
-
import { defineCommand as
|
|
14520
|
+
import { defineCommand as defineCommand108 } from "citty";
|
|
14200
14521
|
registerSchema({
|
|
14201
14522
|
command: "images.pinterest",
|
|
14202
14523
|
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.",
|
|
@@ -14216,7 +14537,7 @@ registerSchema({
|
|
|
14216
14537
|
}
|
|
14217
14538
|
}
|
|
14218
14539
|
});
|
|
14219
|
-
var pinterestCommand =
|
|
14540
|
+
var pinterestCommand = defineCommand108({
|
|
14220
14541
|
meta: {
|
|
14221
14542
|
name: "pinterest",
|
|
14222
14543
|
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'"
|
|
@@ -14256,7 +14577,7 @@ var pinterestCommand = defineCommand107({
|
|
|
14256
14577
|
});
|
|
14257
14578
|
|
|
14258
14579
|
// src/commands/images/screenshot.ts
|
|
14259
|
-
import { defineCommand as
|
|
14580
|
+
import { defineCommand as defineCommand109 } from "citty";
|
|
14260
14581
|
registerSchema({
|
|
14261
14582
|
command: "images.screenshot",
|
|
14262
14583
|
description: "Capture a website screenshot via ScreenshotOne. Auto-ingests on success.",
|
|
@@ -14272,7 +14593,7 @@ registerSchema({
|
|
|
14272
14593
|
}
|
|
14273
14594
|
}
|
|
14274
14595
|
});
|
|
14275
|
-
var screenshotCommand =
|
|
14596
|
+
var screenshotCommand = defineCommand109({
|
|
14276
14597
|
meta: {
|
|
14277
14598
|
name: "screenshot",
|
|
14278
14599
|
description: "Screenshot a URL via ScreenshotOne. $0.009/capture. Auto-ingests to library.\n\nExample: baker images screenshot https://stripe.com --full-page"
|
|
@@ -14322,7 +14643,7 @@ var screenshotCommand = defineCommand108({
|
|
|
14322
14643
|
});
|
|
14323
14644
|
|
|
14324
14645
|
// src/commands/images/search.ts
|
|
14325
|
-
import { defineCommand as
|
|
14646
|
+
import { defineCommand as defineCommand110 } from "citty";
|
|
14326
14647
|
registerSchema({
|
|
14327
14648
|
command: "images.search",
|
|
14328
14649
|
description: "Search images by text query. Only returns ready images.",
|
|
@@ -14338,7 +14659,7 @@ registerSchema({
|
|
|
14338
14659
|
tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
|
|
14339
14660
|
}
|
|
14340
14661
|
});
|
|
14341
|
-
var searchCommand =
|
|
14662
|
+
var searchCommand = defineCommand110({
|
|
14342
14663
|
meta: {
|
|
14343
14664
|
name: "search",
|
|
14344
14665
|
description: "Semantic search images by text query. Uses hybrid BM25 + vector + reranking. Example: baker images search 'hero banner' --aspect-ratio 16:9 --tags logo"
|
|
@@ -14398,7 +14719,7 @@ var searchCommand = defineCommand109({
|
|
|
14398
14719
|
});
|
|
14399
14720
|
|
|
14400
14721
|
// src/commands/images/sticker.ts
|
|
14401
|
-
import { defineCommand as
|
|
14722
|
+
import { defineCommand as defineCommand111 } from "citty";
|
|
14402
14723
|
registerSchema({
|
|
14403
14724
|
command: "images.sticker",
|
|
14404
14725
|
description: "Search Giphy stickers \u2014 transparent-background overlays for ad creative.",
|
|
@@ -14430,7 +14751,7 @@ registerSchema({
|
|
|
14430
14751
|
}
|
|
14431
14752
|
}
|
|
14432
14753
|
});
|
|
14433
|
-
var stickerCommand =
|
|
14754
|
+
var stickerCommand = defineCommand111({
|
|
14434
14755
|
meta: {
|
|
14435
14756
|
name: "sticker",
|
|
14436
14757
|
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"
|
|
@@ -14477,7 +14798,7 @@ var stickerCommand = defineCommand110({
|
|
|
14477
14798
|
});
|
|
14478
14799
|
|
|
14479
14800
|
// src/commands/images/stock.ts
|
|
14480
|
-
import { defineCommand as
|
|
14801
|
+
import { defineCommand as defineCommand112 } from "citty";
|
|
14481
14802
|
registerSchema({
|
|
14482
14803
|
command: "images.stock",
|
|
14483
14804
|
description: "Stock photo, vector illustration, icon-set, and PSD search via Magnific (Freepik's developer API).",
|
|
@@ -14535,7 +14856,7 @@ registerSchema({
|
|
|
14535
14856
|
}
|
|
14536
14857
|
}
|
|
14537
14858
|
});
|
|
14538
|
-
var stockCommand =
|
|
14859
|
+
var stockCommand = defineCommand112({
|
|
14539
14860
|
meta: {
|
|
14540
14861
|
name: "stock",
|
|
14541
14862
|
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"
|
|
@@ -14591,7 +14912,7 @@ var stockCommand = defineCommand111({
|
|
|
14591
14912
|
});
|
|
14592
14913
|
|
|
14593
14914
|
// src/lib/tags-command.ts
|
|
14594
|
-
import { defineCommand as
|
|
14915
|
+
import { defineCommand as defineCommand113 } from "citty";
|
|
14595
14916
|
function makeTagsCommand(command, label, endpoint) {
|
|
14596
14917
|
registerSchema({
|
|
14597
14918
|
command: `${command}.tags`,
|
|
@@ -14600,7 +14921,7 @@ function makeTagsCommand(command, label, endpoint) {
|
|
|
14600
14921
|
output: { type: "string", description: "Output format: md|json", required: false, default: "md" }
|
|
14601
14922
|
}
|
|
14602
14923
|
});
|
|
14603
|
-
return
|
|
14924
|
+
return defineCommand113({
|
|
14604
14925
|
meta: {
|
|
14605
14926
|
name: "tags",
|
|
14606
14927
|
description: `List the available ${label} tag names (defaults + company custom tags). Use before filtering with --tags. Example: baker ${command} tags`
|
|
@@ -14636,9 +14957,9 @@ function makeTagsCommand(command, label, endpoint) {
|
|
|
14636
14957
|
var tagsCommand2 = makeTagsCommand("images", "image", "/api/images/tags");
|
|
14637
14958
|
|
|
14638
14959
|
// src/commands/images/upload.ts
|
|
14639
|
-
import { readFile as
|
|
14960
|
+
import { readFile as readFile11 } from "fs/promises";
|
|
14640
14961
|
import { extname as extname2 } from "path";
|
|
14641
|
-
import { defineCommand as
|
|
14962
|
+
import { defineCommand as defineCommand114 } from "citty";
|
|
14642
14963
|
var MIME_MAP = {
|
|
14643
14964
|
".png": "image/png",
|
|
14644
14965
|
".jpg": "image/jpeg",
|
|
@@ -14693,7 +15014,7 @@ function detectContentType(filePath) {
|
|
|
14693
15014
|
}
|
|
14694
15015
|
return mime;
|
|
14695
15016
|
}
|
|
14696
|
-
var uploadCommand =
|
|
15017
|
+
var uploadCommand = defineCommand114({
|
|
14697
15018
|
meta: {
|
|
14698
15019
|
name: "upload",
|
|
14699
15020
|
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'"
|
|
@@ -14776,7 +15097,7 @@ async function uploadLocal(target, args) {
|
|
|
14776
15097
|
});
|
|
14777
15098
|
return;
|
|
14778
15099
|
}
|
|
14779
|
-
const fileBuffer = await
|
|
15100
|
+
const fileBuffer = await readFile11(target);
|
|
14780
15101
|
const base64 = fileBuffer.toString("base64");
|
|
14781
15102
|
const body = { base64, contentType };
|
|
14782
15103
|
if (args.source) body.source = args.source;
|
|
@@ -14786,7 +15107,7 @@ async function uploadLocal(target, args) {
|
|
|
14786
15107
|
}
|
|
14787
15108
|
|
|
14788
15109
|
// src/commands/images/upscale.ts
|
|
14789
|
-
import { defineCommand as
|
|
15110
|
+
import { defineCommand as defineCommand115 } from "citty";
|
|
14790
15111
|
registerSchema({
|
|
14791
15112
|
command: "images.upscale",
|
|
14792
15113
|
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).",
|
|
@@ -14801,7 +15122,7 @@ registerSchema({
|
|
|
14801
15122
|
}
|
|
14802
15123
|
});
|
|
14803
15124
|
var POLL_INTERVAL_MS3 = 1500;
|
|
14804
|
-
var upscaleCommand =
|
|
15125
|
+
var upscaleCommand = defineCommand115({
|
|
14805
15126
|
meta: {
|
|
14806
15127
|
name: "upscale",
|
|
14807
15128
|
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"
|
|
@@ -14856,7 +15177,7 @@ var upscaleCommand = defineCommand114({
|
|
|
14856
15177
|
});
|
|
14857
15178
|
|
|
14858
15179
|
// src/commands/images/use.ts
|
|
14859
|
-
import { defineCommand as
|
|
15180
|
+
import { defineCommand as defineCommand116 } from "citty";
|
|
14860
15181
|
registerSchema({
|
|
14861
15182
|
command: "images.use",
|
|
14862
15183
|
description: "Ingest a URL and wait for the library record to be ready.",
|
|
@@ -14872,7 +15193,7 @@ registerSchema({
|
|
|
14872
15193
|
}
|
|
14873
15194
|
});
|
|
14874
15195
|
var POLL_INTERVAL_MS4 = 1500;
|
|
14875
|
-
var useCommand =
|
|
15196
|
+
var useCommand = defineCommand116({
|
|
14876
15197
|
meta: {
|
|
14877
15198
|
name: "use",
|
|
14878
15199
|
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"
|
|
@@ -14918,7 +15239,7 @@ var useCommand = defineCommand115({
|
|
|
14918
15239
|
});
|
|
14919
15240
|
|
|
14920
15241
|
// src/commands/images/index.ts
|
|
14921
|
-
var imagesCommand =
|
|
15242
|
+
var imagesCommand = defineCommand117({
|
|
14922
15243
|
meta: {
|
|
14923
15244
|
name: "images",
|
|
14924
15245
|
description: `Find, source, and normalize images. Subcommands route by provider so cost + license are explicit.
|
|
@@ -14988,10 +15309,10 @@ Paid transforms (run on the Convex backend, cost-tracked):
|
|
|
14988
15309
|
});
|
|
14989
15310
|
|
|
14990
15311
|
// src/commands/research/index.ts
|
|
14991
|
-
import { defineCommand as
|
|
15312
|
+
import { defineCommand as defineCommand128 } from "citty";
|
|
14992
15313
|
|
|
14993
15314
|
// src/commands/research/advertisers.ts
|
|
14994
|
-
import { defineCommand as
|
|
15315
|
+
import { defineCommand as defineCommand118 } from "citty";
|
|
14995
15316
|
|
|
14996
15317
|
// src/commands/research/output.ts
|
|
14997
15318
|
var RESEARCH_DATA_NOTE = "Estimates based on third-party SERP data \u2014 not exact figures. Use for directional insights, not precise measurement.";
|
|
@@ -15104,7 +15425,7 @@ var FIELDS3 = {
|
|
|
15104
15425
|
etv: "Estimated traffic value (USD)",
|
|
15105
15426
|
visibility: "SERP visibility score (0-1)"
|
|
15106
15427
|
};
|
|
15107
|
-
var advertisersCommand =
|
|
15428
|
+
var advertisersCommand = defineCommand118({
|
|
15108
15429
|
meta: {
|
|
15109
15430
|
name: "advertisers",
|
|
15110
15431
|
description: `Find domains competing for a keyword in Google SERPs.
|
|
@@ -15151,7 +15472,7 @@ Examples:
|
|
|
15151
15472
|
});
|
|
15152
15473
|
|
|
15153
15474
|
// src/commands/research/autocomplete.ts
|
|
15154
|
-
import { defineCommand as
|
|
15475
|
+
import { defineCommand as defineCommand119 } from "citty";
|
|
15155
15476
|
registerSchema({
|
|
15156
15477
|
command: "research.autocomplete",
|
|
15157
15478
|
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).",
|
|
@@ -15174,7 +15495,7 @@ registerSchema({
|
|
|
15174
15495
|
var FIELDS4 = {
|
|
15175
15496
|
suggestion: "Autocomplete suggestion from Google"
|
|
15176
15497
|
};
|
|
15177
|
-
var autocompleteCommand =
|
|
15498
|
+
var autocompleteCommand = defineCommand119({
|
|
15178
15499
|
meta: {
|
|
15179
15500
|
name: "autocomplete",
|
|
15180
15501
|
description: `Get Google Autocomplete suggestions for keyword expansion.
|
|
@@ -15220,7 +15541,7 @@ Examples:
|
|
|
15220
15541
|
});
|
|
15221
15542
|
|
|
15222
15543
|
// src/commands/research/countries.ts
|
|
15223
|
-
import { defineCommand as
|
|
15544
|
+
import { defineCommand as defineCommand120 } from "citty";
|
|
15224
15545
|
registerSchema({
|
|
15225
15546
|
command: "research.countries",
|
|
15226
15547
|
description: "List all supported country codes for --location flag in research commands.",
|
|
@@ -15277,7 +15598,7 @@ var FIELDS5 = {
|
|
|
15277
15598
|
code: "Country code to pass as --location",
|
|
15278
15599
|
name: "Country name"
|
|
15279
15600
|
};
|
|
15280
|
-
var countriesCommand =
|
|
15601
|
+
var countriesCommand = defineCommand120({
|
|
15281
15602
|
meta: {
|
|
15282
15603
|
name: "countries",
|
|
15283
15604
|
description: "List all supported country codes for --location flag."
|
|
@@ -15288,7 +15609,7 @@ var countriesCommand = defineCommand119({
|
|
|
15288
15609
|
});
|
|
15289
15610
|
|
|
15290
15611
|
// src/commands/research/intent.ts
|
|
15291
|
-
import { defineCommand as
|
|
15612
|
+
import { defineCommand as defineCommand121 } from "citty";
|
|
15292
15613
|
registerSchema({
|
|
15293
15614
|
command: "research.intent",
|
|
15294
15615
|
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.",
|
|
@@ -15311,7 +15632,7 @@ var FIELDS6 = {
|
|
|
15311
15632
|
intent: "Primary Google Search intent: informational, navigational, commercial, transactional",
|
|
15312
15633
|
probability: "Confidence score 0.0-1.0"
|
|
15313
15634
|
};
|
|
15314
|
-
var intentCommand =
|
|
15635
|
+
var intentCommand = defineCommand121({
|
|
15315
15636
|
meta: {
|
|
15316
15637
|
name: "intent",
|
|
15317
15638
|
description: `Classify Google Search intent for keywords. Returns intent type and confidence.
|
|
@@ -15359,7 +15680,7 @@ Examples:
|
|
|
15359
15680
|
});
|
|
15360
15681
|
|
|
15361
15682
|
// src/commands/research/keyword-gap.ts
|
|
15362
|
-
import { defineCommand as
|
|
15683
|
+
import { defineCommand as defineCommand122 } from "citty";
|
|
15363
15684
|
registerSchema({
|
|
15364
15685
|
command: "research.keyword-gap",
|
|
15365
15686
|
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.",
|
|
@@ -15388,7 +15709,7 @@ var FIELDS7 = {
|
|
|
15388
15709
|
cpc: "Cost per click USD",
|
|
15389
15710
|
their_position: "Competitor's ranking position"
|
|
15390
15711
|
};
|
|
15391
|
-
var keywordGapCommand =
|
|
15712
|
+
var keywordGapCommand = defineCommand122({
|
|
15392
15713
|
meta: {
|
|
15393
15714
|
name: "keyword-gap",
|
|
15394
15715
|
description: `Find keywords a competitor has that you don't. Supports pagination via --offset.
|
|
@@ -15462,7 +15783,7 @@ Examples:
|
|
|
15462
15783
|
});
|
|
15463
15784
|
|
|
15464
15785
|
// src/commands/research/keywords-for-site.ts
|
|
15465
|
-
import { defineCommand as
|
|
15786
|
+
import { defineCommand as defineCommand123 } from "citty";
|
|
15466
15787
|
registerSchema({
|
|
15467
15788
|
command: "research.keywords-for-site",
|
|
15468
15789
|
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.",
|
|
@@ -15495,7 +15816,7 @@ var FIELDS8 = {
|
|
|
15495
15816
|
competition: "LOW, MEDIUM, or HIGH",
|
|
15496
15817
|
competition_index: "Competition score 0-100"
|
|
15497
15818
|
};
|
|
15498
|
-
var keywordsForSiteCommand =
|
|
15819
|
+
var keywordsForSiteCommand = defineCommand123({
|
|
15499
15820
|
meta: {
|
|
15500
15821
|
name: "keywords-for-site",
|
|
15501
15822
|
description: `Get keywords a competitor targets in Google. Use --type to filter paid/organic.
|
|
@@ -15548,7 +15869,7 @@ Examples:
|
|
|
15548
15869
|
});
|
|
15549
15870
|
|
|
15550
15871
|
// src/commands/research/languages.ts
|
|
15551
|
-
import { defineCommand as
|
|
15872
|
+
import { defineCommand as defineCommand124 } from "citty";
|
|
15552
15873
|
registerSchema({
|
|
15553
15874
|
command: "research.languages",
|
|
15554
15875
|
description: "List all supported language codes for --language flag in research commands.",
|
|
@@ -15578,7 +15899,7 @@ var FIELDS9 = {
|
|
|
15578
15899
|
code: "Language code to pass as --language",
|
|
15579
15900
|
name: "Language name (also accepted by --language)"
|
|
15580
15901
|
};
|
|
15581
|
-
var languagesCommand2 =
|
|
15902
|
+
var languagesCommand2 = defineCommand124({
|
|
15582
15903
|
meta: {
|
|
15583
15904
|
name: "languages",
|
|
15584
15905
|
description: "List all supported language codes for --language flag."
|
|
@@ -15589,7 +15910,7 @@ var languagesCommand2 = defineCommand123({
|
|
|
15589
15910
|
});
|
|
15590
15911
|
|
|
15591
15912
|
// src/commands/research/lighthouse.ts
|
|
15592
|
-
import { defineCommand as
|
|
15913
|
+
import { defineCommand as defineCommand125 } from "citty";
|
|
15593
15914
|
registerSchema({
|
|
15594
15915
|
command: "research.lighthouse",
|
|
15595
15916
|
description: "Landing page performance audit. Returns metrics that affect Google Ads Quality Score and CPC.",
|
|
@@ -15608,7 +15929,7 @@ var FIELDS10 = {
|
|
|
15608
15929
|
speed_index_ms: "Speed Index in ms (good: < 3400)",
|
|
15609
15930
|
interactive_ms: "Time to Interactive in ms (good: < 3800)"
|
|
15610
15931
|
};
|
|
15611
|
-
var lighthouseCommand =
|
|
15932
|
+
var lighthouseCommand = defineCommand125({
|
|
15612
15933
|
meta: {
|
|
15613
15934
|
name: "lighthouse",
|
|
15614
15935
|
description: `Landing page performance audit. Metrics affecting Google Ads Quality Score.
|
|
@@ -15646,7 +15967,7 @@ Examples:
|
|
|
15646
15967
|
});
|
|
15647
15968
|
|
|
15648
15969
|
// src/commands/research/relevant-pages.ts
|
|
15649
|
-
import { defineCommand as
|
|
15970
|
+
import { defineCommand as defineCommand126 } from "citty";
|
|
15650
15971
|
registerSchema({
|
|
15651
15972
|
command: "research.relevant-pages",
|
|
15652
15973
|
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).",
|
|
@@ -15672,7 +15993,7 @@ var FIELDS11 = {
|
|
|
15672
15993
|
keywords: "Total organic keywords the page ranks for",
|
|
15673
15994
|
top_10: "Keywords in positions 1-10"
|
|
15674
15995
|
};
|
|
15675
|
-
var relevantPagesCommand =
|
|
15996
|
+
var relevantPagesCommand = defineCommand126({
|
|
15676
15997
|
meta: {
|
|
15677
15998
|
name: "relevant-pages",
|
|
15678
15999
|
description: `Get the top pages of a competitor domain with traffic data.
|
|
@@ -15718,7 +16039,7 @@ Examples:
|
|
|
15718
16039
|
});
|
|
15719
16040
|
|
|
15720
16041
|
// src/commands/research/web.ts
|
|
15721
|
-
import { defineCommand as
|
|
16042
|
+
import { defineCommand as defineCommand127 } from "citty";
|
|
15722
16043
|
registerSchema({
|
|
15723
16044
|
command: "research.web",
|
|
15724
16045
|
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).",
|
|
@@ -15769,7 +16090,7 @@ async function runDeepResearch(question) {
|
|
|
15769
16090
|
}
|
|
15770
16091
|
throw new Error("Deep research timed out");
|
|
15771
16092
|
}
|
|
15772
|
-
var webCommand =
|
|
16093
|
+
var webCommand = defineCommand127({
|
|
15773
16094
|
meta: {
|
|
15774
16095
|
name: "web",
|
|
15775
16096
|
description: `Search the web with AI to answer any open-ended marketing question. Uses live internet data via Google Search.
|
|
@@ -15829,7 +16150,7 @@ Examples:
|
|
|
15829
16150
|
});
|
|
15830
16151
|
|
|
15831
16152
|
// src/commands/research/index.ts
|
|
15832
|
-
var researchCommand =
|
|
16153
|
+
var researchCommand = defineCommand128({
|
|
15833
16154
|
meta: {
|
|
15834
16155
|
name: "research",
|
|
15835
16156
|
description: `Competitive intelligence and AI-powered research commands.
|
|
@@ -15869,10 +16190,10 @@ Examples:
|
|
|
15869
16190
|
});
|
|
15870
16191
|
|
|
15871
16192
|
// src/commands/scheduled-actions/index.ts
|
|
15872
|
-
import { defineCommand as
|
|
16193
|
+
import { defineCommand as defineCommand135 } from "citty";
|
|
15873
16194
|
|
|
15874
16195
|
// src/commands/scheduled-actions/create.ts
|
|
15875
|
-
import { defineCommand as
|
|
16196
|
+
import { defineCommand as defineCommand129 } from "citty";
|
|
15876
16197
|
|
|
15877
16198
|
// src/commands/scheduled-actions/shared.ts
|
|
15878
16199
|
var TEMP_SCHEDULED_ACTION_PREFIX = "temp_sched_";
|
|
@@ -15977,7 +16298,7 @@ registerSchema({
|
|
|
15977
16298
|
prompt: { type: "string", description: "Additional prompt instructions for the spawned agent", required: false }
|
|
15978
16299
|
}
|
|
15979
16300
|
});
|
|
15980
|
-
var createCommand2 =
|
|
16301
|
+
var createCommand2 = defineCommand129({
|
|
15981
16302
|
meta: {
|
|
15982
16303
|
name: "create",
|
|
15983
16304
|
description: 'Stage a scheduled action. Example: baker scheduled-actions create --name "Weekly report" --description "..." --cron "0 9 * * MON"'
|
|
@@ -16025,7 +16346,7 @@ var createCommand2 = defineCommand128({
|
|
|
16025
16346
|
});
|
|
16026
16347
|
|
|
16027
16348
|
// src/commands/scheduled-actions/delete.ts
|
|
16028
|
-
import { defineCommand as
|
|
16349
|
+
import { defineCommand as defineCommand130 } from "citty";
|
|
16029
16350
|
registerSchema({
|
|
16030
16351
|
command: "scheduled-actions.delete",
|
|
16031
16352
|
description: "Stage deletion of a published scheduled action or cancellation of a temp_sched_* draft creation.",
|
|
@@ -16033,7 +16354,7 @@ registerSchema({
|
|
|
16033
16354
|
id: { type: "string", description: "Published scheduled action ID or temp_sched_* draft ID", required: true }
|
|
16034
16355
|
}
|
|
16035
16356
|
});
|
|
16036
|
-
var deleteCommand2 =
|
|
16357
|
+
var deleteCommand2 = defineCommand130({
|
|
16037
16358
|
meta: {
|
|
16038
16359
|
name: "delete",
|
|
16039
16360
|
description: "Stage scheduled action deletion. Example: baker scheduled-actions delete <id-or-temp_sched_id>"
|
|
@@ -16062,7 +16383,7 @@ var deleteCommand2 = defineCommand129({
|
|
|
16062
16383
|
});
|
|
16063
16384
|
|
|
16064
16385
|
// src/commands/scheduled-actions/get.ts
|
|
16065
|
-
import { defineCommand as
|
|
16386
|
+
import { defineCommand as defineCommand131 } from "citty";
|
|
16066
16387
|
registerSchema({
|
|
16067
16388
|
command: "scheduled-actions.get",
|
|
16068
16389
|
description: "Get a published scheduled action or a temp_sched_* draft-created scheduled action.",
|
|
@@ -16070,7 +16391,7 @@ registerSchema({
|
|
|
16070
16391
|
id: { type: "string", description: "Published scheduled action ID or temp_sched_* draft ID", required: true }
|
|
16071
16392
|
}
|
|
16072
16393
|
});
|
|
16073
|
-
var getCommand3 =
|
|
16394
|
+
var getCommand3 = defineCommand131({
|
|
16074
16395
|
meta: {
|
|
16075
16396
|
name: "get",
|
|
16076
16397
|
description: "Get a scheduled action. Example: baker scheduled-actions get <id-or-temp_sched_id>"
|
|
@@ -16107,13 +16428,13 @@ var getCommand3 = defineCommand130({
|
|
|
16107
16428
|
});
|
|
16108
16429
|
|
|
16109
16430
|
// src/commands/scheduled-actions/list.ts
|
|
16110
|
-
import { defineCommand as
|
|
16431
|
+
import { defineCommand as defineCommand132 } from "citty";
|
|
16111
16432
|
registerSchema({
|
|
16112
16433
|
command: "scheduled-actions.list",
|
|
16113
16434
|
description: "List published scheduled actions. Includes draft state when BAKER_CHAT_ID is set.",
|
|
16114
16435
|
args: {}
|
|
16115
16436
|
});
|
|
16116
|
-
var listCommand3 =
|
|
16437
|
+
var listCommand3 = defineCommand132({
|
|
16117
16438
|
meta: {
|
|
16118
16439
|
name: "list",
|
|
16119
16440
|
description: "List scheduled actions. Includes staged draft ops when BAKER_CHAT_ID is set."
|
|
@@ -16134,7 +16455,7 @@ var listCommand3 = defineCommand131({
|
|
|
16134
16455
|
});
|
|
16135
16456
|
|
|
16136
16457
|
// src/commands/scheduled-actions/trigger.ts
|
|
16137
|
-
import { defineCommand as
|
|
16458
|
+
import { defineCommand as defineCommand133 } from "citty";
|
|
16138
16459
|
registerSchema({
|
|
16139
16460
|
command: "scheduled-actions.trigger",
|
|
16140
16461
|
description: "Immediately trigger a published scheduled action. Does not require BAKER_CHAT_ID and rejects temp_sched_* IDs.",
|
|
@@ -16142,7 +16463,7 @@ registerSchema({
|
|
|
16142
16463
|
id: { type: "string", description: "Published scheduled action ID", required: true }
|
|
16143
16464
|
}
|
|
16144
16465
|
});
|
|
16145
|
-
var triggerCommand =
|
|
16466
|
+
var triggerCommand = defineCommand133({
|
|
16146
16467
|
meta: {
|
|
16147
16468
|
name: "trigger",
|
|
16148
16469
|
description: "Immediately trigger a published scheduled action. Example: baker scheduled-actions trigger <id>"
|
|
@@ -16179,7 +16500,7 @@ var triggerCommand = defineCommand132({
|
|
|
16179
16500
|
});
|
|
16180
16501
|
|
|
16181
16502
|
// src/commands/scheduled-actions/update.ts
|
|
16182
|
-
import { defineCommand as
|
|
16503
|
+
import { defineCommand as defineCommand134 } from "citty";
|
|
16183
16504
|
registerSchema({
|
|
16184
16505
|
command: "scheduled-actions.update",
|
|
16185
16506
|
description: "Stage an update to a published scheduled action or temp_sched_* draft-created scheduled action.",
|
|
@@ -16204,7 +16525,7 @@ registerSchema({
|
|
|
16204
16525
|
prompt: { type: "string", description: "Replacement additional spawned-agent instructions", required: false }
|
|
16205
16526
|
}
|
|
16206
16527
|
});
|
|
16207
|
-
var updateCommand2 =
|
|
16528
|
+
var updateCommand2 = defineCommand134({
|
|
16208
16529
|
meta: {
|
|
16209
16530
|
name: "update",
|
|
16210
16531
|
description: "Stage a scheduled action update. Example: baker scheduled-actions update <id> --enabled false"
|
|
@@ -16274,7 +16595,7 @@ var updateCommand2 = defineCommand133({
|
|
|
16274
16595
|
});
|
|
16275
16596
|
|
|
16276
16597
|
// src/commands/scheduled-actions/index.ts
|
|
16277
|
-
var scheduledActionsCommand =
|
|
16598
|
+
var scheduledActionsCommand = defineCommand135({
|
|
16278
16599
|
meta: {
|
|
16279
16600
|
name: "scheduled-actions",
|
|
16280
16601
|
description: `Manage Scheduled Actions. Subcommands: list, get, create, update, delete, trigger.
|
|
@@ -16300,8 +16621,8 @@ Examples:
|
|
|
16300
16621
|
});
|
|
16301
16622
|
|
|
16302
16623
|
// src/commands/schema.ts
|
|
16303
|
-
import { defineCommand as
|
|
16304
|
-
var schemaCommand =
|
|
16624
|
+
import { defineCommand as defineCommand136 } from "citty";
|
|
16625
|
+
var schemaCommand = defineCommand136({
|
|
16305
16626
|
meta: {
|
|
16306
16627
|
name: "schema",
|
|
16307
16628
|
description: "Inspect command argument schemas (for AI agent introspection). Lists all commands if no argument given. Example: baker schema images.search"
|
|
@@ -16337,10 +16658,10 @@ var schemaCommand = defineCommand135({
|
|
|
16337
16658
|
});
|
|
16338
16659
|
|
|
16339
16660
|
// src/commands/testimonials/index.ts
|
|
16340
|
-
import { defineCommand as
|
|
16661
|
+
import { defineCommand as defineCommand140 } from "citty";
|
|
16341
16662
|
|
|
16342
16663
|
// src/commands/testimonials/get.ts
|
|
16343
|
-
import { defineCommand as
|
|
16664
|
+
import { defineCommand as defineCommand137 } from "citty";
|
|
16344
16665
|
registerSchema({
|
|
16345
16666
|
command: "testimonials.get",
|
|
16346
16667
|
description: "Get a single testimonial by ID",
|
|
@@ -16348,7 +16669,7 @@ registerSchema({
|
|
|
16348
16669
|
id: { type: "string", description: "Testimonial ID", required: true }
|
|
16349
16670
|
}
|
|
16350
16671
|
});
|
|
16351
|
-
var getCommand4 =
|
|
16672
|
+
var getCommand4 = defineCommand137({
|
|
16352
16673
|
meta: { name: "get", description: "Get a single testimonial by ID. Example: baker testimonials get j571abc123" },
|
|
16353
16674
|
args: {
|
|
16354
16675
|
id: { type: "positional", description: "Testimonial ID", required: false },
|
|
@@ -16385,7 +16706,7 @@ var getCommand4 = defineCommand136({
|
|
|
16385
16706
|
});
|
|
16386
16707
|
|
|
16387
16708
|
// src/commands/testimonials/list.ts
|
|
16388
|
-
import { defineCommand as
|
|
16709
|
+
import { defineCommand as defineCommand138 } from "citty";
|
|
16389
16710
|
registerSchema({
|
|
16390
16711
|
command: "testimonials.list",
|
|
16391
16712
|
description: "List testimonials with optional filters.",
|
|
@@ -16415,7 +16736,7 @@ registerSchema({
|
|
|
16415
16736
|
limit: { type: "number", description: "Max results (default 50)", required: false, default: 50 }
|
|
16416
16737
|
}
|
|
16417
16738
|
});
|
|
16418
|
-
var listCommand4 =
|
|
16739
|
+
var listCommand4 = defineCommand138({
|
|
16419
16740
|
meta: {
|
|
16420
16741
|
name: "list",
|
|
16421
16742
|
description: "List testimonials with optional filters. Example: baker testimonials list --source google --sentiment positive"
|
|
@@ -16464,7 +16785,7 @@ var listCommand4 = defineCommand137({
|
|
|
16464
16785
|
});
|
|
16465
16786
|
|
|
16466
16787
|
// src/commands/testimonials/search.ts
|
|
16467
|
-
import { defineCommand as
|
|
16788
|
+
import { defineCommand as defineCommand139 } from "citty";
|
|
16468
16789
|
registerSchema({
|
|
16469
16790
|
command: "testimonials.search",
|
|
16470
16791
|
description: "Search testimonials by text query. Uses hybrid BM25 + vector + reranking.",
|
|
@@ -16495,7 +16816,7 @@ registerSchema({
|
|
|
16495
16816
|
tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
|
|
16496
16817
|
}
|
|
16497
16818
|
});
|
|
16498
|
-
var searchCommand2 =
|
|
16819
|
+
var searchCommand2 = defineCommand139({
|
|
16499
16820
|
meta: {
|
|
16500
16821
|
name: "search",
|
|
16501
16822
|
description: "Semantic search testimonials by text query. Uses hybrid BM25 + vector + reranking. Example: baker testimonials search 'great service' --rating-min 4"
|
|
@@ -16569,7 +16890,7 @@ var searchCommand2 = defineCommand138({
|
|
|
16569
16890
|
var tagsCommand3 = makeTagsCommand("testimonials", "testimonial", "/api/testimonials/tags");
|
|
16570
16891
|
|
|
16571
16892
|
// src/commands/testimonials/index.ts
|
|
16572
|
-
var testimonialsCommand =
|
|
16893
|
+
var testimonialsCommand = defineCommand140({
|
|
16573
16894
|
meta: {
|
|
16574
16895
|
name: "testimonials",
|
|
16575
16896
|
description: `Find and browse testimonials in Baker. Subcommands: search, get, list, tags.
|
|
@@ -16590,10 +16911,10 @@ Examples:
|
|
|
16590
16911
|
});
|
|
16591
16912
|
|
|
16592
16913
|
// src/commands/videos/index.ts
|
|
16593
|
-
import { defineCommand as
|
|
16914
|
+
import { defineCommand as defineCommand145 } from "citty";
|
|
16594
16915
|
|
|
16595
16916
|
// src/commands/videos/delete.ts
|
|
16596
|
-
import { defineCommand as
|
|
16917
|
+
import { defineCommand as defineCommand141 } from "citty";
|
|
16597
16918
|
registerSchema({
|
|
16598
16919
|
command: "videos.delete",
|
|
16599
16920
|
description: "Delete a video by ID",
|
|
@@ -16607,7 +16928,7 @@ registerSchema({
|
|
|
16607
16928
|
}
|
|
16608
16929
|
}
|
|
16609
16930
|
});
|
|
16610
|
-
var deleteCommand3 =
|
|
16931
|
+
var deleteCommand3 = defineCommand141({
|
|
16611
16932
|
meta: {
|
|
16612
16933
|
name: "delete",
|
|
16613
16934
|
description: "Delete a video by ID. Use --dry-run to preview. Example: baker videos delete j571abc123 --dry-run"
|
|
@@ -16648,7 +16969,7 @@ var deleteCommand3 = defineCommand140({
|
|
|
16648
16969
|
});
|
|
16649
16970
|
|
|
16650
16971
|
// src/commands/videos/get.ts
|
|
16651
|
-
import { defineCommand as
|
|
16972
|
+
import { defineCommand as defineCommand142 } from "citty";
|
|
16652
16973
|
registerSchema({
|
|
16653
16974
|
command: "videos.get",
|
|
16654
16975
|
description: "Get a single video by ID",
|
|
@@ -16656,7 +16977,7 @@ registerSchema({
|
|
|
16656
16977
|
id: { type: "string", description: "Video ID", required: true }
|
|
16657
16978
|
}
|
|
16658
16979
|
});
|
|
16659
|
-
var getCommand5 =
|
|
16980
|
+
var getCommand5 = defineCommand142({
|
|
16660
16981
|
meta: { name: "get", description: "Get a single video by ID. Example: baker videos get j571abc123" },
|
|
16661
16982
|
args: {
|
|
16662
16983
|
id: { type: "positional", description: "Video ID", required: false },
|
|
@@ -16693,7 +17014,7 @@ var getCommand5 = defineCommand141({
|
|
|
16693
17014
|
});
|
|
16694
17015
|
|
|
16695
17016
|
// src/commands/videos/search.ts
|
|
16696
|
-
import { defineCommand as
|
|
17017
|
+
import { defineCommand as defineCommand143 } from "citty";
|
|
16697
17018
|
registerSchema({
|
|
16698
17019
|
command: "videos.search",
|
|
16699
17020
|
description: "Search videos by text query. Only returns ready videos.",
|
|
@@ -16703,7 +17024,7 @@ registerSchema({
|
|
|
16703
17024
|
tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
|
|
16704
17025
|
}
|
|
16705
17026
|
});
|
|
16706
|
-
var searchCommand3 =
|
|
17027
|
+
var searchCommand3 = defineCommand143({
|
|
16707
17028
|
meta: {
|
|
16708
17029
|
name: "search",
|
|
16709
17030
|
description: "Semantic search videos by text query. Uses hybrid BM25 + vector + reranking. Example: baker videos search 'product demo' --tags tutorial"
|
|
@@ -16753,9 +17074,9 @@ var searchCommand3 = defineCommand142({
|
|
|
16753
17074
|
var tagsCommand4 = makeTagsCommand("videos", "video", "/api/videos/tags");
|
|
16754
17075
|
|
|
16755
17076
|
// src/commands/videos/upload.ts
|
|
16756
|
-
import { readFile as
|
|
17077
|
+
import { readFile as readFile12, stat as stat3 } from "fs/promises";
|
|
16757
17078
|
import { extname as extname3 } from "path";
|
|
16758
|
-
import { defineCommand as
|
|
17079
|
+
import { defineCommand as defineCommand144 } from "citty";
|
|
16759
17080
|
var MIME_MAP2 = {
|
|
16760
17081
|
".mp4": "video/mp4",
|
|
16761
17082
|
".mov": "video/quicktime",
|
|
@@ -16789,7 +17110,7 @@ function detectContentType2(filePath) {
|
|
|
16789
17110
|
}
|
|
16790
17111
|
return mime;
|
|
16791
17112
|
}
|
|
16792
|
-
var uploadCommand2 =
|
|
17113
|
+
var uploadCommand2 = defineCommand144({
|
|
16793
17114
|
meta: {
|
|
16794
17115
|
name: "upload",
|
|
16795
17116
|
description: "Upload a video file to Baker via Mux direct upload. Auto-detects content type. Example: baker videos upload ./demo.mp4"
|
|
@@ -16818,7 +17139,7 @@ var uploadCommand2 = defineCommand143({
|
|
|
16818
17139
|
return;
|
|
16819
17140
|
}
|
|
16820
17141
|
const { uploadUrl, videoId } = await apiPost("/api/videos/upload", {});
|
|
16821
|
-
const fileBuffer = await
|
|
17142
|
+
const fileBuffer = await readFile12(filePath);
|
|
16822
17143
|
const uploadResponse = await fetch(uploadUrl, {
|
|
16823
17144
|
method: "PUT",
|
|
16824
17145
|
headers: { "Content-Type": contentType },
|
|
@@ -16843,7 +17164,7 @@ var uploadCommand2 = defineCommand143({
|
|
|
16843
17164
|
});
|
|
16844
17165
|
|
|
16845
17166
|
// src/commands/videos/index.ts
|
|
16846
|
-
var videosCommand =
|
|
17167
|
+
var videosCommand = defineCommand145({
|
|
16847
17168
|
meta: {
|
|
16848
17169
|
name: "videos",
|
|
16849
17170
|
description: `Find and manage videos in Baker. Subcommands: search, get, upload, delete, tags.
|
|
@@ -16866,10 +17187,10 @@ Examples:
|
|
|
16866
17187
|
});
|
|
16867
17188
|
|
|
16868
17189
|
// src/commands/winning-ads/index.ts
|
|
16869
|
-
import { defineCommand as
|
|
17190
|
+
import { defineCommand as defineCommand148 } from "citty";
|
|
16870
17191
|
|
|
16871
17192
|
// src/commands/winning-ads/advertisers.ts
|
|
16872
|
-
import { defineCommand as
|
|
17193
|
+
import { defineCommand as defineCommand146 } from "citty";
|
|
16873
17194
|
registerSchema({
|
|
16874
17195
|
command: "winning-ads.advertisers",
|
|
16875
17196
|
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).",
|
|
@@ -16882,7 +17203,7 @@ registerSchema({
|
|
|
16882
17203
|
function identity(record) {
|
|
16883
17204
|
return record;
|
|
16884
17205
|
}
|
|
16885
|
-
var advertisersCommand2 =
|
|
17206
|
+
var advertisersCommand2 = defineCommand146({
|
|
16886
17207
|
meta: {
|
|
16887
17208
|
name: "advertisers",
|
|
16888
17209
|
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'
|
|
@@ -16933,7 +17254,7 @@ var advertisersCommand2 = defineCommand145({
|
|
|
16933
17254
|
});
|
|
16934
17255
|
|
|
16935
17256
|
// src/commands/winning-ads/search.ts
|
|
16936
|
-
import { defineCommand as
|
|
17257
|
+
import { defineCommand as defineCommand147 } from "citty";
|
|
16937
17258
|
registerSchema({
|
|
16938
17259
|
command: "winning-ads.search",
|
|
16939
17260
|
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.",
|
|
@@ -17041,7 +17362,7 @@ function buildSearchBody(args) {
|
|
|
17041
17362
|
}
|
|
17042
17363
|
return body;
|
|
17043
17364
|
}
|
|
17044
|
-
var searchCommand4 =
|
|
17365
|
+
var searchCommand4 = defineCommand147({
|
|
17045
17366
|
meta: {
|
|
17046
17367
|
name: "search",
|
|
17047
17368
|
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"
|
|
@@ -17153,7 +17474,7 @@ var searchCommand4 = defineCommand146({
|
|
|
17153
17474
|
});
|
|
17154
17475
|
|
|
17155
17476
|
// src/commands/winning-ads/index.ts
|
|
17156
|
-
var winningAdsCommand =
|
|
17477
|
+
var winningAdsCommand = defineCommand148({
|
|
17157
17478
|
meta: {
|
|
17158
17479
|
name: "winning-ads",
|
|
17159
17480
|
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.
|
|
@@ -17193,7 +17514,7 @@ function getCliVersion() {
|
|
|
17193
17514
|
}
|
|
17194
17515
|
|
|
17195
17516
|
// src/cli.ts
|
|
17196
|
-
var main =
|
|
17517
|
+
var main = defineCommand149({
|
|
17197
17518
|
meta: {
|
|
17198
17519
|
name: "baker",
|
|
17199
17520
|
version: getCliVersion(),
|