@koda-sl/baker-cli 0.98.1 → 0.99.0-dev.40c99be71

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ AssetRef,
3
4
  ELEVENLABS_MAX_MUSIC_LENGTH_MS,
4
5
  IMAGE_GENERATE_MODELS,
5
6
  MODEL_REGISTRY,
@@ -7,12 +8,13 @@ import {
7
8
  ValidationError,
8
9
  createEngineFromEnv,
9
10
  defaultRegistry,
11
+ extForMime,
10
12
  generateCatalog,
11
13
  validateCanvasDeep
12
- } from "./chunk-3JVYU72O.js";
14
+ } from "./chunk-FOK2JPRW.js";
13
15
 
14
16
  // src/cli.ts
15
- import { defineCommand as defineCommand149, runMain } from "citty";
17
+ import { defineCommand as defineCommand150, runMain } from "citty";
16
18
 
17
19
  // src/commands/actions/index.ts
18
20
  import { defineCommand as defineCommand17 } from "citty";
@@ -43,6 +45,9 @@ function getEnv() {
43
45
  }
44
46
  return cached;
45
47
  }
48
+ function runtimeEnvVar(name) {
49
+ return process.env[name];
50
+ }
46
51
  function requireChatId() {
47
52
  const env = getEnv();
48
53
  if (!env.BAKER_CHAT_ID) {
@@ -147,9 +152,9 @@ async function handleResponse(response) {
147
152
  throw new ApiError("INTERNAL_ERROR", "Failed to parse API response as JSON");
148
153
  }
149
154
  }
150
- async function apiGet(path11, params) {
155
+ async function apiGet(path12, params) {
151
156
  const env = getEnv();
152
- const url = new URL(path11, env.BAKER_API_URL);
157
+ const url = new URL(path12, env.BAKER_API_URL);
153
158
  if (params) {
154
159
  const clean = sanitizeParams(params);
155
160
  for (const [key, value] of Object.entries(clean)) {
@@ -174,12 +179,12 @@ async function apiGet(path11, params) {
174
179
  }
175
180
  return handleResponse(response);
176
181
  }
177
- async function apiPost(path11, body, opts) {
182
+ async function apiPost(path12, body, opts) {
178
183
  const env = getEnv();
179
184
  const timeoutMs = opts?.timeoutMs ?? 6e4;
180
185
  let response;
181
186
  try {
182
- response = await fetchWithRateLimitRetry(new URL(path11, env.BAKER_API_URL).toString(), {
187
+ response = await fetchWithRateLimitRetry(new URL(path12, env.BAKER_API_URL).toString(), {
183
188
  method: "POST",
184
189
  headers: {
185
190
  Authorization: `Bearer ${env.BAKER_API_KEY}`,
@@ -1327,31 +1332,31 @@ function cachePath(category, key) {
1327
1332
  return join(dir, `${hashKey(key)}.json`);
1328
1333
  }
1329
1334
  function cacheGet(category, key) {
1330
- const path11 = cachePath(category, key);
1331
- if (!existsSync(path11)) {
1335
+ const path12 = cachePath(category, key);
1336
+ if (!existsSync(path12)) {
1332
1337
  return null;
1333
1338
  }
1334
1339
  try {
1335
- const raw = readFileSync(path11, "utf-8");
1340
+ const raw = readFileSync(path12, "utf-8");
1336
1341
  const entry = JSON.parse(raw);
1337
1342
  if (entry.expiresAt < Date.now()) {
1338
- rmSync(path11, { force: true });
1343
+ rmSync(path12, { force: true });
1339
1344
  return null;
1340
1345
  }
1341
1346
  return entry;
1342
1347
  } catch {
1343
- rmSync(path11, { force: true });
1348
+ rmSync(path12, { force: true });
1344
1349
  return null;
1345
1350
  }
1346
1351
  }
1347
1352
  function cacheSet(category, key, data, ttlMs, fields) {
1348
- const path11 = cachePath(category, key);
1353
+ const path12 = cachePath(category, key);
1349
1354
  const entry = {
1350
1355
  expiresAt: Date.now() + ttlMs,
1351
1356
  data,
1352
1357
  fields
1353
1358
  };
1354
- writeFileSync(path11, JSON.stringify(entry), "utf-8");
1359
+ writeFileSync(path12, JSON.stringify(entry), "utf-8");
1355
1360
  }
1356
1361
  var HOUR = 60 * 60 * 1e3;
1357
1362
  var MINUTE = 60 * 1e3;
@@ -8045,7 +8050,7 @@ Examples:
8045
8050
  });
8046
8051
 
8047
8052
  // src/commands/canvas/index.ts
8048
- import { defineCommand as defineCommand85 } from "citty";
8053
+ import { defineCommand as defineCommand86 } from "citty";
8049
8054
 
8050
8055
  // src/commands/canvas/catalog.ts
8051
8056
  import { defineCommand as defineCommand78 } from "citty";
@@ -8061,14 +8066,231 @@ var catalogCommand = defineCommand78({
8061
8066
  }
8062
8067
  });
8063
8068
 
8069
+ // src/commands/canvas/gallery.ts
8070
+ import { readdir, readFile } from "fs/promises";
8071
+ import path from "path";
8072
+ import { defineCommand as defineCommand79 } from "citty";
8073
+
8074
+ // src/engine/gallery/descriptor.ts
8075
+ var KNOWN_RATIOS = [
8076
+ ["9:16", 9 / 16],
8077
+ ["4:5", 4 / 5],
8078
+ ["1:1", 1],
8079
+ ["1.91:1", 1.91],
8080
+ ["16:9", 16 / 9],
8081
+ ["4:1", 4]
8082
+ ];
8083
+ var RATIO_TOLERANCE = 0.06;
8084
+ function aspectLabel(width, height) {
8085
+ if (!width || !height) {
8086
+ return "other";
8087
+ }
8088
+ const ratio = width / height;
8089
+ let best = "other";
8090
+ let bestErr = Number.POSITIVE_INFINITY;
8091
+ for (const [label, value] of KNOWN_RATIOS) {
8092
+ const err = Math.abs(ratio - value) / value;
8093
+ if (err < bestErr) {
8094
+ bestErr = err;
8095
+ best = label;
8096
+ }
8097
+ }
8098
+ return bestErr <= RATIO_TOLERANCE ? best : `${width}x${height}`;
8099
+ }
8100
+ function visualRef(value) {
8101
+ const parsed = AssetRef.safeParse(value);
8102
+ if (!parsed.success) {
8103
+ return null;
8104
+ }
8105
+ if (parsed.data.kind !== "image" && parsed.data.kind !== "video") {
8106
+ return null;
8107
+ }
8108
+ return parsed.data;
8109
+ }
8110
+ function deliverableFor(ref, stem, resolveLocal) {
8111
+ const width = "width" in ref ? ref.width : void 0;
8112
+ const height = "height" in ref ? ref.height : void 0;
8113
+ return {
8114
+ kind: ref.kind,
8115
+ format: aspectLabel(width, height),
8116
+ // Remote-node outputs already carry a public R2 url; local composites are
8117
+ // resolved against the mounted run dir's public base.
8118
+ url: ref.url ?? resolveLocal(`${stem}.${extForMime(ref.mime)}`),
8119
+ width,
8120
+ height,
8121
+ label: stem
8122
+ };
8123
+ }
8124
+ function deliverablesFromOutput(output, resolveLocal) {
8125
+ if (Array.isArray(output)) {
8126
+ const out = [];
8127
+ output.forEach((entry, i) => {
8128
+ const ref2 = visualRef(entry);
8129
+ if (ref2) {
8130
+ out.push(deliverableFor(ref2, `_final__${i}`, resolveLocal));
8131
+ }
8132
+ });
8133
+ return out;
8134
+ }
8135
+ const ref = visualRef(output);
8136
+ return ref ? [deliverableFor(ref, "_final", resolveLocal)] : [];
8137
+ }
8138
+ function buildGeneration(runId, manifest, resolveLocal) {
8139
+ const m = manifest ?? {};
8140
+ const credits = typeof m.stats?.total_credits === "number" ? m.stats.total_credits : 0;
8141
+ return {
8142
+ runId,
8143
+ createdAt: typeof m.completed_at === "number" ? m.completed_at : 0,
8144
+ credits,
8145
+ deliverables: deliverablesFromOutput(m.output, resolveLocal)
8146
+ };
8147
+ }
8148
+ function buildGalleryDescriptor(input) {
8149
+ const generations = [...input.generations].sort((a, b) => b.createdAt - a.createdAt);
8150
+ return {
8151
+ slug: input.slug,
8152
+ title: input.definition.title,
8153
+ platform: input.definition.platform,
8154
+ status: input.definition.status,
8155
+ reference: input.definition.reference,
8156
+ selectedRun: input.definition.selectedRun,
8157
+ generations
8158
+ };
8159
+ }
8160
+ function titleFromSlug(slug) {
8161
+ return slug.split(/[-_/]+/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
8162
+ }
8163
+ function stripQuotes(raw) {
8164
+ const trimmed = raw.trim();
8165
+ if (trimmed.startsWith('"') && trimmed.endsWith('"') || trimmed.startsWith("'") && trimmed.endsWith("'")) {
8166
+ return trimmed.slice(1, -1);
8167
+ }
8168
+ return trimmed;
8169
+ }
8170
+ function parseInlineList(raw) {
8171
+ return raw.slice(1, -1).split(",").map((item) => stripQuotes(item)).filter(Boolean);
8172
+ }
8173
+ function parseFrontmatter(markdown) {
8174
+ const match = markdown.match(/^---\r?\n([\s\S]*?)\r?\n---/);
8175
+ const block = match?.[1];
8176
+ if (!block) {
8177
+ return {};
8178
+ }
8179
+ const out = {};
8180
+ let listKey = null;
8181
+ for (const line of block.split(/\r?\n/)) {
8182
+ const item = line.match(/^\s+-\s+(.*)$/)?.[1];
8183
+ if (listKey && item !== void 0) {
8184
+ out[listKey].push(stripQuotes(item));
8185
+ continue;
8186
+ }
8187
+ const kv = line.match(/^([A-Za-z0-9_]+):\s*(.*)$/);
8188
+ if (!kv?.[1]) {
8189
+ continue;
8190
+ }
8191
+ listKey = null;
8192
+ const key = kv[1];
8193
+ const value = (kv[2] ?? "").trim();
8194
+ if (value === "") {
8195
+ out[key] = [];
8196
+ listKey = key;
8197
+ } else if (value.startsWith("[") && value.endsWith("]")) {
8198
+ out[key] = parseInlineList(value);
8199
+ } else {
8200
+ out[key] = stripQuotes(value);
8201
+ }
8202
+ }
8203
+ return out;
8204
+ }
8205
+ function asString(value) {
8206
+ if (typeof value === "string" && value.length > 0) {
8207
+ return value;
8208
+ }
8209
+ return void 0;
8210
+ }
8211
+ function asList(value) {
8212
+ if (Array.isArray(value)) {
8213
+ return value;
8214
+ }
8215
+ return typeof value === "string" && value.length > 0 ? [value] : [];
8216
+ }
8217
+ function parseCreativeDefinition(markdown, slug) {
8218
+ const fm = parseFrontmatter(markdown);
8219
+ return {
8220
+ title: asString(fm.title) ?? titleFromSlug(slug),
8221
+ platform: asList(fm.platform),
8222
+ formats: asList(fm.formats),
8223
+ status: asString(fm.status) ?? "draft",
8224
+ reference: asString(fm.reference),
8225
+ selectedRun: asString(fm.selected_run)
8226
+ };
8227
+ }
8228
+
8229
+ // src/commands/canvas/gallery.ts
8230
+ async function readJson(file) {
8231
+ try {
8232
+ return JSON.parse(await readFile(file, "utf8"));
8233
+ } catch {
8234
+ return null;
8235
+ }
8236
+ }
8237
+ async function listRunDirs(runsDir) {
8238
+ try {
8239
+ const entries = await readdir(runsDir, { withFileTypes: true });
8240
+ return entries.filter((e) => e.isDirectory()).map((e) => e.name);
8241
+ } catch {
8242
+ return [];
8243
+ }
8244
+ }
8245
+ var galleryCommand = defineCommand79({
8246
+ meta: {
8247
+ name: "gallery",
8248
+ description: "Read a creative's _definition.md + every persisted run manifest and emit the gallery descriptor (JSON) the dashboard renders."
8249
+ },
8250
+ args: {
8251
+ dir: { type: "positional", required: true, description: "Creative folder, e.g. src/creatives/<slug>" },
8252
+ "workspace-dir": { type: "string", description: "R2-mounted workspace root (default ./.creatives-workspace)" },
8253
+ "public-url": { type: "string", description: "R2 public base (default $R2_PUBLIC_URL)" },
8254
+ "company-id": { type: "string", description: "Company id for the R2 prefix (default $BAKER_COMPANY_ID)" }
8255
+ },
8256
+ async run({ args }) {
8257
+ const creativeDir = path.resolve(String(args.dir));
8258
+ const slug = path.basename(creativeDir);
8259
+ const workspaceDir = path.resolve(String(args["workspace-dir"] ?? ".creatives-workspace"));
8260
+ const runsDir = path.join(workspaceDir, slug, "runs");
8261
+ const publicUrl = (args["public-url"] ?? runtimeEnvVar("R2_PUBLIC_URL") ?? "").replace(/\/+$/, "");
8262
+ const companyId = String(args["company-id"] ?? runtimeEnvVar("BAKER_COMPANY_ID") ?? "");
8263
+ const definitionPath = path.join(creativeDir, "_definition.md");
8264
+ let definitionMd = "";
8265
+ try {
8266
+ definitionMd = await readFile(definitionPath, "utf8");
8267
+ } catch {
8268
+ }
8269
+ const definition = parseCreativeDefinition(definitionMd, slug);
8270
+ const generations = [];
8271
+ for (const runId of await listRunDirs(runsDir)) {
8272
+ const manifest = await readJson(path.join(runsDir, runId, "manifest.json"));
8273
+ if (!manifest) {
8274
+ continue;
8275
+ }
8276
+ const runDir = path.join(runsDir, runId);
8277
+ const resolveLocal = (filename) => publicUrl && companyId ? `${publicUrl}/creatives/${companyId}/${slug}/runs/${runId}/${filename}` : path.join(runDir, filename);
8278
+ generations.push(buildGeneration(runId, manifest, resolveLocal));
8279
+ }
8280
+ const descriptor = buildGalleryDescriptor({ slug, definition, generations });
8281
+ process.stdout.write(`${JSON.stringify({ ok: true, descriptor }, null, 2)}
8282
+ `);
8283
+ }
8284
+ });
8285
+
8064
8286
  // src/commands/canvas/inspect.ts
8065
8287
  import { execFile } from "child_process";
8066
- import { readdir, readFile, stat } from "fs/promises";
8067
- import path from "path";
8288
+ import { readdir as readdir2, readFile as readFile2, stat } from "fs/promises";
8289
+ import path2 from "path";
8068
8290
  import { promisify } from "util";
8069
- import { defineCommand as defineCommand79 } from "citty";
8291
+ import { defineCommand as defineCommand80 } from "citty";
8070
8292
  var execFileAsync = promisify(execFile);
8071
- var inspectCommand = defineCommand79({
8293
+ var inspectCommand = defineCommand80({
8072
8294
  meta: {
8073
8295
  name: "inspect",
8074
8296
  description: "Dump a one-page summary of a canvas run: per-node duration + cache status, list of output files in the run dir, and optionally three thumbnail frames per video output. Pass either a run_id (resolved against --outputs-dir) or an absolute run directory."
@@ -8082,7 +8304,7 @@ var inspectCommand = defineCommand79({
8082
8304
  }
8083
8305
  },
8084
8306
  async run({ args }) {
8085
- const outputsDir = path.resolve(String(args["outputs-dir"] ?? "canvas"));
8307
+ const outputsDir = path2.resolve(String(args["outputs-dir"] ?? "canvas"));
8086
8308
  const runArg = String(args.run);
8087
8309
  const runDir = await resolveRunDir(runArg, outputsDir);
8088
8310
  const manifest = await loadManifest(runDir);
@@ -8094,7 +8316,7 @@ var inspectCommand = defineCommand79({
8094
8316
  }
8095
8317
  const summary = {
8096
8318
  ok: true,
8097
- run_id: manifest.run_id ?? path.basename(runDir),
8319
+ run_id: manifest.run_id ?? path2.basename(runDir),
8098
8320
  run_dir: runDir,
8099
8321
  stats: manifest.stats ?? null,
8100
8322
  output: manifest.output ?? null,
@@ -8107,20 +8329,20 @@ var inspectCommand = defineCommand79({
8107
8329
  }
8108
8330
  });
8109
8331
  async function resolveRunDir(run, outputsDir) {
8110
- if (path.isAbsolute(run)) {
8332
+ if (path2.isAbsolute(run)) {
8111
8333
  const s2 = await stat(run).catch(() => null);
8112
8334
  if (s2?.isDirectory()) return run;
8113
8335
  throw new Error(`inspect: ${run} is not a directory`);
8114
8336
  }
8115
- const candidate = path.join(outputsDir, run);
8337
+ const candidate = path2.join(outputsDir, run);
8116
8338
  const s = await stat(candidate).catch(() => null);
8117
8339
  if (s?.isDirectory()) return candidate;
8118
8340
  throw new Error(`inspect: no run directory at ${candidate}`);
8119
8341
  }
8120
8342
  async function loadManifest(runDir) {
8121
- const manifestPath = path.join(runDir, "manifest.json");
8343
+ const manifestPath = path2.join(runDir, "manifest.json");
8122
8344
  try {
8123
- const raw = await readFile(manifestPath, "utf-8");
8345
+ const raw = await readFile2(manifestPath, "utf-8");
8124
8346
  return JSON.parse(raw);
8125
8347
  } catch {
8126
8348
  return {};
@@ -8128,9 +8350,9 @@ async function loadManifest(runDir) {
8128
8350
  }
8129
8351
  async function listRunFiles(runDir) {
8130
8352
  const out = [];
8131
- const names = await readdir(runDir);
8353
+ const names = await readdir2(runDir);
8132
8354
  for (const name of names) {
8133
- const abs = path.join(runDir, name);
8355
+ const abs = path2.join(runDir, name);
8134
8356
  const s = await stat(abs).catch(() => null);
8135
8357
  if (!s?.isFile()) continue;
8136
8358
  out.push({ name, path: abs, size: s.size });
@@ -8175,9 +8397,9 @@ async function probeDuration(filePath) {
8175
8397
  }
8176
8398
 
8177
8399
  // src/commands/canvas/run.ts
8178
- import { readFile as readFile2 } from "fs/promises";
8179
- import path4 from "path";
8180
- import { defineCommand as defineCommand80 } from "citty";
8400
+ import { readFile as readFile3 } from "fs/promises";
8401
+ import path5 from "path";
8402
+ import { defineCommand as defineCommand81 } from "citty";
8181
8403
 
8182
8404
  // src/commands/canvas/placeholders.ts
8183
8405
  function unsuppliedPlaceholderAssets(canvas) {
@@ -8196,7 +8418,7 @@ function unsuppliedPlaceholderAssets(canvas) {
8196
8418
  }
8197
8419
 
8198
8420
  // src/commands/canvas/resolve-paths.ts
8199
- import path2 from "path";
8421
+ import path3 from "path";
8200
8422
  function resolveRelativeCanvasPaths(canvas, baseDir) {
8201
8423
  if (!canvas || typeof canvas !== "object") return canvas;
8202
8424
  const c = canvas;
@@ -8209,37 +8431,37 @@ function resolveNode(node, baseDir) {
8209
8431
  const params = n.params;
8210
8432
  if (!params || typeof params !== "object") return node;
8211
8433
  if (n.type === "ingest" && params.source === "path" && isResolvableRelative(params.path)) {
8212
- return { ...node, params: { ...params, path: path2.resolve(baseDir, params.path) } };
8434
+ return { ...node, params: { ...params, path: path3.resolve(baseDir, params.path) } };
8213
8435
  }
8214
8436
  if (n.type === "hyperframe_render" && isResolvableRelative(params.composition)) {
8215
- return { ...node, params: { ...params, composition: path2.resolve(baseDir, params.composition) } };
8437
+ return { ...node, params: { ...params, composition: path3.resolve(baseDir, params.composition) } };
8216
8438
  }
8217
8439
  return node;
8218
8440
  }
8219
8441
  function isResolvableRelative(value) {
8220
- return typeof value === "string" && value.length > 0 && !value.includes("[TODO") && !path2.isAbsolute(value);
8442
+ return typeof value === "string" && value.length > 0 && !value.includes("[TODO") && !path3.isAbsolute(value);
8221
8443
  }
8222
8444
 
8223
8445
  // src/commands/canvas/run-retention.ts
8224
8446
  import { rm } from "fs/promises";
8225
- import path3 from "path";
8447
+ import path4 from "path";
8226
8448
  function runDirsToPrune(entries, keep, currentRunId) {
8227
8449
  const runs = entries.filter((e) => /^r_[0-9A-Za-z]+$/.test(e) && e !== currentRunId).sort();
8228
8450
  if (keep <= 0) return runs;
8229
8451
  return runs.slice(0, Math.max(0, runs.length - keep));
8230
8452
  }
8231
8453
  async function pruneOldRuns(outputsDir, keep, currentRunId, log) {
8232
- const { readdir: readdir3 } = await import("fs/promises");
8454
+ const { readdir: readdir4 } = await import("fs/promises");
8233
8455
  let entries;
8234
8456
  try {
8235
- entries = await readdir3(outputsDir);
8457
+ entries = await readdir4(outputsDir);
8236
8458
  } catch {
8237
8459
  return;
8238
8460
  }
8239
8461
  const toPrune = runDirsToPrune(entries, keep, currentRunId);
8240
8462
  if (toPrune.length === 0) return;
8241
8463
  for (const dir of toPrune) {
8242
- await rm(path3.join(outputsDir, dir), { recursive: true, force: true }).catch(
8464
+ await rm(path4.join(outputsDir, dir), { recursive: true, force: true }).catch(
8243
8465
  (e) => log(`[prune ] could not remove ${dir}: ${e.message}`)
8244
8466
  );
8245
8467
  }
@@ -8247,7 +8469,7 @@ async function pruneOldRuns(outputsDir, keep, currentRunId, log) {
8247
8469
  }
8248
8470
 
8249
8471
  // src/commands/canvas/run.ts
8250
- var runCommand = defineCommand80({
8472
+ var runCommand = defineCommand81({
8251
8473
  meta: { name: "run", description: "Validate and execute a canvas JSON file." },
8252
8474
  args: {
8253
8475
  file: { type: "positional", required: true, description: "Path to canvas JSON" },
@@ -8261,8 +8483,8 @@ var runCommand = defineCommand80({
8261
8483
  }
8262
8484
  },
8263
8485
  async run({ args }) {
8264
- const filePath = path4.resolve(String(args.file));
8265
- const raw = await readFile2(filePath, "utf8");
8486
+ const filePath = path5.resolve(String(args.file));
8487
+ const raw = await readFile3(filePath, "utf8");
8266
8488
  let parsed;
8267
8489
  try {
8268
8490
  parsed = JSON.parse(raw);
@@ -8272,7 +8494,7 @@ var runCommand = defineCommand80({
8272
8494
  `);
8273
8495
  process.exit(2);
8274
8496
  }
8275
- parsed = resolveRelativeCanvasPaths(parsed, path4.dirname(filePath));
8497
+ parsed = resolveRelativeCanvasPaths(parsed, path5.dirname(filePath));
8276
8498
  const pending = unsuppliedPlaceholderAssets(parsed);
8277
8499
  if (pending.length > 0) {
8278
8500
  process.stderr.write(
@@ -8306,7 +8528,7 @@ var runCommand = defineCommand80({
8306
8528
  });
8307
8529
  const keepRuns = args["keep-runs"] !== void 0 ? Number(args["keep-runs"]) : void 0;
8308
8530
  if (keepRuns !== void 0 && Number.isFinite(keepRuns)) {
8309
- const outputsDir = args["outputs-dir"] ? path4.resolve(String(args["outputs-dir"])) : path4.resolve("canvas");
8531
+ const outputsDir = args["outputs-dir"] ? path5.resolve(String(args["outputs-dir"])) : path5.resolve("canvas");
8310
8532
  await pruneOldRuns(outputsDir, keepRuns, result.run_id, (line) => process.stdout.write(`${line}
8311
8533
  `));
8312
8534
  }
@@ -8341,9 +8563,9 @@ var runCommand = defineCommand80({
8341
8563
  });
8342
8564
 
8343
8565
  // src/commands/canvas/scaffold-static-ad.ts
8344
- import { readFile as readFile3, writeFile } from "fs/promises";
8345
- import path5 from "path";
8346
- import { defineCommand as defineCommand81 } from "citty";
8566
+ import { readFile as readFile4, writeFile } from "fs/promises";
8567
+ import path6 from "path";
8568
+ import { defineCommand as defineCommand82 } from "citty";
8347
8569
 
8348
8570
  // src/engine/scaffold/staticAd.ts
8349
8571
  import { z as z2 } from "zod";
@@ -8556,7 +8778,7 @@ var SELECT_SYSTEM = 'You identify the MAIN, identity-critical visual elements of
8556
8778
  var SELECT_PROMPT = 'AD BLUEPRINT (from image_describe):\n{{blueprint}}\n\nFrom this blueprint, list ONLY the elements that are prominent, important, and identity-bearing \u2014 the ones a reproduction must ground in a real asset:\n- the brand logo/wordmark (from brands_logos with function_in_image = advertiser_brand) -> type "logo"\n- trust/rating/certification/app-store/review badges (brands_logos with function_in_image = trust_badge | review_platform | certification_or_seal | app_store_badge | payment_method) -> type "badge"\n- a showcased/hero product or package (a foreground entry in subjects that the ad is selling) -> type "product"\n- a foreground person whose identity matters (from people) -> type "person"\n- a foreground animal/character with a specific expression (from subjects) -> type "animal"\n\nDROP background extras, decorative props, generic scenery, and anything small or incidental. Keep at most ~6. If there are none, return an empty list.\n\nFor each kept element return: { "type": one of logo|product|person|animal|badge, "label": a short UPPER_SNAKE_CASE name (e.g. LOGO, PRODUCT, HERO_DOG, TRUSTPILOT), "description": a concrete reusable description to source/shoot the real asset (include the exact expression for a living subject), "expression": the facial expression for a living subject or null, "reason": why it is identity-critical, "locator": the blueprint entry this element came from as { "collection": one of "subjects" | "people" | "brands_logos", "index": its 0-based position in that array } (people -> people; logos/badges -> brands_logos; products/animals/objects -> subjects). Output ONLY the JSON object.';
8557
8779
  async function loadAssetText(ref, label) {
8558
8780
  const r = ref;
8559
- if (typeof r?.path === "string") return readFile3(r.path, "utf8");
8781
+ if (typeof r?.path === "string") return readFile4(r.path, "utf8");
8560
8782
  if (typeof r?.url === "string") {
8561
8783
  const res = await fetch(r.url);
8562
8784
  if (!res.ok) throw new Error(`failed to fetch ${label} (${res.status})`);
@@ -8662,7 +8884,7 @@ async function runVisionPasses(canvas) {
8662
8884
  return fail("read_outputs", e instanceof Error ? e.message : String(e));
8663
8885
  }
8664
8886
  }
8665
- var scaffoldStaticAdCommand = defineCommand81({
8887
+ var scaffoldStaticAdCommand = defineCommand82({
8666
8888
  meta: {
8667
8889
  name: "scaffold-static-ad",
8668
8890
  description: "Turn a source/inspiration image into a runnable static-ad canvas. Runs billed passes \u2014 image_describe (the blueprint, baked to prompt.json as the editable 'prompt'), an AI selection of the image's MAIN identity elements, and a structured global-layout pass (the column/row grid with per-region bounds and text sizes) \u2014 then scaffolds a canvas that wires one [TODO] ingest slot per element (logo/product/subject/badge + brand font) into image_generate. Edit prompt.json and drop the real assets, then `baker canvas run` it."
@@ -8679,10 +8901,10 @@ var scaffoldStaticAdCommand = defineCommand81({
8679
8901
  "skip-font": { type: "boolean", description: "Skip the brand-font \u2192 type-specimen slot" }
8680
8902
  },
8681
8903
  async run({ args }) {
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");
8904
+ const imagePath = path6.resolve(String(args.file));
8905
+ const outPath = args.out ? path6.resolve(String(args.out)) : path6.join(path6.dirname(imagePath), "static-ad.canvas.json");
8906
+ const outDir = path6.dirname(outPath);
8907
+ const blueprintPath = path6.join(outDir, "prompt.json");
8686
8908
  const { describeModel, selectModel, layoutModel, genModel } = resolveModels(args);
8687
8909
  const describeCanvas = buildDescribeCanvas(
8688
8910
  imagePath,
@@ -8739,7 +8961,7 @@ var scaffoldStaticAdCommand = defineCommand81({
8739
8961
  run_estimated_credits: validation.estimatedCredits
8740
8962
  },
8741
8963
  checklist: {
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.`,
8964
+ edit_prompt: `Edit ${path6.basename(blueprintPath)} \u2014 it is the blueprint generated from your image; rewrite it into the ad you want (palette, copy, claims, subjects). It feeds the generator directly.`,
8743
8965
  assets_to_supply: report.elements,
8744
8966
  font_slot: report.includes_font ? "Drop a brand font at the [TODO] brandfont path, or delete the brandfont + type_ref nodes to skip it." : "skipped (--skip-font)",
8745
8967
  note: "Replace every [TODO] ingest path with a real file, then `baker canvas validate` and `baker canvas run`. Running generates a billed image \u2014 it is not free."
@@ -8754,13 +8976,13 @@ var scaffoldStaticAdCommand = defineCommand81({
8754
8976
  });
8755
8977
 
8756
8978
  // src/commands/canvas/scaffold-video.ts
8757
- import { cp, mkdir, readFile as readFile6, writeFile as writeFile2 } from "fs/promises";
8758
- import path8 from "path";
8759
- import { defineCommand as defineCommand82 } from "citty";
8979
+ import { cp, mkdir, readFile as readFile7, writeFile as writeFile2 } from "fs/promises";
8980
+ import path9 from "path";
8981
+ import { defineCommand as defineCommand83 } from "citty";
8760
8982
 
8761
8983
  // src/engine/nodes/local/lib/sceneDetect.ts
8762
8984
  import { execFile as execFile2 } from "child_process";
8763
- import { mkdtemp, readdir as readdir2, readFile as readFile4, rm as rm2 } from "fs/promises";
8985
+ import { mkdtemp, readdir as readdir3, readFile as readFile5, rm as rm2 } from "fs/promises";
8764
8986
  import { tmpdir } from "os";
8765
8987
  import { join as join2 } from "path";
8766
8988
  import { promisify as promisify2 } from "util";
@@ -8824,9 +9046,9 @@ async function runSceneDetectOnce(filePath, threshold, minSceneLenS, timeoutMs)
8824
9046
  ],
8825
9047
  { encoding: "utf-8", maxBuffer: 32 * 1024 * 1024, timeout: timeoutMs }
8826
9048
  );
8827
- const csvName = (await readdir2(outDir)).find((f) => f.toLowerCase().endsWith(".csv"));
9049
+ const csvName = (await readdir3(outDir)).find((f) => f.toLowerCase().endsWith(".csv"));
8828
9050
  if (!csvName) return [];
8829
- return parsePySceneDetectCsvCuts(await readFile4(join2(outDir, csvName), "utf-8"));
9051
+ return parsePySceneDetectCsvCuts(await readFile5(join2(outDir, csvName), "utf-8"));
8830
9052
  } finally {
8831
9053
  await rm2(outDir, { recursive: true, force: true });
8832
9054
  }
@@ -11371,23 +11593,23 @@ function videoReport(input, elementsInput) {
11371
11593
 
11372
11594
  // src/commands/canvas/composition-path.ts
11373
11595
  import { existsSync as existsSync3 } from "fs";
11374
- import path6 from "path";
11596
+ import path7 from "path";
11375
11597
  function resolveShippedCanvasDir(name, startDir, exists = existsSync3, maxDepth = 8) {
11376
- const rel = path6.join("canvas", name);
11598
+ const rel = path7.join("canvas", name);
11377
11599
  let dir = startDir;
11378
11600
  for (let i = 0; i < maxDepth; i++) {
11379
- const candidate = path6.join(dir, rel);
11380
- if (exists(path6.join(candidate, "meta.json"))) return candidate;
11381
- const parent = path6.dirname(dir);
11601
+ const candidate = path7.join(dir, rel);
11602
+ if (exists(path7.join(candidate, "meta.json"))) return candidate;
11603
+ const parent = path7.dirname(dir);
11382
11604
  if (parent === dir) break;
11383
11605
  dir = parent;
11384
11606
  }
11385
- return path6.resolve(startDir, "../../../", rel);
11607
+ return path7.resolve(startDir, "../../../", rel);
11386
11608
  }
11387
11609
 
11388
11610
  // src/commands/canvas/gitignore.ts
11389
- import { appendFile, readFile as readFile5 } from "fs/promises";
11390
- import path7 from "path";
11611
+ import { appendFile, readFile as readFile6 } from "fs/promises";
11612
+ import path8 from "path";
11391
11613
  function missingGitignoreEntries(existing, entries) {
11392
11614
  const present = new Set(
11393
11615
  existing.split("\n").map((l) => l.trim().replace(/\/+$/, "")).filter((l) => l.length > 0 && !l.startsWith("#"))
@@ -11395,10 +11617,10 @@ function missingGitignoreEntries(existing, entries) {
11395
11617
  return entries.filter((e) => !present.has(e.trim().replace(/\/+$/, "")));
11396
11618
  }
11397
11619
  async function ensureGitignore(dir, entries) {
11398
- const file = path7.join(dir, ".gitignore");
11620
+ const file = path8.join(dir, ".gitignore");
11399
11621
  let existing;
11400
11622
  try {
11401
- existing = await readFile5(file, "utf8");
11623
+ existing = await readFile6(file, "utf8");
11402
11624
  } catch {
11403
11625
  return;
11404
11626
  }
@@ -11437,7 +11659,7 @@ ONE PERSON, MULTIPLE LOOKS: if a single individual plays MULTIPLE personas or wa
11437
11659
  For each kept element return: { "type": one of person|animal|product|logo|badge|location, "label": a short UPPER_SNAKE_CASE name (e.g. HERO, CREATOR_SKEPTIC, INSURANCE_CARD, LOGO), "description": a concrete reusable description to source/shoot the real asset \u2014 for a person/animal give a NEUTRAL castable role (e.g. "hero pet-owner, woman in her 30s" or "a small beagle"), NOT the original individual's literal face/identity: we RECAST with a FRESH person/animal, so never tell the agent to reuse the original. "expression": a living subject's typical expression or null, "cast_id": the global.cast id if it maps to one else null, "same_as": the label of another element this is the SAME individual as (different wardrobe/persona) else null, "scenes": the 0-based indices of ONLY the scenes where the element is ACTUALLY VISIBLE ON SCREEN \u2014 judged from that scene's start_frame_prompt / end_frame_prompt subjects and its action_detail, NOT from who is merely speaking. A narrator heard over b-roll is NOT present in that b-roll scene; a dog-running cutaway does NOT contain the couch creator just because she talks across it. Do NOT pad the list \u2014 an element wrongly listed in a scene makes the reproduction render the wrong subject there (e.g. the creator appearing in a pure-dog b-roll). When in doubt, leave a scene OUT. Output ONLY the JSON object.`;
11438
11660
  async function loadAssetText2(ref, label) {
11439
11661
  const r = ref;
11440
- if (typeof r?.path === "string") return readFile6(r.path, "utf8");
11662
+ if (typeof r?.path === "string") return readFile7(r.path, "utf8");
11441
11663
  if (typeof r?.url === "string") {
11442
11664
  const res = await fetch(r.url);
11443
11665
  if (!res.ok) throw new Error(`failed to fetch ${label} (${res.status})`);
@@ -11456,7 +11678,7 @@ async function loadTranscriptBestEffort(ref) {
11456
11678
  async function stageCaptions(outDir, transcript) {
11457
11679
  const text = transcript?.trim();
11458
11680
  if (!text || text === "[]") return {};
11459
- const compositionPath = path8.join(outDir, "tiktok-captions-composition");
11681
+ const compositionPath = path9.join(outDir, "tiktok-captions-composition");
11460
11682
  await cp(SHIPPED_CAPTIONS_DIR, compositionPath, { recursive: true });
11461
11683
  return { compositionPath };
11462
11684
  }
@@ -11588,7 +11810,7 @@ async function runAnalysisPasses(deconstructCanvas, selectModel) {
11588
11810
  return fail2("deconstruct", e instanceof Error ? e.message : String(e));
11589
11811
  }
11590
11812
  }
11591
- var scaffoldVideoCommand = defineCommand82({
11813
+ var scaffoldVideoCommand = defineCommand83({
11592
11814
  meta: {
11593
11815
  name: "scaffold-video",
11594
11816
  description: "Turn a reference video into a runnable reproduction canvas in one command. Runs billed passes \u2014 video_deconstruct (the full scene-by-scene blueprint + transcript, baked to prompt.json as the editable 'prompt') and an AI selection of the video's RECURRING identity elements (person/animal/product/logo) \u2014 then scaffolds a pipeline where every scene boundary is a static-ad-grade frame (the blueprint as target_blueprint, a reference legend, the real frame as anchor) and each recurring element gets ONE shared [TODO] ingest slot wired into every frame it appears in. The clips feed Seedance an ultra-detailed motion brief (action, camera, dialogue, transcript). Edit prompt.json, drop the real source images, then `baker canvas run`."
@@ -11618,11 +11840,11 @@ var scaffoldVideoCommand = defineCommand82({
11618
11840
  }
11619
11841
  },
11620
11842
  async run({ args }) {
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");
11843
+ const videoPath = path9.resolve(String(args.file));
11844
+ const base = path9.basename(videoPath, path9.extname(videoPath));
11845
+ const outPath = args.out ? path9.resolve(String(args.out)) : path9.join(path9.dirname(videoPath), `${base}.video.canvas.json`);
11846
+ const outDir = path9.dirname(outPath);
11847
+ const blueprintPath = path9.join(outDir, "prompt.json");
11626
11848
  const frames = args.frames === "reuse" ? "reuse" : "generate";
11627
11849
  const maxScenes = args["max-scenes"] ? Number(args["max-scenes"]) : void 0;
11628
11850
  if (Number.isFinite(maxScenes)) {
@@ -11645,11 +11867,11 @@ var scaffoldVideoCommand = defineCommand82({
11645
11867
  const annotated = annotateBlueprintWithElements(blueprint, elements);
11646
11868
  await writeFile2(blueprintPath, `${JSON.stringify(annotated, null, 2)}
11647
11869
  `, "utf8");
11648
- const compositionDest = path8.join(outDir, "video-overlay-composition");
11870
+ const compositionDest = path9.join(outDir, "video-overlay-composition");
11649
11871
  await cp(SHIPPED_COMPOSITION_DIR, compositionDest, { recursive: true });
11650
- const indexPath = path8.join(compositionDest, "index.html");
11872
+ const indexPath = path9.join(compositionDest, "index.html");
11651
11873
  const overlayHtml = buildOverlayHtml(blueprint);
11652
- const indexHtml = await readFile6(indexPath, "utf8");
11874
+ const indexHtml = await readFile7(indexPath, "utf8");
11653
11875
  const injected = indexHtml.replace("<!--OVERLAYS-->", () => overlayHtml);
11654
11876
  if (injected === indexHtml && overlayHtml.trim()) {
11655
11877
  fail2(
@@ -11662,9 +11884,9 @@ var scaffoldVideoCommand = defineCommand82({
11662
11884
  const opts = {
11663
11885
  imageModel,
11664
11886
  videoModel,
11665
- overlayCompositionPath: path8.relative(outDir, compositionDest),
11666
- captionsCompositionPath: captions.compositionPath ? path8.relative(outDir, captions.compositionPath) : void 0,
11667
- blueprintPath: path8.relative(outDir, blueprintPath),
11887
+ overlayCompositionPath: path9.relative(outDir, compositionDest),
11888
+ captionsCompositionPath: captions.compositionPath ? path9.relative(outDir, captions.compositionPath) : void 0,
11889
+ blueprintPath: path9.relative(outDir, blueprintPath),
11668
11890
  frames,
11669
11891
  ambient: Boolean(args.ambient),
11670
11892
  ...args.resolution ? { resolution: String(args.resolution) } : {}
@@ -11705,7 +11927,7 @@ var scaffoldVideoCommand = defineCommand82({
11705
11927
  run_estimated_credits: validation.estimatedCredits
11706
11928
  },
11707
11929
  checklist: {
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.`,
11930
+ edit_prompt: `Edit ${path9.basename(blueprintPath)} \u2014 the blueprint deconstructed from your video; rewrite it into the ad you want (cast, palette, copy, claims). Every scene frame reads it via target_blueprint.`,
11709
11931
  recurring_elements_to_supply: report.elements,
11710
11932
  voices_to_confirm: report.dialogue.map((d) => ({
11711
11933
  scene: d.scene,
@@ -11731,9 +11953,9 @@ var scaffoldVideoCommand = defineCommand82({
11731
11953
  });
11732
11954
 
11733
11955
  // src/commands/canvas/set-prompt.ts
11734
- import { readFile as readFile7, writeFile as writeFile3 } from "fs/promises";
11735
- import path9 from "path";
11736
- import { defineCommand as defineCommand83 } from "citty";
11956
+ import { readFile as readFile8, writeFile as writeFile3 } from "fs/promises";
11957
+ import path10 from "path";
11958
+ import { defineCommand as defineCommand84 } from "citty";
11737
11959
  function setNodePrompt(canvas, nodeId, text) {
11738
11960
  const nodes = canvas?.nodes;
11739
11961
  if (!Array.isArray(nodes)) throw new Error("canvas has no nodes array");
@@ -11748,7 +11970,7 @@ function setNodePrompt(canvas, nodeId, text) {
11748
11970
  newNodes[idx] = newNode;
11749
11971
  return { ...canvas, nodes: newNodes };
11750
11972
  }
11751
- var setPromptCommand = defineCommand83({
11973
+ var setPromptCommand = defineCommand84({
11752
11974
  meta: {
11753
11975
  name: "set-prompt",
11754
11976
  description: "Safely set a node's params.prompt (a frame description, motion prompt, etc.) without hand-editing the JSON. Prefer --text-file for multi-line/accented copy \u2014 it preserves UTF-8 exactly, unlike shell-quoted jq."
@@ -11760,17 +11982,17 @@ var setPromptCommand = defineCommand83({
11760
11982
  "text-file": { type: "string", description: "Read the new prompt from a UTF-8 file (preserves accents/newlines)" }
11761
11983
  },
11762
11984
  async run({ args }) {
11763
- const filePath = path9.resolve(String(args.file));
11985
+ const filePath = path10.resolve(String(args.file));
11764
11986
  let canvas;
11765
11987
  try {
11766
- canvas = JSON.parse(await readFile7(filePath, "utf8"));
11988
+ canvas = JSON.parse(await readFile8(filePath, "utf8"));
11767
11989
  } catch (e) {
11768
11990
  process.stderr.write(`${JSON.stringify({ ok: false, error: { code: "parse", message: String(e) } }, null, 2)}
11769
11991
  `);
11770
11992
  process.exit(2);
11771
11993
  }
11772
11994
  let text;
11773
- if (args["text-file"]) text = await readFile7(path9.resolve(String(args["text-file"])), "utf8");
11995
+ if (args["text-file"]) text = await readFile8(path10.resolve(String(args["text-file"])), "utf8");
11774
11996
  else if (args.text !== void 0) text = String(args.text);
11775
11997
  else {
11776
11998
  process.stderr.write(
@@ -11791,7 +12013,7 @@ var setPromptCommand = defineCommand83({
11791
12013
  process.exit(2);
11792
12014
  return;
11793
12015
  }
11794
- const validation = await validateCanvasDeep(resolveRelativeCanvasPaths(updated, path9.dirname(filePath)), defaultRegistry());
12016
+ const validation = await validateCanvasDeep(resolveRelativeCanvasPaths(updated, path10.dirname(filePath)), defaultRegistry());
11795
12017
  if (!validation.ok) {
11796
12018
  process.stderr.write(`${JSON.stringify({ ok: false, error: { code: "validation", issues: validation.issues } }, null, 2)}
11797
12019
  `);
@@ -11806,18 +12028,18 @@ var setPromptCommand = defineCommand83({
11806
12028
  });
11807
12029
 
11808
12030
  // 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({
12031
+ import { readFile as readFile9 } from "fs/promises";
12032
+ import path11 from "path";
12033
+ import { defineCommand as defineCommand85 } from "citty";
12034
+ var validateCommand = defineCommand85({
11813
12035
  meta: {
11814
12036
  name: "validate",
11815
12037
  description: "Validate a canvas JSON file (no execution). Includes a per-node cost preview and runs each node's deep validators (composition meta checks for hyperframe_render/_snapshot)."
11816
12038
  },
11817
12039
  args: { file: { type: "positional", required: true, description: "Path to canvas JSON" } },
11818
12040
  async run({ args }) {
11819
- const filePath = path10.resolve(String(args.file));
11820
- const raw = await readFile8(filePath, "utf8");
12041
+ const filePath = path11.resolve(String(args.file));
12042
+ const raw = await readFile9(filePath, "utf8");
11821
12043
  let parsed;
11822
12044
  try {
11823
12045
  parsed = JSON.parse(raw);
@@ -11827,7 +12049,7 @@ var validateCommand = defineCommand84({
11827
12049
  `);
11828
12050
  process.exit(2);
11829
12051
  }
11830
- parsed = resolveRelativeCanvasPaths(parsed, path10.dirname(filePath));
12052
+ parsed = resolveRelativeCanvasPaths(parsed, path11.dirname(filePath));
11831
12053
  const result = await validateCanvasDeep(parsed, defaultRegistry());
11832
12054
  if (!result.ok) {
11833
12055
  process.stderr.write(`${JSON.stringify({ ok: false, issues: result.issues }, null, 2)}
@@ -11852,7 +12074,7 @@ var validateCommand = defineCommand84({
11852
12074
  });
11853
12075
 
11854
12076
  // src/commands/canvas/index.ts
11855
- var canvasCommand = defineCommand85({
12077
+ var canvasCommand = defineCommand86({
11856
12078
  meta: {
11857
12079
  name: "canvas",
11858
12080
  description: `Run Baker creative canvas JSON files locally. Local nodes execute in-process; remote nodes POST to the Convex backend gateway.
@@ -11864,6 +12086,7 @@ Subcommands:
11864
12086
  baker canvas run <file.json> \u2014 execute the canvas, write outputs to ./canvas/<run_id>/
11865
12087
  baker canvas catalog \u2014 print the agent-facing node + composition catalog (JSON Schema)
11866
12088
  baker canvas inspect <run_id> \u2014 one-page summary of a completed run
12089
+ baker canvas gallery <dir> \u2014 read a creative folder's _definition.md + run manifests into the dashboard gallery descriptor (JSON)
11867
12090
  baker canvas scaffold-video <video> \u2014 turn a reference video into a runnable reproduction canvas (deconstruct + recurring-element detection)
11868
12091
  baker canvas scaffold-static-ad <image> \u2014 turn a source image into a runnable static-ad canvas (describe + element detection)`
11869
12092
  },
@@ -11872,6 +12095,7 @@ Subcommands:
11872
12095
  validate: validateCommand,
11873
12096
  catalog: catalogCommand,
11874
12097
  inspect: inspectCommand,
12098
+ gallery: galleryCommand,
11875
12099
  "scaffold-video": scaffoldVideoCommand,
11876
12100
  "scaffold-static-ad": scaffoldStaticAdCommand,
11877
12101
  "set-prompt": setPromptCommand
@@ -11879,10 +12103,10 @@ Subcommands:
11879
12103
  });
11880
12104
 
11881
12105
  // src/commands/ga4/index.ts
11882
- import { defineCommand as defineCommand89 } from "citty";
12106
+ import { defineCommand as defineCommand90 } from "citty";
11883
12107
 
11884
12108
  // src/commands/ga4/audit.ts
11885
- import { defineCommand as defineCommand86 } from "citty";
12109
+ import { defineCommand as defineCommand87 } from "citty";
11886
12110
 
11887
12111
  // src/commands/ga4/resolve.ts
11888
12112
  async function fetchProperties(useCache = true) {
@@ -11945,7 +12169,7 @@ registerSchema({
11945
12169
  "no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
11946
12170
  }
11947
12171
  });
11948
- var auditCommand2 = defineCommand86({
12172
+ var auditCommand2 = defineCommand87({
11949
12173
  meta: {
11950
12174
  name: "audit",
11951
12175
  description: `Run all GA4 admin health checks. Returns property config with playbook warnings.
@@ -11997,7 +12221,7 @@ Examples:
11997
12221
  });
11998
12222
 
11999
12223
  // src/commands/ga4/properties.ts
12000
- import { defineCommand as defineCommand87 } from "citty";
12224
+ import { defineCommand as defineCommand88 } from "citty";
12001
12225
  registerSchema({
12002
12226
  command: "ga4.properties",
12003
12227
  description: "List all accessible GA4 properties. Returns property IDs needed for query and audit commands. Run this first to find property IDs.",
@@ -12005,7 +12229,7 @@ registerSchema({
12005
12229
  "no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
12006
12230
  }
12007
12231
  });
12008
- var propertiesCommand = defineCommand87({
12232
+ var propertiesCommand = defineCommand88({
12009
12233
  meta: {
12010
12234
  name: "properties",
12011
12235
  description: `List accessible GA4 properties.
@@ -12055,7 +12279,7 @@ Examples:
12055
12279
  // src/commands/ga4/query.ts
12056
12280
  import { appendFileSync as appendFileSync2, existsSync as existsSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
12057
12281
  import { resolve as resolve2 } from "path";
12058
- import { defineCommand as defineCommand88 } from "citty";
12282
+ import { defineCommand as defineCommand89 } from "citty";
12059
12283
 
12060
12284
  // src/commands/ga4/presets.ts
12061
12285
  var GA4_PRESETS = [
@@ -12187,7 +12411,7 @@ function handleError(err) {
12187
12411
  });
12188
12412
  process.exit(1);
12189
12413
  }
12190
- var queryCommand2 = defineCommand88({
12414
+ var queryCommand2 = defineCommand89({
12191
12415
  meta: {
12192
12416
  name: "query",
12193
12417
  description: `Run GA4 Data API reports. Preset-first with free-form escape hatch.
@@ -12258,7 +12482,7 @@ Free-form (escape hatch):
12258
12482
  });
12259
12483
 
12260
12484
  // src/commands/ga4/index.ts
12261
- var ga4Command = defineCommand89({
12485
+ var ga4Command = defineCommand90({
12262
12486
  meta: {
12263
12487
  name: "ga4",
12264
12488
  description: `Google Analytics 4 commands. Audit property config, run playbook-aligned reports.
@@ -12281,12 +12505,12 @@ Examples:
12281
12505
  });
12282
12506
 
12283
12507
  // src/commands/gsc/index.ts
12284
- import { defineCommand as defineCommand93 } from "citty";
12508
+ import { defineCommand as defineCommand94 } from "citty";
12285
12509
 
12286
12510
  // src/commands/gsc/query.ts
12287
12511
  import { appendFileSync as appendFileSync3, existsSync as existsSync5, readFileSync as readFileSync7, writeFileSync as writeFileSync5 } from "fs";
12288
12512
  import { resolve as resolve3 } from "path";
12289
- import { defineCommand as defineCommand90 } from "citty";
12513
+ import { defineCommand as defineCommand91 } from "citty";
12290
12514
 
12291
12515
  // src/commands/gsc/presets.ts
12292
12516
  var GSC_PRESETS = [
@@ -12474,7 +12698,7 @@ function handleError2(err) {
12474
12698
  });
12475
12699
  process.exit(1);
12476
12700
  }
12477
- var queryCommand3 = defineCommand90({
12701
+ var queryCommand3 = defineCommand91({
12478
12702
  meta: {
12479
12703
  name: "query",
12480
12704
  description: `Run GSC Search Analytics queries. Preset-first with free-form escape hatch.
@@ -12552,7 +12776,7 @@ Free-form (escape hatch):
12552
12776
  });
12553
12777
 
12554
12778
  // src/commands/gsc/sitemaps.ts
12555
- import { defineCommand as defineCommand91 } from "citty";
12779
+ import { defineCommand as defineCommand92 } from "citty";
12556
12780
  registerSchema({
12557
12781
  command: "gsc.sitemaps",
12558
12782
  description: "List sitemaps for a Search Console site. Check sitemap health and errors.",
@@ -12561,7 +12785,7 @@ registerSchema({
12561
12785
  "no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
12562
12786
  }
12563
12787
  });
12564
- var sitemapsCommand = defineCommand91({
12788
+ var sitemapsCommand = defineCommand92({
12565
12789
  meta: {
12566
12790
  name: "sitemaps",
12567
12791
  description: `List sitemaps for a site. Check health and errors.
@@ -12611,7 +12835,7 @@ Examples:
12611
12835
  });
12612
12836
 
12613
12837
  // src/commands/gsc/sites.ts
12614
- import { defineCommand as defineCommand92 } from "citty";
12838
+ import { defineCommand as defineCommand93 } from "citty";
12615
12839
  registerSchema({
12616
12840
  command: "gsc.sites",
12617
12841
  description: "List all verified Google Search Console sites. Returns site URLs needed for query and sitemaps commands.",
@@ -12619,7 +12843,7 @@ registerSchema({
12619
12843
  "no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
12620
12844
  }
12621
12845
  });
12622
- var sitesCommand = defineCommand92({
12846
+ var sitesCommand = defineCommand93({
12623
12847
  meta: {
12624
12848
  name: "sites",
12625
12849
  description: `List verified Search Console sites.
@@ -12667,7 +12891,7 @@ Examples:
12667
12891
  });
12668
12892
 
12669
12893
  // src/commands/gsc/index.ts
12670
- var gscCommand = defineCommand93({
12894
+ var gscCommand = defineCommand94({
12671
12895
  meta: {
12672
12896
  name: "gsc",
12673
12897
  description: `Google Search Console commands. PPC-SEO arbitrage, brand halo analysis, negative keyword discovery.
@@ -12690,10 +12914,10 @@ Examples:
12690
12914
  });
12691
12915
 
12692
12916
  // src/commands/images/index.ts
12693
- import { defineCommand as defineCommand117 } from "citty";
12917
+ import { defineCommand as defineCommand118 } from "citty";
12694
12918
 
12695
12919
  // src/commands/images/crop.ts
12696
- import { defineCommand as defineCommand94 } from "citty";
12920
+ import { defineCommand as defineCommand95 } from "citty";
12697
12921
 
12698
12922
  // src/lib/image/crop-sprite.ts
12699
12923
  import sharp from "sharp";
@@ -12708,7 +12932,7 @@ function cropSprite(input, region) {
12708
12932
 
12709
12933
  // src/lib/image/io.ts
12710
12934
  import { randomBytes } from "crypto";
12711
- import { glob as fsGlob, readFile as readFile9, rename, stat as stat2, writeFile as writeFile4 } from "fs/promises";
12935
+ import { glob as fsGlob, readFile as readFile10, rename, stat as stat2, writeFile as writeFile4 } from "fs/promises";
12712
12936
  import { dirname, extname, join as join3, resolve as resolve4 } from "path";
12713
12937
  var REMOTE_RE = /^https?:\/\//i;
12714
12938
  var GLOB_RE = /[*?[\]{}]/;
@@ -12744,11 +12968,11 @@ async function readImageBuffer(pathOrUrl) {
12744
12968
  }
12745
12969
  return Buffer.from(await response.arrayBuffer());
12746
12970
  }
12747
- return readFile9(pathOrUrl);
12971
+ return readFile10(pathOrUrl);
12748
12972
  }
12749
- async function isDirectory(path11) {
12973
+ async function isDirectory(path12) {
12750
12974
  try {
12751
- const s = await stat2(path11);
12975
+ const s = await stat2(path12);
12752
12976
  return s.isDirectory();
12753
12977
  } catch {
12754
12978
  return false;
@@ -12818,7 +13042,7 @@ function emitError2(err) {
12818
13042
  }
12819
13043
  process.exit(1);
12820
13044
  }
12821
- var cropCommand = defineCommand94({
13045
+ var cropCommand = defineCommand95({
12822
13046
  meta: {
12823
13047
  name: "crop",
12824
13048
  description: "Crop a rectangular region from an image.\n\nExample: baker images crop sprite.png --x 0 --y 0 --width 64 --height 64 --output icon.png"
@@ -12854,7 +13078,7 @@ var cropCommand = defineCommand94({
12854
13078
  });
12855
13079
 
12856
13080
  // src/commands/images/delete.ts
12857
- import { defineCommand as defineCommand95 } from "citty";
13081
+ import { defineCommand as defineCommand96 } from "citty";
12858
13082
  registerSchema({
12859
13083
  command: "images.delete",
12860
13084
  description: "Delete an image by ID",
@@ -12868,7 +13092,7 @@ registerSchema({
12868
13092
  }
12869
13093
  }
12870
13094
  });
12871
- var deleteCommand = defineCommand95({
13095
+ var deleteCommand = defineCommand96({
12872
13096
  meta: {
12873
13097
  name: "delete",
12874
13098
  description: "Delete an image by ID. Use --dry-run to preview. Example: baker images delete j571abc123 --dry-run"
@@ -12909,7 +13133,7 @@ var deleteCommand = defineCommand95({
12909
13133
  });
12910
13134
 
12911
13135
  // src/commands/images/dimensions.ts
12912
- import { defineCommand as defineCommand96 } from "citty";
13136
+ import { defineCommand as defineCommand97 } from "citty";
12913
13137
 
12914
13138
  // src/lib/image/dimensions.ts
12915
13139
  import { imageSize } from "image-size";
@@ -12932,7 +13156,7 @@ registerSchema({
12932
13156
  target: { type: "string", description: "Local file path or remote http(s) URL", required: true }
12933
13157
  }
12934
13158
  });
12935
- var dimensionsCommand = defineCommand96({
13159
+ var dimensionsCommand = defineCommand97({
12936
13160
  meta: {
12937
13161
  name: "dimensions",
12938
13162
  description: "Read image dimensions without decoding the full file.\n\nExample: baker images dimensions ./logo.png\nExample: baker images dimensions https://acme.com/hero.png"
@@ -12976,7 +13200,7 @@ var dimensionsCommand = defineCommand96({
12976
13200
  });
12977
13201
 
12978
13202
  // src/commands/images/extract.ts
12979
- import { defineCommand as defineCommand97 } from "citty";
13203
+ import { defineCommand as defineCommand98 } from "citty";
12980
13204
  registerSchema({
12981
13205
  command: "images.extract",
12982
13206
  description: "Extract images from a URL via Firecrawl (formats: images).",
@@ -12992,7 +13216,7 @@ registerSchema({
12992
13216
  }
12993
13217
  }
12994
13218
  });
12995
- var extractCommand = defineCommand97({
13219
+ var extractCommand = defineCommand98({
12996
13220
  meta: {
12997
13221
  name: "extract",
12998
13222
  description: "Pull every image from a single URL via Firecrawl. ~$0.001/scrape. Cap auto-ingest at 20.\n\nExample: baker images extract https://stripe.com --auto-ingest 5"
@@ -13030,7 +13254,7 @@ var extractCommand = defineCommand97({
13030
13254
  });
13031
13255
 
13032
13256
  // src/commands/images/find.ts
13033
- import { defineCommand as defineCommand98 } from "citty";
13257
+ import { defineCommand as defineCommand99 } from "citty";
13034
13258
  registerSchema({
13035
13259
  command: "images.find",
13036
13260
  description: "Fanout image search: library first, then opted-in external providers.",
@@ -13062,7 +13286,7 @@ registerSchema({
13062
13286
  }
13063
13287
  }
13064
13288
  });
13065
- var findCommand = defineCommand98({
13289
+ var findCommand = defineCommand99({
13066
13290
  meta: {
13067
13291
  name: "find",
13068
13292
  description: "Library-first fanout image search. Opt in to providers with --sources. `--fallback` short-circuits to externals only when library is thin. With --auto-ingest, ingested external hits return Baker-owned URLs.\n\nExample: baker images find 'office' --sources library,magnific --limit 20"
@@ -13108,8 +13332,8 @@ var findCommand = defineCommand98({
13108
13332
  });
13109
13333
 
13110
13334
  // src/commands/images/generate.ts
13111
- import { readFile as readFile10 } from "fs/promises";
13112
- import { defineCommand as defineCommand99 } from "citty";
13335
+ import { readFile as readFile11 } from "fs/promises";
13336
+ import { defineCommand as defineCommand100 } from "citty";
13113
13337
  import sharp2 from "sharp";
13114
13338
  var GENERATE_TIMEOUT_MS = 18e4;
13115
13339
  var REFERENCE_MAX_EDGE = 1536;
@@ -13191,7 +13415,7 @@ async function resolveReferences(spec) {
13191
13415
  }
13192
13416
  let raw;
13193
13417
  try {
13194
- raw = await readFile10(entry);
13418
+ raw = await readFile11(entry);
13195
13419
  } catch {
13196
13420
  throw new ApiError("VALIDATION_ERROR", `Reference file not found: ${entry}`);
13197
13421
  }
@@ -13205,7 +13429,7 @@ async function resolveReferences(spec) {
13205
13429
  }
13206
13430
  return out;
13207
13431
  }
13208
- var generateCommand = defineCommand99({
13432
+ var generateCommand = defineCommand100({
13209
13433
  meta: {
13210
13434
  name: "generate",
13211
13435
  description: "Generate an image with AI and store it in the library (cost-tracked per request via OpenRouter usage). Models mirror the canvas: openai/gpt-5.4-image-2 (default \u2014 photoreal, cleanest text, best for ad/landing reproduction), google/gemini-3-pro-image-preview (Nano Banana Pro), google/gemini-3.5-flash & google/gemini-3.1-flash-image-preview (fast, extreme aspect ratios), recraft/recraft-v4.1-pro-vector (vector/SVG-style with palette control). The result is auto-ingested (describe + embed), so the next `baker images library` query finds it. Pass --reference with image URLs and/or local file paths (Pinterest, stock, brand assets, sandbox files) to ground generation in reality.\n\nExamples:\n baker images generate 'a friendly golden retriever sitting in a bright modern living room' --aspect-ratio 16:9\n baker images generate 'hero shot of a matte black water bottle on marble' --model google/gemini-3-pro-image-preview --image-size 2K\n baker images generate 'lifestyle photo matching this mood' --reference 'https://\u2026/ref1.jpg,https://\u2026/ref2.jpg'\n baker images generate 'put this product on a marble countertop, soft daylight' --reference './src/brand/logos/product.png,./refs/kitchen-mood.jpg'\n baker images generate 'flat geometric mascot, brand palette' --model recraft/recraft-v4.1-pro-vector --rgb-colors '[[10,10,10],[255,80,0]]'"
@@ -13257,7 +13481,7 @@ var generateCommand = defineCommand99({
13257
13481
  });
13258
13482
 
13259
13483
  // src/commands/images/get.ts
13260
- import { defineCommand as defineCommand100 } from "citty";
13484
+ import { defineCommand as defineCommand101 } from "citty";
13261
13485
  registerSchema({
13262
13486
  command: "images.get",
13263
13487
  description: "Get a single image by ID",
@@ -13265,7 +13489,7 @@ registerSchema({
13265
13489
  id: { type: "string", description: "Image ID", required: true }
13266
13490
  }
13267
13491
  });
13268
- var getCommand2 = defineCommand100({
13492
+ var getCommand2 = defineCommand101({
13269
13493
  meta: { name: "get", description: "Get a single image by ID. Example: baker images get j571abc123" },
13270
13494
  args: {
13271
13495
  id: { type: "positional", description: "Image ID", required: false },
@@ -13301,7 +13525,7 @@ var getCommand2 = defineCommand100({
13301
13525
  });
13302
13526
 
13303
13527
  // src/commands/images/gif.ts
13304
- import { defineCommand as defineCommand101 } from "citty";
13528
+ import { defineCommand as defineCommand102 } from "citty";
13305
13529
  registerSchema({
13306
13530
  command: "images.gif",
13307
13531
  description: "Search Giphy for GIFs / reaction memes (paid social creative).",
@@ -13333,7 +13557,7 @@ registerSchema({
13333
13557
  }
13334
13558
  }
13335
13559
  });
13336
- var gifCommand = defineCommand101({
13560
+ var gifCommand = defineCommand102({
13337
13561
  meta: {
13338
13562
  name: "gif",
13339
13563
  description: "Search Giphy for GIFs / reaction memes \u2014 built for paid-social creative (Meta, TikTok, LinkedIn, X). Free API. Each hit carries WebP + GIF + MP4 URLs in providerMeta so you can pick the right format per platform.\n\nExample: baker images gif 'this is fine' --limit 10\nExample: baker images gif 'office reaction' --rating pg --auto-ingest 2\nExample: baker images gif --trending --limit 25"
@@ -13380,7 +13604,7 @@ var gifCommand = defineCommand101({
13380
13604
  });
13381
13605
 
13382
13606
  // src/commands/images/google.ts
13383
- import { defineCommand as defineCommand102 } from "citty";
13607
+ import { defineCommand as defineCommand103 } from "citty";
13384
13608
  registerSchema({
13385
13609
  command: "images.google",
13386
13610
  description: "Google Images search via the official Custom Search JSON API. Unverified source \u2014 inspect before placing.",
@@ -13416,7 +13640,7 @@ registerSchema({
13416
13640
  }
13417
13641
  }
13418
13642
  });
13419
- var googleCommand2 = defineCommand102({
13643
+ var googleCommand2 = defineCommand103({
13420
13644
  meta: {
13421
13645
  name: "google",
13422
13646
  description: "Google Images via the official Custom Search JSON API ($0.005/query, free 100/day). \u26A0 Source unverified \u2014 watermarks, low-res, mislabeled results are common. Use as last resort. With --auto-ingest, ingested hits return Baker-owned URLs.\n\nExample: baker images google 'industrial workshop' --type photo --size large --limit 20"
@@ -13464,7 +13688,7 @@ var googleCommand2 = defineCommand102({
13464
13688
  });
13465
13689
 
13466
13690
  // src/commands/images/icon.ts
13467
- import { defineCommand as defineCommand103 } from "citty";
13691
+ import { defineCommand as defineCommand104 } from "citty";
13468
13692
  registerSchema({
13469
13693
  command: "images.icon",
13470
13694
  description: "Icon lookup via Iconify (200+ icon sets, free CDN).",
@@ -13490,7 +13714,7 @@ registerSchema({
13490
13714
  }
13491
13715
  }
13492
13716
  });
13493
- var iconCommand = defineCommand103({
13717
+ var iconCommand = defineCommand104({
13494
13718
  meta: {
13495
13719
  name: "icon",
13496
13720
  description: "Icon via Iconify (simple-icons, logos, lucide, devicon, heroicons, tabler, phosphor, material-symbols, \u2026). Free CDN, no API key.\n\nExample: baker images icon react --set devicon\nExample: baker images icon lucide:check --color '#0a0a0a'"
@@ -13530,7 +13754,7 @@ var iconCommand = defineCommand103({
13530
13754
  });
13531
13755
 
13532
13756
  // src/commands/images/ingest.ts
13533
- import { defineCommand as defineCommand104 } from "citty";
13757
+ import { defineCommand as defineCommand105 } from "citty";
13534
13758
  registerSchema({
13535
13759
  command: "images.ingest",
13536
13760
  description: "Ingest a remote image URL into the library (full describe + embed).",
@@ -13542,7 +13766,7 @@ registerSchema({
13542
13766
  context: { type: "string", description: "Description context hint", required: false }
13543
13767
  }
13544
13768
  });
13545
- var ingestCommand = defineCommand104({
13769
+ var ingestCommand = defineCommand105({
13546
13770
  meta: {
13547
13771
  name: "ingest",
13548
13772
  description: "Download a remote URL and store it in the library. Hash-deduped on bytes + externalId.\n\nExample: baker images ingest https://img.freepik.com/free-photo/xyz.jpg --source magnific --external-id 12345"
@@ -13584,7 +13808,7 @@ var ingestCommand = defineCommand104({
13584
13808
  });
13585
13809
 
13586
13810
  // src/commands/images/library.ts
13587
- import { defineCommand as defineCommand105 } from "citty";
13811
+ import { defineCommand as defineCommand106 } from "citty";
13588
13812
  registerSchema({
13589
13813
  command: "images.library",
13590
13814
  description: "Search the company image library. Returns only ready images.",
@@ -13610,7 +13834,7 @@ registerSchema({
13610
13834
  }
13611
13835
  }
13612
13836
  });
13613
- var libraryCommand = defineCommand105({
13837
+ var libraryCommand = defineCommand106({
13614
13838
  meta: {
13615
13839
  name: "library",
13616
13840
  description: "Search the company image library (hybrid BM25 + vector + Cohere rerank). Use this BEFORE any external provider.\n\nExample: baker images library 'hero banner' --aspect-ratio 16:9 --source magnific"
@@ -13667,7 +13891,7 @@ var libraryCommand = defineCommand105({
13667
13891
  });
13668
13892
 
13669
13893
  // src/commands/images/logo.ts
13670
- import { defineCommand as defineCommand106 } from "citty";
13894
+ import { defineCommand as defineCommand107 } from "citty";
13671
13895
  registerSchema({
13672
13896
  command: "images.logo",
13673
13897
  description: "Brand logo lookup via Brandfetch CDN (fallback/404). Auto-ingests by default.",
@@ -13692,7 +13916,7 @@ registerSchema({
13692
13916
  }
13693
13917
  }
13694
13918
  });
13695
- var logoCommand = defineCommand106({
13919
+ var logoCommand = defineCommand107({
13696
13920
  meta: {
13697
13921
  name: "logo",
13698
13922
  description: "Brand logo via Brandfetch CDN. Returns up to 5 variants (icon, light/dark logo, light/dark symbol). Auto-ingests the first variant.\n\nExample: baker images logo stripe.com --variant logo"
@@ -13730,7 +13954,7 @@ var logoCommand = defineCommand106({
13730
13954
  });
13731
13955
 
13732
13956
  // src/commands/images/normalize.ts
13733
- import { defineCommand as defineCommand107 } from "citty";
13957
+ import { defineCommand as defineCommand108 } from "citty";
13734
13958
 
13735
13959
  // src/lib/image/color-changer.ts
13736
13960
  import quantize from "quantize";
@@ -14462,7 +14686,7 @@ function coerceRawArgs(args) {
14462
14686
  "dry-run": bool(args["dry-run"])
14463
14687
  };
14464
14688
  }
14465
- var normalizeCommand = defineCommand107({
14689
+ var normalizeCommand = defineCommand108({
14466
14690
  meta: {
14467
14691
  name: "normalize",
14468
14692
  description: `Normalize logos / images: declarative recolor + bg removal + trim + resize. Operates on local files; writes in-place by default.
@@ -14517,7 +14741,7 @@ Examples:
14517
14741
  });
14518
14742
 
14519
14743
  // src/commands/images/pinterest.ts
14520
- import { defineCommand as defineCommand108 } from "citty";
14744
+ import { defineCommand as defineCommand109 } from "citty";
14521
14745
  registerSchema({
14522
14746
  command: "images.pinterest",
14523
14747
  description: "Pinterest image search via ScrapeCreators. Reference-grade real-world photography, product styling, interiors, fashion, food, and aesthetic mood boards. Inspect before placing \u2014 Pinterest is unverified, trademark-bearing web content.",
@@ -14537,7 +14761,7 @@ registerSchema({
14537
14761
  }
14538
14762
  }
14539
14763
  });
14540
- var pinterestCommand = defineCommand108({
14764
+ var pinterestCommand = defineCommand109({
14541
14765
  meta: {
14542
14766
  name: "pinterest",
14543
14767
  description: "Pinterest image search via ScrapeCreators ($0.00188/request). Best for photo-realistic reference imagery \u2014 lifestyle, interiors, fashion, food, product styling, and mood boards to brief AI generation against. \u26A0 Unverified, trademark-bearing web content \u2014 inspect and respect rights before placing on a customer page. Browse first; auto-ingest only the pins you commit to.\n\nExamples:\n baker images pinterest 'scandinavian living room'\n baker images pinterest 'minimalist skincare product photography' --limit 20\n baker images pinterest 'cozy coffee shop interior' --auto-ingest 2 --context 'Mood reference for hero photography'"
@@ -14577,7 +14801,7 @@ var pinterestCommand = defineCommand108({
14577
14801
  });
14578
14802
 
14579
14803
  // src/commands/images/screenshot.ts
14580
- import { defineCommand as defineCommand109 } from "citty";
14804
+ import { defineCommand as defineCommand110 } from "citty";
14581
14805
  registerSchema({
14582
14806
  command: "images.screenshot",
14583
14807
  description: "Capture a website screenshot via ScreenshotOne. Auto-ingests on success.",
@@ -14593,7 +14817,7 @@ registerSchema({
14593
14817
  }
14594
14818
  }
14595
14819
  });
14596
- var screenshotCommand = defineCommand109({
14820
+ var screenshotCommand = defineCommand110({
14597
14821
  meta: {
14598
14822
  name: "screenshot",
14599
14823
  description: "Screenshot a URL via ScreenshotOne. $0.009/capture. Auto-ingests to library.\n\nExample: baker images screenshot https://stripe.com --full-page"
@@ -14643,7 +14867,7 @@ var screenshotCommand = defineCommand109({
14643
14867
  });
14644
14868
 
14645
14869
  // src/commands/images/search.ts
14646
- import { defineCommand as defineCommand110 } from "citty";
14870
+ import { defineCommand as defineCommand111 } from "citty";
14647
14871
  registerSchema({
14648
14872
  command: "images.search",
14649
14873
  description: "Search images by text query. Only returns ready images.",
@@ -14659,7 +14883,7 @@ registerSchema({
14659
14883
  tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
14660
14884
  }
14661
14885
  });
14662
- var searchCommand = defineCommand110({
14886
+ var searchCommand = defineCommand111({
14663
14887
  meta: {
14664
14888
  name: "search",
14665
14889
  description: "Semantic search images by text query. Uses hybrid BM25 + vector + reranking. Example: baker images search 'hero banner' --aspect-ratio 16:9 --tags logo"
@@ -14719,7 +14943,7 @@ var searchCommand = defineCommand110({
14719
14943
  });
14720
14944
 
14721
14945
  // src/commands/images/sticker.ts
14722
- import { defineCommand as defineCommand111 } from "citty";
14946
+ import { defineCommand as defineCommand112 } from "citty";
14723
14947
  registerSchema({
14724
14948
  command: "images.sticker",
14725
14949
  description: "Search Giphy stickers \u2014 transparent-background overlays for ad creative.",
@@ -14751,7 +14975,7 @@ registerSchema({
14751
14975
  }
14752
14976
  }
14753
14977
  });
14754
- var stickerCommand = defineCommand111({
14978
+ var stickerCommand = defineCommand112({
14755
14979
  meta: {
14756
14980
  name: "sticker",
14757
14981
  description: "Search Giphy's sticker corpus \u2014 transparent-background WebPs / GIFs ideal for overlaying on ad creative (Meta, TikTok, Stories). Same Giphy free API as `baker images gif`; results carry WebP + GIF + MP4 URLs in providerMeta.\n\nExample: baker images sticker 'thumbs up' --limit 10\nExample: baker images sticker celebration --rating g --auto-ingest 3\nExample: baker images sticker --trending --limit 25"
@@ -14798,7 +15022,7 @@ var stickerCommand = defineCommand111({
14798
15022
  });
14799
15023
 
14800
15024
  // src/commands/images/stock.ts
14801
- import { defineCommand as defineCommand112 } from "citty";
15025
+ import { defineCommand as defineCommand113 } from "citty";
14802
15026
  registerSchema({
14803
15027
  command: "images.stock",
14804
15028
  description: "Stock photo, vector illustration, icon-set, and PSD search via Magnific (Freepik's developer API).",
@@ -14856,7 +15080,7 @@ registerSchema({
14856
15080
  }
14857
15081
  }
14858
15082
  });
14859
- var stockCommand = defineCommand112({
15083
+ var stockCommand = defineCommand113({
14860
15084
  meta: {
14861
15085
  name: "stock",
14862
15086
  description: "Stock search via Magnific \u2014 Freepik's developer API (~250M assets: photos, vectors, illustrations, icons, PSDs). $0.002/req. With --auto-ingest, ingested hits return Baker-owned URLs.\n\nExamples:\n baker images stock 'minimalist office'\n baker images stock 'flat office workers' --type vector\n baker images stock 'hero photo of a kitchen' --type photo --orientation landscape --ai exclude\n baker images stock 'brand pattern' --color '#0a0a0a' --license freemium --auto-ingest 2"
@@ -14912,7 +15136,7 @@ var stockCommand = defineCommand112({
14912
15136
  });
14913
15137
 
14914
15138
  // src/lib/tags-command.ts
14915
- import { defineCommand as defineCommand113 } from "citty";
15139
+ import { defineCommand as defineCommand114 } from "citty";
14916
15140
  function makeTagsCommand(command, label, endpoint) {
14917
15141
  registerSchema({
14918
15142
  command: `${command}.tags`,
@@ -14921,7 +15145,7 @@ function makeTagsCommand(command, label, endpoint) {
14921
15145
  output: { type: "string", description: "Output format: md|json", required: false, default: "md" }
14922
15146
  }
14923
15147
  });
14924
- return defineCommand113({
15148
+ return defineCommand114({
14925
15149
  meta: {
14926
15150
  name: "tags",
14927
15151
  description: `List the available ${label} tag names (defaults + company custom tags). Use before filtering with --tags. Example: baker ${command} tags`
@@ -14957,9 +15181,9 @@ function makeTagsCommand(command, label, endpoint) {
14957
15181
  var tagsCommand2 = makeTagsCommand("images", "image", "/api/images/tags");
14958
15182
 
14959
15183
  // src/commands/images/upload.ts
14960
- import { readFile as readFile11 } from "fs/promises";
15184
+ import { readFile as readFile12 } from "fs/promises";
14961
15185
  import { extname as extname2 } from "path";
14962
- import { defineCommand as defineCommand114 } from "citty";
15186
+ import { defineCommand as defineCommand115 } from "citty";
14963
15187
  var MIME_MAP = {
14964
15188
  ".png": "image/png",
14965
15189
  ".jpg": "image/jpeg",
@@ -15014,7 +15238,7 @@ function detectContentType(filePath) {
15014
15238
  }
15015
15239
  return mime;
15016
15240
  }
15017
- var uploadCommand = defineCommand114({
15241
+ var uploadCommand = defineCommand115({
15018
15242
  meta: {
15019
15243
  name: "upload",
15020
15244
  description: "Upload an image to the library \u2014 accepts a local file path OR a remote http(s) URL.\n\nLocal: reads bytes, sends to /api/images/upload, content-type auto-detected from extension.\nRemote: dispatches to /api/images/ingest with hash-dedup on bytes + externalId.\n\nExamples:\n baker images upload ./logo.png --source uploaded\n baker images upload ./cert.png --context 'ISO 27001 badge \u2014 enterprise tier'\n baker images upload https://acme.com/hero.png --source firecrawl --context 'Acme competitor pricing hero'"
@@ -15097,7 +15321,7 @@ async function uploadLocal(target, args) {
15097
15321
  });
15098
15322
  return;
15099
15323
  }
15100
- const fileBuffer = await readFile11(target);
15324
+ const fileBuffer = await readFile12(target);
15101
15325
  const base64 = fileBuffer.toString("base64");
15102
15326
  const body = { base64, contentType };
15103
15327
  if (args.source) body.source = args.source;
@@ -15107,7 +15331,7 @@ async function uploadLocal(target, args) {
15107
15331
  }
15108
15332
 
15109
15333
  // src/commands/images/upscale.ts
15110
- import { defineCommand as defineCommand115 } from "citty";
15334
+ import { defineCommand as defineCommand116 } from "citty";
15111
15335
  registerSchema({
15112
15336
  command: "images.upscale",
15113
15337
  description: "Upscale a library image via the backend (Replicate, cost-tracked). Waits for completion by default. The image must be status 'ready' and raster (not SVG/AVIF).",
@@ -15122,7 +15346,7 @@ registerSchema({
15122
15346
  }
15123
15347
  });
15124
15348
  var POLL_INTERVAL_MS3 = 1500;
15125
- var upscaleCommand = defineCommand115({
15349
+ var upscaleCommand = defineCommand116({
15126
15350
  meta: {
15127
15351
  name: "upscale",
15128
15352
  description: "Upscale a library image via the Convex backend (Replicate, cost-tracked at $0.05/image). Waits for completion by default.\n\nExample: baker images upscale j571abc123def\nExample: baker images upscale j571abc123def --max-wait 0 # fire-and-forget"
@@ -15177,7 +15401,7 @@ var upscaleCommand = defineCommand115({
15177
15401
  });
15178
15402
 
15179
15403
  // src/commands/images/use.ts
15180
- import { defineCommand as defineCommand116 } from "citty";
15404
+ import { defineCommand as defineCommand117 } from "citty";
15181
15405
  registerSchema({
15182
15406
  command: "images.use",
15183
15407
  description: "Ingest a URL and wait for the library record to be ready.",
@@ -15193,7 +15417,7 @@ registerSchema({
15193
15417
  }
15194
15418
  });
15195
15419
  var POLL_INTERVAL_MS4 = 1500;
15196
- var useCommand = defineCommand116({
15420
+ var useCommand = defineCommand117({
15197
15421
  meta: {
15198
15422
  name: "use",
15199
15423
  description: "Sugar over `ingest`: download \u2192 store \u2192 wait until describe + embed complete \u2192 return ready library record.\n\nExample: baker images use https://cdn.example.com/hero.png --source uploaded"
@@ -15239,7 +15463,7 @@ var useCommand = defineCommand116({
15239
15463
  });
15240
15464
 
15241
15465
  // src/commands/images/index.ts
15242
- var imagesCommand = defineCommand117({
15466
+ var imagesCommand = defineCommand118({
15243
15467
  meta: {
15244
15468
  name: "images",
15245
15469
  description: `Find, source, and normalize images. Subcommands route by provider so cost + license are explicit.
@@ -15309,10 +15533,10 @@ Paid transforms (run on the Convex backend, cost-tracked):
15309
15533
  });
15310
15534
 
15311
15535
  // src/commands/research/index.ts
15312
- import { defineCommand as defineCommand128 } from "citty";
15536
+ import { defineCommand as defineCommand129 } from "citty";
15313
15537
 
15314
15538
  // src/commands/research/advertisers.ts
15315
- import { defineCommand as defineCommand118 } from "citty";
15539
+ import { defineCommand as defineCommand119 } from "citty";
15316
15540
 
15317
15541
  // src/commands/research/output.ts
15318
15542
  var RESEARCH_DATA_NOTE = "Estimates based on third-party SERP data \u2014 not exact figures. Use for directional insights, not precise measurement.";
@@ -15425,7 +15649,7 @@ var FIELDS3 = {
15425
15649
  etv: "Estimated traffic value (USD)",
15426
15650
  visibility: "SERP visibility score (0-1)"
15427
15651
  };
15428
- var advertisersCommand = defineCommand118({
15652
+ var advertisersCommand = defineCommand119({
15429
15653
  meta: {
15430
15654
  name: "advertisers",
15431
15655
  description: `Find domains competing for a keyword in Google SERPs.
@@ -15472,7 +15696,7 @@ Examples:
15472
15696
  });
15473
15697
 
15474
15698
  // src/commands/research/autocomplete.ts
15475
- import { defineCommand as defineCommand119 } from "citty";
15699
+ import { defineCommand as defineCommand120 } from "citty";
15476
15700
  registerSchema({
15477
15701
  command: "research.autocomplete",
15478
15702
  description: "Get Google Autocomplete suggestions for a seed keyword. Useful for keyword expansion and discovering what people actually search for. IMPORTANT: If --location and --language are omitted, defaults to United States (us) and English (en).",
@@ -15495,7 +15719,7 @@ registerSchema({
15495
15719
  var FIELDS4 = {
15496
15720
  suggestion: "Autocomplete suggestion from Google"
15497
15721
  };
15498
- var autocompleteCommand = defineCommand119({
15722
+ var autocompleteCommand = defineCommand120({
15499
15723
  meta: {
15500
15724
  name: "autocomplete",
15501
15725
  description: `Get Google Autocomplete suggestions for keyword expansion.
@@ -15541,7 +15765,7 @@ Examples:
15541
15765
  });
15542
15766
 
15543
15767
  // src/commands/research/countries.ts
15544
- import { defineCommand as defineCommand120 } from "citty";
15768
+ import { defineCommand as defineCommand121 } from "citty";
15545
15769
  registerSchema({
15546
15770
  command: "research.countries",
15547
15771
  description: "List all supported country codes for --location flag in research commands.",
@@ -15598,7 +15822,7 @@ var FIELDS5 = {
15598
15822
  code: "Country code to pass as --location",
15599
15823
  name: "Country name"
15600
15824
  };
15601
- var countriesCommand = defineCommand120({
15825
+ var countriesCommand = defineCommand121({
15602
15826
  meta: {
15603
15827
  name: "countries",
15604
15828
  description: "List all supported country codes for --location flag."
@@ -15609,7 +15833,7 @@ var countriesCommand = defineCommand120({
15609
15833
  });
15610
15834
 
15611
15835
  // src/commands/research/intent.ts
15612
- import { defineCommand as defineCommand121 } from "citty";
15836
+ import { defineCommand as defineCommand122 } from "citty";
15613
15837
  registerSchema({
15614
15838
  command: "research.intent",
15615
15839
  description: "Classify Google Search intent for keywords. Determines if someone searching is looking to buy, research, or navigate. IMPORTANT: If --language is omitted, defaults to English (en). The response includes a query_context object showing which language was used.",
@@ -15632,7 +15856,7 @@ var FIELDS6 = {
15632
15856
  intent: "Primary Google Search intent: informational, navigational, commercial, transactional",
15633
15857
  probability: "Confidence score 0.0-1.0"
15634
15858
  };
15635
- var intentCommand = defineCommand121({
15859
+ var intentCommand = defineCommand122({
15636
15860
  meta: {
15637
15861
  name: "intent",
15638
15862
  description: `Classify Google Search intent for keywords. Returns intent type and confidence.
@@ -15680,7 +15904,7 @@ Examples:
15680
15904
  });
15681
15905
 
15682
15906
  // src/commands/research/keyword-gap.ts
15683
- import { defineCommand as defineCommand122 } from "citty";
15907
+ import { defineCommand as defineCommand123 } from "citty";
15684
15908
  registerSchema({
15685
15909
  command: "research.keyword-gap",
15686
15910
  description: "Find keywords a competitor ranks for (organic or paid) that you don't. Discovers expansion opportunities. IMPORTANT: If --location and --language are omitted, defaults to United States (us) and English (en). The response includes a query_context object showing which location/language were used.",
@@ -15709,7 +15933,7 @@ var FIELDS7 = {
15709
15933
  cpc: "Cost per click USD",
15710
15934
  their_position: "Competitor's ranking position"
15711
15935
  };
15712
- var keywordGapCommand = defineCommand122({
15936
+ var keywordGapCommand = defineCommand123({
15713
15937
  meta: {
15714
15938
  name: "keyword-gap",
15715
15939
  description: `Find keywords a competitor has that you don't. Supports pagination via --offset.
@@ -15783,7 +16007,7 @@ Examples:
15783
16007
  });
15784
16008
 
15785
16009
  // src/commands/research/keywords-for-site.ts
15786
- import { defineCommand as defineCommand123 } from "citty";
16010
+ import { defineCommand as defineCommand124 } from "citty";
15787
16011
  registerSchema({
15788
16012
  command: "research.keywords-for-site",
15789
16013
  description: "Get keywords a competitor targets in Google. Use --type paid to see only paid keywords, --type organic for organic only. IMPORTANT: If --location and --language are omitted, defaults to United States (us) and English (en). The response includes a query_context object showing which location/language were used.",
@@ -15816,7 +16040,7 @@ var FIELDS8 = {
15816
16040
  competition: "LOW, MEDIUM, or HIGH",
15817
16041
  competition_index: "Competition score 0-100"
15818
16042
  };
15819
- var keywordsForSiteCommand = defineCommand123({
16043
+ var keywordsForSiteCommand = defineCommand124({
15820
16044
  meta: {
15821
16045
  name: "keywords-for-site",
15822
16046
  description: `Get keywords a competitor targets in Google. Use --type to filter paid/organic.
@@ -15869,7 +16093,7 @@ Examples:
15869
16093
  });
15870
16094
 
15871
16095
  // src/commands/research/languages.ts
15872
- import { defineCommand as defineCommand124 } from "citty";
16096
+ import { defineCommand as defineCommand125 } from "citty";
15873
16097
  registerSchema({
15874
16098
  command: "research.languages",
15875
16099
  description: "List all supported language codes for --language flag in research commands.",
@@ -15899,7 +16123,7 @@ var FIELDS9 = {
15899
16123
  code: "Language code to pass as --language",
15900
16124
  name: "Language name (also accepted by --language)"
15901
16125
  };
15902
- var languagesCommand2 = defineCommand124({
16126
+ var languagesCommand2 = defineCommand125({
15903
16127
  meta: {
15904
16128
  name: "languages",
15905
16129
  description: "List all supported language codes for --language flag."
@@ -15910,7 +16134,7 @@ var languagesCommand2 = defineCommand124({
15910
16134
  });
15911
16135
 
15912
16136
  // src/commands/research/lighthouse.ts
15913
- import { defineCommand as defineCommand125 } from "citty";
16137
+ import { defineCommand as defineCommand126 } from "citty";
15914
16138
  registerSchema({
15915
16139
  command: "research.lighthouse",
15916
16140
  description: "Landing page performance audit. Returns metrics that affect Google Ads Quality Score and CPC.",
@@ -15929,7 +16153,7 @@ var FIELDS10 = {
15929
16153
  speed_index_ms: "Speed Index in ms (good: < 3400)",
15930
16154
  interactive_ms: "Time to Interactive in ms (good: < 3800)"
15931
16155
  };
15932
- var lighthouseCommand = defineCommand125({
16156
+ var lighthouseCommand = defineCommand126({
15933
16157
  meta: {
15934
16158
  name: "lighthouse",
15935
16159
  description: `Landing page performance audit. Metrics affecting Google Ads Quality Score.
@@ -15967,7 +16191,7 @@ Examples:
15967
16191
  });
15968
16192
 
15969
16193
  // src/commands/research/relevant-pages.ts
15970
- import { defineCommand as defineCommand126 } from "citty";
16194
+ import { defineCommand as defineCommand127 } from "citty";
15971
16195
  registerSchema({
15972
16196
  command: "research.relevant-pages",
15973
16197
  description: "Get the top pages of a competitor domain with organic traffic and ranking data. Shows which pages drive the most traffic. IMPORTANT: If --location and --language are omitted, defaults to United States (us) and English (en).",
@@ -15993,7 +16217,7 @@ var FIELDS11 = {
15993
16217
  keywords: "Total organic keywords the page ranks for",
15994
16218
  top_10: "Keywords in positions 1-10"
15995
16219
  };
15996
- var relevantPagesCommand = defineCommand126({
16220
+ var relevantPagesCommand = defineCommand127({
15997
16221
  meta: {
15998
16222
  name: "relevant-pages",
15999
16223
  description: `Get the top pages of a competitor domain with traffic data.
@@ -16039,7 +16263,7 @@ Examples:
16039
16263
  });
16040
16264
 
16041
16265
  // src/commands/research/web.ts
16042
- import { defineCommand as defineCommand127 } from "citty";
16266
+ import { defineCommand as defineCommand128 } from "citty";
16043
16267
  registerSchema({
16044
16268
  command: "research.web",
16045
16269
  description: "Search the web with AI to answer marketing questions \u2014 competitors, ICP, pricing, pain points, market trends. Three depth levels: medium (quick, default), high (thorough), xhigh (exhaustive deep research).",
@@ -16090,7 +16314,7 @@ async function runDeepResearch(question) {
16090
16314
  }
16091
16315
  throw new Error("Deep research timed out");
16092
16316
  }
16093
- var webCommand = defineCommand127({
16317
+ var webCommand = defineCommand128({
16094
16318
  meta: {
16095
16319
  name: "web",
16096
16320
  description: `Search the web with AI to answer any open-ended marketing question. Uses live internet data via Google Search.
@@ -16150,7 +16374,7 @@ Examples:
16150
16374
  });
16151
16375
 
16152
16376
  // src/commands/research/index.ts
16153
- var researchCommand = defineCommand128({
16377
+ var researchCommand = defineCommand129({
16154
16378
  meta: {
16155
16379
  name: "research",
16156
16380
  description: `Competitive intelligence and AI-powered research commands.
@@ -16190,10 +16414,10 @@ Examples:
16190
16414
  });
16191
16415
 
16192
16416
  // src/commands/scheduled-actions/index.ts
16193
- import { defineCommand as defineCommand135 } from "citty";
16417
+ import { defineCommand as defineCommand136 } from "citty";
16194
16418
 
16195
16419
  // src/commands/scheduled-actions/create.ts
16196
- import { defineCommand as defineCommand129 } from "citty";
16420
+ import { defineCommand as defineCommand130 } from "citty";
16197
16421
 
16198
16422
  // src/commands/scheduled-actions/shared.ts
16199
16423
  var TEMP_SCHEDULED_ACTION_PREFIX = "temp_sched_";
@@ -16298,7 +16522,7 @@ registerSchema({
16298
16522
  prompt: { type: "string", description: "Additional prompt instructions for the spawned agent", required: false }
16299
16523
  }
16300
16524
  });
16301
- var createCommand2 = defineCommand129({
16525
+ var createCommand2 = defineCommand130({
16302
16526
  meta: {
16303
16527
  name: "create",
16304
16528
  description: 'Stage a scheduled action. Example: baker scheduled-actions create --name "Weekly report" --description "..." --cron "0 9 * * MON"'
@@ -16346,7 +16570,7 @@ var createCommand2 = defineCommand129({
16346
16570
  });
16347
16571
 
16348
16572
  // src/commands/scheduled-actions/delete.ts
16349
- import { defineCommand as defineCommand130 } from "citty";
16573
+ import { defineCommand as defineCommand131 } from "citty";
16350
16574
  registerSchema({
16351
16575
  command: "scheduled-actions.delete",
16352
16576
  description: "Stage deletion of a published scheduled action or cancellation of a temp_sched_* draft creation.",
@@ -16354,7 +16578,7 @@ registerSchema({
16354
16578
  id: { type: "string", description: "Published scheduled action ID or temp_sched_* draft ID", required: true }
16355
16579
  }
16356
16580
  });
16357
- var deleteCommand2 = defineCommand130({
16581
+ var deleteCommand2 = defineCommand131({
16358
16582
  meta: {
16359
16583
  name: "delete",
16360
16584
  description: "Stage scheduled action deletion. Example: baker scheduled-actions delete <id-or-temp_sched_id>"
@@ -16383,7 +16607,7 @@ var deleteCommand2 = defineCommand130({
16383
16607
  });
16384
16608
 
16385
16609
  // src/commands/scheduled-actions/get.ts
16386
- import { defineCommand as defineCommand131 } from "citty";
16610
+ import { defineCommand as defineCommand132 } from "citty";
16387
16611
  registerSchema({
16388
16612
  command: "scheduled-actions.get",
16389
16613
  description: "Get a published scheduled action or a temp_sched_* draft-created scheduled action.",
@@ -16391,7 +16615,7 @@ registerSchema({
16391
16615
  id: { type: "string", description: "Published scheduled action ID or temp_sched_* draft ID", required: true }
16392
16616
  }
16393
16617
  });
16394
- var getCommand3 = defineCommand131({
16618
+ var getCommand3 = defineCommand132({
16395
16619
  meta: {
16396
16620
  name: "get",
16397
16621
  description: "Get a scheduled action. Example: baker scheduled-actions get <id-or-temp_sched_id>"
@@ -16428,13 +16652,13 @@ var getCommand3 = defineCommand131({
16428
16652
  });
16429
16653
 
16430
16654
  // src/commands/scheduled-actions/list.ts
16431
- import { defineCommand as defineCommand132 } from "citty";
16655
+ import { defineCommand as defineCommand133 } from "citty";
16432
16656
  registerSchema({
16433
16657
  command: "scheduled-actions.list",
16434
16658
  description: "List published scheduled actions. Includes draft state when BAKER_CHAT_ID is set.",
16435
16659
  args: {}
16436
16660
  });
16437
- var listCommand3 = defineCommand132({
16661
+ var listCommand3 = defineCommand133({
16438
16662
  meta: {
16439
16663
  name: "list",
16440
16664
  description: "List scheduled actions. Includes staged draft ops when BAKER_CHAT_ID is set."
@@ -16455,7 +16679,7 @@ var listCommand3 = defineCommand132({
16455
16679
  });
16456
16680
 
16457
16681
  // src/commands/scheduled-actions/trigger.ts
16458
- import { defineCommand as defineCommand133 } from "citty";
16682
+ import { defineCommand as defineCommand134 } from "citty";
16459
16683
  registerSchema({
16460
16684
  command: "scheduled-actions.trigger",
16461
16685
  description: "Immediately trigger a published scheduled action. Does not require BAKER_CHAT_ID and rejects temp_sched_* IDs.",
@@ -16463,7 +16687,7 @@ registerSchema({
16463
16687
  id: { type: "string", description: "Published scheduled action ID", required: true }
16464
16688
  }
16465
16689
  });
16466
- var triggerCommand = defineCommand133({
16690
+ var triggerCommand = defineCommand134({
16467
16691
  meta: {
16468
16692
  name: "trigger",
16469
16693
  description: "Immediately trigger a published scheduled action. Example: baker scheduled-actions trigger <id>"
@@ -16500,7 +16724,7 @@ var triggerCommand = defineCommand133({
16500
16724
  });
16501
16725
 
16502
16726
  // src/commands/scheduled-actions/update.ts
16503
- import { defineCommand as defineCommand134 } from "citty";
16727
+ import { defineCommand as defineCommand135 } from "citty";
16504
16728
  registerSchema({
16505
16729
  command: "scheduled-actions.update",
16506
16730
  description: "Stage an update to a published scheduled action or temp_sched_* draft-created scheduled action.",
@@ -16525,7 +16749,7 @@ registerSchema({
16525
16749
  prompt: { type: "string", description: "Replacement additional spawned-agent instructions", required: false }
16526
16750
  }
16527
16751
  });
16528
- var updateCommand2 = defineCommand134({
16752
+ var updateCommand2 = defineCommand135({
16529
16753
  meta: {
16530
16754
  name: "update",
16531
16755
  description: "Stage a scheduled action update. Example: baker scheduled-actions update <id> --enabled false"
@@ -16595,7 +16819,7 @@ var updateCommand2 = defineCommand134({
16595
16819
  });
16596
16820
 
16597
16821
  // src/commands/scheduled-actions/index.ts
16598
- var scheduledActionsCommand = defineCommand135({
16822
+ var scheduledActionsCommand = defineCommand136({
16599
16823
  meta: {
16600
16824
  name: "scheduled-actions",
16601
16825
  description: `Manage Scheduled Actions. Subcommands: list, get, create, update, delete, trigger.
@@ -16621,8 +16845,8 @@ Examples:
16621
16845
  });
16622
16846
 
16623
16847
  // src/commands/schema.ts
16624
- import { defineCommand as defineCommand136 } from "citty";
16625
- var schemaCommand = defineCommand136({
16848
+ import { defineCommand as defineCommand137 } from "citty";
16849
+ var schemaCommand = defineCommand137({
16626
16850
  meta: {
16627
16851
  name: "schema",
16628
16852
  description: "Inspect command argument schemas (for AI agent introspection). Lists all commands if no argument given. Example: baker schema images.search"
@@ -16658,10 +16882,10 @@ var schemaCommand = defineCommand136({
16658
16882
  });
16659
16883
 
16660
16884
  // src/commands/testimonials/index.ts
16661
- import { defineCommand as defineCommand140 } from "citty";
16885
+ import { defineCommand as defineCommand141 } from "citty";
16662
16886
 
16663
16887
  // src/commands/testimonials/get.ts
16664
- import { defineCommand as defineCommand137 } from "citty";
16888
+ import { defineCommand as defineCommand138 } from "citty";
16665
16889
  registerSchema({
16666
16890
  command: "testimonials.get",
16667
16891
  description: "Get a single testimonial by ID",
@@ -16669,7 +16893,7 @@ registerSchema({
16669
16893
  id: { type: "string", description: "Testimonial ID", required: true }
16670
16894
  }
16671
16895
  });
16672
- var getCommand4 = defineCommand137({
16896
+ var getCommand4 = defineCommand138({
16673
16897
  meta: { name: "get", description: "Get a single testimonial by ID. Example: baker testimonials get j571abc123" },
16674
16898
  args: {
16675
16899
  id: { type: "positional", description: "Testimonial ID", required: false },
@@ -16706,7 +16930,7 @@ var getCommand4 = defineCommand137({
16706
16930
  });
16707
16931
 
16708
16932
  // src/commands/testimonials/list.ts
16709
- import { defineCommand as defineCommand138 } from "citty";
16933
+ import { defineCommand as defineCommand139 } from "citty";
16710
16934
  registerSchema({
16711
16935
  command: "testimonials.list",
16712
16936
  description: "List testimonials with optional filters.",
@@ -16736,7 +16960,7 @@ registerSchema({
16736
16960
  limit: { type: "number", description: "Max results (default 50)", required: false, default: 50 }
16737
16961
  }
16738
16962
  });
16739
- var listCommand4 = defineCommand138({
16963
+ var listCommand4 = defineCommand139({
16740
16964
  meta: {
16741
16965
  name: "list",
16742
16966
  description: "List testimonials with optional filters. Example: baker testimonials list --source google --sentiment positive"
@@ -16785,7 +17009,7 @@ var listCommand4 = defineCommand138({
16785
17009
  });
16786
17010
 
16787
17011
  // src/commands/testimonials/search.ts
16788
- import { defineCommand as defineCommand139 } from "citty";
17012
+ import { defineCommand as defineCommand140 } from "citty";
16789
17013
  registerSchema({
16790
17014
  command: "testimonials.search",
16791
17015
  description: "Search testimonials by text query. Uses hybrid BM25 + vector + reranking.",
@@ -16816,7 +17040,7 @@ registerSchema({
16816
17040
  tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
16817
17041
  }
16818
17042
  });
16819
- var searchCommand2 = defineCommand139({
17043
+ var searchCommand2 = defineCommand140({
16820
17044
  meta: {
16821
17045
  name: "search",
16822
17046
  description: "Semantic search testimonials by text query. Uses hybrid BM25 + vector + reranking. Example: baker testimonials search 'great service' --rating-min 4"
@@ -16890,7 +17114,7 @@ var searchCommand2 = defineCommand139({
16890
17114
  var tagsCommand3 = makeTagsCommand("testimonials", "testimonial", "/api/testimonials/tags");
16891
17115
 
16892
17116
  // src/commands/testimonials/index.ts
16893
- var testimonialsCommand = defineCommand140({
17117
+ var testimonialsCommand = defineCommand141({
16894
17118
  meta: {
16895
17119
  name: "testimonials",
16896
17120
  description: `Find and browse testimonials in Baker. Subcommands: search, get, list, tags.
@@ -16911,10 +17135,10 @@ Examples:
16911
17135
  });
16912
17136
 
16913
17137
  // src/commands/videos/index.ts
16914
- import { defineCommand as defineCommand145 } from "citty";
17138
+ import { defineCommand as defineCommand146 } from "citty";
16915
17139
 
16916
17140
  // src/commands/videos/delete.ts
16917
- import { defineCommand as defineCommand141 } from "citty";
17141
+ import { defineCommand as defineCommand142 } from "citty";
16918
17142
  registerSchema({
16919
17143
  command: "videos.delete",
16920
17144
  description: "Delete a video by ID",
@@ -16928,7 +17152,7 @@ registerSchema({
16928
17152
  }
16929
17153
  }
16930
17154
  });
16931
- var deleteCommand3 = defineCommand141({
17155
+ var deleteCommand3 = defineCommand142({
16932
17156
  meta: {
16933
17157
  name: "delete",
16934
17158
  description: "Delete a video by ID. Use --dry-run to preview. Example: baker videos delete j571abc123 --dry-run"
@@ -16969,7 +17193,7 @@ var deleteCommand3 = defineCommand141({
16969
17193
  });
16970
17194
 
16971
17195
  // src/commands/videos/get.ts
16972
- import { defineCommand as defineCommand142 } from "citty";
17196
+ import { defineCommand as defineCommand143 } from "citty";
16973
17197
  registerSchema({
16974
17198
  command: "videos.get",
16975
17199
  description: "Get a single video by ID",
@@ -16977,7 +17201,7 @@ registerSchema({
16977
17201
  id: { type: "string", description: "Video ID", required: true }
16978
17202
  }
16979
17203
  });
16980
- var getCommand5 = defineCommand142({
17204
+ var getCommand5 = defineCommand143({
16981
17205
  meta: { name: "get", description: "Get a single video by ID. Example: baker videos get j571abc123" },
16982
17206
  args: {
16983
17207
  id: { type: "positional", description: "Video ID", required: false },
@@ -17014,7 +17238,7 @@ var getCommand5 = defineCommand142({
17014
17238
  });
17015
17239
 
17016
17240
  // src/commands/videos/search.ts
17017
- import { defineCommand as defineCommand143 } from "citty";
17241
+ import { defineCommand as defineCommand144 } from "citty";
17018
17242
  registerSchema({
17019
17243
  command: "videos.search",
17020
17244
  description: "Search videos by text query. Only returns ready videos.",
@@ -17024,7 +17248,7 @@ registerSchema({
17024
17248
  tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
17025
17249
  }
17026
17250
  });
17027
- var searchCommand3 = defineCommand143({
17251
+ var searchCommand3 = defineCommand144({
17028
17252
  meta: {
17029
17253
  name: "search",
17030
17254
  description: "Semantic search videos by text query. Uses hybrid BM25 + vector + reranking. Example: baker videos search 'product demo' --tags tutorial"
@@ -17074,9 +17298,9 @@ var searchCommand3 = defineCommand143({
17074
17298
  var tagsCommand4 = makeTagsCommand("videos", "video", "/api/videos/tags");
17075
17299
 
17076
17300
  // src/commands/videos/upload.ts
17077
- import { readFile as readFile12, stat as stat3 } from "fs/promises";
17301
+ import { readFile as readFile13, stat as stat3 } from "fs/promises";
17078
17302
  import { extname as extname3 } from "path";
17079
- import { defineCommand as defineCommand144 } from "citty";
17303
+ import { defineCommand as defineCommand145 } from "citty";
17080
17304
  var MIME_MAP2 = {
17081
17305
  ".mp4": "video/mp4",
17082
17306
  ".mov": "video/quicktime",
@@ -17110,7 +17334,7 @@ function detectContentType2(filePath) {
17110
17334
  }
17111
17335
  return mime;
17112
17336
  }
17113
- var uploadCommand2 = defineCommand144({
17337
+ var uploadCommand2 = defineCommand145({
17114
17338
  meta: {
17115
17339
  name: "upload",
17116
17340
  description: "Upload a video file to Baker via Mux direct upload. Auto-detects content type. Example: baker videos upload ./demo.mp4"
@@ -17139,7 +17363,7 @@ var uploadCommand2 = defineCommand144({
17139
17363
  return;
17140
17364
  }
17141
17365
  const { uploadUrl, videoId } = await apiPost("/api/videos/upload", {});
17142
- const fileBuffer = await readFile12(filePath);
17366
+ const fileBuffer = await readFile13(filePath);
17143
17367
  const uploadResponse = await fetch(uploadUrl, {
17144
17368
  method: "PUT",
17145
17369
  headers: { "Content-Type": contentType },
@@ -17164,7 +17388,7 @@ var uploadCommand2 = defineCommand144({
17164
17388
  });
17165
17389
 
17166
17390
  // src/commands/videos/index.ts
17167
- var videosCommand = defineCommand145({
17391
+ var videosCommand = defineCommand146({
17168
17392
  meta: {
17169
17393
  name: "videos",
17170
17394
  description: `Find and manage videos in Baker. Subcommands: search, get, upload, delete, tags.
@@ -17187,10 +17411,10 @@ Examples:
17187
17411
  });
17188
17412
 
17189
17413
  // src/commands/winning-ads/index.ts
17190
- import { defineCommand as defineCommand148 } from "citty";
17414
+ import { defineCommand as defineCommand149 } from "citty";
17191
17415
 
17192
17416
  // src/commands/winning-ads/advertisers.ts
17193
- import { defineCommand as defineCommand146 } from "citty";
17417
+ import { defineCommand as defineCommand147 } from "citty";
17194
17418
  registerSchema({
17195
17419
  command: "winning-ads.advertisers",
17196
17420
  description: "Resolve a brand name to advertiser_id(s) in the ad-dna corpus \u2014 to find your OWN advertiser (to --exclude-advertiser) or a competitor (to --advertiser-id).",
@@ -17203,7 +17427,7 @@ registerSchema({
17203
17427
  function identity(record) {
17204
17428
  return record;
17205
17429
  }
17206
- var advertisersCommand2 = defineCommand146({
17430
+ var advertisersCommand2 = defineCommand147({
17207
17431
  meta: {
17208
17432
  name: "advertisers",
17209
17433
  description: 'Resolve a brand name to advertiser_id(s). Use it to find your own advertiser for --exclude-advertiser, or a competitor for --advertiser-id. Example: baker winning-ads advertisers "Deel" --output md'
@@ -17254,7 +17478,7 @@ var advertisersCommand2 = defineCommand146({
17254
17478
  });
17255
17479
 
17256
17480
  // src/commands/winning-ads/search.ts
17257
- import { defineCommand as defineCommand147 } from "citty";
17481
+ import { defineCommand as defineCommand148 } from "citty";
17258
17482
  registerSchema({
17259
17483
  command: "winning-ads.search",
17260
17484
  description: "Search the ad-dna corpus of scored winning ads. Returns a lean shortlist (advertiser, summary, scores, media_url) to pick a reference to reproduce.",
@@ -17362,7 +17586,7 @@ function buildSearchBody(args) {
17362
17586
  }
17363
17587
  return body;
17364
17588
  }
17365
- var searchCommand4 = defineCommand147({
17589
+ var searchCommand4 = defineCommand148({
17366
17590
  meta: {
17367
17591
  name: "search",
17368
17592
  description: "Search winning reference ads. Example: baker winning-ads search 'B2B SaaS before/after AI automation' --platform meta --format static --winner-category winner --exclude-advertiser adv_123 --output md"
@@ -17474,7 +17698,7 @@ var searchCommand4 = defineCommand147({
17474
17698
  });
17475
17699
 
17476
17700
  // src/commands/winning-ads/index.ts
17477
- var winningAdsCommand = defineCommand148({
17701
+ var winningAdsCommand = defineCommand149({
17478
17702
  meta: {
17479
17703
  name: "winning-ads",
17480
17704
  description: `Search the ad-dna corpus of scored "winning" ads for reference creatives to reproduce. Proxied through the Baker backend (BAKER_API_KEY) \u2014 no separate token needed.
@@ -17514,7 +17738,7 @@ function getCliVersion() {
17514
17738
  }
17515
17739
 
17516
17740
  // src/cli.ts
17517
- var main = defineCommand149({
17741
+ var main = defineCommand150({
17518
17742
  meta: {
17519
17743
  name: "baker",
17520
17744
  version: getCliVersion(),