@koda-sl/baker-cli 0.375.0 → 0.376.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
@@ -80,7 +80,7 @@ import {
80
80
  resolveEffectiveStatus,
81
81
  statusFilterHints,
82
82
  todayIso
83
- } from "./chunk-N3H66QUV.js";
83
+ } from "./chunk-WKGKDYX3.js";
84
84
  import {
85
85
  buildQueryCacheKey,
86
86
  cacheGet,
@@ -96,7 +96,7 @@ import {
96
96
  writeAdsJson,
97
97
  writeAdsOutput,
98
98
  writeJsonEnvelope
99
- } from "./chunk-BJP4G3X4.js";
99
+ } from "./chunk-XHC4LMK4.js";
100
100
  import {
101
101
  ApiError,
102
102
  apiGet,
@@ -174,6 +174,17 @@ function rewriteBeforeDoubleDash(argv, rewrite) {
174
174
  return argv.flatMap((token, index) => index >= limit ? [token] : rewrite(token));
175
175
  }
176
176
 
177
+ // src/closed-pipe.ts
178
+ function exitQuietlyOnClosedPipe(stream, exit) {
179
+ stream.on("error", (err) => {
180
+ if (err.code === "EPIPE") {
181
+ exit(0);
182
+ return;
183
+ }
184
+ throw err;
185
+ });
186
+ }
187
+
177
188
  // src/commands/actions/index.ts
178
189
  import { defineCommand as defineCommand18 } from "citty";
179
190
 
@@ -23194,9 +23205,72 @@ Subcommands:
23194
23205
 
23195
23206
  // src/commands/ads/linkedin/creatives.ts
23196
23207
  import { defineCommand as defineCommand44 } from "citty";
23208
+
23209
+ // src/commands/ads/list-rows.ts
23197
23210
  function asRecord(value) {
23198
23211
  return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
23199
23212
  }
23213
+ function readPath2(row, path48) {
23214
+ let current = row;
23215
+ for (const segment of path48.split(".")) {
23216
+ const record = asRecord(current);
23217
+ if (!record) return void 0;
23218
+ current = record[segment];
23219
+ }
23220
+ return current;
23221
+ }
23222
+ function projectFields(rows, paths) {
23223
+ return rows.map((row) => {
23224
+ const projected = {};
23225
+ for (const path48 of paths) {
23226
+ const value = readPath2(row, path48);
23227
+ if (value !== void 0) {
23228
+ projected[path48] = value;
23229
+ }
23230
+ }
23231
+ return projected;
23232
+ });
23233
+ }
23234
+ function shapeListRows(rows, args5, compact4) {
23235
+ const raw = rows;
23236
+ const fields = typeof args5.fields === "string" ? args5.fields : void 0;
23237
+ if (fields) {
23238
+ const paths = fields.split(",").map((field) => field.trim()).filter((field) => field.length > 0);
23239
+ if (paths.length > 0) {
23240
+ const projected = projectFields(raw, paths).map((row, i) => {
23241
+ const missing = paths.filter((path48) => row[path48] === void 0);
23242
+ const source = rows[i];
23243
+ if (missing.length === 0 || source === void 0) return row;
23244
+ const compactRow3 = compact4.row(source);
23245
+ for (const path48 of missing) {
23246
+ if (compactRow3[path48] !== void 0) row[path48] = compactRow3[path48];
23247
+ }
23248
+ return row;
23249
+ });
23250
+ const unmatched = paths.filter((path48) => projected.every((row) => row[path48] === void 0));
23251
+ if (projected.length === 0 || unmatched.length === 0) return { rows: projected, fields: paths };
23252
+ const carried = /* @__PURE__ */ new Set([...compact4.columns, ...raw.flatMap((row) => Object.keys(row))]);
23253
+ return {
23254
+ rows: projected,
23255
+ fields: paths,
23256
+ hints: [
23257
+ `--fields matched nothing for: ${unmatched.join(", ")}. The fields these rows carry are: ${[...carried].join(", ")} (reach nested ones with dots, e.g. targeting.geo_locations).`
23258
+ ]
23259
+ };
23260
+ }
23261
+ }
23262
+ if (args5.full) {
23263
+ const columns = /* @__PURE__ */ new Set();
23264
+ for (const row of raw) for (const key of Object.keys(row)) columns.add(key);
23265
+ return { rows: raw, fields: [...columns] };
23266
+ }
23267
+ return { rows: rows.map(compact4.row), fields: [...compact4.columns] };
23268
+ }
23269
+
23270
+ // src/commands/ads/linkedin/creatives.ts
23271
+ function asRecord2(value) {
23272
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
23273
+ }
23200
23274
  function asString(value) {
23201
23275
  return typeof value === "string" && value.length > 0 ? value : void 0;
23202
23276
  }
@@ -23204,12 +23278,12 @@ function creativeDestination(content) {
23204
23278
  if (!content) return { format: "unknown" };
23205
23279
  const reference = asString(content.reference);
23206
23280
  if (reference) return { format: "post", postUrn: reference };
23207
- const textAd = asRecord(content.textAd);
23281
+ const textAd = asRecord2(content.textAd);
23208
23282
  if (textAd) return { format: "text", landingUrl: asString(textAd.landingPage) };
23209
- const spotlight = asRecord(content.spotlight);
23283
+ const spotlight = asRecord2(content.spotlight);
23210
23284
  if (spotlight) return { format: "spotlight", landingUrl: asString(spotlight.landingPage) };
23211
- if (asRecord(content.follower)) return { format: "follower" };
23212
- if (asRecord(content.jobs)) return { format: "jobs" };
23285
+ if (asRecord2(content.follower)) return { format: "follower" };
23286
+ if (asRecord2(content.jobs)) return { format: "jobs" };
23213
23287
  return { format: "unknown" };
23214
23288
  }
23215
23289
  var COMPACT_COLUMNS = [
@@ -23237,27 +23311,6 @@ function compactRow(row) {
23237
23311
  ...destination.postUrn ? { postUrn: destination.postUrn } : {}
23238
23312
  };
23239
23313
  }
23240
- function readPath2(row, path48) {
23241
- let current = row;
23242
- for (const segment of path48.split(".")) {
23243
- const record = asRecord(current);
23244
- if (!record) return void 0;
23245
- current = record[segment];
23246
- }
23247
- return current;
23248
- }
23249
- function projectFields(rows, paths) {
23250
- return rows.map((row) => {
23251
- const projected = {};
23252
- for (const path48 of paths) {
23253
- const value = readPath2(row, path48);
23254
- if (value !== void 0) {
23255
- projected[path48] = value;
23256
- }
23257
- }
23258
- return projected;
23259
- });
23260
- }
23261
23314
  function unmappedShapeWarnings(rows, rawContentReturned) {
23262
23315
  const unmapped = rows.filter((row) => row.content && creativeDestination(row.content).format === "unknown");
23263
23316
  if (unmapped.length === 0) return [];
@@ -23269,18 +23322,6 @@ function unmappedShapeWarnings(rows, rawContentReturned) {
23269
23322
  }
23270
23323
  ];
23271
23324
  }
