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

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,6 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- AssetRef,
4
3
  ELEVENLABS_MAX_MUSIC_LENGTH_MS,
5
4
  IMAGE_GENERATE_MODELS,
6
5
  MODEL_REGISTRY,
@@ -8,16 +7,15 @@ import {
8
7
  ValidationError,
9
8
  createEngineFromEnv,
10
9
  defaultRegistry,
11
- extForMime,
12
10
  generateCatalog,
13
11
  validateCanvasDeep
14
- } from "./chunk-FOK2JPRW.js";
12
+ } from "./chunk-3JVYU72O.js";
15
13
 
16
14
  // src/cli.ts
17
- import { defineCommand as defineCommand150, runMain } from "citty";
15
+ import { defineCommand as defineCommand152, runMain } from "citty";
18
16
 
19
17
  // src/commands/actions/index.ts
20
- import { defineCommand as defineCommand17 } from "citty";
18
+ import { defineCommand as defineCommand18 } from "citty";
21
19
 
22
20
  // src/commands/actions/claim.ts
23
21
  import { defineCommand } from "citty";
@@ -45,9 +43,6 @@ function getEnv() {
45
43
  }
46
44
  return cached;
47
45
  }
48
- function runtimeEnvVar(name) {
49
- return process.env[name];
50
- }
51
46
  function requireChatId() {
52
47
  const env = getEnv();
53
48
  if (!env.BAKER_CHAT_ID) {
@@ -152,9 +147,9 @@ async function handleResponse(response) {
152
147
  throw new ApiError("INTERNAL_ERROR", "Failed to parse API response as JSON");
153
148
  }
154
149
  }
155
- async function apiGet(path12, params) {
150
+ async function apiGet(path11, params) {
156
151
  const env = getEnv();
157
- const url = new URL(path12, env.BAKER_API_URL);
152
+ const url = new URL(path11, env.BAKER_API_URL);
158
153
  if (params) {
159
154
  const clean = sanitizeParams(params);
160
155
  for (const [key, value] of Object.entries(clean)) {
@@ -179,12 +174,12 @@ async function apiGet(path12, params) {
179
174
  }
180
175
  return handleResponse(response);
181
176
  }
182
- async function apiPost(path12, body, opts) {
177
+ async function apiPost(path11, body, opts) {
183
178
  const env = getEnv();
184
179
  const timeoutMs = opts?.timeoutMs ?? 6e4;
185
180
  let response;
186
181
  try {
187
- response = await fetchWithRateLimitRetry(new URL(path12, env.BAKER_API_URL).toString(), {
182
+ response = await fetchWithRateLimitRetry(new URL(path11, env.BAKER_API_URL).toString(), {
188
183
  method: "POST",
189
184
  headers: {
190
185
  Authorization: `Bearer ${env.BAKER_API_KEY}`,
@@ -562,12 +557,17 @@ var claimCommand = defineCommand({
562
557
 
563
558
  // src/commands/actions/complete.ts
564
559
  import { defineCommand as defineCommand2 } from "citty";
560
+ var COMPLETE_NOTE_MIN = 20;
565
561
  registerSchema({
566
562
  command: "actions.complete",
567
- description: "Stage completion of an action (it was DONE). Accepts a real action ID (must be claimed) or a temp ID from the same draft. The action becomes completed when the chat is published. Do NOT use this to drop an action you no longer want \u2014 to remove a staged op use `actions draft remove`, to close an unwanted published action use `actions discard`.",
563
+ description: "Stage completion of an action (it was DONE). Accepts a real action ID (must be claimed) or a temp ID from the same draft. The action becomes completed when the chat is published. --note is REQUIRED and must describe what you actually did to resolve it (what changed, where, and the outcome) \u2014 it is the client-facing record surfaced by `baker actions log`. Do NOT use this to drop an action you no longer want \u2014 to remove a staged op use `actions draft remove`, to close an unwanted published action use `actions discard`.",
568
564
  args: {
569
565
  id: { type: "string", description: "Action ID or temp ID", required: true },
570
- note: { type: "string", description: "What was done \u2014 context for the team and AI", required: false }
566
+ note: {
567
+ type: "string",
568
+ description: "REQUIRED. Detailed description of what you did to resolve this: what changed, where, and the outcome. This is the durable, client-facing record shown by `baker actions log`.",
569
+ required: true
570
+ }
571
571
  }
572
572
  });
573
573
  var completeCommand = defineCommand2({
@@ -578,7 +578,11 @@ var completeCommand = defineCommand2({
578
578
  args: {
579
579
  id: { type: "positional", description: "Action ID or temp ID", required: false },
580
580
  "action-id": { type: "string", description: "Action ID or temp ID", required: false },
581
- note: { type: "string", description: "What was done \u2014 context for the team and AI", required: false }
581
+ note: {
582
+ type: "string",
583
+ description: "REQUIRED. What you did to resolve this: what changed, where, and the outcome.",
584
+ required: false
585
+ }
582
586
  },
583
587
  run: async ({ args }) => {
584
588
  try {
@@ -589,8 +593,14 @@ var completeCommand = defineCommand2({
589
593
  if (!isTempId(id)) {
590
594
  validateConvexId(id);
591
595
  }
596
+ const note = args.note?.trim() ?? "";
597
+ if (note.length < COMPLETE_NOTE_MIN) {
598
+ failValidation(
599
+ `--note is required and must describe what you did (\u2265${COMPLETE_NOTE_MIN} chars): what changed, where, and the outcome. This becomes the client-facing record surfaced by \`baker actions log\`.`
600
+ );
601
+ }
592
602
  const chatId = requireChatId();
593
- await apiPost("/api/actions/complete", { chatId, actionRef: id, note: args.note });
603
+ await apiPost("/api/actions/complete", { chatId, actionRef: id, note });
594
604
  writeOk();
595
605
  } catch (err) {
596
606
  failApi(err);
@@ -970,8 +980,77 @@ var listCommand2 = defineCommand8({
970
980
  }
971
981
  });
972
982
 
973
- // src/commands/actions/release.ts
983
+ // src/commands/actions/log.ts
974
984
  import { defineCommand as defineCommand9 } from "citty";
985
+ var DAY_MS = 864e5;
986
+ function startOfLocalDay(date) {
987
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime();
988
+ }
989
+ function resolveWindow(args) {
990
+ const fromArg = args.from;
991
+ const toArg = args.to;
992
+ if (fromArg) {
993
+ const fromMs = Date.parse(fromArg);
994
+ if (Number.isNaN(fromMs)) {
995
+ failValidation(`--from is not a valid ISO date/datetime: ${fromArg}`);
996
+ }
997
+ const toMs = toArg ? Date.parse(toArg) : Date.now();
998
+ if (Number.isNaN(toMs)) {
999
+ failValidation(`--to is not a valid ISO date/datetime: ${toArg}`);
1000
+ }
1001
+ return { fromMs, toMs };
1002
+ }
1003
+ const since = (args.since ?? "today").trim().toLowerCase();
1004
+ const now = Date.now();
1005
+ if (since === "today") {
1006
+ return { fromMs: startOfLocalDay(new Date(now)), toMs: now };
1007
+ }
1008
+ if (since === "yesterday") {
1009
+ const todayStart = startOfLocalDay(new Date(now));
1010
+ return { fromMs: todayStart - DAY_MS, toMs: todayStart };
1011
+ }
1012
+ const days = /^(\d+)d$/.exec(since);
1013
+ if (days) {
1014
+ return { fromMs: now - Number(days[1]) * DAY_MS, toMs: now };
1015
+ }
1016
+ return failValidation(`--since must be one of: today | yesterday | <N>d (e.g. 7d). Got: ${since}`);
1017
+ }
1018
+ registerSchema({
1019
+ command: "actions.log",
1020
+ description: "List actions COMPLETED in a time window, newest first, each with its completion note (what was done). Use this to report to the client what was accomplished \u2014 e.g. `baker actions log` for today, or `baker actions log --since 7d` for the last week. Only published completions appear (not ops staged in an unpublished chat). Window defaults to today in local time.",
1021
+ args: {
1022
+ since: {
1023
+ type: "string",
1024
+ description: "Relative window: today | yesterday | <N>d (e.g. 7d). Default: today.",
1025
+ required: false
1026
+ },
1027
+ from: { type: "string", description: "Window start (ISO date/datetime). Overrides --since.", required: false },
1028
+ to: { type: "string", description: "Window end (ISO date/datetime). Defaults to now.", required: false }
1029
+ }
1030
+ });
1031
+ var logCommand = defineCommand9({
1032
+ meta: {
1033
+ name: "log",
1034
+ description: "List completed actions in a window with their completion notes (what was done). Example: baker actions log --since today"
1035
+ },
1036
+ args: {
1037
+ since: { type: "string", description: "today | yesterday | <N>d (default: today)", required: false },
1038
+ from: { type: "string", description: "Window start (ISO). Overrides --since", required: false },
1039
+ to: { type: "string", description: "Window end (ISO). Defaults to now", required: false }
1040
+ },
1041
+ run: async ({ args }) => {
1042
+ try {
1043
+ const { fromMs, toMs } = resolveWindow(args);
1044
+ const response = await apiPost("/api/actions/log", { fromMs, toMs });
1045
+ writeJson(response);
1046
+ } catch (err) {
1047
+ failApi(err);
1048
+ }
1049
+ }
1050
+ });
1051
+
1052
+ // src/commands/actions/release.ts
1053
+ import { defineCommand as defineCommand10 } from "citty";
975
1054
  registerSchema({
976
1055
  command: "actions.release",
977
1056
  description: "Release an action you previously claimed (no-op if you don't own the claim).",
@@ -979,7 +1058,7 @@ registerSchema({
979
1058
  id: { type: "string", description: "Action ID", required: true }
980
1059
  }
981
1060
  });
982
- var releaseCommand = defineCommand9({
1061
+ var releaseCommand = defineCommand10({
983
1062
  meta: {
984
1063
  name: "release",
985
1064
  description: "Release a claim you made on an action. Example: baker actions release <action-id>"
@@ -1005,7 +1084,7 @@ var releaseCommand = defineCommand9({
1005
1084
  });
1006
1085
 
1007
1086
  // src/commands/actions/status.ts
1008
- import { defineCommand as defineCommand10 } from "citty";
1087
+ import { defineCommand as defineCommand11 } from "citty";
1009
1088
  registerSchema({
1010
1089
  command: "actions.status",
1011
1090
  description: "Resolve one or more Work Action refs by real action ID or temp_* ref in a single batch call. When BAKER_CHAT_ID is set, a temp_* ref still staged in THIS chat resolves to status 'draft' (not 'not_found') \u2014 staged ops only become published actions on chat publish.",
@@ -1013,7 +1092,7 @@ registerSchema({
1013
1092
  refs: { type: "string", description: "One or more action refs: real action IDs or temp_* refs", required: true }
1014
1093
  }
1015
1094
  });
1016
- var statusCommand = defineCommand10({
1095
+ var statusCommand = defineCommand11({
1017
1096
  meta: {
1018
1097
  name: "status",
1019
1098
  description: "Resolve Work Action refs by real ID or temp_* ref. Example: baker actions status temp_hero jx123"
@@ -1038,10 +1117,10 @@ var statusCommand = defineCommand10({
1038
1117
  });
1039
1118
 
1040
1119
  // src/commands/actions/tags/index.ts
1041
- import { defineCommand as defineCommand14 } from "citty";
1120
+ import { defineCommand as defineCommand15 } from "citty";
1042
1121
 
1043
1122
  // src/commands/actions/tags/create.ts
1044
- import { defineCommand as defineCommand11 } from "citty";
1123
+ import { defineCommand as defineCommand12 } from "citty";
1045
1124
  registerSchema({
1046
1125
  command: "actions.tags.create",
1047
1126
  description: "Create a company custom action tag, minting a new slug usable with --tags. The name is slugified (lowercased, spaces\u2192hyphens). Use when no existing tag fits the work.",
@@ -1050,7 +1129,7 @@ registerSchema({
1050
1129
  description: { type: "string", description: "What this tag means", required: false }
1051
1130
  }
1052
1131
  });
1053
- var tagsCreateCommand = defineCommand11({
1132
+ var tagsCreateCommand = defineCommand12({
1054
1133
  meta: {
1055
1134
  name: "create",
1056
1135
  description: 'Create a custom action tag. Example: baker actions tags create --slug pmax --description "Performance Max work"'
@@ -1077,7 +1156,7 @@ var tagsCreateCommand = defineCommand11({
1077
1156
  });
1078
1157
 
1079
1158
  // src/commands/actions/tags/delete.ts
1080
- import { defineCommand as defineCommand12 } from "citty";
1159
+ import { defineCommand as defineCommand13 } from "citty";
1081
1160
  registerSchema({
1082
1161
  command: "actions.tags.delete",
1083
1162
  description: "Delete a company custom action tag by slug. Built-in default tags cannot be deleted. Existing actions keep the slug (it just stops appearing in the taxonomy).",
@@ -1085,7 +1164,7 @@ registerSchema({
1085
1164
  slug: { type: "string", description: "Custom tag slug to delete", required: true }
1086
1165
  }
1087
1166
  });
1088
- var tagsDeleteCommand = defineCommand12({
1167
+ var tagsDeleteCommand = defineCommand13({
1089
1168
  meta: {
1090
1169
  name: "delete",
1091
1170
  description: "Delete a custom action tag. Example: baker actions tags delete --slug pmax"
@@ -1108,13 +1187,13 @@ var tagsDeleteCommand = defineCommand12({
1108
1187
  });
1109
1188
 
1110
1189
  // src/commands/actions/tags/list.ts
1111
- import { defineCommand as defineCommand13 } from "citty";
1190
+ import { defineCommand as defineCommand14 } from "citty";
1112
1191
  registerSchema({
1113
1192
  command: "actions.tags.list",
1114
1193
  description: "List the available action tag taxonomy (built-in defaults + this company's custom tags). Tags are strict \u2014 only these names are accepted by --tags. Run before tagging.",
1115
1194
  args: { output: { type: "string", description: "Output format: md|json", required: false, default: "md" } }
1116
1195
  });
1117
- var tagsListCommand = defineCommand13({
1196
+ var tagsListCommand = defineCommand14({
1118
1197
  meta: {
1119
1198
  name: "list",
1120
1199
  description: "List available action tag names (defaults + company custom tags). Use before --tags. Example: baker actions tags list"
@@ -1144,7 +1223,7 @@ var tagsListCommand = defineCommand13({
1144
1223
  });
1145
1224
 
1146
1225
  // src/commands/actions/tags/index.ts
1147
- var tagsCommand = defineCommand14({
1226
+ var tagsCommand = defineCommand15({
1148
1227
  meta: {
1149
1228
  name: "tags",
1150
1229
  description: `Manage the action tag taxonomy (built-in defaults + company custom tags). Tags are strict \u2014 only listed names work with --tags on create/update.
@@ -1162,7 +1241,7 @@ Examples:
1162
1241
  });
1163
1242
 
1164
1243
  // src/commands/actions/unlink.ts
1165
- import { defineCommand as defineCommand15 } from "citty";
1244
+ import { defineCommand as defineCommand16 } from "citty";
1166
1245
  registerSchema({
1167
1246
  command: "actions.unlink",
1168
1247
  description: "Stage removal of a 'blocker -> blocked' dependency. The blocked action must be claimed by current chat.",
@@ -1171,7 +1250,7 @@ registerSchema({
1171
1250
  blocked: { type: "string", description: "Blocked action ID (must be claimed by current chat)", required: true }
1172
1251
  }
1173
1252
  });
1174
- var unlinkCommand = defineCommand15({
1253
+ var unlinkCommand = defineCommand16({
1175
1254
  meta: {
1176
1255
  name: "unlink",
1177
1256
  description: "Stage removal of a dependency. Example: baker actions unlink --blocker <id> --blocked <id>"
@@ -1203,7 +1282,7 @@ var unlinkCommand = defineCommand15({
1203
1282
  });
1204
1283
 
1205
1284
  // src/commands/actions/update.ts
1206
- import { defineCommand as defineCommand16 } from "citty";
1285
+ import { defineCommand as defineCommand17 } from "citty";
1207
1286
  registerSchema({
1208
1287
  command: "actions.update",
1209
1288
  description: "Stage an update on a claimed action (name, description, tags, and/or priority). Applies on publish. --tags REPLACES the tag set; pass --tags '' to clear. --priority accepts urgent|high|medium|low or 'none' to clear back to unset (== normal).",
@@ -1223,7 +1302,7 @@ registerSchema({
1223
1302
  }
1224
1303
  }
1225
1304
  });
1226
- var updateCommand = defineCommand16({
1305
+ var updateCommand = defineCommand17({
1227
1306
  meta: {
1228
1307
  name: "update",
1229
1308
  description: 'Stage an update on a claimed action. Example: baker actions update <id> --name "New name"'
@@ -1265,10 +1344,10 @@ var updateCommand = defineCommand16({
1265
1344
  });
1266
1345
 
1267
1346
  // src/commands/actions/index.ts
1268
- var actionsCommand = defineCommand17({
1347
+ var actionsCommand = defineCommand18({
1269
1348
  meta: {
1270
1349
  name: "actions",
1271
- description: `Manage action items for the current chat. Subcommands: list, draft, get, status, claim, release, create, update, complete, discard, link, unlink.
1350
+ description: `Manage action items for the current chat. Subcommands: list, log, draft, get, status, claim, release, create, update, complete, discard, link, unlink.
1272
1351
 
1273
1352
  Lifecycle: claim an action before working on it. Stage create/update/complete/discard/link via this CLI; they apply when the chat is published. Release if you decide not to work on it after all.
1274
1353
 
@@ -1276,6 +1355,8 @@ Staged vs published: create/update/complete/discard/link are STAGED in this chat
1276
1355
 
1277
1356
  Examples:
1278
1357
  baker actions list # bucketed view of PUBLISHED actions
1358
+ baker actions log # actions COMPLETED today, with what was done (client report)
1359
+ baker actions log --since 7d # everything completed in the last 7 days
1279
1360
  baker actions draft # review what THIS chat has staged (pre-publish)
1280
1361
  baker actions draft remove temp_hero # drop a staged create (cascades its complete/link ops)
1281
1362
  baker actions draft clear # drop everything staged in this chat
@@ -1288,6 +1369,7 @@ Examples:
1288
1369
  },
1289
1370
  subCommands: {
1290
1371
  list: listCommand2,
1372
+ log: logCommand,
1291
1373
  draft: draftCommand,
1292
1374
  get: getCommand,
1293
1375
  status: statusCommand,
@@ -1304,13 +1386,13 @@ Examples:
1304
1386
  });
1305
1387
 
1306
1388
  // src/commands/ads/index.ts
1307
- import { defineCommand as defineCommand77 } from "citty";
1389
+ import { defineCommand as defineCommand78 } from "citty";
1308
1390
 
1309
1391
  // src/commands/ads/google/index.ts
1310
- import { defineCommand as defineCommand28 } from "citty";
1392
+ import { defineCommand as defineCommand29 } from "citty";
1311
1393
 
1312
1394
  // src/commands/ads/google/accounts.ts
1313
- import { defineCommand as defineCommand18 } from "citty";
1395
+ import { defineCommand as defineCommand19 } from "citty";
1314
1396
 
1315
1397
  // src/commands/ads/cache.ts
1316
1398
  import { createHash } from "crypto";
@@ -1332,31 +1414,31 @@ function cachePath(category, key) {
1332
1414
  return join(dir, `${hashKey(key)}.json`);
1333
1415
  }
1334
1416
  function cacheGet(category, key) {
1335
- const path12 = cachePath(category, key);
1336
- if (!existsSync(path12)) {
1417
+ const path11 = cachePath(category, key);
1418
+ if (!existsSync(path11)) {
1337
1419
  return null;
1338
1420
  }
1339
1421
  try {
1340
- const raw = readFileSync(path12, "utf-8");
1422
+ const raw = readFileSync(path11, "utf-8");
1341
1423
  const entry = JSON.parse(raw);
1342
1424
  if (entry.expiresAt < Date.now()) {
1343
- rmSync(path12, { force: true });
1425
+ rmSync(path11, { force: true });
1344
1426
  return null;
1345
1427
  }
1346
1428
  return entry;
1347
1429
  } catch {
1348
- rmSync(path12, { force: true });
1430
+ rmSync(path11, { force: true });
1349
1431
  return null;
1350
1432
  }
1351
1433
  }
1352
1434
  function cacheSet(category, key, data, ttlMs, fields) {
1353
- const path12 = cachePath(category, key);
1435
+ const path11 = cachePath(category, key);
1354
1436
  const entry = {
1355
1437
  expiresAt: Date.now() + ttlMs,
1356
1438
  data,
1357
1439
  fields
1358
1440
  };
1359
- writeFileSync(path12, JSON.stringify(entry), "utf-8");
1441
+ writeFileSync(path11, JSON.stringify(entry), "utf-8");
1360
1442
  }
1361
1443
  var HOUR = 60 * 60 * 1e3;
1362
1444
  var MINUTE = 60 * 1e3;
@@ -1586,7 +1668,7 @@ function handleAccountsError(err) {
1586
1668
  writeAdsJson({ ok: false, error: { code: "NETWORK_ERROR", message: "Unexpected error" } });
1587
1669
  process.exit(1);
1588
1670
  }
1589
- var accountsCommand = defineCommand18({
1671
+ var accountsCommand = defineCommand19({
1590
1672
  meta: {
1591
1673
  name: "accounts",
1592
1674
  description: `List accessible Google Ads accounts. Returns customer IDs needed for all other commands.
@@ -1626,7 +1708,7 @@ Examples:
1626
1708
  });
1627
1709
 
1628
1710
  // src/commands/ads/google/changes.ts
1629
- import { defineCommand as defineCommand19 } from "citty";
1711
+ import { defineCommand as defineCommand20 } from "citty";
1630
1712
 
1631
1713
  // src/commands/ads/field-descriptions.ts
1632
1714
  var FIELD_DESCRIPTIONS = {
@@ -2178,7 +2260,7 @@ registerSchema({
2178
2260
  output: { type: "string", description: "Format: json|csv|jsonl|md", required: false, default: "json" }
2179
2261
  }
2180
2262
  });
2181
- var changesCommand = defineCommand19({
2263
+ var changesCommand = defineCommand20({
2182
2264
  meta: {
2183
2265
  name: "changes",
2184
2266
  description: `Get recent changes in a Google Ads account with performance data.
@@ -2229,7 +2311,7 @@ Examples:
2229
2311
  });
2230
2312
 
2231
2313
  // src/commands/ads/google/currency.ts
2232
- import { defineCommand as defineCommand20 } from "citty";
2314
+ import { defineCommand as defineCommand21 } from "citty";
2233
2315
  registerSchema({
2234
2316
  command: "ads.google.currency",
2235
2317
  description: "Get the currency code for a Google Ads account. Returns currency_code, customer_id, account_name, and access_type. Call this before interpreting cost_micros values.",
@@ -2241,7 +2323,7 @@ registerSchema({
2241
2323
  }
2242
2324
  }
2243
2325
  });
2244
- var currencyCommand = defineCommand20({
2326
+ var currencyCommand = defineCommand21({
2245
2327
  meta: {
2246
2328
  name: "currency",
2247
2329
  description: `Get account currency code. Use this to interpret metrics.cost_micros values.
@@ -2290,10 +2372,10 @@ Examples:
2290
2372
  });
2291
2373
 
2292
2374
  // src/commands/ads/google/keywords/index.ts
2293
- import { defineCommand as defineCommand25 } from "citty";
2375
+ import { defineCommand as defineCommand26 } from "citty";
2294
2376
 
2295
2377
  // src/commands/ads/google/keywords/discover.ts
2296
- import { defineCommand as defineCommand21 } from "citty";
2378
+ import { defineCommand as defineCommand22 } from "citty";
2297
2379
 
2298
2380
  // src/geo-context.ts
2299
2381
  var GOOGLE_ADS_LOCATIONS = [
@@ -2568,7 +2650,7 @@ function handleKeywordError(err) {
2568
2650
  writeAdsJson({ ok: false, error: { code: "NETWORK_ERROR", message: "Unexpected error" } });
2569
2651
  process.exit(1);
2570
2652
  }
2571
- var discoverCommand = defineCommand21({
2653
+ var discoverCommand = defineCommand22({
2572
2654
  meta: {
2573
2655
  name: "discover",
2574
2656
  description: `Discover new keyword ideas from seed keywords or competitor URLs.
@@ -2630,7 +2712,7 @@ Examples:
2630
2712
  });
2631
2713
 
2632
2714
  // src/commands/ads/google/keywords/languages.ts
2633
- import { defineCommand as defineCommand22 } from "citty";
2715
+ import { defineCommand as defineCommand23 } from "citty";
2634
2716
  registerSchema({
2635
2717
  command: "ads.google.keywords.languages",
2636
2718
  description: "List all supported language IDs for --language flag in Google Ads keyword commands.",
@@ -2640,7 +2722,7 @@ var FIELDS = {
2640
2722
  id: "Language ID to pass as --language",
2641
2723
  name: "Language name"
2642
2724
  };
2643
- var languagesCommand = defineCommand22({
2725
+ var languagesCommand = defineCommand23({
2644
2726
  meta: {
2645
2727
  name: "languages",
2646
2728
  description: "List all supported language IDs for --language flag."
@@ -2651,7 +2733,7 @@ var languagesCommand = defineCommand22({
2651
2733
  });
2652
2734
 
2653
2735
  // src/commands/ads/google/keywords/locations.ts
2654
- import { defineCommand as defineCommand23 } from "citty";
2736
+ import { defineCommand as defineCommand24 } from "citty";
2655
2737
  registerSchema({
2656
2738
  command: "ads.google.keywords.locations",
2657
2739
  description: "List all supported geo target IDs for --location flag in Google Ads keyword commands.",
@@ -2661,7 +2743,7 @@ var FIELDS2 = {
2661
2743
  id: "Geo target ID to pass as --location",
2662
2744
  name: "Country/region name"
2663
2745
  };
2664
- var locationsCommand = defineCommand23({
2746
+ var locationsCommand = defineCommand24({
2665
2747
  meta: {
2666
2748
  name: "locations",
2667
2749
  description: "List all supported geo target IDs for --location flag."
@@ -2672,7 +2754,7 @@ var locationsCommand = defineCommand23({
2672
2754
  });
2673
2755
 
2674
2756
  // src/commands/ads/google/keywords/metrics.ts
2675
- import { defineCommand as defineCommand24 } from "citty";
2757
+ import { defineCommand as defineCommand25 } from "citty";
2676
2758
  registerSchema({
2677
2759
  command: "ads.google.keywords.metrics",
2678
2760
  description: "Get historical metrics for specific keywords. Returns { historical_metrics: [...] } with snake_case fields matching the Google Ads API. IMPORTANT: If --location and --language are omitted, defaults to United States (2840) and English (1000). The response includes a query_context object showing which location/language were used.",
@@ -2696,7 +2778,7 @@ registerSchema({
2696
2778
  output: { type: "string", description: "Format: json|csv|jsonl|md", required: false, default: "json" }
2697
2779
  }
2698
2780
  });
2699
- var metricsCommand = defineCommand24({
2781
+ var metricsCommand = defineCommand25({
2700
2782
  meta: {
2701
2783
  name: "metrics",
2702
2784
  description: `Get historical search metrics for specific keywords.
@@ -2783,7 +2865,7 @@ Examples:
2783
2865
  });
2784
2866
 
2785
2867
  // src/commands/ads/google/keywords/index.ts
2786
- var keywordsCommand = defineCommand25({
2868
+ var keywordsCommand = defineCommand26({
2787
2869
  meta: {
2788
2870
  name: "keywords",
2789
2871
  description: `Keyword research tools. Subcommands: discover, metrics, locations, languages.
@@ -2803,8 +2885,8 @@ Examples:
2803
2885
  });
2804
2886
 
2805
2887
  // src/commands/ads/google/library/index.ts
2806
- import { defineCommand as defineCommand26 } from "citty";
2807
- var listAdvertisers = defineCommand26({
2888
+ import { defineCommand as defineCommand27 } from "citty";
2889
+ var listAdvertisers = defineCommand27({
2808
2890
  meta: {
2809
2891
  name: "list-advertisers",
2810
2892
  description: "List tracked Google advertisers and their accounts"
@@ -2821,7 +2903,7 @@ var listAdvertisers = defineCommand26({
2821
2903
  }
2822
2904
  }
2823
2905
  });
2824
- var syncStatus = defineCommand26({
2906
+ var syncStatus = defineCommand27({
2825
2907
  meta: {
2826
2908
  name: "sync-status",
2827
2909
  description: "Check the sync status and ad counts of a Google account"
@@ -2841,7 +2923,7 @@ var syncStatus = defineCommand26({
2841
2923
  writeAdsJson({ ok: true, data });
2842
2924
  }
2843
2925
  });
2844
- var searchAds = defineCommand26({
2926
+ var searchAds = defineCommand27({
2845
2927
  meta: {
2846
2928
  name: "search-ads",
2847
2929
  description: "Search and filter Google ads for an account"
@@ -2898,7 +2980,7 @@ var searchAds = defineCommand26({
2898
2980
  }
2899
2981
  }
2900
2982
  });
2901
- var searchAdvertiser = defineCommand26({
2983
+ var searchAdvertiser = defineCommand27({
2902
2984
  meta: {
2903
2985
  name: "search-advertiser",
2904
2986
  description: "Search for an advertiser on the Google Ads Transparency Center"
@@ -2933,7 +3015,7 @@ var searchAdvertiser = defineCommand26({
2933
3015
  function sleep(ms) {
2934
3016
  return new Promise((resolve5) => setTimeout(resolve5, ms));
2935
3017
  }
2936
- var track = defineCommand26({
3018
+ var track = defineCommand27({
2937
3019
  meta: {
2938
3020
  name: "track",
2939
3021
  description: "Track a new Google advertiser (from search results). Waits for initial sync to complete before returning."
@@ -2991,7 +3073,7 @@ var track = defineCommand26({
2991
3073
  process.exit(1);
2992
3074
  }
2993
3075
  });
2994
- var sync = defineCommand26({
3076
+ var sync = defineCommand27({
2995
3077
  meta: {
2996
3078
  name: "sync",
2997
3079
  description: "Trigger an immediate sync for a Google account. Waits for completion before returning."
@@ -3035,7 +3117,7 @@ var sync = defineCommand26({
3035
3117
  process.exit(1);
3036
3118
  }
3037
3119
  });
3038
- var searchCompetitors = defineCommand26({
3120
+ var searchCompetitors = defineCommand27({
3039
3121
  meta: {
3040
3122
  name: "search-competitors",
3041
3123
  description: "Search for competitors running Google ads for a keyword (DataForSEO)"
@@ -3067,7 +3149,7 @@ var searchCompetitors = defineCommand26({
3067
3149
  }
3068
3150
  }
3069
3151
  });
3070
- var library = defineCommand26({
3152
+ var library = defineCommand27({
3071
3153
  meta: {
3072
3154
  name: "library",
3073
3155
  description: "Manage and search the Google Ads Library"
@@ -3086,7 +3168,7 @@ var library = defineCommand26({
3086
3168
  // src/commands/ads/google/query.ts
3087
3169
  import { appendFileSync, existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
3088
3170
  import { resolve } from "path";
3089
- import { defineCommand as defineCommand27 } from "citty";
3171
+ import { defineCommand as defineCommand28 } from "citty";
3090
3172
 
3091
3173
  // src/commands/ads/google/preflight.ts
3092
3174
  function buildCommand2(query, customerId) {
@@ -3542,7 +3624,7 @@ function handleQueryError(err, finalQuery, customerId) {
3542
3624
  });
3543
3625
  process.exit(1);
3544
3626
  }
3545
- var queryCommand = defineCommand27({
3627
+ var queryCommand = defineCommand28({
3546
3628
  meta: {
3547
3629
  name: "query",
3548
3630
  description: `Run GAQL queries against Google Ads. Supports raw GAQL, presets, pagination, file export, and caching.
@@ -3600,7 +3682,7 @@ Examples:
3600
3682
  });
3601
3683
 
3602
3684
  // src/commands/ads/google/index.ts
3603
- var googleCommand = defineCommand28({
3685
+ var googleCommand = defineCommand29({
3604
3686
  meta: {
3605
3687
  name: "google",
3606
3688
  description: `Google Ads commands. Query campaigns, keywords, search terms, and more via GAQL.
@@ -3628,7 +3710,7 @@ Examples:
3628
3710
  });
3629
3711
 
3630
3712
  // src/commands/ads/linkedin/index.ts
3631
- import { defineCommand as defineCommand46 } from "citty";
3713
+ import { defineCommand as defineCommand47 } from "citty";
3632
3714
 
3633
3715
  // src/commands/ads/linkedin/schemas.ts
3634
3716
  registerSchema({
@@ -3928,10 +4010,10 @@ registerSchema({
3928
4010
  });
3929
4011
 
3930
4012
  // src/commands/ads/linkedin/account.ts
3931
- import { defineCommand as defineCommand29 } from "citty";
4013
+ import { defineCommand as defineCommand30 } from "citty";
3932
4014
 
3933
4015
  // src/commands/ads/linkedin/shared.ts
3934
- var DAY_MS = 864e5;
4016
+ var DAY_MS2 = 864e5;
3935
4017
  function handleLinkedinError(err) {
3936
4018
  if (err instanceof ApiError) {
3937
4019
  if (err.code === "UNAUTHORIZED") {
@@ -4014,7 +4096,7 @@ function todayIso() {
4014
4096
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
4015
4097
  }
4016
4098
  function daysAgoIso(days) {
4017
- return new Date(Date.now() - days * DAY_MS).toISOString().slice(0, 10);
4099
+ return new Date(Date.now() - days * DAY_MS2).toISOString().slice(0, 10);
4018
4100
  }
4019
4101
  function csvOrJson(args) {
4020
4102
  return args.output ?? "json";
@@ -4031,7 +4113,7 @@ function resolveStatusFilter(args) {
4031
4113
  }
4032
4114
 
4033
4115
  // src/commands/ads/linkedin/account.ts
4034
- var accountCommand = defineCommand29({
4116
+ var accountCommand = defineCommand30({
4035
4117
  meta: {
4036
4118
  name: "account",
4037
4119
  description: `Single LinkedIn ad account detail (currency, status, type).
@@ -4065,9 +4147,9 @@ Examples:
4065
4147
  });
4066
4148
 
4067
4149
  // src/commands/ads/linkedin/accounts.ts
4068
- import { defineCommand as defineCommand30 } from "citty";
4150
+ import { defineCommand as defineCommand31 } from "citty";
4069
4151
  var ACCOUNTS_TTL_MS = 60 * 60 * 1e3;
4070
- var accountsCommand2 = defineCommand30({
4152
+ var accountsCommand2 = defineCommand31({
4071
4153
  meta: {
4072
4154
  name: "accounts",
4073
4155
  description: `List LinkedIn ad accounts in this company's connected scope.
@@ -4115,7 +4197,7 @@ Examples:
4115
4197
  });
4116
4198
 
4117
4199
  // src/commands/ads/linkedin/analytics.ts
4118
- import { defineCommand as defineCommand31 } from "citty";
4200
+ import { defineCommand as defineCommand32 } from "citty";
4119
4201
 
4120
4202
  // src/commands/ads/linkedin/presets.ts
4121
4203
  var INTENTS = {
@@ -4387,7 +4469,7 @@ function numberOf(v) {
4387
4469
  }
4388
4470
  return 0;
4389
4471
  }
4390
- var analyticsCommand = defineCommand31({
4472
+ var analyticsCommand = defineCommand32({
4391
4473
  meta: {
4392
4474
  name: "analytics",
4393
4475
  description: `Performance reporting \u2014 the workhorse for AI agents.
@@ -4515,7 +4597,7 @@ Examples \u2014 common AI questions:
4515
4597
 
4516
4598
  // src/commands/ads/linkedin/audience-size.ts
4517
4599
  import { readFileSync as readFileSync3 } from "fs";
4518
- import { defineCommand as defineCommand32 } from "citty";
4600
+ import { defineCommand as defineCommand33 } from "citty";
4519
4601
  function loadTargeting(args) {
4520
4602
  const inline = args.targeting;
4521
4603
  if (inline) {
@@ -4537,7 +4619,7 @@ function loadTargeting(args) {
4537
4619
  }
4538
4620
  handleLinkedinError(new Error("Pass --targeting-file <path> or --targeting '{...JSON...}'"));
4539
4621
  }
4540
- var audienceSizeCommand = defineCommand32({
4622
+ var audienceSizeCommand = defineCommand33({
4541
4623
  meta: {
4542
4624
  name: "audience-size",
4543
4625
  description: `Estimate audience size for a targeting payload \u2014 pre-launch sanity check.
@@ -4582,7 +4664,7 @@ Examples:
4582
4664
  });
4583
4665
 
4584
4666
  // src/commands/ads/linkedin/audit.ts
4585
- import { defineCommand as defineCommand33 } from "citty";
4667
+ import { defineCommand as defineCommand34 } from "citty";
4586
4668
  var SEVERITY_RANK = {
4587
4669
  critical: 0,
4588
4670
  high: 1,
@@ -4641,7 +4723,7 @@ function noteOf(f) {
4641
4723
  const fix = f.fix?.explanation ?? "";
4642
4724
  return [fix, ev].filter(Boolean).join(" \u2014 ");
4643
4725
  }
4644
- var auditCommand = defineCommand33({
4726
+ var auditCommand = defineCommand34({
4645
4727
  meta: {
4646
4728
  name: "audit",
4647
4729
  description: `Run a LinkedIn Ads playbook audit \u2014 30+ checks across Settings, Tracking,
@@ -4708,7 +4790,7 @@ Examples:
4708
4790
 
4709
4791
  // src/commands/ads/linkedin/bid-pricing.ts
4710
4792
  import { readFileSync as readFileSync4 } from "fs";
4711
- import { defineCommand as defineCommand34 } from "citty";
4793
+ import { defineCommand as defineCommand35 } from "citty";
4712
4794
  function loadTargeting2(args) {
4713
4795
  const inline = args.targeting;
4714
4796
  if (inline) {
@@ -4730,7 +4812,7 @@ function loadTargeting2(args) {
4730
4812
  }
4731
4813
  handleLinkedinError(new Error("Pass --targeting-file <path> or --targeting '{...JSON...}'"));
4732
4814
  }
4733
- var bidPricingCommand = defineCommand34({
4815
+ var bidPricingCommand = defineCommand35({
4734
4816
  meta: {
4735
4817
  name: "bid-pricing",
4736
4818
  description: `Get LinkedIn's suggested bid range for a targeting + objective + cost type.
@@ -4780,8 +4862,8 @@ Examples:
4780
4862
  });
4781
4863
 
4782
4864
  // src/commands/ads/linkedin/campaign-groups.ts
4783
- import { defineCommand as defineCommand35 } from "citty";
4784
- var campaignGroupsCommand = defineCommand35({
4865
+ import { defineCommand as defineCommand36 } from "citty";
4866
+ var campaignGroupsCommand = defineCommand36({
4785
4867
  meta: {
4786
4868
  name: "campaign-groups",
4787
4869
  description: `List LinkedIn campaign groups.
@@ -4824,8 +4906,8 @@ Examples:
4824
4906
  });
4825
4907
 
4826
4908
  // src/commands/ads/linkedin/campaigns.ts
4827
- import { defineCommand as defineCommand36 } from "citty";
4828
- var campaignsCommand = defineCommand36({
4909
+ import { defineCommand as defineCommand37 } from "citty";
4910
+ var campaignsCommand = defineCommand37({
4829
4911
  meta: {
4830
4912
  name: "campaigns",
4831
4913
  description: `List LinkedIn campaigns.
@@ -4874,8 +4956,8 @@ Examples:
4874
4956
  });
4875
4957
 
4876
4958
  // src/commands/ads/linkedin/conversation.ts
4877
- import { defineCommand as defineCommand37 } from "citty";
4878
- var conversationCommand = defineCommand37({
4959
+ import { defineCommand as defineCommand38 } from "citty";
4960
+ var conversationCommand = defineCommand38({
4879
4961
  meta: {
4880
4962
  name: "conversation",
4881
4963
  description: `Per-button click rates inside Sponsored Messaging / Conversation Ads.
@@ -4938,14 +5020,14 @@ Examples:
4938
5020
  });
4939
5021
 
4940
5022
  // src/commands/ads/linkedin/conversions.ts
4941
- import { defineCommand as defineCommand38 } from "citty";
4942
- var DAY_MS2 = 864e5;
5023
+ import { defineCommand as defineCommand39 } from "citty";
5024
+ var DAY_MS3 = 864e5;
4943
5025
  function healthOf(rules) {
4944
5026
  const enabled = rules.filter((r) => r.enabled !== false);
4945
5027
  const capi = enabled.filter((r) => r.conversionMethod === "CONVERSIONS_API");
4946
5028
  const pixel = enabled.filter((r) => r.conversionMethod === "PIXEL");
4947
5029
  const staleCapi = capi.filter(
4948
- (r) => !r.lastConversionReportedAt || Date.now() - r.lastConversionReportedAt > 7 * DAY_MS2
5030
+ (r) => !r.lastConversionReportedAt || Date.now() - r.lastConversionReportedAt > 7 * DAY_MS3
4949
5031
  );
4950
5032
  const longView = enabled.filter(
4951
5033
  (r) => r.viewThroughAttributionWindowSize !== void 0 && r.viewThroughAttributionWindowSize > 7
@@ -4964,7 +5046,7 @@ function healthOf(rules) {
4964
5046
  wrongLeadDedup: wrongDedup
4965
5047
  };
4966
5048
  }
4967
- var listCmd = defineCommand38({
5049
+ var listCmd = defineCommand39({
4968
5050
  meta: {
4969
5051
  name: "list",
4970
5052
  description: `List conversion rules on the account.`
@@ -4992,7 +5074,7 @@ var listCmd = defineCommand38({
4992
5074
  }
4993
5075
  }
4994
5076
  });
4995
- var healthCmd = defineCommand38({
5077
+ var healthCmd = defineCommand39({
4996
5078
  meta: {
4997
5079
  name: "health",
4998
5080
  description: `5-point Insight Tag / CAPI health check (playbook \xA707).
@@ -5022,7 +5104,7 @@ Surfaces:
5022
5104
  }
5023
5105
  }
5024
5106
  });
5025
- var conversionsCommand = defineCommand38({
5107
+ var conversionsCommand = defineCommand39({
5026
5108
  meta: {
5027
5109
  name: "conversions",
5028
5110
  description: `Conversion rules \u2014 Insight Tag and Conversions API.
@@ -5038,8 +5120,8 @@ Subcommands:
5038
5120
  });
5039
5121
 
5040
5122
  // src/commands/ads/linkedin/creatives.ts
5041
- import { defineCommand as defineCommand39 } from "citty";
5042
- var creativesCommand = defineCommand39({
5123
+ import { defineCommand as defineCommand40 } from "citty";
5124
+ var creativesCommand = defineCommand40({
5043
5125
  meta: {
5044
5126
  name: "creatives",
5045
5127
  description: `List LinkedIn creatives (ads).
@@ -5088,7 +5170,7 @@ Examples:
5088
5170
  });
5089
5171
 
5090
5172
  // src/commands/ads/linkedin/demographics.ts
5091
- import { defineCommand as defineCommand40 } from "citty";
5173
+ import { defineCommand as defineCommand41 } from "citty";
5092
5174
  var DEFAULT_PIVOTS = ["job-title", "company", "industry", "seniority", "job-function", "company-size"];
5093
5175
  function numberOf2(v) {
5094
5176
  if (typeof v === "number") return Number.isFinite(v) ? v : 0;
@@ -5101,7 +5183,7 @@ function numberOf2(v) {
5101
5183
  function topByImpressions(rows, limit) {
5102
5184
  return [...rows].sort((a, b) => numberOf2(b.impressions) - numberOf2(a.impressions)).slice(0, limit);
5103
5185
  }
5104
- var demographicsCommand = defineCommand40({
5186
+ var demographicsCommand = defineCommand41({
5105
5187
  meta: {
5106
5188
  name: "demographics",
5107
5189
  description: `Sweep all firmographic pivots in one command \u2014 LinkedIn's superpower.
@@ -5198,8 +5280,8 @@ function resolveRange(args) {
5198
5280
  }
5199
5281
 
5200
5282
  // src/commands/ads/linkedin/facets.ts
5201
- import { defineCommand as defineCommand41 } from "citty";
5202
- var listCmd2 = defineCommand41({
5283
+ import { defineCommand as defineCommand42 } from "citty";
5284
+ var listCmd2 = defineCommand42({
5203
5285
  meta: {
5204
5286
  name: "list",
5205
5287
  description: `List every targeting facet LinkedIn supports.
@@ -5227,7 +5309,7 @@ seniorities, titles, employers, growthRate, companyCategory, skills, etc.).`
5227
5309
  }
5228
5310
  }
5229
5311
  });
5230
- var valuesCmd = defineCommand41({
5312
+ var valuesCmd = defineCommand42({
5231
5313
  meta: {
5232
5314
  name: "values",
5233
5315
  description: `Look up entity values for a single facet \u2014 full list or typeahead search.
@@ -5268,7 +5350,7 @@ or the full URN (urn:li:adTargetingFacet:industries).`
5268
5350
  }
5269
5351
  }
5270
5352
  });
5271
- var facetsCommand = defineCommand41({
5353
+ var facetsCommand = defineCommand42({
5272
5354
  meta: {
5273
5355
  name: "facets",
5274
5356
  description: `LinkedIn targeting facets and entity lookup.
@@ -5286,7 +5368,7 @@ Subcommands:
5286
5368
 
5287
5369
  // src/commands/ads/linkedin/forecast.ts
5288
5370
  import { readFileSync as readFileSync5 } from "fs";
5289
- import { defineCommand as defineCommand42 } from "citty";
5371
+ import { defineCommand as defineCommand43 } from "citty";
5290
5372
  function loadTargeting3(args) {
5291
5373
  const inline = args.targeting;
5292
5374
  if (inline) {
@@ -5316,7 +5398,7 @@ function parseMoney(raw) {
5316
5398
  }
5317
5399
  return { amount: m[1] ?? "0", currencyCode: m[2] ?? "USD" };
5318
5400
  }
5319
- var forecastCommand = defineCommand42({
5401
+ var forecastCommand = defineCommand43({
5320
5402
  meta: {
5321
5403
  name: "forecast",
5322
5404
  description: `Forecast reach + impressions + clicks + spend for a hypothetical campaign.
@@ -5363,9 +5445,9 @@ Examples:
5363
5445
  });
5364
5446
 
5365
5447
  // src/commands/ads/linkedin/leads.ts
5366
- import { defineCommand as defineCommand43 } from "citty";
5367
- var DAY_MS3 = 864e5;
5368
- var leadsCommand = defineCommand43({
5448
+ import { defineCommand as defineCommand44 } from "citty";
5449
+ var DAY_MS4 = 864e5;
5450
+ var leadsCommand = defineCommand44({
5369
5451
  meta: {
5370
5452
  name: "leads",
5371
5453
  description: `List Lead Gen Form responses (playbook \xA707).
@@ -5400,7 +5482,7 @@ Examples:
5400
5482
  if (args["form-id"]) params["form-id"] = String(args["form-id"]);
5401
5483
  if (args["campaign-id"]) params["campaign-id"] = String(args["campaign-id"]);
5402
5484
  const sinceDays = args["since-days"] ? Number(args["since-days"]) : void 0;
5403
- const sinceMs = args["since-ms"] ? Number(args["since-ms"]) : sinceDays ? Date.now() - sinceDays * DAY_MS3 : void 0;
5485
+ const sinceMs = args["since-ms"] ? Number(args["since-ms"]) : sinceDays ? Date.now() - sinceDays * DAY_MS4 : void 0;
5404
5486
  if (sinceMs) params["since-ms"] = String(sinceMs);
5405
5487
  if (args.limit) params.limit = String(args.limit);
5406
5488
  if (args["skip-cache"]) params["skip-cache"] = "true";
@@ -5425,7 +5507,7 @@ Examples:
5425
5507
  });
5426
5508
 
5427
5509
  // src/commands/ads/linkedin/resolve.ts
5428
- import { defineCommand as defineCommand44 } from "citty";
5510
+ import { defineCommand as defineCommand45 } from "citty";
5429
5511
  function toOrgUrn(raw) {
5430
5512
  const trimmed = raw.trim();
5431
5513
  if (trimmed.length === 0) {
@@ -5436,7 +5518,7 @@ function toOrgUrn(raw) {
5436
5518
  }
5437
5519
  return /^\d+$/.test(trimmed) ? `urn:li:organization:${trimmed}` : null;
5438
5520
  }
5439
- var resolveCommand = defineCommand44({
5521
+ var resolveCommand = defineCommand45({
5440
5522
  meta: {
5441
5523
  name: "resolve",
5442
5524
  description: `Resolve organization URNs to company names.
@@ -5478,8 +5560,8 @@ couldn't be resolved \u2014 typically an org outside LinkedIn's targetable set.`
5478
5560
  });
5479
5561
 
5480
5562
  // src/commands/ads/linkedin/top-companies.ts
5481
- import { defineCommand as defineCommand45 } from "citty";
5482
- var topCompaniesCommand = defineCommand45({
5563
+ import { defineCommand as defineCommand46 } from "citty";
5564
+ var topCompaniesCommand = defineCommand46({
5483
5565
  meta: {
5484
5566
  name: "top-companies",
5485
5567
  description: `Top companies whose employees saw / clicked / converted on a campaign.
@@ -5550,7 +5632,7 @@ Examples:
5550
5632
  });
5551
5633
 
5552
5634
  // src/commands/ads/linkedin/index.ts
5553
- var linkedinCommand = defineCommand46({
5635
+ var linkedinCommand = defineCommand47({
5554
5636
  meta: {
5555
5637
  name: "linkedin",
5556
5638
  description: `LinkedIn Marketing API \u2014 AI-first command surface for B2B ad insights.
@@ -5602,13 +5684,13 @@ Account ID format:
5602
5684
  });
5603
5685
 
5604
5686
  // src/commands/ads/meta/index.ts
5605
- import { defineCommand as defineCommand59 } from "citty";
5687
+ import { defineCommand as defineCommand60 } from "citty";
5606
5688
 
5607
5689
  // src/commands/ads/meta/account.ts
5608
- import { defineCommand as defineCommand47 } from "citty";
5690
+ import { defineCommand as defineCommand48 } from "citty";
5609
5691
 
5610
5692
  // src/commands/ads/meta/shared.ts
5611
- var DAY_MS4 = 864e5;
5693
+ var DAY_MS5 = 864e5;
5612
5694
  function handleMetaError(err) {
5613
5695
  if (err instanceof ApiError) {
5614
5696
  if (err.code === "UNAUTHORIZED" || err.code === "NOT_FOUND") {
@@ -5667,7 +5749,7 @@ function todayIso2() {
5667
5749
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
5668
5750
  }
5669
5751
  function daysAgoIso2(days) {
5670
- return new Date(Date.now() - days * DAY_MS4).toISOString().slice(0, 10);
5752
+ return new Date(Date.now() - days * DAY_MS5).toISOString().slice(0, 10);
5671
5753
  }
5672
5754
  function csvOrJson2(args) {
5673
5755
  return args.output ?? "json";
@@ -5684,7 +5766,7 @@ function resolveEffectiveStatus(args) {
5684
5766
  }
5685
5767
 
5686
5768
  // src/commands/ads/meta/account.ts
5687
- var accountCommand2 = defineCommand47({
5769
+ var accountCommand2 = defineCommand48({
5688
5770
  meta: {
5689
5771
  name: "account",
5690
5772
  description: `Show single Meta ad account detail (currency, timezone, balance, business).
@@ -5711,8 +5793,8 @@ Examples:
5711
5793
  });
5712
5794
 
5713
5795
  // src/commands/ads/meta/accounts.ts
5714
- import { defineCommand as defineCommand48 } from "citty";
5715
- var accountsCommand3 = defineCommand48({
5796
+ import { defineCommand as defineCommand49 } from "citty";
5797
+ var accountsCommand3 = defineCommand49({
5716
5798
  meta: {
5717
5799
  name: "accounts",
5718
5800
  description: `List Meta ad accounts in this company's connected scope.
@@ -5760,8 +5842,8 @@ Examples:
5760
5842
  });
5761
5843
 
5762
5844
  // src/commands/ads/meta/activities.ts
5763
- import { defineCommand as defineCommand49 } from "citty";
5764
- var activitiesCommand = defineCommand49({
5845
+ import { defineCommand as defineCommand50 } from "citty";
5846
+ var activitiesCommand = defineCommand50({
5765
5847
  meta: {
5766
5848
  name: "activities",
5767
5849
  description: `Audit log of recent ad-account changes (created, paused, edited). Default lookback 7 days,
@@ -5798,8 +5880,8 @@ Examples:
5798
5880
  });
5799
5881
 
5800
5882
  // src/commands/ads/meta/ads.ts
5801
- import { defineCommand as defineCommand50 } from "citty";
5802
- var adsListCommand = defineCommand50({
5883
+ import { defineCommand as defineCommand51 } from "citty";
5884
+ var adsListCommand = defineCommand51({
5803
5885
  meta: {
5804
5886
  name: "ads",
5805
5887
  description: `List ads in a Meta ad account. Defaults to ACTIVE only \u2014 pass --all-statuses to widen.
@@ -5847,8 +5929,8 @@ Examples:
5847
5929
  });
5848
5930
 
5849
5931
  // src/commands/ads/meta/adsets.ts
5850
- import { defineCommand as defineCommand51 } from "citty";
5851
- var adsetsCommand = defineCommand51({
5932
+ import { defineCommand as defineCommand52 } from "citty";
5933
+ var adsetsCommand = defineCommand52({
5852
5934
  meta: {
5853
5935
  name: "adsets",
5854
5936
  description: `List ad sets in a Meta ad account, optionally scoped to one campaign. Defaults to ACTIVE only.
@@ -5890,8 +5972,8 @@ Examples:
5890
5972
  });
5891
5973
 
5892
5974
  // src/commands/ads/meta/audiences.ts
5893
- import { defineCommand as defineCommand52 } from "citty";
5894
- var audiencesCommand = defineCommand52({
5975
+ import { defineCommand as defineCommand53 } from "citty";
5976
+ var audiencesCommand = defineCommand53({
5895
5977
  meta: {
5896
5978
  name: "audiences",
5897
5979
  description: `List custom audiences for a Meta ad account. Includes lookalikes, website-pixel audiences,
@@ -5926,8 +6008,8 @@ Examples:
5926
6008
  });
5927
6009
 
5928
6010
  // src/commands/ads/meta/businesses.ts
5929
- import { defineCommand as defineCommand53 } from "citty";
5930
- var businessesCommand = defineCommand53({
6011
+ import { defineCommand as defineCommand54 } from "citty";
6012
+ var businessesCommand = defineCommand54({
5931
6013
  meta: {
5932
6014
  name: "businesses",
5933
6015
  description: `List Meta Business Manager accounts the connected user has access to. Required for ad-studies and product-catalogs commands.
@@ -5957,8 +6039,8 @@ Examples:
5957
6039
  });
5958
6040
 
5959
6041
  // src/commands/ads/meta/campaigns.ts
5960
- import { defineCommand as defineCommand54 } from "citty";
5961
- var campaignsCommand2 = defineCommand54({
6042
+ import { defineCommand as defineCommand55 } from "citty";
6043
+ var campaignsCommand2 = defineCommand55({
5962
6044
  meta: {
5963
6045
  name: "campaigns",
5964
6046
  description: `List campaigns for a Meta ad account. Defaults to ACTIVE only \u2014 pass --all-statuses to widen.
@@ -6002,8 +6084,8 @@ Examples:
6002
6084
  });
6003
6085
 
6004
6086
  // src/commands/ads/meta/creatives.ts
6005
- import { defineCommand as defineCommand55 } from "citty";
6006
- var creativesCommand2 = defineCommand55({
6087
+ import { defineCommand as defineCommand56 } from "citty";
6088
+ var creativesCommand2 = defineCommand56({
6007
6089
  meta: {
6008
6090
  name: "creatives",
6009
6091
  description: `List ad creatives in an account, or fetch a single creative by ID.
@@ -6047,7 +6129,7 @@ Examples:
6047
6129
  });
6048
6130
 
6049
6131
  // src/commands/ads/meta/insights.ts
6050
- import { defineCommand as defineCommand56 } from "citty";
6132
+ import { defineCommand as defineCommand57 } from "citty";
6051
6133
 
6052
6134
  // src/commands/ads/meta/presets.ts
6053
6135
  var INSIGHTS_INTENTS = {
@@ -6252,7 +6334,7 @@ function sortRowsBySpendDesc(rows) {
6252
6334
  return sb - sa;
6253
6335
  });
6254
6336
  }
6255
- var insightsCommand = defineCommand56({
6337
+ var insightsCommand = defineCommand57({
6256
6338
  meta: {
6257
6339
  name: "insights",
6258
6340
  description: `Performance reporting \u2014 the main Meta tool for AI agents.
@@ -6353,8 +6435,8 @@ Async is automatic for heavy queries; pass --async to force it, or --no-async to
6353
6435
  });
6354
6436
 
6355
6437
  // src/commands/ads/meta/pixels.ts
6356
- import { defineCommand as defineCommand57 } from "citty";
6357
- var pixelsCommand = defineCommand57({
6438
+ import { defineCommand as defineCommand58 } from "citty";
6439
+ var pixelsCommand = defineCommand58({
6358
6440
  meta: {
6359
6441
  name: "pixels",
6360
6442
  description: `List Meta Pixels for an ad account, or fetch firing stats for one pixel.
@@ -6425,7 +6507,7 @@ function emit(data, args) {
6425
6507
 
6426
6508
  // src/commands/ads/meta/preview.ts
6427
6509
  import { writeFileSync as writeFileSync3 } from "fs";
6428
- import { defineCommand as defineCommand58 } from "citty";
6510
+ import { defineCommand as defineCommand59 } from "citty";
6429
6511
  var VALID_AD_FORMATS = [
6430
6512
  "DESKTOP_FEED_STANDARD",
6431
6513
  "MOBILE_FEED_STANDARD",
@@ -6459,7 +6541,7 @@ var VALID_AD_FORMATS = [
6459
6541
  "MARKETPLACE_MOBILE",
6460
6542
  "BIZ_DISCO_FEED_MOBILE"
6461
6543
  ];
6462
- var previewCommand = defineCommand58({
6544
+ var previewCommand = defineCommand59({
6463
6545
  meta: {
6464
6546
  name: "preview",
6465
6547
  description: `Generate a Meta-hosted preview iframe for a creative or ad. Returns iframe HTML which you
@@ -6506,7 +6588,7 @@ Examples:
6506
6588
  });
6507
6589
 
6508
6590
  // src/commands/ads/meta/index.ts
6509
- var metaCommand = defineCommand59({
6591
+ var metaCommand = defineCommand60({
6510
6592
  meta: {
6511
6593
  name: "meta",
6512
6594
  description: `Meta Marketing API \u2014 AI-first command surface (Facebook + Instagram ads).
@@ -6558,10 +6640,10 @@ Audit & review:
6558
6640
  });
6559
6641
 
6560
6642
  // src/commands/ads/x/index.ts
6561
- import { defineCommand as defineCommand76 } from "citty";
6643
+ import { defineCommand as defineCommand77 } from "citty";
6562
6644
 
6563
6645
  // src/commands/ads/x/accounts.ts
6564
- import { defineCommand as defineCommand60 } from "citty";
6646
+ import { defineCommand as defineCommand61 } from "citty";
6565
6647
  registerSchema({
6566
6648
  command: "ads.x.accounts",
6567
6649
  description: "List all accessible X Ads accounts. Returns accounts with id (base36), name, approval_status, timezone, currency. Run this first to find account IDs for other commands.",
@@ -6589,7 +6671,7 @@ function handleAccountsError2(err) {
6589
6671
  writeAdsJson({ ok: false, error: { code: "NETWORK_ERROR", message: "Unexpected error" } });
6590
6672
  process.exit(1);
6591
6673
  }
6592
- var accountsCommand4 = defineCommand60({
6674
+ var accountsCommand4 = defineCommand61({
6593
6675
  meta: {
6594
6676
  name: "accounts",
6595
6677
  description: `List accessible X Ads accounts. Returns account IDs needed for all other commands.
@@ -6629,7 +6711,7 @@ Examples:
6629
6711
  });
6630
6712
 
6631
6713
  // src/commands/ads/x/active-entities.ts
6632
- import { defineCommand as defineCommand61 } from "citty";
6714
+ import { defineCommand as defineCommand62 } from "citty";
6633
6715
 
6634
6716
  // src/commands/ads/x/error-parser.ts
6635
6717
  function mapXErrorCode(message) {
@@ -6780,7 +6862,7 @@ function parseCsv(v) {
6780
6862
  const parts = v.split(",").map((s) => s.trim()).filter(Boolean);
6781
6863
  return parts.length > 0 ? parts : void 0;
6782
6864
  }
6783
- var activeEntitiesCommand = defineCommand61({
6865
+ var activeEntitiesCommand = defineCommand62({
6784
6866
  meta: {
6785
6867
  name: "active-entities",
6786
6868
  description: `List entities with metric activity in a time range.
@@ -6838,7 +6920,7 @@ Examples:
6838
6920
  });
6839
6921
 
6840
6922
  // src/commands/ads/x/audiences.ts
6841
- import { defineCommand as defineCommand62 } from "citty";
6923
+ import { defineCommand as defineCommand63 } from "citty";
6842
6924
  registerSchema({
6843
6925
  command: "ads.x.audiences",
6844
6926
  description: "List custom audiences for an X Ads account. Returns id, name, audience_size, audience_type, targetable status. Audiences need 100+ active users in the past 90 days to be targetable.",
@@ -6847,7 +6929,7 @@ registerSchema({
6847
6929
  "no-cache": { type: "boolean", description: "Skip cache", required: false }
6848
6930
  }
6849
6931
  });
6850
- var audiencesCommand2 = defineCommand62({
6932
+ var audiencesCommand2 = defineCommand63({
6851
6933
  meta: {
6852
6934
  name: "audiences",
6853
6935
  description: `List X Ads custom audiences.
@@ -6896,7 +6978,7 @@ Examples:
6896
6978
  });
6897
6979
 
6898
6980
  // src/commands/ads/x/campaigns.ts
6899
- import { defineCommand as defineCommand63 } from "citty";
6981
+ import { defineCommand as defineCommand64 } from "citty";
6900
6982
 
6901
6983
  // src/commands/ads/x/run-list.ts
6902
6984
  function buildCleanParams(opts) {
@@ -6959,7 +7041,7 @@ registerSchema({
6959
7041
  "no-cache": { type: "boolean", description: "Skip cache", required: false }
6960
7042
  }
6961
7043
  });
6962
- var campaignsCommand3 = defineCommand63({
7044
+ var campaignsCommand3 = defineCommand64({
6963
7045
  meta: {
6964
7046
  name: "campaigns",
6965
7047
  description: `List X Ads campaigns. Returns budget, schedule, funding instrument, status.
@@ -7001,7 +7083,7 @@ Examples:
7001
7083
  });
7002
7084
 
7003
7085
  // src/commands/ads/x/cards.ts
7004
- import { defineCommand as defineCommand64 } from "citty";
7086
+ import { defineCommand as defineCommand65 } from "citty";
7005
7087
  registerSchema({
7006
7088
  command: "ads.x.cards",
7007
7089
  description: "List website cards, video cards, and carousels for an X Ads account.",
@@ -7010,7 +7092,7 @@ registerSchema({
7010
7092
  "no-cache": { type: "boolean", description: "Skip cache", required: false }
7011
7093
  }
7012
7094
  });
7013
- var cardsCommand = defineCommand64({
7095
+ var cardsCommand = defineCommand65({
7014
7096
  meta: {
7015
7097
  name: "cards",
7016
7098
  description: `List X Ads cards (rich creatives).
@@ -7059,7 +7141,7 @@ Examples:
7059
7141
  });
7060
7142
 
7061
7143
  // src/commands/ads/x/funding.ts
7062
- import { defineCommand as defineCommand65 } from "citty";
7144
+ import { defineCommand as defineCommand66 } from "citty";
7063
7145
  registerSchema({
7064
7146
  command: "ads.x.funding",
7065
7147
  description: "List funding instruments for an X Ads account. Returns id, type, currency, credit_limit_local_micro, funded_amount_local_micro, status. Falls back to BAKER_X_ADS_ACCOUNT_ID env var.",
@@ -7068,7 +7150,7 @@ registerSchema({
7068
7150
  "no-cache": { type: "boolean", description: "Skip cache", required: false }
7069
7151
  }
7070
7152
  });
7071
- var fundingCommand = defineCommand65({
7153
+ var fundingCommand = defineCommand66({
7072
7154
  meta: {
7073
7155
  name: "funding",
7074
7156
  description: `List funding instruments for an X Ads account.
@@ -7117,7 +7199,7 @@ Examples:
7117
7199
  });
7118
7200
 
7119
7201
  // src/commands/ads/x/line-items.ts
7120
- import { defineCommand as defineCommand66 } from "citty";
7202
+ import { defineCommand as defineCommand67 } from "citty";
7121
7203
  registerSchema({
7122
7204
  command: "ads.x.lineItems",
7123
7205
  description: "List line items (ad groups) for an X Ads account. Returns bid, product_type, objective, placements, schedule. Filter by campaign-ids or line-item-ids (CSV).",
@@ -7129,7 +7211,7 @@ registerSchema({
7129
7211
  "no-cache": { type: "boolean", description: "Skip cache", required: false }
7130
7212
  }
7131
7213
  });
7132
- var lineItemsCommand = defineCommand66({
7214
+ var lineItemsCommand = defineCommand67({
7133
7215
  meta: {
7134
7216
  name: "line-items",
7135
7217
  description: `List X Ads line items (ad groups).
@@ -7170,7 +7252,7 @@ Examples:
7170
7252
  });
7171
7253
 
7172
7254
  // src/commands/ads/x/media.ts
7173
- import { defineCommand as defineCommand67 } from "citty";
7255
+ import { defineCommand as defineCommand68 } from "citty";
7174
7256
  registerSchema({
7175
7257
  command: "ads.x.media",
7176
7258
  description: "List media assets in the X Ads media library (images, GIFs, videos). Filter by media-type (IMAGE, GIF, VIDEO).",
@@ -7180,7 +7262,7 @@ registerSchema({
7180
7262
  "no-cache": { type: "boolean", description: "Skip cache", required: false }
7181
7263
  }
7182
7264
  });
7183
- var mediaCommand = defineCommand67({
7265
+ var mediaCommand = defineCommand68({
7184
7266
  meta: {
7185
7267
  name: "media",
7186
7268
  description: `List media assets in the X Ads media library.
@@ -7232,7 +7314,7 @@ Examples:
7232
7314
  });
7233
7315
 
7234
7316
  // src/commands/ads/x/promoted-tweets.ts
7235
- import { defineCommand as defineCommand68 } from "citty";
7317
+ import { defineCommand as defineCommand69 } from "citty";
7236
7318
  registerSchema({
7237
7319
  command: "ads.x.promotedTweets",
7238
7320
  description: "List promoted tweets for an X Ads account. Returns id, line_item_id, tweet_id, approval_status. Filter by line-item-ids (CSV).",
@@ -7243,7 +7325,7 @@ registerSchema({
7243
7325
  "no-cache": { type: "boolean", description: "Skip cache", required: false }
7244
7326
  }
7245
7327
  });
7246
- var promotedTweetsCommand = defineCommand68({
7328
+ var promotedTweetsCommand = defineCommand69({
7247
7329
  meta: {
7248
7330
  name: "promoted-tweets",
7249
7331
  description: `List X Ads promoted tweets.
@@ -7297,11 +7379,11 @@ Examples:
7297
7379
  });
7298
7380
 
7299
7381
  // src/commands/ads/x/stats/index.ts
7300
- import { defineCommand as defineCommand73 } from "citty";
7382
+ import { defineCommand as defineCommand74 } from "citty";
7301
7383
 
7302
7384
  // src/commands/ads/x/stats/job.ts
7303
7385
  import { gunzipSync } from "zlib";
7304
- import { defineCommand as defineCommand69 } from "citty";
7386
+ import { defineCommand as defineCommand70 } from "citty";
7305
7387
  var POLL_INTERVAL_MS2 = 1e4;
7306
7388
  var DEADLINE_MS = 12 * 60 * 1e3;
7307
7389
  var RESULT_CACHE_TTL_MS = 6 * 60 * 60 * 1e3;
@@ -7371,7 +7453,7 @@ async function pollUntilDone(accountId, jobId) {
7371
7453
  function buildCacheKey(body) {
7372
7454
  return `stats-job:${JSON.stringify(body)}`;
7373
7455
  }
7374
- var statsJobCommand = defineCommand69({
7456
+ var statsJobCommand = defineCommand70({
7375
7457
  meta: {
7376
7458
  name: "job",
7377
7459
  description: `Async X Ads stats job, sync from the CLI's perspective. Creates \u2192 polls \u2192 downloads \u2192 returns.
@@ -7476,7 +7558,7 @@ For fine-grained control (don't wait, poll yourself), use:
7476
7558
  });
7477
7559
 
7478
7560
  // src/commands/ads/x/stats/job-create.ts
7479
- import { defineCommand as defineCommand70 } from "citty";
7561
+ import { defineCommand as defineCommand71 } from "citty";
7480
7562
  registerSchema({
7481
7563
  command: "ads.x.statsJobCreate",
7482
7564
  description: "Create an asynchronous X Ads stats job (range up to 90 days non-segmented, 45 days segmented). Returns a job id; poll with `stats job-status`. Times must be ISO 8601 hour-aligned.",
@@ -7499,7 +7581,7 @@ function parseCsv3(v) {
7499
7581
  const parts = v.split(",").map((s) => s.trim()).filter(Boolean);
7500
7582
  return parts.length > 0 ? parts : void 0;
7501
7583
  }
7502
- var statsJobCreateCommand = defineCommand70({
7584
+ var statsJobCreateCommand = defineCommand71({
7503
7585
  meta: {
7504
7586
  name: "job-create",
7505
7587
  description: `Create an async X Ads stats job (up to 90 days, supports segmentation).
@@ -7562,7 +7644,7 @@ Examples:
7562
7644
  });
7563
7645
 
7564
7646
  // src/commands/ads/x/stats/job-status.ts
7565
- import { defineCommand as defineCommand71 } from "citty";
7647
+ import { defineCommand as defineCommand72 } from "citty";
7566
7648
  registerSchema({
7567
7649
  command: "ads.x.statsJobStatus",
7568
7650
  description: "Check the status of one or more X Ads stats jobs. Returns status (PROCESSING|SUCCESS|FAILED) and a downloadable url when SUCCESS. Pass --job-id or --job-ids (CSV).",
@@ -7572,7 +7654,7 @@ registerSchema({
7572
7654
  "job-ids": { type: "string", description: "CSV of job IDs", required: false }
7573
7655
  }
7574
7656
  });
7575
- var statsJobStatusCommand = defineCommand71({
7657
+ var statsJobStatusCommand = defineCommand72({
7576
7658
  meta: {
7577
7659
  name: "job-status",
7578
7660
  description: `Poll the status of an async X Ads stats job.
@@ -7613,7 +7695,7 @@ Examples:
7613
7695
  });
7614
7696
 
7615
7697
  // src/commands/ads/x/stats/sync.ts
7616
- import { defineCommand as defineCommand72 } from "citty";
7698
+ import { defineCommand as defineCommand73 } from "citty";
7617
7699
 
7618
7700
  // src/commands/ads/x/presets.ts
7619
7701
  var X_STATS_PRESETS = [
@@ -7772,7 +7854,7 @@ async function runSync(args, q) {
7772
7854
  process.exit(1);
7773
7855
  }
7774
7856
  }
7775
- var statsSyncCommand = defineCommand72({
7857
+ var statsSyncCommand = defineCommand73({
7776
7858
  meta: {
7777
7859
  name: "sync",
7778
7860
  description: `Synchronous X Ads analytics (max 7-day window).
@@ -7815,7 +7897,7 @@ Examples:
7815
7897
  });
7816
7898
 
7817
7899
  // src/commands/ads/x/stats/index.ts
7818
- var statsCommand = defineCommand73({
7900
+ var statsCommand = defineCommand74({
7819
7901
  meta: {
7820
7902
  name: "stats",
7821
7903
  description: `X Ads analytics. Sync (\u22647 days, no segmentation) or async jobs (\u226490 days, segmentable).
@@ -7843,7 +7925,7 @@ Examples:
7843
7925
  });
7844
7926
 
7845
7927
  // src/commands/ads/x/targeting-constants.ts
7846
- import { defineCommand as defineCommand74 } from "citty";
7928
+ import { defineCommand as defineCommand75 } from "citty";
7847
7929
  var ALLOWED_CONSTANTS = [
7848
7930
  "locations",
7849
7931
  "interests",
@@ -7871,7 +7953,7 @@ registerSchema({
7871
7953
  "no-cache": { type: "boolean", description: "Skip cache", required: false }
7872
7954
  }
7873
7955
  });
7874
- var targetingConstantsCommand = defineCommand74({
7956
+ var targetingConstantsCommand = defineCommand75({
7875
7957
  meta: {
7876
7958
  name: "targeting-constants",
7877
7959
  description: `Lookup X Ads targeting constants.
@@ -7921,7 +8003,7 @@ Examples:
7921
8003
  });
7922
8004
 
7923
8005
  // src/commands/ads/x/targeting-criteria.ts
7924
- import { defineCommand as defineCommand75 } from "citty";
8006
+ import { defineCommand as defineCommand76 } from "citty";
7925
8007
  registerSchema({
7926
8008
  command: "ads.x.targetingCriteria",
7927
8009
  description: "List targeting criteria attached to line items in an X Ads account. Returns targeting_type, targeting_value, name, operator_type per criterion. Filter by line-item-ids.",
@@ -7931,7 +8013,7 @@ registerSchema({
7931
8013
  "no-cache": { type: "boolean", description: "Skip cache", required: false }
7932
8014
  }
7933
8015
  });
7934
- var targetingCriteriaCommand = defineCommand75({
8016
+ var targetingCriteriaCommand = defineCommand76({
7935
8017
  meta: {
7936
8018
  name: "targeting-criteria",
7937
8019
  description: `List targeting criteria attached to line items.
@@ -7982,7 +8064,7 @@ Examples:
7982
8064
  });
7983
8065
 
7984
8066
  // src/commands/ads/x/index.ts
7985
- var xCommand = defineCommand76({
8067
+ var xCommand = defineCommand77({
7986
8068
  meta: {
7987
8069
  name: "x",
7988
8070
  description: `X (Twitter) Ads commands. Read campaigns, line items, promoted tweets, creatives, audiences, and analytics.
@@ -8020,7 +8102,7 @@ The CLI auto-detects --account-id when exactly one X Ads account is connected, o
8020
8102
  });
8021
8103
 
8022
8104
  // src/commands/ads/index.ts
8023
- var adsCommand = defineCommand77({
8105
+ var adsCommand = defineCommand78({
8024
8106
  meta: {
8025
8107
  name: "ads",
8026
8108
  description: `Ad platform commands. Each platform exposes its own native command surface \u2014 no forced parity.
@@ -8053,8 +8135,8 @@ Examples:
8053
8135
  import { defineCommand as defineCommand86 } from "citty";
8054
8136
 
8055
8137
  // src/commands/canvas/catalog.ts
8056
- import { defineCommand as defineCommand78 } from "citty";
8057
- var catalogCommand = defineCommand78({
8138
+ import { defineCommand as defineCommand79 } from "citty";
8139
+ var catalogCommand = defineCommand79({
8058
8140
  meta: {
8059
8141
  name: "catalog",
8060
8142
  description: "Print the agent-facing node catalog (JSON Schema). Includes every registered node grouped by category."
@@ -8066,227 +8148,10 @@ var catalogCommand = defineCommand78({
8066
8148
  }
8067
8149
  });
8068
8150
 
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
-
8286
8151
  // src/commands/canvas/inspect.ts
8287
8152
  import { execFile } from "child_process";
8288
- import { readdir as readdir2, readFile as readFile2, stat } from "fs/promises";
8289
- import path2 from "path";
8153
+ import { readdir, readFile, stat } from "fs/promises";
8154
+ import path from "path";
8290
8155
  import { promisify } from "util";
8291
8156
  import { defineCommand as defineCommand80 } from "citty";
8292
8157
  var execFileAsync = promisify(execFile);
@@ -8304,7 +8169,7 @@ var inspectCommand = defineCommand80({
8304
8169
  }
8305
8170
  },
8306
8171
  async run({ args }) {
8307
- const outputsDir = path2.resolve(String(args["outputs-dir"] ?? "canvas"));
8172
+ const outputsDir = path.resolve(String(args["outputs-dir"] ?? "canvas"));
8308
8173
  const runArg = String(args.run);
8309
8174
  const runDir = await resolveRunDir(runArg, outputsDir);
8310
8175
  const manifest = await loadManifest(runDir);
@@ -8316,7 +8181,7 @@ var inspectCommand = defineCommand80({
8316
8181
  }
8317
8182
  const summary = {
8318
8183
  ok: true,
8319
- run_id: manifest.run_id ?? path2.basename(runDir),
8184
+ run_id: manifest.run_id ?? path.basename(runDir),
8320
8185
  run_dir: runDir,
8321
8186
  stats: manifest.stats ?? null,
8322
8187
  output: manifest.output ?? null,
@@ -8329,20 +8194,20 @@ var inspectCommand = defineCommand80({
8329
8194
  }
8330
8195
  });
8331
8196
  async function resolveRunDir(run, outputsDir) {
8332
- if (path2.isAbsolute(run)) {
8197
+ if (path.isAbsolute(run)) {
8333
8198
  const s2 = await stat(run).catch(() => null);
8334
8199
  if (s2?.isDirectory()) return run;
8335
8200
  throw new Error(`inspect: ${run} is not a directory`);
8336
8201
  }
8337
- const candidate = path2.join(outputsDir, run);
8202
+ const candidate = path.join(outputsDir, run);
8338
8203
  const s = await stat(candidate).catch(() => null);
8339
8204
  if (s?.isDirectory()) return candidate;
8340
8205
  throw new Error(`inspect: no run directory at ${candidate}`);
8341
8206
  }
8342
8207
  async function loadManifest(runDir) {
8343
- const manifestPath = path2.join(runDir, "manifest.json");
8208
+ const manifestPath = path.join(runDir, "manifest.json");
8344
8209
  try {
8345
- const raw = await readFile2(manifestPath, "utf-8");
8210
+ const raw = await readFile(manifestPath, "utf-8");
8346
8211
  return JSON.parse(raw);
8347
8212
  } catch {
8348
8213
  return {};
@@ -8350,9 +8215,9 @@ async function loadManifest(runDir) {
8350
8215
  }
8351
8216
  async function listRunFiles(runDir) {
8352
8217
  const out = [];
8353
- const names = await readdir2(runDir);
8218
+ const names = await readdir(runDir);
8354
8219
  for (const name of names) {
8355
- const abs = path2.join(runDir, name);
8220
+ const abs = path.join(runDir, name);
8356
8221
  const s = await stat(abs).catch(() => null);
8357
8222
  if (!s?.isFile()) continue;
8358
8223
  out.push({ name, path: abs, size: s.size });
@@ -8397,8 +8262,8 @@ async function probeDuration(filePath) {
8397
8262
  }
8398
8263
 
8399
8264
  // src/commands/canvas/run.ts
8400
- import { readFile as readFile3 } from "fs/promises";
8401
- import path5 from "path";
8265
+ import { readFile as readFile2 } from "fs/promises";
8266
+ import path4 from "path";
8402
8267
  import { defineCommand as defineCommand81 } from "citty";
8403
8268
 
8404
8269
  // src/commands/canvas/placeholders.ts
@@ -8418,7 +8283,7 @@ function unsuppliedPlaceholderAssets(canvas) {
8418
8283
  }
8419
8284
 
8420
8285
  // src/commands/canvas/resolve-paths.ts
8421
- import path3 from "path";
8286
+ import path2 from "path";
8422
8287
  function resolveRelativeCanvasPaths(canvas, baseDir) {
8423
8288
  if (!canvas || typeof canvas !== "object") return canvas;
8424
8289
  const c = canvas;
@@ -8431,37 +8296,37 @@ function resolveNode(node, baseDir) {
8431
8296
  const params = n.params;
8432
8297
  if (!params || typeof params !== "object") return node;
8433
8298
  if (n.type === "ingest" && params.source === "path" && isResolvableRelative(params.path)) {
8434
- return { ...node, params: { ...params, path: path3.resolve(baseDir, params.path) } };
8299
+ return { ...node, params: { ...params, path: path2.resolve(baseDir, params.path) } };
8435
8300
  }
8436
8301
  if (n.type === "hyperframe_render" && isResolvableRelative(params.composition)) {
8437
- return { ...node, params: { ...params, composition: path3.resolve(baseDir, params.composition) } };
8302
+ return { ...node, params: { ...params, composition: path2.resolve(baseDir, params.composition) } };
8438
8303
  }
8439
8304
  return node;
8440
8305
  }
8441
8306
  function isResolvableRelative(value) {
8442
- return typeof value === "string" && value.length > 0 && !value.includes("[TODO") && !path3.isAbsolute(value);
8307
+ return typeof value === "string" && value.length > 0 && !value.includes("[TODO") && !path2.isAbsolute(value);
8443
8308
  }
8444
8309
 
8445
8310
  // src/commands/canvas/run-retention.ts
8446
8311
  import { rm } from "fs/promises";
8447
- import path4 from "path";
8312
+ import path3 from "path";
8448
8313
  function runDirsToPrune(entries, keep, currentRunId) {
8449
8314
  const runs = entries.filter((e) => /^r_[0-9A-Za-z]+$/.test(e) && e !== currentRunId).sort();
8450
8315
  if (keep <= 0) return runs;
8451
8316
  return runs.slice(0, Math.max(0, runs.length - keep));
8452
8317
  }
8453
8318
  async function pruneOldRuns(outputsDir, keep, currentRunId, log) {
8454
- const { readdir: readdir4 } = await import("fs/promises");
8319
+ const { readdir: readdir3 } = await import("fs/promises");
8455
8320
  let entries;
8456
8321
  try {
8457
- entries = await readdir4(outputsDir);
8322
+ entries = await readdir3(outputsDir);
8458
8323
  } catch {
8459
8324
  return;
8460
8325
  }
8461
8326
  const toPrune = runDirsToPrune(entries, keep, currentRunId);
8462
8327
  if (toPrune.length === 0) return;
8463
8328
  for (const dir of toPrune) {
8464
- await rm(path4.join(outputsDir, dir), { recursive: true, force: true }).catch(
8329
+ await rm(path3.join(outputsDir, dir), { recursive: true, force: true }).catch(
8465
8330
  (e) => log(`[prune ] could not remove ${dir}: ${e.message}`)
8466
8331
  );
8467
8332
  }
@@ -8483,8 +8348,8 @@ var runCommand = defineCommand81({
8483
8348
  }
8484
8349
  },
8485
8350
  async run({ args }) {
8486
- const filePath = path5.resolve(String(args.file));
8487
- const raw = await readFile3(filePath, "utf8");
8351
+ const filePath = path4.resolve(String(args.file));
8352
+ const raw = await readFile2(filePath, "utf8");
8488
8353
  let parsed;
8489
8354
  try {
8490
8355
  parsed = JSON.parse(raw);
@@ -8494,7 +8359,7 @@ var runCommand = defineCommand81({
8494
8359
  `);
8495
8360
  process.exit(2);
8496
8361
  }
8497
- parsed = resolveRelativeCanvasPaths(parsed, path5.dirname(filePath));
8362
+ parsed = resolveRelativeCanvasPaths(parsed, path4.dirname(filePath));
8498
8363
  const pending = unsuppliedPlaceholderAssets(parsed);
8499
8364
  if (pending.length > 0) {
8500
8365
  process.stderr.write(
@@ -8528,7 +8393,7 @@ var runCommand = defineCommand81({
8528
8393
  });
8529
8394
  const keepRuns = args["keep-runs"] !== void 0 ? Number(args["keep-runs"]) : void 0;
8530
8395
  if (keepRuns !== void 0 && Number.isFinite(keepRuns)) {
8531
- const outputsDir = args["outputs-dir"] ? path5.resolve(String(args["outputs-dir"])) : path5.resolve("canvas");
8396
+ const outputsDir = args["outputs-dir"] ? path4.resolve(String(args["outputs-dir"])) : path4.resolve("canvas");
8532
8397
  await pruneOldRuns(outputsDir, keepRuns, result.run_id, (line) => process.stdout.write(`${line}
8533
8398
  `));
8534
8399
  }
@@ -8563,8 +8428,8 @@ var runCommand = defineCommand81({
8563
8428
  });
8564
8429
 
8565
8430
  // src/commands/canvas/scaffold-static-ad.ts
8566
- import { readFile as readFile4, writeFile } from "fs/promises";
8567
- import path6 from "path";
8431
+ import { readFile as readFile3, writeFile } from "fs/promises";
8432
+ import path5 from "path";
8568
8433
  import { defineCommand as defineCommand82 } from "citty";
8569
8434
 
8570
8435
  // src/engine/scaffold/staticAd.ts
@@ -8778,7 +8643,7 @@ var SELECT_SYSTEM = 'You identify the MAIN, identity-critical visual elements of
8778
8643
  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.';
8779
8644
  async function loadAssetText(ref, label) {
8780
8645
  const r = ref;
8781
- if (typeof r?.path === "string") return readFile4(r.path, "utf8");
8646
+ if (typeof r?.path === "string") return readFile3(r.path, "utf8");
8782
8647
  if (typeof r?.url === "string") {
8783
8648
  const res = await fetch(r.url);
8784
8649
  if (!res.ok) throw new Error(`failed to fetch ${label} (${res.status})`);
@@ -8901,10 +8766,10 @@ var scaffoldStaticAdCommand = defineCommand82({
8901
8766
  "skip-font": { type: "boolean", description: "Skip the brand-font \u2192 type-specimen slot" }
8902
8767
  },
8903
8768
  async run({ args }) {
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");
8769
+ const imagePath = path5.resolve(String(args.file));
8770
+ const outPath = args.out ? path5.resolve(String(args.out)) : path5.join(path5.dirname(imagePath), "static-ad.canvas.json");
8771
+ const outDir = path5.dirname(outPath);
8772
+ const blueprintPath = path5.join(outDir, "prompt.json");
8908
8773
  const { describeModel, selectModel, layoutModel, genModel } = resolveModels(args);
8909
8774
  const describeCanvas = buildDescribeCanvas(
8910
8775
  imagePath,
@@ -8961,7 +8826,7 @@ var scaffoldStaticAdCommand = defineCommand82({
8961
8826
  run_estimated_credits: validation.estimatedCredits
8962
8827
  },
8963
8828
  checklist: {
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.`,
8829
+ 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.`,
8965
8830
  assets_to_supply: report.elements,
8966
8831
  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)",
8967
8832
  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."
@@ -8976,13 +8841,13 @@ var scaffoldStaticAdCommand = defineCommand82({
8976
8841
  });
8977
8842
 
8978
8843
  // src/commands/canvas/scaffold-video.ts
8979
- import { cp, mkdir, readFile as readFile7, writeFile as writeFile2 } from "fs/promises";
8980
- import path9 from "path";
8844
+ import { cp, mkdir, readFile as readFile6, writeFile as writeFile2 } from "fs/promises";
8845
+ import path8 from "path";
8981
8846
  import { defineCommand as defineCommand83 } from "citty";
8982
8847
 
8983
8848
  // src/engine/nodes/local/lib/sceneDetect.ts
8984
8849
  import { execFile as execFile2 } from "child_process";
8985
- import { mkdtemp, readdir as readdir3, readFile as readFile5, rm as rm2 } from "fs/promises";
8850
+ import { mkdtemp, readdir as readdir2, readFile as readFile4, rm as rm2 } from "fs/promises";
8986
8851
  import { tmpdir } from "os";
8987
8852
  import { join as join2 } from "path";
8988
8853
  import { promisify as promisify2 } from "util";
@@ -9046,9 +8911,9 @@ async function runSceneDetectOnce(filePath, threshold, minSceneLenS, timeoutMs)
9046
8911
  ],
9047
8912
  { encoding: "utf-8", maxBuffer: 32 * 1024 * 1024, timeout: timeoutMs }
9048
8913
  );
9049
- const csvName = (await readdir3(outDir)).find((f) => f.toLowerCase().endsWith(".csv"));
8914
+ const csvName = (await readdir2(outDir)).find((f) => f.toLowerCase().endsWith(".csv"));
9050
8915
  if (!csvName) return [];
9051
- return parsePySceneDetectCsvCuts(await readFile5(join2(outDir, csvName), "utf-8"));
8916
+ return parsePySceneDetectCsvCuts(await readFile4(join2(outDir, csvName), "utf-8"));
9052
8917
  } finally {
9053
8918
  await rm2(outDir, { recursive: true, force: true });
9054
8919
  }
@@ -11593,23 +11458,23 @@ function videoReport(input, elementsInput) {
11593
11458
 
11594
11459
  // src/commands/canvas/composition-path.ts
11595
11460
  import { existsSync as existsSync3 } from "fs";
11596
- import path7 from "path";
11461
+ import path6 from "path";
11597
11462
  function resolveShippedCanvasDir(name, startDir, exists = existsSync3, maxDepth = 8) {
11598
- const rel = path7.join("canvas", name);
11463
+ const rel = path6.join("canvas", name);
11599
11464
  let dir = startDir;
11600
11465
  for (let i = 0; i < maxDepth; i++) {
11601
- const candidate = path7.join(dir, rel);
11602
- if (exists(path7.join(candidate, "meta.json"))) return candidate;
11603
- const parent = path7.dirname(dir);
11466
+ const candidate = path6.join(dir, rel);
11467
+ if (exists(path6.join(candidate, "meta.json"))) return candidate;
11468
+ const parent = path6.dirname(dir);
11604
11469
  if (parent === dir) break;
11605
11470
  dir = parent;
11606
11471
  }
11607
- return path7.resolve(startDir, "../../../", rel);
11472
+ return path6.resolve(startDir, "../../../", rel);
11608
11473
  }
11609
11474
 
11610
11475
  // src/commands/canvas/gitignore.ts
11611
- import { appendFile, readFile as readFile6 } from "fs/promises";
11612
- import path8 from "path";
11476
+ import { appendFile, readFile as readFile5 } from "fs/promises";
11477
+ import path7 from "path";
11613
11478
  function missingGitignoreEntries(existing, entries) {
11614
11479
  const present = new Set(
11615
11480
  existing.split("\n").map((l) => l.trim().replace(/\/+$/, "")).filter((l) => l.length > 0 && !l.startsWith("#"))
@@ -11617,10 +11482,10 @@ function missingGitignoreEntries(existing, entries) {
11617
11482
  return entries.filter((e) => !present.has(e.trim().replace(/\/+$/, "")));
11618
11483
  }
11619
11484
  async function ensureGitignore(dir, entries) {
11620
- const file = path8.join(dir, ".gitignore");
11485
+ const file = path7.join(dir, ".gitignore");
11621
11486
  let existing;
11622
11487
  try {
11623
- existing = await readFile6(file, "utf8");
11488
+ existing = await readFile5(file, "utf8");
11624
11489
  } catch {
11625
11490
  return;
11626
11491
  }
@@ -11659,7 +11524,7 @@ ONE PERSON, MULTIPLE LOOKS: if a single individual plays MULTIPLE personas or wa
11659
11524
  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.`;
11660
11525
  async function loadAssetText2(ref, label) {
11661
11526
  const r = ref;
11662
- if (typeof r?.path === "string") return readFile7(r.path, "utf8");
11527
+ if (typeof r?.path === "string") return readFile6(r.path, "utf8");
11663
11528
  if (typeof r?.url === "string") {
11664
11529
  const res = await fetch(r.url);
11665
11530
  if (!res.ok) throw new Error(`failed to fetch ${label} (${res.status})`);
@@ -11678,7 +11543,7 @@ async function loadTranscriptBestEffort(ref) {
11678
11543
  async function stageCaptions(outDir, transcript) {
11679
11544
  const text = transcript?.trim();
11680
11545
  if (!text || text === "[]") return {};
11681
- const compositionPath = path9.join(outDir, "tiktok-captions-composition");
11546
+ const compositionPath = path8.join(outDir, "tiktok-captions-composition");
11682
11547
  await cp(SHIPPED_CAPTIONS_DIR, compositionPath, { recursive: true });
11683
11548
  return { compositionPath };
11684
11549
  }
@@ -11840,11 +11705,11 @@ var scaffoldVideoCommand = defineCommand83({
11840
11705
  }
11841
11706
  },
11842
11707
  async run({ args }) {
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");
11708
+ const videoPath = path8.resolve(String(args.file));
11709
+ const base = path8.basename(videoPath, path8.extname(videoPath));
11710
+ const outPath = args.out ? path8.resolve(String(args.out)) : path8.join(path8.dirname(videoPath), `${base}.video.canvas.json`);
11711
+ const outDir = path8.dirname(outPath);
11712
+ const blueprintPath = path8.join(outDir, "prompt.json");
11848
11713
  const frames = args.frames === "reuse" ? "reuse" : "generate";
11849
11714
  const maxScenes = args["max-scenes"] ? Number(args["max-scenes"]) : void 0;
11850
11715
  if (Number.isFinite(maxScenes)) {
@@ -11867,11 +11732,11 @@ var scaffoldVideoCommand = defineCommand83({
11867
11732
  const annotated = annotateBlueprintWithElements(blueprint, elements);
11868
11733
  await writeFile2(blueprintPath, `${JSON.stringify(annotated, null, 2)}
11869
11734
  `, "utf8");
11870
- const compositionDest = path9.join(outDir, "video-overlay-composition");
11735
+ const compositionDest = path8.join(outDir, "video-overlay-composition");
11871
11736
  await cp(SHIPPED_COMPOSITION_DIR, compositionDest, { recursive: true });
11872
- const indexPath = path9.join(compositionDest, "index.html");
11737
+ const indexPath = path8.join(compositionDest, "index.html");
11873
11738
  const overlayHtml = buildOverlayHtml(blueprint);
11874
- const indexHtml = await readFile7(indexPath, "utf8");
11739
+ const indexHtml = await readFile6(indexPath, "utf8");
11875
11740
  const injected = indexHtml.replace("<!--OVERLAYS-->", () => overlayHtml);
11876
11741
  if (injected === indexHtml && overlayHtml.trim()) {
11877
11742
  fail2(
@@ -11884,9 +11749,9 @@ var scaffoldVideoCommand = defineCommand83({
11884
11749
  const opts = {
11885
11750
  imageModel,
11886
11751
  videoModel,
11887
- overlayCompositionPath: path9.relative(outDir, compositionDest),
11888
- captionsCompositionPath: captions.compositionPath ? path9.relative(outDir, captions.compositionPath) : void 0,
11889
- blueprintPath: path9.relative(outDir, blueprintPath),
11752
+ overlayCompositionPath: path8.relative(outDir, compositionDest),
11753
+ captionsCompositionPath: captions.compositionPath ? path8.relative(outDir, captions.compositionPath) : void 0,
11754
+ blueprintPath: path8.relative(outDir, blueprintPath),
11890
11755
  frames,
11891
11756
  ambient: Boolean(args.ambient),
11892
11757
  ...args.resolution ? { resolution: String(args.resolution) } : {}
@@ -11927,7 +11792,7 @@ var scaffoldVideoCommand = defineCommand83({
11927
11792
  run_estimated_credits: validation.estimatedCredits
11928
11793
  },
11929
11794
  checklist: {
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.`,
11795
+ 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.`,
11931
11796
  recurring_elements_to_supply: report.elements,
11932
11797
  voices_to_confirm: report.dialogue.map((d) => ({
11933
11798
  scene: d.scene,
@@ -11953,8 +11818,8 @@ var scaffoldVideoCommand = defineCommand83({
11953
11818
  });
11954
11819
 
11955
11820
  // src/commands/canvas/set-prompt.ts
11956
- import { readFile as readFile8, writeFile as writeFile3 } from "fs/promises";
11957
- import path10 from "path";
11821
+ import { readFile as readFile7, writeFile as writeFile3 } from "fs/promises";
11822
+ import path9 from "path";
11958
11823
  import { defineCommand as defineCommand84 } from "citty";
11959
11824
  function setNodePrompt(canvas, nodeId, text) {
11960
11825
  const nodes = canvas?.nodes;
@@ -11982,17 +11847,17 @@ var setPromptCommand = defineCommand84({
11982
11847
  "text-file": { type: "string", description: "Read the new prompt from a UTF-8 file (preserves accents/newlines)" }
11983
11848
  },
11984
11849
  async run({ args }) {
11985
- const filePath = path10.resolve(String(args.file));
11850
+ const filePath = path9.resolve(String(args.file));
11986
11851
  let canvas;
11987
11852
  try {
11988
- canvas = JSON.parse(await readFile8(filePath, "utf8"));
11853
+ canvas = JSON.parse(await readFile7(filePath, "utf8"));
11989
11854
  } catch (e) {
11990
11855
  process.stderr.write(`${JSON.stringify({ ok: false, error: { code: "parse", message: String(e) } }, null, 2)}
11991
11856
  `);
11992
11857
  process.exit(2);
11993
11858
  }
11994
11859
  let text;
11995
- if (args["text-file"]) text = await readFile8(path10.resolve(String(args["text-file"])), "utf8");
11860
+ if (args["text-file"]) text = await readFile7(path9.resolve(String(args["text-file"])), "utf8");
11996
11861
  else if (args.text !== void 0) text = String(args.text);
11997
11862
  else {
11998
11863
  process.stderr.write(
@@ -12013,7 +11878,7 @@ var setPromptCommand = defineCommand84({
12013
11878
  process.exit(2);
12014
11879
  return;
12015
11880
  }
12016
- const validation = await validateCanvasDeep(resolveRelativeCanvasPaths(updated, path10.dirname(filePath)), defaultRegistry());
11881
+ const validation = await validateCanvasDeep(resolveRelativeCanvasPaths(updated, path9.dirname(filePath)), defaultRegistry());
12017
11882
  if (!validation.ok) {
12018
11883
  process.stderr.write(`${JSON.stringify({ ok: false, error: { code: "validation", issues: validation.issues } }, null, 2)}
12019
11884
  `);
@@ -12028,8 +11893,8 @@ var setPromptCommand = defineCommand84({
12028
11893
  });
12029
11894
 
12030
11895
  // src/commands/canvas/validate.ts
12031
- import { readFile as readFile9 } from "fs/promises";
12032
- import path11 from "path";
11896
+ import { readFile as readFile8 } from "fs/promises";
11897
+ import path10 from "path";
12033
11898
  import { defineCommand as defineCommand85 } from "citty";
12034
11899
  var validateCommand = defineCommand85({
12035
11900
  meta: {
@@ -12038,8 +11903,8 @@ var validateCommand = defineCommand85({
12038
11903
  },
12039
11904
  args: { file: { type: "positional", required: true, description: "Path to canvas JSON" } },
12040
11905
  async run({ args }) {
12041
- const filePath = path11.resolve(String(args.file));
12042
- const raw = await readFile9(filePath, "utf8");
11906
+ const filePath = path10.resolve(String(args.file));
11907
+ const raw = await readFile8(filePath, "utf8");
12043
11908
  let parsed;
12044
11909
  try {
12045
11910
  parsed = JSON.parse(raw);
@@ -12049,7 +11914,7 @@ var validateCommand = defineCommand85({
12049
11914
  `);
12050
11915
  process.exit(2);
12051
11916
  }
12052
- parsed = resolveRelativeCanvasPaths(parsed, path11.dirname(filePath));
11917
+ parsed = resolveRelativeCanvasPaths(parsed, path10.dirname(filePath));
12053
11918
  const result = await validateCanvasDeep(parsed, defaultRegistry());
12054
11919
  if (!result.ok) {
12055
11920
  process.stderr.write(`${JSON.stringify({ ok: false, issues: result.issues }, null, 2)}
@@ -12086,7 +11951,6 @@ Subcommands:
12086
11951
  baker canvas run <file.json> \u2014 execute the canvas, write outputs to ./canvas/<run_id>/
12087
11952
  baker canvas catalog \u2014 print the agent-facing node + composition catalog (JSON Schema)
12088
11953
  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)
12090
11954
  baker canvas scaffold-video <video> \u2014 turn a reference video into a runnable reproduction canvas (deconstruct + recurring-element detection)
12091
11955
  baker canvas scaffold-static-ad <image> \u2014 turn a source image into a runnable static-ad canvas (describe + element detection)`
12092
11956
  },
@@ -12095,18 +11959,200 @@ Subcommands:
12095
11959
  validate: validateCommand,
12096
11960
  catalog: catalogCommand,
12097
11961
  inspect: inspectCommand,
12098
- gallery: galleryCommand,
12099
11962
  "scaffold-video": scaffoldVideoCommand,
12100
11963
  "scaffold-static-ad": scaffoldStaticAdCommand,
12101
11964
  "set-prompt": setPromptCommand
12102
11965
  }
12103
11966
  });
12104
11967
 
11968
+ // src/commands/creatives/index.ts
11969
+ import { defineCommand as defineCommand88 } from "citty";
11970
+
11971
+ // src/commands/creatives/publish.ts
11972
+ import { defineCommand as defineCommand87 } from "citty";
11973
+
11974
+ // src/commands/images/api.ts
11975
+ import { readFile as readFile9 } from "fs/promises";
11976
+ import { extname } from "path";
11977
+ var imageProcessingTimeoutMs = 18e4;
11978
+ var imageReadyPollIntervalMs = 2e3;
11979
+ var mimeMap = {
11980
+ ".png": "image/png",
11981
+ ".jpg": "image/jpeg",
11982
+ ".jpeg": "image/jpeg",
11983
+ ".gif": "image/gif",
11984
+ ".webp": "image/webp",
11985
+ ".svg": "image/svg+xml",
11986
+ ".avif": "image/avif"
11987
+ };
11988
+ var defaultImageApiDeps = {
11989
+ readFile: readFile9,
11990
+ post: apiPost,
11991
+ get: apiGet,
11992
+ sleep: (ms) => new Promise((resolve5) => setTimeout(resolve5, ms))
11993
+ };
11994
+ function detectImageContentType(filePath, opts = {}) {
11995
+ const ext = extname(filePath).toLowerCase();
11996
+ const contentType = mimeMap[ext];
11997
+ if (!contentType || opts.allowedContentTypes && !opts.allowedContentTypes.includes(contentType)) {
11998
+ throw new ApiError(
11999
+ "VALIDATION_ERROR",
12000
+ opts.unsupportedMessage ?? `Cannot detect content type for extension "${ext}". Use --content-type.`
12001
+ );
12002
+ }
12003
+ return contentType;
12004
+ }
12005
+ async function uploadLocalImage(args, deps = defaultImageApiDeps) {
12006
+ const fileBuffer = await deps.readFile(args.file);
12007
+ const body = {
12008
+ base64: fileBuffer.toString("base64"),
12009
+ contentType: args.contentType
12010
+ };
12011
+ if (args.source) body.source = args.source;
12012
+ if (args.descriptionContext) body.descriptionContext = args.descriptionContext;
12013
+ return deps.post("/api/images/upload", body, { timeoutMs: imageProcessingTimeoutMs });
12014
+ }
12015
+ function getImage(deps, imageId) {
12016
+ return deps.get("/api/images/get", { id: imageId });
12017
+ }
12018
+ function updateImageTags(deps, args) {
12019
+ return deps.post("/api/images/tag", args);
12020
+ }
12021
+ async function waitForReadyImage(deps, imageId, opts = {}) {
12022
+ const timeoutMs = opts.timeoutMs ?? imageProcessingTimeoutMs;
12023
+ const pollIntervalMs = opts.pollIntervalMs ?? imageReadyPollIntervalMs;
12024
+ const deadline = Date.now() + timeoutMs;
12025
+ let lastStatus = "unknown";
12026
+ while (Date.now() <= deadline) {
12027
+ const image = await getImage(deps, imageId);
12028
+ lastStatus = image.status ?? "unknown";
12029
+ if (image.status === "ready") {
12030
+ return image;
12031
+ }
12032
+ if (image.status === "error") {
12033
+ throw new ApiError("IMAGE_PROCESSING_ERROR", "Image processing failed");
12034
+ }
12035
+ await deps.sleep(pollIntervalMs);
12036
+ }
12037
+ throw new ApiError("TIMEOUT", `Image was not ready before timeout; last status: ${lastStatus}`);
12038
+ }
12039
+
12040
+ // src/commands/creatives/publish.ts
12041
+ var creativeTag = "creative";
12042
+ var creativeContentTypes = ["image/png", "image/jpeg", "image/webp"];
12043
+ registerSchema({
12044
+ command: "creatives.publish",
12045
+ description: "Publish a final static creative image to Baker Images, apply the official creative tag, and return an image reference.",
12046
+ args: {
12047
+ file: { type: "string", description: "Local PNG/JPG/WebP creative image path", required: true },
12048
+ title: { type: "string", description: "Human title for the creative output", required: true },
12049
+ context: { type: "string", description: "Optional describe context for the image row", required: false }
12050
+ }
12051
+ });
12052
+ function detectCreativeContentType(filePath) {
12053
+ return detectImageContentType(filePath, {
12054
+ allowedContentTypes: creativeContentTypes,
12055
+ unsupportedMessage: "Unsupported creative image extension. Use PNG, JPG, or WebP."
12056
+ });
12057
+ }
12058
+ function imageToCreativeReference(image, title) {
12059
+ if (!image.imageUrl) {
12060
+ throw new ApiError("IMAGE_PROCESSING_ERROR", "Published image is missing imageUrl");
12061
+ }
12062
+ return {
12063
+ type: "image",
12064
+ slug: image._id,
12065
+ title,
12066
+ tags: image.tags?.includes(creativeTag) ? image.tags : [...image.tags ?? [], creativeTag],
12067
+ imageUrl: image.imageUrl,
12068
+ thumbnailUrl: image.thumbnailUrl ?? image.imageUrl,
12069
+ storageKey: image.storageKey,
12070
+ width: image.width,
12071
+ height: image.height,
12072
+ aspectRatio: image.aspectRatio,
12073
+ source: image.source
12074
+ };
12075
+ }
12076
+ async function publishCreative(args, deps = defaultImageApiDeps) {
12077
+ const title = args.title.trim();
12078
+ if (!title) {
12079
+ throw new ApiError("VALIDATION_ERROR", "--title is required");
12080
+ }
12081
+ const contentType = detectCreativeContentType(args.file);
12082
+ const upload = await uploadLocalImage(
12083
+ {
12084
+ file: args.file,
12085
+ contentType,
12086
+ source: "ai_generated",
12087
+ descriptionContext: args.context ?? `Static ad creative: ${title}`
12088
+ },
12089
+ deps
12090
+ );
12091
+ const readyImage = await waitForReadyImage(deps, upload.imageId, { timeoutMs: imageProcessingTimeoutMs });
12092
+ await updateImageTags(deps, {
12093
+ imageIds: [upload.imageId],
12094
+ addTags: [creativeTag],
12095
+ removeTags: []
12096
+ });
12097
+ const taggedImage = await getImage(deps, upload.imageId);
12098
+ return { imageId: upload.imageId, reference: imageToCreativeReference({ ...readyImage, ...taggedImage }, title) };
12099
+ }
12100
+ var publishCommand = defineCommand87({
12101
+ meta: {
12102
+ name: "publish",
12103
+ description: "Publish a final static creative image to Baker Images, deterministically tag it as creative, and print the image reference JSON."
12104
+ },
12105
+ args: {
12106
+ file: { type: "positional", description: "Local PNG/JPG/WebP creative image path", required: false },
12107
+ title: { type: "string", description: "Human title for the creative output", required: false },
12108
+ context: { type: "string", description: "Optional describe context for the image row", required: false }
12109
+ },
12110
+ run: async ({ args }) => {
12111
+ try {
12112
+ const file = args.file;
12113
+ const title = args.title;
12114
+ if (!file) {
12115
+ writeJson({ ok: false, error: { code: "VALIDATION_ERROR", message: "Image path is required" } });
12116
+ process.exit(1);
12117
+ }
12118
+ if (!title) {
12119
+ writeJson({ ok: false, error: { code: "VALIDATION_ERROR", message: "--title is required" } });
12120
+ process.exit(1);
12121
+ }
12122
+ const data = await publishCreative({ file, title, context: args.context });
12123
+ writeJson({ ok: true, data });
12124
+ } catch (err) {
12125
+ if (err instanceof ApiError) {
12126
+ writeJson({ ok: false, error: { code: err.code, message: err.message } });
12127
+ process.exit(1);
12128
+ }
12129
+ writeJson({ ok: false, error: { code: "INTERNAL_ERROR", message: "Unexpected error" } });
12130
+ process.exit(1);
12131
+ }
12132
+ }
12133
+ });
12134
+
12135
+ // src/commands/creatives/index.ts
12136
+ var creativesCommand3 = defineCommand88({
12137
+ meta: {
12138
+ name: "creatives",
12139
+ description: `Publish static ad creatives as first-class Baker outputs.
12140
+
12141
+ Static creative handoff:
12142
+ baker creatives publish ./canvas/run/final.png --title "Spring Offer Static Ad"
12143
+
12144
+ Publishing uploads the image to the Company image library, applies the official creative tag, and returns an image reference for chat previews.`
12145
+ },
12146
+ subCommands: {
12147
+ publish: publishCommand
12148
+ }
12149
+ });
12150
+
12105
12151
  // src/commands/ga4/index.ts
12106
- import { defineCommand as defineCommand90 } from "citty";
12152
+ import { defineCommand as defineCommand92 } from "citty";
12107
12153
 
12108
12154
  // src/commands/ga4/audit.ts
12109
- import { defineCommand as defineCommand87 } from "citty";
12155
+ import { defineCommand as defineCommand89 } from "citty";
12110
12156
 
12111
12157
  // src/commands/ga4/resolve.ts
12112
12158
  async function fetchProperties(useCache = true) {
@@ -12169,7 +12215,7 @@ registerSchema({
12169
12215
  "no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
12170
12216
  }
12171
12217
  });
12172
- var auditCommand2 = defineCommand87({
12218
+ var auditCommand2 = defineCommand89({
12173
12219
  meta: {
12174
12220
  name: "audit",
12175
12221
  description: `Run all GA4 admin health checks. Returns property config with playbook warnings.
@@ -12221,7 +12267,7 @@ Examples:
12221
12267
  });
12222
12268
 
12223
12269
  // src/commands/ga4/properties.ts
12224
- import { defineCommand as defineCommand88 } from "citty";
12270
+ import { defineCommand as defineCommand90 } from "citty";
12225
12271
  registerSchema({
12226
12272
  command: "ga4.properties",
12227
12273
  description: "List all accessible GA4 properties. Returns property IDs needed for query and audit commands. Run this first to find property IDs.",
@@ -12229,7 +12275,7 @@ registerSchema({
12229
12275
  "no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
12230
12276
  }
12231
12277
  });
12232
- var propertiesCommand = defineCommand88({
12278
+ var propertiesCommand = defineCommand90({
12233
12279
  meta: {
12234
12280
  name: "properties",
12235
12281
  description: `List accessible GA4 properties.
@@ -12279,7 +12325,7 @@ Examples:
12279
12325
  // src/commands/ga4/query.ts
12280
12326
  import { appendFileSync as appendFileSync2, existsSync as existsSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
12281
12327
  import { resolve as resolve2 } from "path";
12282
- import { defineCommand as defineCommand89 } from "citty";
12328
+ import { defineCommand as defineCommand91 } from "citty";
12283
12329
 
12284
12330
  // src/commands/ga4/presets.ts
12285
12331
  var GA4_PRESETS = [
@@ -12411,7 +12457,7 @@ function handleError(err) {
12411
12457
  });
12412
12458
  process.exit(1);
12413
12459
  }
12414
- var queryCommand2 = defineCommand89({
12460
+ var queryCommand2 = defineCommand91({
12415
12461
  meta: {
12416
12462
  name: "query",
12417
12463
  description: `Run GA4 Data API reports. Preset-first with free-form escape hatch.
@@ -12482,7 +12528,7 @@ Free-form (escape hatch):
12482
12528
  });
12483
12529
 
12484
12530
  // src/commands/ga4/index.ts
12485
- var ga4Command = defineCommand90({
12531
+ var ga4Command = defineCommand92({
12486
12532
  meta: {
12487
12533
  name: "ga4",
12488
12534
  description: `Google Analytics 4 commands. Audit property config, run playbook-aligned reports.
@@ -12505,12 +12551,12 @@ Examples:
12505
12551
  });
12506
12552
 
12507
12553
  // src/commands/gsc/index.ts
12508
- import { defineCommand as defineCommand94 } from "citty";
12554
+ import { defineCommand as defineCommand96 } from "citty";
12509
12555
 
12510
12556
  // src/commands/gsc/query.ts
12511
12557
  import { appendFileSync as appendFileSync3, existsSync as existsSync5, readFileSync as readFileSync7, writeFileSync as writeFileSync5 } from "fs";
12512
12558
  import { resolve as resolve3 } from "path";
12513
- import { defineCommand as defineCommand91 } from "citty";
12559
+ import { defineCommand as defineCommand93 } from "citty";
12514
12560
 
12515
12561
  // src/commands/gsc/presets.ts
12516
12562
  var GSC_PRESETS = [
@@ -12698,7 +12744,7 @@ function handleError2(err) {
12698
12744
  });
12699
12745
  process.exit(1);
12700
12746
  }
12701
- var queryCommand3 = defineCommand91({
12747
+ var queryCommand3 = defineCommand93({
12702
12748
  meta: {
12703
12749
  name: "query",
12704
12750
  description: `Run GSC Search Analytics queries. Preset-first with free-form escape hatch.
@@ -12776,7 +12822,7 @@ Free-form (escape hatch):
12776
12822
  });
12777
12823
 
12778
12824
  // src/commands/gsc/sitemaps.ts
12779
- import { defineCommand as defineCommand92 } from "citty";
12825
+ import { defineCommand as defineCommand94 } from "citty";
12780
12826
  registerSchema({
12781
12827
  command: "gsc.sitemaps",
12782
12828
  description: "List sitemaps for a Search Console site. Check sitemap health and errors.",
@@ -12785,7 +12831,7 @@ registerSchema({
12785
12831
  "no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
12786
12832
  }
12787
12833
  });
12788
- var sitemapsCommand = defineCommand92({
12834
+ var sitemapsCommand = defineCommand94({
12789
12835
  meta: {
12790
12836
  name: "sitemaps",
12791
12837
  description: `List sitemaps for a site. Check health and errors.
@@ -12835,7 +12881,7 @@ Examples:
12835
12881
  });
12836
12882
 
12837
12883
  // src/commands/gsc/sites.ts
12838
- import { defineCommand as defineCommand93 } from "citty";
12884
+ import { defineCommand as defineCommand95 } from "citty";
12839
12885
  registerSchema({
12840
12886
  command: "gsc.sites",
12841
12887
  description: "List all verified Google Search Console sites. Returns site URLs needed for query and sitemaps commands.",
@@ -12843,7 +12889,7 @@ registerSchema({
12843
12889
  "no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false }
12844
12890
  }
12845
12891
  });
12846
- var sitesCommand = defineCommand93({
12892
+ var sitesCommand = defineCommand95({
12847
12893
  meta: {
12848
12894
  name: "sites",
12849
12895
  description: `List verified Search Console sites.
@@ -12891,7 +12937,7 @@ Examples:
12891
12937
  });
12892
12938
 
12893
12939
  // src/commands/gsc/index.ts
12894
- var gscCommand = defineCommand94({
12940
+ var gscCommand = defineCommand96({
12895
12941
  meta: {
12896
12942
  name: "gsc",
12897
12943
  description: `Google Search Console commands. PPC-SEO arbitrage, brand halo analysis, negative keyword discovery.
@@ -12914,10 +12960,10 @@ Examples:
12914
12960
  });
12915
12961
 
12916
12962
  // src/commands/images/index.ts
12917
- import { defineCommand as defineCommand118 } from "citty";
12963
+ import { defineCommand as defineCommand120 } from "citty";
12918
12964
 
12919
12965
  // src/commands/images/crop.ts
12920
- import { defineCommand as defineCommand95 } from "citty";
12966
+ import { defineCommand as defineCommand97 } from "citty";
12921
12967
 
12922
12968
  // src/lib/image/crop-sprite.ts
12923
12969
  import sharp from "sharp";
@@ -12933,7 +12979,7 @@ function cropSprite(input, region) {
12933
12979
  // src/lib/image/io.ts
12934
12980
  import { randomBytes } from "crypto";
12935
12981
  import { glob as fsGlob, readFile as readFile10, rename, stat as stat2, writeFile as writeFile4 } from "fs/promises";
12936
- import { dirname, extname, join as join3, resolve as resolve4 } from "path";
12982
+ import { dirname, extname as extname2, join as join3, resolve as resolve4 } from "path";
12937
12983
  var REMOTE_RE = /^https?:\/\//i;
12938
12984
  var GLOB_RE = /[*?[\]{}]/;
12939
12985
  function isRemoteUrl(value) {
@@ -12970,16 +13016,16 @@ async function readImageBuffer(pathOrUrl) {
12970
13016
  }
12971
13017
  return readFile10(pathOrUrl);
12972
13018
  }
12973
- async function isDirectory(path12) {
13019
+ async function isDirectory(path11) {
12974
13020
  try {
12975
- const s = await stat2(path12);
13021
+ const s = await stat2(path11);
12976
13022
  return s.isDirectory();
12977
13023
  } catch {
12978
13024
  return false;
12979
13025
  }
12980
13026
  }
12981
13027
  async function resolveOutputPath(inputPath, outputArg, options) {
12982
- const base = options.newExtension ? inputPath.slice(0, -extname(inputPath).length) + options.newExtension : inputPath;
13028
+ const base = options.newExtension ? inputPath.slice(0, -extname2(inputPath).length) + options.newExtension : inputPath;
12983
13029
  if (!outputArg) return base;
12984
13030
  if (options.multipleInputs || await isDirectory(outputArg)) {
12985
13031
  const filename = base.split("/").pop() ?? "out.png";
@@ -13042,7 +13088,7 @@ function emitError2(err) {
13042
13088
  }
13043
13089
  process.exit(1);
13044
13090
  }
13045
- var cropCommand = defineCommand95({
13091
+ var cropCommand = defineCommand97({
13046
13092
  meta: {
13047
13093
  name: "crop",
13048
13094
  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"
@@ -13078,7 +13124,7 @@ var cropCommand = defineCommand95({
13078
13124
  });
13079
13125
 
13080
13126
  // src/commands/images/delete.ts
13081
- import { defineCommand as defineCommand96 } from "citty";
13127
+ import { defineCommand as defineCommand98 } from "citty";
13082
13128
  registerSchema({
13083
13129
  command: "images.delete",
13084
13130
  description: "Delete an image by ID",
@@ -13092,7 +13138,7 @@ registerSchema({
13092
13138
  }
13093
13139
  }
13094
13140
  });
13095
- var deleteCommand = defineCommand96({
13141
+ var deleteCommand = defineCommand98({
13096
13142
  meta: {
13097
13143
  name: "delete",
13098
13144
  description: "Delete an image by ID. Use --dry-run to preview. Example: baker images delete j571abc123 --dry-run"
@@ -13133,7 +13179,7 @@ var deleteCommand = defineCommand96({
13133
13179
  });
13134
13180
 
13135
13181
  // src/commands/images/dimensions.ts
13136
- import { defineCommand as defineCommand97 } from "citty";
13182
+ import { defineCommand as defineCommand99 } from "citty";
13137
13183
 
13138
13184
  // src/lib/image/dimensions.ts
13139
13185
  import { imageSize } from "image-size";
@@ -13156,7 +13202,7 @@ registerSchema({
13156
13202
  target: { type: "string", description: "Local file path or remote http(s) URL", required: true }
13157
13203
  }
13158
13204
  });
13159
- var dimensionsCommand = defineCommand97({
13205
+ var dimensionsCommand = defineCommand99({
13160
13206
  meta: {
13161
13207
  name: "dimensions",
13162
13208
  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"
@@ -13200,7 +13246,7 @@ var dimensionsCommand = defineCommand97({
13200
13246
  });
13201
13247
 
13202
13248
  // src/commands/images/extract.ts
13203
- import { defineCommand as defineCommand98 } from "citty";
13249
+ import { defineCommand as defineCommand100 } from "citty";
13204
13250
  registerSchema({
13205
13251
  command: "images.extract",
13206
13252
  description: "Extract images from a URL via Firecrawl (formats: images).",
@@ -13216,7 +13262,7 @@ registerSchema({
13216
13262
  }
13217
13263
  }
13218
13264
  });
13219
- var extractCommand = defineCommand98({
13265
+ var extractCommand = defineCommand100({
13220
13266
  meta: {
13221
13267
  name: "extract",
13222
13268
  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"
@@ -13254,7 +13300,7 @@ var extractCommand = defineCommand98({
13254
13300
  });
13255
13301
 
13256
13302
  // src/commands/images/find.ts
13257
- import { defineCommand as defineCommand99 } from "citty";
13303
+ import { defineCommand as defineCommand101 } from "citty";
13258
13304
  registerSchema({
13259
13305
  command: "images.find",
13260
13306
  description: "Fanout image search: library first, then opted-in external providers.",
@@ -13286,7 +13332,7 @@ registerSchema({
13286
13332
  }
13287
13333
  }
13288
13334
  });
13289
- var findCommand = defineCommand99({
13335
+ var findCommand = defineCommand101({
13290
13336
  meta: {
13291
13337
  name: "find",
13292
13338
  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"
@@ -13333,7 +13379,7 @@ var findCommand = defineCommand99({
13333
13379
 
13334
13380
  // src/commands/images/generate.ts
13335
13381
  import { readFile as readFile11 } from "fs/promises";
13336
- import { defineCommand as defineCommand100 } from "citty";
13382
+ import { defineCommand as defineCommand102 } from "citty";
13337
13383
  import sharp2 from "sharp";
13338
13384
  var GENERATE_TIMEOUT_MS = 18e4;
13339
13385
  var REFERENCE_MAX_EDGE = 1536;
@@ -13429,7 +13475,7 @@ async function resolveReferences(spec) {
13429
13475
  }
13430
13476
  return out;
13431
13477
  }
13432
- var generateCommand = defineCommand100({
13478
+ var generateCommand = defineCommand102({
13433
13479
  meta: {
13434
13480
  name: "generate",
13435
13481
  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]]'"
@@ -13481,7 +13527,7 @@ var generateCommand = defineCommand100({
13481
13527
  });
13482
13528
 
13483
13529
  // src/commands/images/get.ts
13484
- import { defineCommand as defineCommand101 } from "citty";
13530
+ import { defineCommand as defineCommand103 } from "citty";
13485
13531
  registerSchema({
13486
13532
  command: "images.get",
13487
13533
  description: "Get a single image by ID",
@@ -13489,7 +13535,7 @@ registerSchema({
13489
13535
  id: { type: "string", description: "Image ID", required: true }
13490
13536
  }
13491
13537
  });
13492
- var getCommand2 = defineCommand101({
13538
+ var getCommand2 = defineCommand103({
13493
13539
  meta: { name: "get", description: "Get a single image by ID. Example: baker images get j571abc123" },
13494
13540
  args: {
13495
13541
  id: { type: "positional", description: "Image ID", required: false },
@@ -13525,7 +13571,7 @@ var getCommand2 = defineCommand101({
13525
13571
  });
13526
13572
 
13527
13573
  // src/commands/images/gif.ts
13528
- import { defineCommand as defineCommand102 } from "citty";
13574
+ import { defineCommand as defineCommand104 } from "citty";
13529
13575
  registerSchema({
13530
13576
  command: "images.gif",
13531
13577
  description: "Search Giphy for GIFs / reaction memes (paid social creative).",
@@ -13557,7 +13603,7 @@ registerSchema({
13557
13603
  }
13558
13604
  }
13559
13605
  });
13560
- var gifCommand = defineCommand102({
13606
+ var gifCommand = defineCommand104({
13561
13607
  meta: {
13562
13608
  name: "gif",
13563
13609
  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"
@@ -13604,7 +13650,7 @@ var gifCommand = defineCommand102({
13604
13650
  });
13605
13651
 
13606
13652
  // src/commands/images/google.ts
13607
- import { defineCommand as defineCommand103 } from "citty";
13653
+ import { defineCommand as defineCommand105 } from "citty";
13608
13654
  registerSchema({
13609
13655
  command: "images.google",
13610
13656
  description: "Google Images search via the official Custom Search JSON API. Unverified source \u2014 inspect before placing.",
@@ -13640,7 +13686,7 @@ registerSchema({
13640
13686
  }
13641
13687
  }
13642
13688
  });
13643
- var googleCommand2 = defineCommand103({
13689
+ var googleCommand2 = defineCommand105({
13644
13690
  meta: {
13645
13691
  name: "google",
13646
13692
  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"
@@ -13688,7 +13734,7 @@ var googleCommand2 = defineCommand103({
13688
13734
  });
13689
13735
 
13690
13736
  // src/commands/images/icon.ts
13691
- import { defineCommand as defineCommand104 } from "citty";
13737
+ import { defineCommand as defineCommand106 } from "citty";
13692
13738
  registerSchema({
13693
13739
  command: "images.icon",
13694
13740
  description: "Icon lookup via Iconify (200+ icon sets, free CDN).",
@@ -13714,7 +13760,7 @@ registerSchema({
13714
13760
  }
13715
13761
  }
13716
13762
  });
13717
- var iconCommand = defineCommand104({
13763
+ var iconCommand = defineCommand106({
13718
13764
  meta: {
13719
13765
  name: "icon",
13720
13766
  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'"
@@ -13754,7 +13800,7 @@ var iconCommand = defineCommand104({
13754
13800
  });
13755
13801
 
13756
13802
  // src/commands/images/ingest.ts
13757
- import { defineCommand as defineCommand105 } from "citty";
13803
+ import { defineCommand as defineCommand107 } from "citty";
13758
13804
  registerSchema({
13759
13805
  command: "images.ingest",
13760
13806
  description: "Ingest a remote image URL into the library (full describe + embed).",
@@ -13766,7 +13812,7 @@ registerSchema({
13766
13812
  context: { type: "string", description: "Description context hint", required: false }
13767
13813
  }
13768
13814
  });
13769
- var ingestCommand = defineCommand105({
13815
+ var ingestCommand = defineCommand107({
13770
13816
  meta: {
13771
13817
  name: "ingest",
13772
13818
  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"
@@ -13808,7 +13854,7 @@ var ingestCommand = defineCommand105({
13808
13854
  });
13809
13855
 
13810
13856
  // src/commands/images/library.ts
13811
- import { defineCommand as defineCommand106 } from "citty";
13857
+ import { defineCommand as defineCommand108 } from "citty";
13812
13858
  registerSchema({
13813
13859
  command: "images.library",
13814
13860
  description: "Search the company image library. Returns only ready images.",
@@ -13834,7 +13880,7 @@ registerSchema({
13834
13880
  }
13835
13881
  }
13836
13882
  });
13837
- var libraryCommand = defineCommand106({
13883
+ var libraryCommand = defineCommand108({
13838
13884
  meta: {
13839
13885
  name: "library",
13840
13886
  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"
@@ -13891,7 +13937,7 @@ var libraryCommand = defineCommand106({
13891
13937
  });
13892
13938
 
13893
13939
  // src/commands/images/logo.ts
13894
- import { defineCommand as defineCommand107 } from "citty";
13940
+ import { defineCommand as defineCommand109 } from "citty";
13895
13941
  registerSchema({
13896
13942
  command: "images.logo",
13897
13943
  description: "Brand logo lookup via Brandfetch CDN (fallback/404). Auto-ingests by default.",
@@ -13916,7 +13962,7 @@ registerSchema({
13916
13962
  }
13917
13963
  }
13918
13964
  });
13919
- var logoCommand = defineCommand107({
13965
+ var logoCommand = defineCommand109({
13920
13966
  meta: {
13921
13967
  name: "logo",
13922
13968
  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"
@@ -13954,7 +14000,7 @@ var logoCommand = defineCommand107({
13954
14000
  });
13955
14001
 
13956
14002
  // src/commands/images/normalize.ts
13957
- import { defineCommand as defineCommand108 } from "citty";
14003
+ import { defineCommand as defineCommand110 } from "citty";
13958
14004
 
13959
14005
  // src/lib/image/color-changer.ts
13960
14006
  import quantize from "quantize";
@@ -14686,7 +14732,7 @@ function coerceRawArgs(args) {
14686
14732
  "dry-run": bool(args["dry-run"])
14687
14733
  };
14688
14734
  }
14689
- var normalizeCommand = defineCommand108({
14735
+ var normalizeCommand = defineCommand110({
14690
14736
  meta: {
14691
14737
  name: "normalize",
14692
14738
  description: `Normalize logos / images: declarative recolor + bg removal + trim + resize. Operates on local files; writes in-place by default.
@@ -14741,7 +14787,7 @@ Examples:
14741
14787
  });
14742
14788
 
14743
14789
  // src/commands/images/pinterest.ts
14744
- import { defineCommand as defineCommand109 } from "citty";
14790
+ import { defineCommand as defineCommand111 } from "citty";
14745
14791
  registerSchema({
14746
14792
  command: "images.pinterest",
14747
14793
  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.",
@@ -14761,7 +14807,7 @@ registerSchema({
14761
14807
  }
14762
14808
  }
14763
14809
  });
14764
- var pinterestCommand = defineCommand109({
14810
+ var pinterestCommand = defineCommand111({
14765
14811
  meta: {
14766
14812
  name: "pinterest",
14767
14813
  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'"
@@ -14801,7 +14847,7 @@ var pinterestCommand = defineCommand109({
14801
14847
  });
14802
14848
 
14803
14849
  // src/commands/images/screenshot.ts
14804
- import { defineCommand as defineCommand110 } from "citty";
14850
+ import { defineCommand as defineCommand112 } from "citty";
14805
14851
  registerSchema({
14806
14852
  command: "images.screenshot",
14807
14853
  description: "Capture a website screenshot via ScreenshotOne. Auto-ingests on success.",
@@ -14817,7 +14863,7 @@ registerSchema({
14817
14863
  }
14818
14864
  }
14819
14865
  });
14820
- var screenshotCommand = defineCommand110({
14866
+ var screenshotCommand = defineCommand112({
14821
14867
  meta: {
14822
14868
  name: "screenshot",
14823
14869
  description: "Screenshot a URL via ScreenshotOne. $0.009/capture. Auto-ingests to library.\n\nExample: baker images screenshot https://stripe.com --full-page"
@@ -14867,7 +14913,7 @@ var screenshotCommand = defineCommand110({
14867
14913
  });
14868
14914
 
14869
14915
  // src/commands/images/search.ts
14870
- import { defineCommand as defineCommand111 } from "citty";
14916
+ import { defineCommand as defineCommand113 } from "citty";
14871
14917
  registerSchema({
14872
14918
  command: "images.search",
14873
14919
  description: "Search images by text query. Only returns ready images.",
@@ -14883,7 +14929,7 @@ registerSchema({
14883
14929
  tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
14884
14930
  }
14885
14931
  });
14886
- var searchCommand = defineCommand111({
14932
+ var searchCommand = defineCommand113({
14887
14933
  meta: {
14888
14934
  name: "search",
14889
14935
  description: "Semantic search images by text query. Uses hybrid BM25 + vector + reranking. Example: baker images search 'hero banner' --aspect-ratio 16:9 --tags logo"
@@ -14943,7 +14989,7 @@ var searchCommand = defineCommand111({
14943
14989
  });
14944
14990
 
14945
14991
  // src/commands/images/sticker.ts
14946
- import { defineCommand as defineCommand112 } from "citty";
14992
+ import { defineCommand as defineCommand114 } from "citty";
14947
14993
  registerSchema({
14948
14994
  command: "images.sticker",
14949
14995
  description: "Search Giphy stickers \u2014 transparent-background overlays for ad creative.",
@@ -14975,7 +15021,7 @@ registerSchema({
14975
15021
  }
14976
15022
  }
14977
15023
  });
14978
- var stickerCommand = defineCommand112({
15024
+ var stickerCommand = defineCommand114({
14979
15025
  meta: {
14980
15026
  name: "sticker",
14981
15027
  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"
@@ -15022,7 +15068,7 @@ var stickerCommand = defineCommand112({
15022
15068
  });
15023
15069
 
15024
15070
  // src/commands/images/stock.ts
15025
- import { defineCommand as defineCommand113 } from "citty";
15071
+ import { defineCommand as defineCommand115 } from "citty";
15026
15072
  registerSchema({
15027
15073
  command: "images.stock",
15028
15074
  description: "Stock photo, vector illustration, icon-set, and PSD search via Magnific (Freepik's developer API).",
@@ -15080,7 +15126,7 @@ registerSchema({
15080
15126
  }
15081
15127
  }
15082
15128
  });
15083
- var stockCommand = defineCommand113({
15129
+ var stockCommand = defineCommand115({
15084
15130
  meta: {
15085
15131
  name: "stock",
15086
15132
  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"
@@ -15136,7 +15182,7 @@ var stockCommand = defineCommand113({
15136
15182
  });
15137
15183
 
15138
15184
  // src/lib/tags-command.ts
15139
- import { defineCommand as defineCommand114 } from "citty";
15185
+ import { defineCommand as defineCommand116 } from "citty";
15140
15186
  function makeTagsCommand(command, label, endpoint) {
15141
15187
  registerSchema({
15142
15188
  command: `${command}.tags`,
@@ -15145,7 +15191,7 @@ function makeTagsCommand(command, label, endpoint) {
15145
15191
  output: { type: "string", description: "Output format: md|json", required: false, default: "md" }
15146
15192
  }
15147
15193
  });
15148
- return defineCommand114({
15194
+ return defineCommand116({
15149
15195
  meta: {
15150
15196
  name: "tags",
15151
15197
  description: `List the available ${label} tag names (defaults + company custom tags). Use before filtering with --tags. Example: baker ${command} tags`
@@ -15181,18 +15227,7 @@ function makeTagsCommand(command, label, endpoint) {
15181
15227
  var tagsCommand2 = makeTagsCommand("images", "image", "/api/images/tags");
15182
15228
 
15183
15229
  // src/commands/images/upload.ts
15184
- import { readFile as readFile12 } from "fs/promises";
15185
- import { extname as extname2 } from "path";
15186
- import { defineCommand as defineCommand115 } from "citty";
15187
- var MIME_MAP = {
15188
- ".png": "image/png",
15189
- ".jpg": "image/jpeg",
15190
- ".jpeg": "image/jpeg",
15191
- ".gif": "image/gif",
15192
- ".webp": "image/webp",
15193
- ".svg": "image/svg+xml",
15194
- ".avif": "image/avif"
15195
- };
15230
+ import { defineCommand as defineCommand117 } from "citty";
15196
15231
  registerSchema({
15197
15232
  command: "images.upload",
15198
15233
  description: "Upload an image to the library \u2014 local file path or remote http(s) URL.",
@@ -15230,15 +15265,7 @@ registerSchema({
15230
15265
  function isRemoteUrl2(value) {
15231
15266
  return /^https?:\/\//i.test(value);
15232
15267
  }
15233
- function detectContentType(filePath) {
15234
- const ext = extname2(filePath).toLowerCase();
15235
- const mime = MIME_MAP[ext];
15236
- if (!mime) {
15237
- throw new ApiError("VALIDATION_ERROR", `Cannot detect content type for extension "${ext}". Use --content-type.`);
15238
- }
15239
- return mime;
15240
- }
15241
- var uploadCommand = defineCommand115({
15268
+ var uploadCommand = defineCommand117({
15242
15269
  meta: {
15243
15270
  name: "upload",
15244
15271
  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'"
@@ -15306,7 +15333,7 @@ async function uploadRemote(target, args) {
15306
15333
  writeJson({ ok: true, data });
15307
15334
  }
15308
15335
  async function uploadLocal(target, args) {
15309
- const contentType = args["content-type"] || detectContentType(target);
15336
+ const contentType = args["content-type"] || detectImageContentType(target);
15310
15337
  if (args["dry-run"]) {
15311
15338
  writeJson({
15312
15339
  ok: true,
@@ -15321,17 +15348,17 @@ async function uploadLocal(target, args) {
15321
15348
  });
15322
15349
  return;
15323
15350
  }
15324
- const fileBuffer = await readFile12(target);
15325
- const base64 = fileBuffer.toString("base64");
15326
- const body = { base64, contentType };
15327
- if (args.source) body.source = args.source;
15328
- if (args.context) body.descriptionContext = args.context;
15329
- const data = await apiPost("/api/images/upload", body);
15351
+ const data = await uploadLocalImage({
15352
+ file: target,
15353
+ contentType,
15354
+ source: args.source,
15355
+ descriptionContext: args.context
15356
+ });
15330
15357
  writeJson({ ok: true, data });
15331
15358
  }
15332
15359
 
15333
15360
  // src/commands/images/upscale.ts
15334
- import { defineCommand as defineCommand116 } from "citty";
15361
+ import { defineCommand as defineCommand118 } from "citty";
15335
15362
  registerSchema({
15336
15363
  command: "images.upscale",
15337
15364
  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).",
@@ -15346,7 +15373,7 @@ registerSchema({
15346
15373
  }
15347
15374
  });
15348
15375
  var POLL_INTERVAL_MS3 = 1500;
15349
- var upscaleCommand = defineCommand116({
15376
+ var upscaleCommand = defineCommand118({
15350
15377
  meta: {
15351
15378
  name: "upscale",
15352
15379
  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"
@@ -15401,7 +15428,7 @@ var upscaleCommand = defineCommand116({
15401
15428
  });
15402
15429
 
15403
15430
  // src/commands/images/use.ts
15404
- import { defineCommand as defineCommand117 } from "citty";
15431
+ import { defineCommand as defineCommand119 } from "citty";
15405
15432
  registerSchema({
15406
15433
  command: "images.use",
15407
15434
  description: "Ingest a URL and wait for the library record to be ready.",
@@ -15417,7 +15444,7 @@ registerSchema({
15417
15444
  }
15418
15445
  });
15419
15446
  var POLL_INTERVAL_MS4 = 1500;
15420
- var useCommand = defineCommand117({
15447
+ var useCommand = defineCommand119({
15421
15448
  meta: {
15422
15449
  name: "use",
15423
15450
  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"
@@ -15463,7 +15490,7 @@ var useCommand = defineCommand117({
15463
15490
  });
15464
15491
 
15465
15492
  // src/commands/images/index.ts
15466
- var imagesCommand = defineCommand118({
15493
+ var imagesCommand = defineCommand120({
15467
15494
  meta: {
15468
15495
  name: "images",
15469
15496
  description: `Find, source, and normalize images. Subcommands route by provider so cost + license are explicit.
@@ -15533,10 +15560,10 @@ Paid transforms (run on the Convex backend, cost-tracked):
15533
15560
  });
15534
15561
 
15535
15562
  // src/commands/research/index.ts
15536
- import { defineCommand as defineCommand129 } from "citty";
15563
+ import { defineCommand as defineCommand131 } from "citty";
15537
15564
 
15538
15565
  // src/commands/research/advertisers.ts
15539
- import { defineCommand as defineCommand119 } from "citty";
15566
+ import { defineCommand as defineCommand121 } from "citty";
15540
15567
 
15541
15568
  // src/commands/research/output.ts
15542
15569
  var RESEARCH_DATA_NOTE = "Estimates based on third-party SERP data \u2014 not exact figures. Use for directional insights, not precise measurement.";
@@ -15649,7 +15676,7 @@ var FIELDS3 = {
15649
15676
  etv: "Estimated traffic value (USD)",
15650
15677
  visibility: "SERP visibility score (0-1)"
15651
15678
  };
15652
- var advertisersCommand = defineCommand119({
15679
+ var advertisersCommand = defineCommand121({
15653
15680
  meta: {
15654
15681
  name: "advertisers",
15655
15682
  description: `Find domains competing for a keyword in Google SERPs.
@@ -15696,7 +15723,7 @@ Examples:
15696
15723
  });
15697
15724
 
15698
15725
  // src/commands/research/autocomplete.ts
15699
- import { defineCommand as defineCommand120 } from "citty";
15726
+ import { defineCommand as defineCommand122 } from "citty";
15700
15727
  registerSchema({
15701
15728
  command: "research.autocomplete",
15702
15729
  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).",
@@ -15719,7 +15746,7 @@ registerSchema({
15719
15746
  var FIELDS4 = {
15720
15747
  suggestion: "Autocomplete suggestion from Google"
15721
15748
  };
15722
- var autocompleteCommand = defineCommand120({
15749
+ var autocompleteCommand = defineCommand122({
15723
15750
  meta: {
15724
15751
  name: "autocomplete",
15725
15752
  description: `Get Google Autocomplete suggestions for keyword expansion.
@@ -15765,7 +15792,7 @@ Examples:
15765
15792
  });
15766
15793
 
15767
15794
  // src/commands/research/countries.ts
15768
- import { defineCommand as defineCommand121 } from "citty";
15795
+ import { defineCommand as defineCommand123 } from "citty";
15769
15796
  registerSchema({
15770
15797
  command: "research.countries",
15771
15798
  description: "List all supported country codes for --location flag in research commands.",
@@ -15822,7 +15849,7 @@ var FIELDS5 = {
15822
15849
  code: "Country code to pass as --location",
15823
15850
  name: "Country name"
15824
15851
  };
15825
- var countriesCommand = defineCommand121({
15852
+ var countriesCommand = defineCommand123({
15826
15853
  meta: {
15827
15854
  name: "countries",
15828
15855
  description: "List all supported country codes for --location flag."
@@ -15833,7 +15860,7 @@ var countriesCommand = defineCommand121({
15833
15860
  });
15834
15861
 
15835
15862
  // src/commands/research/intent.ts
15836
- import { defineCommand as defineCommand122 } from "citty";
15863
+ import { defineCommand as defineCommand124 } from "citty";
15837
15864
  registerSchema({
15838
15865
  command: "research.intent",
15839
15866
  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.",
@@ -15856,7 +15883,7 @@ var FIELDS6 = {
15856
15883
  intent: "Primary Google Search intent: informational, navigational, commercial, transactional",
15857
15884
  probability: "Confidence score 0.0-1.0"
15858
15885
  };
15859
- var intentCommand = defineCommand122({
15886
+ var intentCommand = defineCommand124({
15860
15887
  meta: {
15861
15888
  name: "intent",
15862
15889
  description: `Classify Google Search intent for keywords. Returns intent type and confidence.
@@ -15904,7 +15931,7 @@ Examples:
15904
15931
  });
15905
15932
 
15906
15933
  // src/commands/research/keyword-gap.ts
15907
- import { defineCommand as defineCommand123 } from "citty";
15934
+ import { defineCommand as defineCommand125 } from "citty";
15908
15935
  registerSchema({
15909
15936
  command: "research.keyword-gap",
15910
15937
  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.",
@@ -15933,7 +15960,7 @@ var FIELDS7 = {
15933
15960
  cpc: "Cost per click USD",
15934
15961
  their_position: "Competitor's ranking position"
15935
15962
  };
15936
- var keywordGapCommand = defineCommand123({
15963
+ var keywordGapCommand = defineCommand125({
15937
15964
  meta: {
15938
15965
  name: "keyword-gap",
15939
15966
  description: `Find keywords a competitor has that you don't. Supports pagination via --offset.
@@ -16007,7 +16034,7 @@ Examples:
16007
16034
  });
16008
16035
 
16009
16036
  // src/commands/research/keywords-for-site.ts
16010
- import { defineCommand as defineCommand124 } from "citty";
16037
+ import { defineCommand as defineCommand126 } from "citty";
16011
16038
  registerSchema({
16012
16039
  command: "research.keywords-for-site",
16013
16040
  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.",
@@ -16040,7 +16067,7 @@ var FIELDS8 = {
16040
16067
  competition: "LOW, MEDIUM, or HIGH",
16041
16068
  competition_index: "Competition score 0-100"
16042
16069
  };
16043
- var keywordsForSiteCommand = defineCommand124({
16070
+ var keywordsForSiteCommand = defineCommand126({
16044
16071
  meta: {
16045
16072
  name: "keywords-for-site",
16046
16073
  description: `Get keywords a competitor targets in Google. Use --type to filter paid/organic.
@@ -16093,7 +16120,7 @@ Examples:
16093
16120
  });
16094
16121
 
16095
16122
  // src/commands/research/languages.ts
16096
- import { defineCommand as defineCommand125 } from "citty";
16123
+ import { defineCommand as defineCommand127 } from "citty";
16097
16124
  registerSchema({
16098
16125
  command: "research.languages",
16099
16126
  description: "List all supported language codes for --language flag in research commands.",
@@ -16123,7 +16150,7 @@ var FIELDS9 = {
16123
16150
  code: "Language code to pass as --language",
16124
16151
  name: "Language name (also accepted by --language)"
16125
16152
  };
16126
- var languagesCommand2 = defineCommand125({
16153
+ var languagesCommand2 = defineCommand127({
16127
16154
  meta: {
16128
16155
  name: "languages",
16129
16156
  description: "List all supported language codes for --language flag."
@@ -16134,7 +16161,7 @@ var languagesCommand2 = defineCommand125({
16134
16161
  });
16135
16162
 
16136
16163
  // src/commands/research/lighthouse.ts
16137
- import { defineCommand as defineCommand126 } from "citty";
16164
+ import { defineCommand as defineCommand128 } from "citty";
16138
16165
  registerSchema({
16139
16166
  command: "research.lighthouse",
16140
16167
  description: "Landing page performance audit. Returns metrics that affect Google Ads Quality Score and CPC.",
@@ -16153,7 +16180,7 @@ var FIELDS10 = {
16153
16180
  speed_index_ms: "Speed Index in ms (good: < 3400)",
16154
16181
  interactive_ms: "Time to Interactive in ms (good: < 3800)"
16155
16182
  };
16156
- var lighthouseCommand = defineCommand126({
16183
+ var lighthouseCommand = defineCommand128({
16157
16184
  meta: {
16158
16185
  name: "lighthouse",
16159
16186
  description: `Landing page performance audit. Metrics affecting Google Ads Quality Score.
@@ -16191,7 +16218,7 @@ Examples:
16191
16218
  });
16192
16219
 
16193
16220
  // src/commands/research/relevant-pages.ts
16194
- import { defineCommand as defineCommand127 } from "citty";
16221
+ import { defineCommand as defineCommand129 } from "citty";
16195
16222
  registerSchema({
16196
16223
  command: "research.relevant-pages",
16197
16224
  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).",
@@ -16217,7 +16244,7 @@ var FIELDS11 = {
16217
16244
  keywords: "Total organic keywords the page ranks for",
16218
16245
  top_10: "Keywords in positions 1-10"
16219
16246
  };
16220
- var relevantPagesCommand = defineCommand127({
16247
+ var relevantPagesCommand = defineCommand129({
16221
16248
  meta: {
16222
16249
  name: "relevant-pages",
16223
16250
  description: `Get the top pages of a competitor domain with traffic data.
@@ -16263,7 +16290,7 @@ Examples:
16263
16290
  });
16264
16291
 
16265
16292
  // src/commands/research/web.ts
16266
- import { defineCommand as defineCommand128 } from "citty";
16293
+ import { defineCommand as defineCommand130 } from "citty";
16267
16294
  registerSchema({
16268
16295
  command: "research.web",
16269
16296
  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).",
@@ -16314,7 +16341,7 @@ async function runDeepResearch(question) {
16314
16341
  }
16315
16342
  throw new Error("Deep research timed out");
16316
16343
  }
16317
- var webCommand = defineCommand128({
16344
+ var webCommand = defineCommand130({
16318
16345
  meta: {
16319
16346
  name: "web",
16320
16347
  description: `Search the web with AI to answer any open-ended marketing question. Uses live internet data via Google Search.
@@ -16374,7 +16401,7 @@ Examples:
16374
16401
  });
16375
16402
 
16376
16403
  // src/commands/research/index.ts
16377
- var researchCommand = defineCommand129({
16404
+ var researchCommand = defineCommand131({
16378
16405
  meta: {
16379
16406
  name: "research",
16380
16407
  description: `Competitive intelligence and AI-powered research commands.
@@ -16414,10 +16441,10 @@ Examples:
16414
16441
  });
16415
16442
 
16416
16443
  // src/commands/scheduled-actions/index.ts
16417
- import { defineCommand as defineCommand136 } from "citty";
16444
+ import { defineCommand as defineCommand138 } from "citty";
16418
16445
 
16419
16446
  // src/commands/scheduled-actions/create.ts
16420
- import { defineCommand as defineCommand130 } from "citty";
16447
+ import { defineCommand as defineCommand132 } from "citty";
16421
16448
 
16422
16449
  // src/commands/scheduled-actions/shared.ts
16423
16450
  var TEMP_SCHEDULED_ACTION_PREFIX = "temp_sched_";
@@ -16522,7 +16549,7 @@ registerSchema({
16522
16549
  prompt: { type: "string", description: "Additional prompt instructions for the spawned agent", required: false }
16523
16550
  }
16524
16551
  });
16525
- var createCommand2 = defineCommand130({
16552
+ var createCommand2 = defineCommand132({
16526
16553
  meta: {
16527
16554
  name: "create",
16528
16555
  description: 'Stage a scheduled action. Example: baker scheduled-actions create --name "Weekly report" --description "..." --cron "0 9 * * MON"'
@@ -16570,7 +16597,7 @@ var createCommand2 = defineCommand130({
16570
16597
  });
16571
16598
 
16572
16599
  // src/commands/scheduled-actions/delete.ts
16573
- import { defineCommand as defineCommand131 } from "citty";
16600
+ import { defineCommand as defineCommand133 } from "citty";
16574
16601
  registerSchema({
16575
16602
  command: "scheduled-actions.delete",
16576
16603
  description: "Stage deletion of a published scheduled action or cancellation of a temp_sched_* draft creation.",
@@ -16578,7 +16605,7 @@ registerSchema({
16578
16605
  id: { type: "string", description: "Published scheduled action ID or temp_sched_* draft ID", required: true }
16579
16606
  }
16580
16607
  });
16581
- var deleteCommand2 = defineCommand131({
16608
+ var deleteCommand2 = defineCommand133({
16582
16609
  meta: {
16583
16610
  name: "delete",
16584
16611
  description: "Stage scheduled action deletion. Example: baker scheduled-actions delete <id-or-temp_sched_id>"
@@ -16607,7 +16634,7 @@ var deleteCommand2 = defineCommand131({
16607
16634
  });
16608
16635
 
16609
16636
  // src/commands/scheduled-actions/get.ts
16610
- import { defineCommand as defineCommand132 } from "citty";
16637
+ import { defineCommand as defineCommand134 } from "citty";
16611
16638
  registerSchema({
16612
16639
  command: "scheduled-actions.get",
16613
16640
  description: "Get a published scheduled action or a temp_sched_* draft-created scheduled action.",
@@ -16615,7 +16642,7 @@ registerSchema({
16615
16642
  id: { type: "string", description: "Published scheduled action ID or temp_sched_* draft ID", required: true }
16616
16643
  }
16617
16644
  });
16618
- var getCommand3 = defineCommand132({
16645
+ var getCommand3 = defineCommand134({
16619
16646
  meta: {
16620
16647
  name: "get",
16621
16648
  description: "Get a scheduled action. Example: baker scheduled-actions get <id-or-temp_sched_id>"
@@ -16652,13 +16679,13 @@ var getCommand3 = defineCommand132({
16652
16679
  });
16653
16680
 
16654
16681
  // src/commands/scheduled-actions/list.ts
16655
- import { defineCommand as defineCommand133 } from "citty";
16682
+ import { defineCommand as defineCommand135 } from "citty";
16656
16683
  registerSchema({
16657
16684
  command: "scheduled-actions.list",
16658
16685
  description: "List published scheduled actions. Includes draft state when BAKER_CHAT_ID is set.",
16659
16686
  args: {}
16660
16687
  });
16661
- var listCommand3 = defineCommand133({
16688
+ var listCommand3 = defineCommand135({
16662
16689
  meta: {
16663
16690
  name: "list",
16664
16691
  description: "List scheduled actions. Includes staged draft ops when BAKER_CHAT_ID is set."
@@ -16679,7 +16706,7 @@ var listCommand3 = defineCommand133({
16679
16706
  });
16680
16707
 
16681
16708
  // src/commands/scheduled-actions/trigger.ts
16682
- import { defineCommand as defineCommand134 } from "citty";
16709
+ import { defineCommand as defineCommand136 } from "citty";
16683
16710
  registerSchema({
16684
16711
  command: "scheduled-actions.trigger",
16685
16712
  description: "Immediately trigger a published scheduled action. Does not require BAKER_CHAT_ID and rejects temp_sched_* IDs.",
@@ -16687,7 +16714,7 @@ registerSchema({
16687
16714
  id: { type: "string", description: "Published scheduled action ID", required: true }
16688
16715
  }
16689
16716
  });
16690
- var triggerCommand = defineCommand134({
16717
+ var triggerCommand = defineCommand136({
16691
16718
  meta: {
16692
16719
  name: "trigger",
16693
16720
  description: "Immediately trigger a published scheduled action. Example: baker scheduled-actions trigger <id>"
@@ -16724,7 +16751,7 @@ var triggerCommand = defineCommand134({
16724
16751
  });
16725
16752
 
16726
16753
  // src/commands/scheduled-actions/update.ts
16727
- import { defineCommand as defineCommand135 } from "citty";
16754
+ import { defineCommand as defineCommand137 } from "citty";
16728
16755
  registerSchema({
16729
16756
  command: "scheduled-actions.update",
16730
16757
  description: "Stage an update to a published scheduled action or temp_sched_* draft-created scheduled action.",
@@ -16749,7 +16776,7 @@ registerSchema({
16749
16776
  prompt: { type: "string", description: "Replacement additional spawned-agent instructions", required: false }
16750
16777
  }
16751
16778
  });
16752
- var updateCommand2 = defineCommand135({
16779
+ var updateCommand2 = defineCommand137({
16753
16780
  meta: {
16754
16781
  name: "update",
16755
16782
  description: "Stage a scheduled action update. Example: baker scheduled-actions update <id> --enabled false"
@@ -16819,7 +16846,7 @@ var updateCommand2 = defineCommand135({
16819
16846
  });
16820
16847
 
16821
16848
  // src/commands/scheduled-actions/index.ts
16822
- var scheduledActionsCommand = defineCommand136({
16849
+ var scheduledActionsCommand = defineCommand138({
16823
16850
  meta: {
16824
16851
  name: "scheduled-actions",
16825
16852
  description: `Manage Scheduled Actions. Subcommands: list, get, create, update, delete, trigger.
@@ -16845,8 +16872,8 @@ Examples:
16845
16872
  });
16846
16873
 
16847
16874
  // src/commands/schema.ts
16848
- import { defineCommand as defineCommand137 } from "citty";
16849
- var schemaCommand = defineCommand137({
16875
+ import { defineCommand as defineCommand139 } from "citty";
16876
+ var schemaCommand = defineCommand139({
16850
16877
  meta: {
16851
16878
  name: "schema",
16852
16879
  description: "Inspect command argument schemas (for AI agent introspection). Lists all commands if no argument given. Example: baker schema images.search"
@@ -16882,10 +16909,10 @@ var schemaCommand = defineCommand137({
16882
16909
  });
16883
16910
 
16884
16911
  // src/commands/testimonials/index.ts
16885
- import { defineCommand as defineCommand141 } from "citty";
16912
+ import { defineCommand as defineCommand143 } from "citty";
16886
16913
 
16887
16914
  // src/commands/testimonials/get.ts
16888
- import { defineCommand as defineCommand138 } from "citty";
16915
+ import { defineCommand as defineCommand140 } from "citty";
16889
16916
  registerSchema({
16890
16917
  command: "testimonials.get",
16891
16918
  description: "Get a single testimonial by ID",
@@ -16893,7 +16920,7 @@ registerSchema({
16893
16920
  id: { type: "string", description: "Testimonial ID", required: true }
16894
16921
  }
16895
16922
  });
16896
- var getCommand4 = defineCommand138({
16923
+ var getCommand4 = defineCommand140({
16897
16924
  meta: { name: "get", description: "Get a single testimonial by ID. Example: baker testimonials get j571abc123" },
16898
16925
  args: {
16899
16926
  id: { type: "positional", description: "Testimonial ID", required: false },
@@ -16930,7 +16957,7 @@ var getCommand4 = defineCommand138({
16930
16957
  });
16931
16958
 
16932
16959
  // src/commands/testimonials/list.ts
16933
- import { defineCommand as defineCommand139 } from "citty";
16960
+ import { defineCommand as defineCommand141 } from "citty";
16934
16961
  registerSchema({
16935
16962
  command: "testimonials.list",
16936
16963
  description: "List testimonials with optional filters.",
@@ -16960,7 +16987,7 @@ registerSchema({
16960
16987
  limit: { type: "number", description: "Max results (default 50)", required: false, default: 50 }
16961
16988
  }
16962
16989
  });
16963
- var listCommand4 = defineCommand139({
16990
+ var listCommand4 = defineCommand141({
16964
16991
  meta: {
16965
16992
  name: "list",
16966
16993
  description: "List testimonials with optional filters. Example: baker testimonials list --source google --sentiment positive"
@@ -17009,7 +17036,7 @@ var listCommand4 = defineCommand139({
17009
17036
  });
17010
17037
 
17011
17038
  // src/commands/testimonials/search.ts
17012
- import { defineCommand as defineCommand140 } from "citty";
17039
+ import { defineCommand as defineCommand142 } from "citty";
17013
17040
  registerSchema({
17014
17041
  command: "testimonials.search",
17015
17042
  description: "Search testimonials by text query. Uses hybrid BM25 + vector + reranking.",
@@ -17040,7 +17067,7 @@ registerSchema({
17040
17067
  tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
17041
17068
  }
17042
17069
  });
17043
- var searchCommand2 = defineCommand140({
17070
+ var searchCommand2 = defineCommand142({
17044
17071
  meta: {
17045
17072
  name: "search",
17046
17073
  description: "Semantic search testimonials by text query. Uses hybrid BM25 + vector + reranking. Example: baker testimonials search 'great service' --rating-min 4"
@@ -17114,7 +17141,7 @@ var searchCommand2 = defineCommand140({
17114
17141
  var tagsCommand3 = makeTagsCommand("testimonials", "testimonial", "/api/testimonials/tags");
17115
17142
 
17116
17143
  // src/commands/testimonials/index.ts
17117
- var testimonialsCommand = defineCommand141({
17144
+ var testimonialsCommand = defineCommand143({
17118
17145
  meta: {
17119
17146
  name: "testimonials",
17120
17147
  description: `Find and browse testimonials in Baker. Subcommands: search, get, list, tags.
@@ -17135,10 +17162,10 @@ Examples:
17135
17162
  });
17136
17163
 
17137
17164
  // src/commands/videos/index.ts
17138
- import { defineCommand as defineCommand146 } from "citty";
17165
+ import { defineCommand as defineCommand148 } from "citty";
17139
17166
 
17140
17167
  // src/commands/videos/delete.ts
17141
- import { defineCommand as defineCommand142 } from "citty";
17168
+ import { defineCommand as defineCommand144 } from "citty";
17142
17169
  registerSchema({
17143
17170
  command: "videos.delete",
17144
17171
  description: "Delete a video by ID",
@@ -17152,7 +17179,7 @@ registerSchema({
17152
17179
  }
17153
17180
  }
17154
17181
  });
17155
- var deleteCommand3 = defineCommand142({
17182
+ var deleteCommand3 = defineCommand144({
17156
17183
  meta: {
17157
17184
  name: "delete",
17158
17185
  description: "Delete a video by ID. Use --dry-run to preview. Example: baker videos delete j571abc123 --dry-run"
@@ -17193,7 +17220,7 @@ var deleteCommand3 = defineCommand142({
17193
17220
  });
17194
17221
 
17195
17222
  // src/commands/videos/get.ts
17196
- import { defineCommand as defineCommand143 } from "citty";
17223
+ import { defineCommand as defineCommand145 } from "citty";
17197
17224
  registerSchema({
17198
17225
  command: "videos.get",
17199
17226
  description: "Get a single video by ID",
@@ -17201,7 +17228,7 @@ registerSchema({
17201
17228
  id: { type: "string", description: "Video ID", required: true }
17202
17229
  }
17203
17230
  });
17204
- var getCommand5 = defineCommand143({
17231
+ var getCommand5 = defineCommand145({
17205
17232
  meta: { name: "get", description: "Get a single video by ID. Example: baker videos get j571abc123" },
17206
17233
  args: {
17207
17234
  id: { type: "positional", description: "Video ID", required: false },
@@ -17238,7 +17265,7 @@ var getCommand5 = defineCommand143({
17238
17265
  });
17239
17266
 
17240
17267
  // src/commands/videos/search.ts
17241
- import { defineCommand as defineCommand144 } from "citty";
17268
+ import { defineCommand as defineCommand146 } from "citty";
17242
17269
  registerSchema({
17243
17270
  command: "videos.search",
17244
17271
  description: "Search videos by text query. Only returns ready videos.",
@@ -17248,7 +17275,7 @@ registerSchema({
17248
17275
  tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
17249
17276
  }
17250
17277
  });
17251
- var searchCommand3 = defineCommand144({
17278
+ var searchCommand3 = defineCommand146({
17252
17279
  meta: {
17253
17280
  name: "search",
17254
17281
  description: "Semantic search videos by text query. Uses hybrid BM25 + vector + reranking. Example: baker videos search 'product demo' --tags tutorial"
@@ -17298,10 +17325,10 @@ var searchCommand3 = defineCommand144({
17298
17325
  var tagsCommand4 = makeTagsCommand("videos", "video", "/api/videos/tags");
17299
17326
 
17300
17327
  // src/commands/videos/upload.ts
17301
- import { readFile as readFile13, stat as stat3 } from "fs/promises";
17328
+ import { readFile as readFile12, stat as stat3 } from "fs/promises";
17302
17329
  import { extname as extname3 } from "path";
17303
- import { defineCommand as defineCommand145 } from "citty";
17304
- var MIME_MAP2 = {
17330
+ import { defineCommand as defineCommand147 } from "citty";
17331
+ var MIME_MAP = {
17305
17332
  ".mp4": "video/mp4",
17306
17333
  ".mov": "video/quicktime",
17307
17334
  ".webm": "video/webm",
@@ -17326,15 +17353,15 @@ registerSchema({
17326
17353
  }
17327
17354
  }
17328
17355
  });
17329
- function detectContentType2(filePath) {
17356
+ function detectContentType(filePath) {
17330
17357
  const ext = extname3(filePath).toLowerCase();
17331
- const mime = MIME_MAP2[ext];
17358
+ const mime = MIME_MAP[ext];
17332
17359
  if (!mime) {
17333
17360
  throw new ApiError("VALIDATION_ERROR", `Cannot detect content type for extension "${ext}". Use --content-type.`);
17334
17361
  }
17335
17362
  return mime;
17336
17363
  }
17337
- var uploadCommand2 = defineCommand145({
17364
+ var uploadCommand2 = defineCommand147({
17338
17365
  meta: {
17339
17366
  name: "upload",
17340
17367
  description: "Upload a video file to Baker via Mux direct upload. Auto-detects content type. Example: baker videos upload ./demo.mp4"
@@ -17351,7 +17378,7 @@ var uploadCommand2 = defineCommand145({
17351
17378
  writeJson({ ok: false, error: { code: "VALIDATION_ERROR", message: "File path is required" } });
17352
17379
  process.exit(1);
17353
17380
  }
17354
- const contentType = args["content-type"] || detectContentType2(filePath);
17381
+ const contentType = args["content-type"] || detectContentType(filePath);
17355
17382
  if (args["dry-run"]) {
17356
17383
  const fileStats = await stat3(filePath);
17357
17384
  writeJson({
@@ -17363,7 +17390,7 @@ var uploadCommand2 = defineCommand145({
17363
17390
  return;
17364
17391
  }
17365
17392
  const { uploadUrl, videoId } = await apiPost("/api/videos/upload", {});
17366
- const fileBuffer = await readFile13(filePath);
17393
+ const fileBuffer = await readFile12(filePath);
17367
17394
  const uploadResponse = await fetch(uploadUrl, {
17368
17395
  method: "PUT",
17369
17396
  headers: { "Content-Type": contentType },
@@ -17388,7 +17415,7 @@ var uploadCommand2 = defineCommand145({
17388
17415
  });
17389
17416
 
17390
17417
  // src/commands/videos/index.ts
17391
- var videosCommand = defineCommand146({
17418
+ var videosCommand = defineCommand148({
17392
17419
  meta: {
17393
17420
  name: "videos",
17394
17421
  description: `Find and manage videos in Baker. Subcommands: search, get, upload, delete, tags.
@@ -17411,10 +17438,10 @@ Examples:
17411
17438
  });
17412
17439
 
17413
17440
  // src/commands/winning-ads/index.ts
17414
- import { defineCommand as defineCommand149 } from "citty";
17441
+ import { defineCommand as defineCommand151 } from "citty";
17415
17442
 
17416
17443
  // src/commands/winning-ads/advertisers.ts
17417
- import { defineCommand as defineCommand147 } from "citty";
17444
+ import { defineCommand as defineCommand149 } from "citty";
17418
17445
  registerSchema({
17419
17446
  command: "winning-ads.advertisers",
17420
17447
  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).",
@@ -17427,7 +17454,7 @@ registerSchema({
17427
17454
  function identity(record) {
17428
17455
  return record;
17429
17456
  }
17430
- var advertisersCommand2 = defineCommand147({
17457
+ var advertisersCommand2 = defineCommand149({
17431
17458
  meta: {
17432
17459
  name: "advertisers",
17433
17460
  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'
@@ -17478,7 +17505,7 @@ var advertisersCommand2 = defineCommand147({
17478
17505
  });
17479
17506
 
17480
17507
  // src/commands/winning-ads/search.ts
17481
- import { defineCommand as defineCommand148 } from "citty";
17508
+ import { defineCommand as defineCommand150 } from "citty";
17482
17509
  registerSchema({
17483
17510
  command: "winning-ads.search",
17484
17511
  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.",
@@ -17586,7 +17613,7 @@ function buildSearchBody(args) {
17586
17613
  }
17587
17614
  return body;
17588
17615
  }
17589
- var searchCommand4 = defineCommand148({
17616
+ var searchCommand4 = defineCommand150({
17590
17617
  meta: {
17591
17618
  name: "search",
17592
17619
  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"
@@ -17698,7 +17725,7 @@ var searchCommand4 = defineCommand148({
17698
17725
  });
17699
17726
 
17700
17727
  // src/commands/winning-ads/index.ts
17701
- var winningAdsCommand = defineCommand149({
17728
+ var winningAdsCommand = defineCommand151({
17702
17729
  meta: {
17703
17730
  name: "winning-ads",
17704
17731
  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.
@@ -17738,7 +17765,7 @@ function getCliVersion() {
17738
17765
  }
17739
17766
 
17740
17767
  // src/cli.ts
17741
- var main = defineCommand150({
17768
+ var main = defineCommand152({
17742
17769
  meta: {
17743
17770
  name: "baker",
17744
17771
  version: getCliVersion(),
@@ -17757,6 +17784,7 @@ Introspection: Run 'baker schema <command>' to inspect argument schemas.`
17757
17784
  ga4: ga4Command,
17758
17785
  gsc: gscCommand,
17759
17786
  research: researchCommand,
17787
+ creatives: creativesCommand3,
17760
17788
  images: imagesCommand,
17761
17789
  videos: videosCommand,
17762
17790
  testimonials: testimonialsCommand,