23272
- function shapeRows(rows, args5) {
23273
- const raw = rows;
23274
- const fields = typeof args5.fields === "string" ? args5.fields : void 0;
23275
- if (fields) {
23276
- const paths = fields.split(",").map((field) => field.trim()).filter((field) => field.length > 0);
23277
- if (paths.length > 0) {
23278
- return { rows: projectFields(raw, paths), fields: paths };
23279
- }
23280
- }
23281
- if (args5.full) return { rows: raw };
23282
- return { rows: rows.map(compactRow), fields: [...COMPACT_COLUMNS] };
23283
- }
23284
23325
  var listArgs3 = {
23285
23326
  "account-id": { type: "string", description: "Numeric account ID or urn:li:sponsoredAccount:N" },
23286
23327
  "account-urn": { type: "string", description: "Alias for --account-id" },
@@ -23312,14 +23353,22 @@ var creativesListCommand = defineCommand44({
23312
23353
  if (args5.limit) params.limit = String(args5.limit);
23313
23354
  if (args5["no-cache"]) params["skip-cache"] = "true";
23314
23355
  const data = await apiGet("/api/ads/linkedin/creatives", params);
23315
- const shaped = shapeRows(data, args5);
23356
+ const shaped = shapeListRows(data, args5, {
23357
+ row: compactRow,
23358
+ columns: COMPACT_COLUMNS
23359
+ });
23316
23360
  const fmt = csvOrJson2(args5);
23317
23361
  if (fmt !== "json") {
23318
- writeAdsOutput(shaped.rows, fmt, shaped.fields);
23362
+ writeAdsOutput(shaped.rows, fmt, shaped.fields, shaped.hints);
23319
23363
  return;
23320
23364
  }
23321
23365
  const warnings = unmappedShapeWarnings(data, args5.full === true);
23322
- writeAdsJson({ ok: true, data: shaped.rows, ...warnings.length > 0 ? { warnings } : {} });
23366
+ writeJsonEnvelope({
23367
+ ok: true,
23368
+ data: shaped.rows,
23369
+ ...warnings.length > 0 ? { warnings } : {},
23370
+ ...shaped.hints ? { hints: shaped.hints } : {}
23371
+ });
23323
23372
  } catch (err) {
23324
23373
  handleLinkedinError(err);
23325
23374
  }
@@ -24330,22 +24379,191 @@ Examples:
24330
24379
 
24331
24380
  // src/commands/ads/meta/activities.ts
24332
24381
  import { defineCommand as defineCommand56 } from "citty";
24382
+
24383
+ // src/commands/ads/meta/list-rows.ts
24384
+ function pick(row, keys) {
24385
+ const picked = {};
24386
+ for (const key of keys) {
24387
+ if (row[key] !== void 0) picked[key] = row[key];
24388
+ }
24389
+ return picked;
24390
+ }
24391
+ var CAMPAIGN_COLUMNS = ["id", "name", "effective_status", "daily_budget", "lifetime_budget", "created_date"];
24392
+ function compactCampaign(row) {
24393
+ const created = row.created_time;
24394
+ return {
24395
+ ...pick(row, ["id", "name", "effective_status", "daily_budget", "lifetime_budget"]),
24396
+ ...typeof created === "string" ? { created_date: created.slice(0, 10) } : {}
24397
+ };
24398
+ }
24399
+ var ADSET_KEYS = [
24400
+ "id",
24401
+ "name",
24402
+ "campaign_id",
24403
+ "effective_status",
24404
+ "optimization_goal",
24405
+ "billing_event",
24406
+ "bid_strategy",
24407
+ "daily_budget",
24408
+ "lifetime_budget",
24409
+ "destination_type",
24410
+ // A Dynamic Creative ad set refuses every new ad, which changes the plan before anything is staged.
24411
+ "is_dynamic_creative"
24412
+ ];
24413
+ var ADSET_COLUMNS = [...ADSET_KEYS, "learning_stage", "end_time", "created_time"];
24414
+ function compactAdSet(row) {
24415
+ const learning = asRecord(row.learning_stage_info)?.status;
24416
+ return {
24417
+ ...pick(row, ADSET_KEYS),
24418
+ ...typeof learning === "string" ? { learning_stage: learning } : {},
24419
+ ...pick(row, ["end_time", "created_time"])
24420
+ };
24421
+ }
24422
+ var AD_COLUMNS = [
24423
+ "id",
24424
+ "name",
24425
+ "adset_id",
24426
+ "campaign_id",
24427
+ "effective_status",
24428
+ "creative_id",
24429
+ "issues",
24430
+ "created_time"
24431
+ ];
24432
+ function adIssues(value) {
24433
+ if (!Array.isArray(value)) return [];
24434
+ return value.flatMap((entry) => {
24435
+ const issue = asRecord(entry);
24436
+ const text2 = issue?.error_summary ?? issue?.error_message;
24437
+ return typeof text2 === "string" && text2 ? [text2] : [];
24438
+ });
24439
+ }
24440
+ function compactAd(row) {
24441
+ const creativeId = asRecord(row.creative)?.id;
24442
+ const issues = adIssues(row.issues_info);
24443
+ return {
24444
+ ...pick(row, ["id", "name", "adset_id", "campaign_id", "effective_status"]),
24445
+ ...creativeId !== void 0 ? { creative_id: creativeId } : {},
24446
+ ...issues.length > 0 ? { issues } : {},
24447
+ ...pick(row, ["created_time"])
24448
+ };
24449
+ }
24450
+ var ACTIVITY_COLUMNS = [
24451
+ "event_time",
24452
+ "event_type",
24453
+ "actor_name",
24454
+ "object_type",
24455
+ "object_name",
24456
+ "object_id",
24457
+ "change"
24458
+ ];
24459
+ function isScalar(value) {
24460
+ return value === null || typeof value === "string" || typeof value === "number";
24461
+ }
24462
+ function activityChange(extraData) {
24463
+ if (typeof extraData !== "string") return void 0;
24464
+ let parsed;
24465
+ try {
24466
+ parsed = JSON.parse(extraData);
24467
+ } catch {
24468
+ return void 0;
24469
+ }
24470
+ const data = asRecord(parsed);
24471
+ if (!data || !("new_value" in data) || !("old_value" in data)) return void 0;
24472
+ const { old_value: before, new_value: after } = data;
24473
+ if (!isScalar(before) || !isScalar(after)) return void 0;
24474
+ const show = (value) => value === null ? "(none)" : String(value);
24475
+ return `${show(before)} \u2192 ${show(after)}`;
24476
+ }
24477
+ function compactActivity(row) {
24478
+ const change = activityChange(row.extra_data);
24479
+ return {
24480
+ ...pick(row, ["event_time", "event_type", "actor_name", "object_type", "object_name", "object_id"]),
24481
+ ...change !== void 0 ? { change } : {}
24482
+ };
24483
+ }
24484
+ var PROJECTIONS = {
24485
+ campaigns: { row: compactCampaign, columns: CAMPAIGN_COLUMNS },
24486
+ adsets: { row: compactAdSet, columns: ADSET_COLUMNS },
24487
+ ads: { row: compactAd, columns: AD_COLUMNS },
24488
+ activities: { row: compactActivity, columns: ACTIVITY_COLUMNS }
24489
+ };
24490
+ function shapeMetaListRows(kind, rows, args5) {
24491
+ return shapeListRows(rows, args5, PROJECTIONS[kind]);
24492
+ }
24493
+ var NOUNS = {
24494
+ campaigns: "campaigns",
24495
+ adsets: "ad sets",
24496
+ ads: "ads",
24497
+ activities: "activities"
24498
+ };
24499
+ function writeMetaListRows(kind, shaped, format, hints2 = []) {
24500
+ if (format === "md" && shaped.rows.length === 0) {
24501
+ process.stdout.write(`${hints2.length > 0 ? hints2.join("\n") : `No ${NOUNS[kind]} matched.`}
24502
+ `);
24503
+ return;
24504
+ }
24505
+ writeAdsOutput(shaped.rows, format, shaped.fields, [...hints2, ...shaped.hints ?? []]);
24506
+ }
24507
+ var META_LIST_SHAPE_ARGS = {
24508
+ fields: {
24509
+ type: "string",
24510
+ description: "CSV of dotted paths to return instead of the compact row, e.g. id,name,targeting.geo_locations"
24511
+ },
24512
+ full: { type: "boolean", description: "Return every field Meta sent (targeting, tracking specs, raw extra_data)" },
24513
+ output: {
24514
+ type: "string",
24515
+ description: "md|json|csv|jsonl \u2014 md (default) prints a table; json returns the rows in the { ok, data } envelope",
24516
+ default: "md"
24517
+ }
24518
+ };
24519
+ function registerMetaListSchema(kind, description, args5) {
24520
+ registerSchema({
24521
+ command: `ads.meta.${kind}`,
24522
+ description,
24523
+ args: Object.fromEntries(
24524
+ Object.entries(args5).map(([name, def]) => [
24525
+ name,
24526
+ {
24527
+ type: def.type,
24528
+ description: def.description ?? "",
24529
+ required: false,
24530
+ ...def.default !== void 0 ? { default: def.default } : {}
24531
+ }
24532
+ ])
24533
+ )
24534
+ });
24535
+ }
24536
+
24537
+ // src/commands/ads/meta/activities.ts
24538
+ var listArgs4 = {
24539
+ "account-id": { type: "string", description: "Meta ad account ID" },
24540
+ days: { type: "string", description: "Lookback days (default 7)" },
24541
+ limit: { type: "string", description: "Max rows" },
24542
+ "no-cache": NO_CACHE_ARG,
24543
+ ...META_LIST_SHAPE_ARGS
24544
+ };
24545
+ registerMetaListSchema(
24546
+ "activities",
24547
+ "Account change log, as a table by default, one row per event: event_time, event_type, actor_name, object_type, object_name, object_id, and change ('old \u2192 new' when the change is a single value). Start here: baker ads meta activities --account-id act_123 --days 2. --fields event_time,object_name,extra_data or --full for the raw change payload; --output json returns the rows in the envelope.",
24548
+ listArgs4
24549
+ );
24333
24550
  var activitiesCommand = defineCommand56({
24334
24551
  meta: {
24335
24552
  name: "activities",
24336
24553
  description: `Audit log of recent ad-account changes (created, paused, edited). Default lookback 7 days,
24337
24554
  ~90 day retention server-side.
24338
24555
 
24556
+ A table by default, one row per event: event_time, event_type, actor_name, object_type,
24557
+ object_name, object_id, and change ("old \u2192 new" when the change is a single value: status,
24558
+ name, budget, goal). --fields takes dotted paths (extra_data holds the raw change); --full returns
24559
+ every field Meta sent; --output json returns the rows as JSON.
24560
+
24339
24561
  Examples:
24340
- baker ads meta activities --account-id act_123 --days 14`
24341
- },
24342
- args: {
24343
- "account-id": { type: "string", description: "Meta ad account ID" },
24344
- days: { type: "string", description: "Lookback days (default 7)" },
24345
- limit: { type: "string", description: "Max rows" },
24346
- "no-cache": NO_CACHE_ARG,
24347
- output: { type: "string", description: "Output format", default: "json" }
24562
+ baker ads meta activities --account-id act_123 --days 14
24563
+ baker ads meta activities --account-id act_123 --days 2 --output json
24564
+ baker ads meta activities --account-id act_123 --fields event_time,object_name,extra_data`
24348
24565
  },
24566
+ args: listArgs4,
24349
24567
  run: async ({ args: args5 }) => {
24350
24568
  const accountId = resolveAccountIdArg(args5);
24351
24569
  try {
@@ -24354,12 +24572,8 @@ Examples:
24354
24572
  if (args5.limit) params.limit = args5.limit;
24355
24573
  if (args5["no-cache"]) params["skip-cache"] = "true";
24356
24574
  const data = await apiGet("/api/ads/meta/activities", params);
24357
- const fmt = csvOrJson(args5);
24358
- if (fmt !== "json") {
24359
- writeAdsOutput(data, fmt);
24360
- return;
24361
- }
24362
- writeAdsJson({ ok: true, data });
24575
+ const shaped = shapeMetaListRows("activities", data, args5);
24576
+ writeMetaListRows("activities", shaped, csvOrJson(args5));
24363
24577
  } catch (err) {
24364
24578
  handleMetaError(err);
24365
24579
  }
@@ -26620,8 +26834,8 @@ Example: baker ads meta ads retag 120252158038400247 --url-tags "utm_source={{si
26620
26834
  run: async ({ args: args5 }) => {
26621
26835
  const { apiPost: apiPost2 } = await import("./client-GR6YL3YX.js");
26622
26836
  const { requireChatId: requireChatId2 } = await import("./env-4P5HOGNA.js");
26623
- const { writeJsonEnvelope: writeJsonEnvelope2 } = await import("./output-AFWVXYWA.js");
26624
- const { handleMetaError: handleMetaError2 } = await import("./shared-SDKT2Y7Z.js");
26837
+ const { writeJsonEnvelope: writeJsonEnvelope2 } = await import("./output-NMQXZF3Z.js");
26838
+ const { handleMetaError: handleMetaError2 } = await import("./shared-VAA3SCQR.js");
26625
26839
  try {
26626
26840
  const accountId = bareAccountId2(args5);
26627
26841
  const urlTags = typeof args5["url-tags"] === "string" ? args5["url-tags"] : void 0;
@@ -26768,8 +26982,8 @@ function duplicateCommand2(entity, label) {
26768
26982
  run: async ({ args: args5 }) => {
26769
26983
  const { apiPost: apiPost2 } = await import("./client-GR6YL3YX.js");
26770
26984
  const { requireChatId: requireChatId2 } = await import("./env-4P5HOGNA.js");
26771
- const { writeJsonEnvelope: writeJsonEnvelope2 } = await import("./output-AFWVXYWA.js");
26772
- const { handleMetaError: handleMetaError2 } = await import("./shared-SDKT2Y7Z.js");
26985
+ const { writeJsonEnvelope: writeJsonEnvelope2 } = await import("./output-NMQXZF3Z.js");
26986
+ const { handleMetaError: handleMetaError2 } = await import("./shared-VAA3SCQR.js");
26773
26987
  try {
26774
26988
  const accountId = bareAccountId2(args5);
26775
26989
  const chatId = requireChatId2();
@@ -26802,7 +27016,7 @@ var adsArchiveCommand = statusCommand3("archive", "ad.update", "ad");
26802
27016
  var adsDuplicateCommand = duplicateCommand2("ad", "ad");
26803
27017
 
26804
27018
  // src/commands/ads/meta/ads.ts
26805
- var listArgs4 = {
27019
+ var listArgs5 = {
26806
27020
  "account-id": { type: "string", description: "Meta ad account ID" },
26807
27021
  "adset-id": { type: "string", description: "Filter to one adset" },
26808
27022
  "campaign-id": { type: "string", description: "Filter to one campaign" },
@@ -26810,14 +27024,19 @@ var listArgs4 = {
26810
27024
  "all-statuses": { type: "boolean", description: "Drop the default ACTIVE filter" },
26811
27025
  limit: { type: "string", description: "Max rows (default 1000)" },
26812
27026
  "no-cache": NO_CACHE_ARG,
26813
- output: { type: "string", description: "Output format", default: "json" }
27027
+ ...META_LIST_SHAPE_ARGS
26814
27028
  };
27029
+ registerMetaListSchema(
27030
+ "ads",
27031
+ "List ads in a Meta ad account, as a table by default: id, name, adset_id, campaign_id, effective_status, creative_id, issues (why an ad is WITH_ISSUES), created_time. Start here: baker ads meta ads --adset-id 6123. --fields takes dotted paths (e.g. id,tracking_specs); --full returns every field Meta sent; --output json returns the rows in the envelope.",
27032
+ listArgs5
27033
+ );
26815
27034
  var listCommand4 = defineCommand58({
26816
27035
  meta: {
26817
27036
  name: "list",
26818
27037
  description: "List ads in a Meta ad account. Runs by default when no subcommand is given. Example: baker ads meta ads --account-id act_123"
26819
27038
  },
26820
- args: listArgs4,
27039
+ args: listArgs5,
26821
27040
  run: async ({ args: args5 }) => {
26822
27041
  const accountId = resolveAccountIdArg(args5);
26823
27042
  const effectiveStatus = resolveEffectiveStatus(args5);
@@ -26829,7 +27048,8 @@ var listCommand4 = defineCommand58({
26829
27048
  if (args5.limit) params.limit = args5.limit;
26830
27049
  if (args5["no-cache"]) params["skip-cache"] = "true";
26831
27050
  const data = await apiGet("/api/ads/meta/ads", params);
26832
- writeAdsOutput(data, csvOrJson(args5), void 0, statusFilterHints(data, effectiveStatus, "ads"));
27051
+ const shaped = shapeMetaListRows("ads", data, args5);
27052
+ writeMetaListRows("ads", shaped, csvOrJson(args5), statusFilterHints(data, effectiveStatus, "ads"));
26833
27053
  } catch (err) {
26834
27054
  handleMetaError(err);
26835
27055
  }
@@ -26843,9 +27063,14 @@ Defaults to ACTIVE only \u2014 pass --all-statuses to widen. Write subcommands s
26843
27063
 
26844
27064
  The dashboard shows effective_status (e.g. WITH_ISSUES, PENDING_REVIEW, DISAPPROVED, ADSET_PAUSED), not status.
26845
27065
 
27066
+ Listings print a table by default: id, name, adset_id, campaign_id, effective_status, creative_id, issues
27067
+ (why an ad is WITH_ISSUES), created_time. --fields takes dotted paths (e.g. tracking_specs,
27068
+ preview_shareable_link); --full returns every field; --output json returns the rows as JSON.
27069
+
26846
27070
  Examples:
26847
27071
  baker ads meta ads --account-id act_123
26848
27072
  baker ads meta ads --adset-id 6123
27073
+ baker ads meta ads --adset-id 6123 --fields id,name,preview_shareable_link
26849
27074
  baker ads meta ads create --name "Ad 1" --adset meta_temp_as01 --creative meta_temp_cr01
26850
27075
  baker ads meta ads pause 6123 --account-id act_123
26851
27076
  baker ads meta ads retag 6123 --set "utm_medium=paid-social" \u2014 fix tracking on a LIVE ad, keeping everything else`
@@ -26864,27 +27089,32 @@ Examples:
26864
27089
  // subcommand name using THIS command's arg defs, so without them `--account-id act_1`
26865
27090
  // would read `act_1` as a subcommand. `default` (not `run`) dispatches the bare
26866
27091
  // invocation — citty falls through to `run` after a subcommand, double-executing it.
26867
- args: listArgs4,
27092
+ args: listArgs5,
26868
27093
  default: "list"
26869
27094
  });
26870
27095
 
26871
27096
  // src/commands/ads/meta/adsets.ts
26872
27097
  import { defineCommand as defineCommand59 } from "citty";
26873
- var listArgs5 = {
27098
+ var listArgs6 = {
26874
27099
  "account-id": { type: "string", description: "Meta ad account ID" },
26875
27100
  "campaign-id": { type: "string", description: "Filter to one campaign" },
26876
27101
  "effective-status": { type: "string", description: "Comma-separated effective_status filter (overrides default)" },
26877
27102
  "all-statuses": { type: "boolean", description: "Drop the default ACTIVE filter" },
26878
27103
  limit: { type: "string", description: "Max rows (default 1000)" },
26879
27104
  "no-cache": NO_CACHE_ARG,
26880
- output: { type: "string", description: "Output format", default: "json" }
27105
+ ...META_LIST_SHAPE_ARGS
26881
27106
  };
27107
+ registerMetaListSchema(
27108
+ "adsets",
27109
+ "List ad sets in a Meta ad account, as a table by default: id, name, campaign_id, effective_status, optimization_goal, billing_event, bid_strategy, budgets, destination_type, is_dynamic_creative, learning_stage, end_time, created_time. Targeting is not in the compact row \u2014 ask for it with --fields id,name,targeting (or --full). Start here: baker ads meta adsets --campaign-id 6123 --all-statuses. --output json returns the rows in the envelope.",
27110
+ listArgs6
27111
+ );
26882
27112
  var listCommand5 = defineCommand59({
26883
27113
  meta: {
26884
27114
  name: "list",
26885
27115
  description: "List ad sets in a Meta ad account. Runs by default when no subcommand is given. Example: baker ads meta adsets --account-id act_123"
26886
27116
  },
26887
- args: listArgs5,
27117
+ args: listArgs6,
26888
27118
  run: async ({ args: args5 }) => {
26889
27119
  const accountId = resolveAccountIdArg(args5);
26890
27120
  const effectiveStatus = resolveEffectiveStatus(args5);
@@ -26895,7 +27125,8 @@ var listCommand5 = defineCommand59({
26895
27125
  if (args5.limit) params.limit = args5.limit;
26896
27126
  if (args5["no-cache"]) params["skip-cache"] = "true";
26897
27127
  const data = await apiGet("/api/ads/meta/adsets", params);
26898
- writeAdsOutput(data, csvOrJson(args5), void 0, statusFilterHints(data, effectiveStatus, "ad sets"));
27128
+ const shaped = shapeMetaListRows("adsets", data, args5);
27129
+ writeMetaListRows("adsets", shaped, csvOrJson(args5), statusFilterHints(data, effectiveStatus, "ad sets"));
26899
27130
  } catch (err) {
26900
27131
  handleMetaError(err);
26901
27132
  }
@@ -26907,9 +27138,14 @@ var adsetsCommand = defineCommand59({
26907
27138
  description: `List ad sets in a Meta ad account, or stage writes (create/update/pause/resume/archive/duplicate).
26908
27139
  Defaults to ACTIVE only. Write subcommands stage ops on this chat's draft.
26909
27140
 
27141
+ Listings print a table by default: id, name, campaign_id, effective_status, optimization_goal, billing_event,
27142
+ bid_strategy, budgets, destination_type, is_dynamic_creative, learning_stage, end_time, created_time. Targeting
27143
+ is not in the compact row \u2014 ask for it with --fields (dotted paths) or --full. --output json returns the rows as JSON.
27144
+
26910
27145
  Examples:
26911
27146
  baker ads meta adsets --account-id act_123
26912
27147
  baker ads meta adsets --campaign-id 6123456789
27148
+ baker ads meta adsets --campaign-id 6123456789 --fields id,name,targeting.geo_locations
26913
27149
  baker ads meta adsets create --campaign meta_temp_ab12 --name "US 25-54" --optimization-goal LINK_CLICKS --billing-event IMPRESSIONS --daily-budget 50 --targeting-file t.json`
26914
27150
  },
26915
27151
  subCommands: {
@@ -26925,13 +27161,13 @@ Examples:
26925
27161
  // subcommand name using THIS command's arg defs, so without them `--account-id act_1`
26926
27162
  // would read `act_1` as a subcommand. `default` (not `run`) dispatches the bare
26927
27163
  // invocation — citty falls through to `run` after a subcommand, double-executing it.
26928
- args: listArgs5,
27164
+ args: listArgs6,
26929
27165
  default: "list"
26930
27166
  });
26931
27167
 
26932
27168
  // src/commands/ads/meta/audiences.ts
26933
27169
  import { defineCommand as defineCommand60 } from "citty";
26934
- var listArgs6 = {
27170
+ var listArgs7 = {
26935
27171
  "account-id": { type: "string", description: "Meta ad account ID" },
26936
27172
  limit: { type: "string", description: "Max rows" },
26937
27173
  "no-cache": NO_CACHE_ARG,
@@ -26942,7 +27178,7 @@ var listCommand6 = defineCommand60({
26942
27178
  name: "list",
26943
27179
  description: "List custom audiences. Runs by default when no subcommand is given. Example: baker ads meta audiences --account-id act_123"
26944
27180
  },
26945
- args: listArgs6,
27181
+ args: listArgs7,
26946
27182
  run: async ({ args: args5 }) => {
26947
27183
  const accountId = resolveAccountIdArg(args5);
26948
27184
  try {
@@ -26980,7 +27216,7 @@ Examples:
26980
27216
  // subcommand name using THIS command's arg defs, so without them `--account-id act_1`
26981
27217
  // would read `act_1` as a subcommand. `default` (not `run`) dispatches the bare
26982
27218
  // invocation — citty falls through to `run` after a subcommand, double-executing it.
26983
- args: listArgs6,
27219
+ args: listArgs7,
26984
27220
  default: "list"
26985
27221
  });
26986
27222
 
@@ -27017,20 +27253,25 @@ Examples:
27017
27253
 
27018
27254
  // src/commands/ads/meta/campaigns.ts
27019
27255
  import { defineCommand as defineCommand62 } from "citty";
27020
- var listArgs7 = {
27256
+ var listArgs8 = {
27021
27257
  "account-id": { type: "string", description: "Meta ad account ID" },
27022
27258
  "effective-status": { type: "string", description: "Comma-separated effective_status filter (overrides default)" },
27023
27259
  "all-statuses": { type: "boolean", description: "Drop the default ACTIVE filter and return everything" },
27024
27260
  limit: { type: "string", description: "Max rows (default 1000)" },
27025
27261
  "no-cache": NO_CACHE_ARG,
27026
- output: { type: "string", description: "Output format", default: "json" }
27262
+ ...META_LIST_SHAPE_ARGS
27027
27263
  };
27264
+ registerMetaListSchema(
27265
+ "campaigns",
27266
+ "List campaigns in a Meta ad account, as a table by default: id, name, effective_status, daily_budget, lifetime_budget, created_date. ACTIVE only unless --all-statuses. Start here: baker ads meta campaigns --account-id act_123 --all-statuses. --fields takes dotted paths for anything else (e.g. id,name,objective,bid_strategy,special_ad_categories); --full returns every field Meta sent; --output json returns the rows in the envelope.",
27267
+ listArgs8
27268
+ );
27028
27269
  var listCommand7 = defineCommand62({
27029
27270
  meta: {
27030
27271
  name: "list",
27031
27272
  description: "List campaigns for a Meta ad account. Runs by default when no subcommand is given. Example: baker ads meta campaigns --account-id act_123"
27032
27273
  },
27033
- args: listArgs7,
27274
+ args: listArgs8,
27034
27275
  run: async ({ args: args5 }) => {
27035
27276
  const accountId = resolveAccountIdArg(args5);
27036
27277
  const effectiveStatus = resolveEffectiveStatus(args5);
@@ -27040,7 +27281,8 @@ var listCommand7 = defineCommand62({
27040
27281
  if (args5.limit) params.limit = args5.limit;
27041
27282
  if (args5["no-cache"]) params["skip-cache"] = "true";
27042
27283
  const data = await apiGet("/api/ads/meta/campaigns", params);
27043
- writeAdsOutput(data, csvOrJson(args5), void 0, statusFilterHints(data, effectiveStatus, "campaigns"));
27284
+ const shaped = shapeMetaListRows("campaigns", data, args5);
27285
+ writeMetaListRows("campaigns", shaped, csvOrJson(args5), statusFilterHints(data, effectiveStatus, "campaigns"));
27044
27286
  } catch (err) {
27045
27287
  handleMetaError(err);
27046
27288
  }
@@ -27056,9 +27298,15 @@ apply only when the chat is published.
27056
27298
  In Meta's API "campaign" is the top-of-tree object (what marketers usually call a campaign group).
27057
27299
  The dashboard shows effective_status: ACTIVE, PAUSED, DELETED, ARCHIVED, IN_PROCESS, WITH_ISSUES, etc.
27058
27300
 
27301
+ Listings print a table by default: id, name, effective_status, daily/lifetime budget, created_date.
27302
+ --fields takes dotted paths for anything else (objective, bid_strategy, special_ad_categories, created_time);
27303
+ --full returns every field; --output json returns the same rows in the { ok, data } envelope.
27304
+
27059
27305
  Examples:
27060
27306
  baker ads meta campaigns --account-id act_123 # ACTIVE only
27061
27307
  baker ads meta campaigns --account-id act_123 --all-statuses # everything
27308
+ baker ads meta campaigns --account-id act_123 --fields id,name,objective,bid_strategy,special_ad_categories
27309
+ baker ads meta campaigns --account-id act_123 --output json # rows as JSON
27062
27310
  baker ads meta campaigns create --account-id act_123 --name "Q3" --objective OUTCOME_LEADS --daily-budget 50
27063
27311
  baker ads meta campaigns pause 6123 --account-id act_123`
27064
27312
  },
@@ -27075,13 +27323,13 @@ Examples:
27075
27323
  // subcommand name using THIS command's arg defs, so without them `--account-id act_1`
27076
27324
  // would read `act_1` as a subcommand. `default` (not `run`) dispatches the bare
27077
27325
  // invocation — citty falls through to `run` after a subcommand, double-executing it.
27078
- args: listArgs7,
27326
+ args: listArgs8,
27079
27327
  default: "list"
27080
27328
  });
27081
27329
 
27082
27330
  // src/commands/ads/meta/creatives.ts
27083
27331
  import { defineCommand as defineCommand63 } from "citty";
27084
- var listArgs8 = {
27332
+ var listArgs9 = {
27085
27333
  "account-id": { type: "string", description: "Meta ad account ID (required if no --creative-id)" },
27086
27334
  "creative-id": { type: "string", description: "Single creative ID" },
27087
27335
  limit: { type: "string", description: "Max rows (default 500)" },
@@ -27093,7 +27341,7 @@ var listCommand8 = defineCommand63({
27093
27341
  name: "list",
27094
27342
  description: "List ad creatives, or fetch one by ID. Runs by default when no subcommand is given. Example: baker ads meta creatives --account-id act_123"
27095
27343
  },
27096
- args: listArgs8,
27344
+ args: listArgs9,
27097
27345
  run: async ({ args: args5 }) => {
27098
27346
  try {
27099
27347
  const params = {};
@@ -27139,7 +27387,7 @@ Examples:
27139
27387
  // subcommand name using THIS command's arg defs, so without them `--account-id act_1`
27140
27388
  // would read `act_1` as a subcommand. `default` (not `run`) dispatches the bare
27141
27389
  // invocation — citty falls through to `run` after a subcommand, double-executing it.
27142
- args: listArgs8,
27390
+ args: listArgs9,
27143
27391
  default: "list"
27144
27392
  });
27145
27393
 
@@ -27187,7 +27435,7 @@ registerSchema({
27187
27435
  output: { type: "string", description: "json|csv", required: false, default: "json" }
27188
27436
  }
27189
27437
  });
27190
- var listArgs9 = {
27438
+ var listArgs10 = {
27191
27439
  "account-id": { type: "string", description: "Meta ad account ID" },
27192
27440
  full: { type: "boolean", description: "Include the raw rule JSON, retention and creation times" },
27193
27441
  limit: { type: "string", description: "Max rows" },
@@ -27199,7 +27447,7 @@ var listCommand9 = defineCommand64({
27199
27447
  name: "list",
27200
27448
  description: "List custom conversions. Runs by default when no subcommand is given. Example: baker ads meta custom-conversions --account-id act_123"
27201
27449
  },
27202
- args: listArgs9,
27450
+ args: listArgs10,
27203
27451
  run: async ({ args: args5 }) => {
27204
27452
  const accountId = resolveAccountIdArg(args5);
27205
27453
  try {
@@ -27237,7 +27485,7 @@ Examples:
27237
27485
  // `args` stays even though the parent has no `run`: citty scans rawArgs for
27238
27486
  // the subcommand name using THIS command's arg defs. `default` (not `run`)
27239
27487
  // dispatches the bare invocation.
27240
- args: listArgs9,
27488
+ args: listArgs10,
27241
27489
  default: "list"
27242
27490
  });
27243
27491
 
@@ -29058,7 +29306,7 @@ registerSchema({
29058
29306
  output: { type: "string", description: "Format: json|csv|md", required: false, default: "json" }
29059
29307
  }
29060
29308
  });
29061
- var listArgs10 = {
29309
+ var listArgs11 = {
29062
29310
  "account-id": { type: "string", description: "X Ads account ID" },
29063
29311
  "funding-instrument-ids": { type: "string", description: "CSV of funding instrument IDs" },
29064
29312
  "campaign-ids": { type: "string", description: "CSV of campaign IDs" },
@@ -29128,7 +29376,7 @@ Examples:
29128
29376
  },
29129
29377
  // A parent must never declare `run`: citty falls through to it AFTER the
29130
29378
  // matched subcommand, so every write would also trigger a full live list.
29131
- args: listArgs10,
29379
+ args: listArgs11,
29132
29380
  default: "list"
29133
29381
  });
29134
29382
 
@@ -43396,12 +43644,12 @@ function fail3(code, message) {
43396
43644
  process.exit(2);
43397
43645
  }
43398
43646
  function resolveModels(args5) {
43399
- const pick = (flag, kind, fallback) => args5[flag] ? String(args5[flag]) : resolveModel(kind, fallback);
43647
+ const pick2 = (flag, kind, fallback) => args5[flag] ? String(args5[flag]) : resolveModel(kind, fallback);
43400
43648
  return {
43401
- describeModel: pick("describe-model", "image_describe", "~google/gemini-pro-latest"),
43402
- selectModel: pick("select-model", "text_generate", "~google/gemini-flash-latest"),
43403
- layoutModel: pick("layout-model", "text_generate", "~google/gemini-flash-latest"),
43404
- genModel: pick("gen-model", "image_generate", "openai/gpt-image-2")
43649
+ describeModel: pick2("describe-model", "image_describe", "~google/gemini-pro-latest"),
43650
+ selectModel: pick2("select-model", "text_generate", "~google/gemini-flash-latest"),
43651
+ layoutModel: pick2("layout-model", "text_generate", "~google/gemini-flash-latest"),
43652
+ genModel: pick2("gen-model", "image_generate", "openai/gpt-image-2")
43405
43653
  };
43406
43654
  }
43407
43655
  var PLATFORM_PLACEMENTS = {
@@ -45446,18 +45694,18 @@ function parseBudget(raw) {
45446
45694
  throw new Error(`--budget must be one of ${VIDEO_BUDGETS.join(", ")} (got "${v}")`);
45447
45695
  }
45448
45696
  function resolveModels2(args5) {
45449
- const pick = (flag, kind, fallback) => args5[flag] ? String(args5[flag]) : resolveModel2(kind, fallback);
45697
+ const pick2 = (flag, kind, fallback) => args5[flag] ? String(args5[flag]) : resolveModel2(kind, fallback);
45450
45698
  return {
45451
45699
  // Flash by default: ~2-3× faster per call than Pro, which keeps each
45452
45700
  // per-scene deconstruct step well inside the action time budget and turns a
45453
45701
  // ~9 min run into ~3-4 min. Override with --deconstruct-model
45454
45702
  // ~google/gemini-pro-latest for the densest extraction when speed matters less.
45455
- deconstructModel: pick("deconstruct-model", "video_deconstruct", "~google/gemini-flash-latest"),
45456
- selectModel: pick("select-model", "text_generate", "~google/gemini-flash-latest"),
45703
+ deconstructModel: pick2("deconstruct-model", "video_deconstruct", "~google/gemini-flash-latest"),
45704
+ selectModel: pick2("select-model", "text_generate", "~google/gemini-flash-latest"),
45457
45705
  // Default to the strongest image model (matches the static-ad scaffold); the
45458
45706
  // frame generators need the most faithful text/identity reproduction. Override
45459
45707
  // with --image-model for a cheaper/faster pass.
45460
- imageModel: pick("image-model", "image_generate", "openai/gpt-image-2.5-sunburst")
45708
+ imageModel: pick2("image-model", "image_generate", "openai/gpt-image-2.5-sunburst")
45461
45709
  };
45462
45710
  }
45463
45711
  function hasPhotorealCast(elements) {
@@ -54546,7 +54794,7 @@ var extractCommand = defineCommand149({
54546
54794
  import { defineCommand as defineCommand150 } from "citty";
54547
54795
 
54548
54796
  // src/commands/images/providerHits.ts
54549
- function asRecord2(value) {
54797
+ function asRecord3(value) {
54550
54798
  return value && typeof value === "object" ? value : {};
54551
54799
  }
54552
54800
  function str(value) {
@@ -54571,7 +54819,7 @@ function providerHitNormalizer(record, full) {
54571
54819
  if (!full) {
54572
54820
  return compact4;
54573
54821
  }
54574
- const group = asRecord2(record.group);
54822
+ const group = asRecord3(record.group);
54575
54823
  return {
54576
54824
  ...compact4,
54577
54825
  externalUrl: str(record.externalUrl),
@@ -66925,7 +67173,7 @@ async function listTags(json) {
66925
67173
  failApi3(err);
66926
67174
  }
66927
67175
  }
66928
- var listArgs11 = {
67176
+ var listArgs12 = {
66929
67177
  json: { type: "boolean", description: "Print the raw JSON envelope instead of the readable list" }
66930
67178
  };
66931
67179
  var listCommand19 = defineCommand222({
@@ -66933,7 +67181,7 @@ var listCommand19 = defineCommand222({
66933
67181
  name: "list",
66934
67182
  description: "Effective tags for this chat (production + staged), with each tag's full readable config (secrets excluded) \u2014 reuse a stored value to pre-fill a change rather than asking the user. Refs printed here are what flow side-effect tagIds should use. Example: baker tags list"
66935
67183
  },
66936
- args: listArgs11,
67184
+ args: listArgs12,
66937
67185
  run: async ({ args: args5 }) => {
66938
67186
  await listTags(args5.json === true);
66939
67187
  }
@@ -66981,7 +67229,7 @@ Full guide: __tooling__/docs/tools/baker/tags.md`
66981
67229
  // command's flags when it scans rawArgs for a subcommand name, and `default` (not
66982
67230
  // `run`) dispatches the bare invocation — citty falls through to `run` after a
66983
67231
  // subcommand, so a `run` here would also list on every `baker tags draft`.
66984
- args: listArgs11,
67232
+ args: listArgs12,
66985
67233
  default: "list"
66986
67234
  });
66987
67235
 
@@ -69559,6 +69807,7 @@ Introspection: Run 'baker schema <command>' to inspect argument schemas.`
69559
69807
  schema: schemaCommand2
69560
69808
  }
69561
69809
  });
69810
+ exitQuietlyOnClosedPipe(process.stdout, (code) => process.exit(code));
69562
69811
  process.argv = [...process.argv.slice(0, 2), ...normalizeCacheFlag(process.argv.slice(2))];
69563
69812
  installStreamTaps();
69564
69813
  logInvocation(process.argv.slice(2));