@koda-sl/baker-cli 0.501.0 → 0.502.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.
Files changed (73) hide show
  1. package/README.md +6 -0
  2. package/dist/{account-assets-GAKJQB6R.js → account-assets-LSXSW4RQ.js} +6 -6
  3. package/dist/{account-level-CAVVN4ZN.js → account-level-6T2WAPF3.js} +4 -4
  4. package/dist/{activities-CTGCJHLC.js → activities-LKLPORDI.js} +2 -2
  5. package/dist/{ads-HH5YTV4O.js → ads-CE3WX7VO.js} +2 -2
  6. package/dist/{ads-WU4ITH6J.js → ads-K2TIHZFC.js} +11 -11
  7. package/dist/{adsets-MMPN2SKX.js → adsets-MTB4LNE3.js} +15 -11
  8. package/dist/adsets-MTB4LNE3.js.map +1 -0
  9. package/dist/{asset-writes-IE3HUPWM.js → asset-writes-6QPHEAKF.js} +4 -4
  10. package/dist/{audience-writes-VXQTCSHH.js → audience-writes-3PSC7LRY.js} +4 -4
  11. package/dist/{audiences-75WHI3A3.js → audiences-UZ2V66OY.js} +6 -6
  12. package/dist/{campaigns-WHMJUFYV.js → campaigns-XSAJ3XSB.js} +13 -11
  13. package/dist/campaigns-XSAJ3XSB.js.map +1 -0
  14. package/dist/{catalogs-ORSZM5SY.js → catalogs-AIRFPJAJ.js} +3 -3
  15. package/dist/{chunk-GCLKAQUS.js → chunk-5YFQPJVS.js} +2 -2
  16. package/dist/{chunk-YIN6QNZD.js → chunk-6R2BU3FJ.js} +2 -2
  17. package/dist/{chunk-PRVX32SQ.js → chunk-HH7B2L3Z.js} +2 -2
  18. package/dist/{chunk-C4LZIBNP.js → chunk-KUY26RCF.js} +10 -1
  19. package/dist/{chunk-C4LZIBNP.js.map → chunk-KUY26RCF.js.map} +1 -1
  20. package/dist/{chunk-YGCRKABE.js → chunk-SHLA4JF7.js} +2 -2
  21. package/dist/{chunk-5B2WEPYR.js → chunk-SQCALAI7.js} +6 -3
  22. package/dist/chunk-SQCALAI7.js.map +1 -0
  23. package/dist/cli.js +1 -1
  24. package/dist/{copy-writes-OVCOZODC.js → copy-writes-2XW7VCDE.js} +4 -4
  25. package/dist/{creatives-RF3AG7HW.js → creatives-DPS46JXU.js} +4 -4
  26. package/dist/{custom-conversions-QFGIAISN.js → custom-conversions-E5RMKIPB.js} +4 -4
  27. package/dist/{insights-GISXHHOI.js → insights-7V3HWXS6.js} +2 -2
  28. package/dist/{instant-experiences-Y53I7FT4.js → instant-experiences-47IACDUJ.js} +3 -3
  29. package/dist/{leads-GF24GM54.js → leads-OYRLKTS6.js} +3 -3
  30. package/dist/{media-RTXIJEHY.js → media-2AKV75J4.js} +3 -3
  31. package/dist/{meta-AHI2HVBM.js → meta-CUWDMZQH.js} +32 -32
  32. package/dist/{page-photos-UUZRIJ4U.js → page-photos-BY7HNDX2.js} +3 -3
  33. package/dist/{preview-BM3NBH53.js → preview-SIKDCR27.js} +2 -2
  34. package/dist/{rule-writes-5FFQKSOE.js → rule-writes-BVHLNJLE.js} +4 -4
  35. package/dist/{rules-3FKLSJ5R.js → rules-R47FOFVB.js} +7 -7
  36. package/dist/{studies-ULLCWJSM.js → studies-ZYGAQVMK.js} +5 -5
  37. package/dist/{study-writes-ZAASDTGZ.js → study-writes-APXFR4OK.js} +3 -3
  38. package/dist/{targeting-TKV7XGRQ.js → targeting-EMKTVFJ2.js} +3 -3
  39. package/dist/{write-commands-S7AX24WF.js → write-commands-2L7T43YO.js} +21 -8
  40. package/dist/write-commands-2L7T43YO.js.map +1 -0
  41. package/package.json +1 -1
  42. package/dist/adsets-MMPN2SKX.js.map +0 -1
  43. package/dist/campaigns-WHMJUFYV.js.map +0 -1
  44. package/dist/chunk-5B2WEPYR.js.map +0 -1
  45. package/dist/write-commands-S7AX24WF.js.map +0 -1
  46. /package/dist/{account-assets-GAKJQB6R.js.map → account-assets-LSXSW4RQ.js.map} +0 -0
  47. /package/dist/{account-level-CAVVN4ZN.js.map → account-level-6T2WAPF3.js.map} +0 -0
  48. /package/dist/{activities-CTGCJHLC.js.map → activities-LKLPORDI.js.map} +0 -0
  49. /package/dist/{ads-HH5YTV4O.js.map → ads-CE3WX7VO.js.map} +0 -0
  50. /package/dist/{ads-WU4ITH6J.js.map → ads-K2TIHZFC.js.map} +0 -0
  51. /package/dist/{asset-writes-IE3HUPWM.js.map → asset-writes-6QPHEAKF.js.map} +0 -0
  52. /package/dist/{audience-writes-VXQTCSHH.js.map → audience-writes-3PSC7LRY.js.map} +0 -0
  53. /package/dist/{audiences-75WHI3A3.js.map → audiences-UZ2V66OY.js.map} +0 -0
  54. /package/dist/{catalogs-ORSZM5SY.js.map → catalogs-AIRFPJAJ.js.map} +0 -0
  55. /package/dist/{chunk-GCLKAQUS.js.map → chunk-5YFQPJVS.js.map} +0 -0
  56. /package/dist/{chunk-YIN6QNZD.js.map → chunk-6R2BU3FJ.js.map} +0 -0
  57. /package/dist/{chunk-PRVX32SQ.js.map → chunk-HH7B2L3Z.js.map} +0 -0
  58. /package/dist/{chunk-YGCRKABE.js.map → chunk-SHLA4JF7.js.map} +0 -0
  59. /package/dist/{copy-writes-OVCOZODC.js.map → copy-writes-2XW7VCDE.js.map} +0 -0
  60. /package/dist/{creatives-RF3AG7HW.js.map → creatives-DPS46JXU.js.map} +0 -0
  61. /package/dist/{custom-conversions-QFGIAISN.js.map → custom-conversions-E5RMKIPB.js.map} +0 -0
  62. /package/dist/{insights-GISXHHOI.js.map → insights-7V3HWXS6.js.map} +0 -0
  63. /package/dist/{instant-experiences-Y53I7FT4.js.map → instant-experiences-47IACDUJ.js.map} +0 -0
  64. /package/dist/{leads-GF24GM54.js.map → leads-OYRLKTS6.js.map} +0 -0
  65. /package/dist/{media-RTXIJEHY.js.map → media-2AKV75J4.js.map} +0 -0
  66. /package/dist/{meta-AHI2HVBM.js.map → meta-CUWDMZQH.js.map} +0 -0
  67. /package/dist/{page-photos-UUZRIJ4U.js.map → page-photos-BY7HNDX2.js.map} +0 -0
  68. /package/dist/{preview-BM3NBH53.js.map → preview-SIKDCR27.js.map} +0 -0
  69. /package/dist/{rule-writes-5FFQKSOE.js.map → rule-writes-BVHLNJLE.js.map} +0 -0
  70. /package/dist/{rules-3FKLSJ5R.js.map → rules-R47FOFVB.js.map} +0 -0
  71. /package/dist/{studies-ULLCWJSM.js.map → studies-ZYGAQVMK.js.map} +0 -0
  72. /package/dist/{study-writes-ZAASDTGZ.js.map → study-writes-APXFR4OK.js.map} +0 -0
  73. /package/dist/{targeting-TKV7XGRQ.js.map → targeting-EMKTVFJ2.js.map} +0 -0
package/README.md CHANGED
@@ -1169,6 +1169,12 @@ baker ads meta lead-forms spec 987654321 > form.json # a live f
1169
1169
  baker ads meta campaigns --account-id act_123 # ACTIVE only by default
1170
1170
  baker ads meta ads --account-id act_123 --all-statuses # widen to everything
1171
1171
 
1172
+ # "Raise it from 80 to 100 a day" — listed budgets are in cents, as Meta sends them (a hint
1173
+ # says so); --daily-budget takes whole currency. A raise past 3x the current budget is refused
1174
+ # (usually an amount copied in cents) unless restated with --confirm-budget-increase.
1175
+ baker ads meta adsets --campaign-id 6123 # daily_budget "8000" is 80 EUR
1176
+ baker ads meta adsets update 6124 --daily-budget 100 # summary: daily budget 80 → 100 EUR
1177
+
1172
1178
  # "Find the October ad" — Meta matches the name, so only that row is read
1173
1179
  baker ads meta ads --account-id act_123 --all-statuses --name-contains octubre --fields id,name,adset_id,creative_id
1174
1180
 
@@ -221,11 +221,11 @@ var labelsCommand = defineCommand({
221
221
  },
222
222
  subCommands: {
223
223
  list: () => labelsListCommand,
224
- create: () => import("./asset-writes-IE3HUPWM.js").then((m) => m.labelsCreateCommand),
225
- rename: () => import("./asset-writes-IE3HUPWM.js").then((m) => m.labelsRenameCommand),
226
- delete: () => import("./asset-writes-IE3HUPWM.js").then((m) => m.labelsDeleteCommand),
227
- attach: () => import("./asset-writes-IE3HUPWM.js").then((m) => m.labelsAttachCommand),
228
- detach: () => import("./asset-writes-IE3HUPWM.js").then((m) => m.labelsDetachCommand)
224
+ create: () => import("./asset-writes-6QPHEAKF.js").then((m) => m.labelsCreateCommand),
225
+ rename: () => import("./asset-writes-6QPHEAKF.js").then((m) => m.labelsRenameCommand),
226
+ delete: () => import("./asset-writes-6QPHEAKF.js").then((m) => m.labelsDeleteCommand),
227
+ attach: () => import("./asset-writes-6QPHEAKF.js").then((m) => m.labelsAttachCommand),
228
+ detach: () => import("./asset-writes-6QPHEAKF.js").then((m) => m.labelsDetachCommand)
229
229
  },
230
230
  args: labelsListArgs,
231
231
  default: "list"
@@ -287,4 +287,4 @@ export {
287
287
  instagramIdentityHints,
288
288
  labelsCommand
289
289
  };
290
- //# sourceMappingURL=account-assets-GAKJQB6R.js.map
290
+ //# sourceMappingURL=account-assets-LSXSW4RQ.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  dayPartingFromFlags
3
- } from "./chunk-GCLKAQUS.js";
3
+ } from "./chunk-5YFQPJVS.js";
4
4
  import {
5
5
  bareAccountId,
6
6
  failWriteValidation,
@@ -8,8 +8,8 @@ import {
8
8
  numberFlag,
9
9
  requireTarget,
10
10
  stageOp
11
- } from "./chunk-YIN6QNZD.js";
12
- import "./chunk-5B2WEPYR.js";
11
+ } from "./chunk-6R2BU3FJ.js";
12
+ import "./chunk-SQCALAI7.js";
13
13
  import "./chunk-GDFJOCDO.js";
14
14
  import {
15
15
  handleMetaError
@@ -606,4 +606,4 @@ export {
606
606
  pagePostsCommand,
607
607
  reachFrequencyCommand
608
608
  };
609
- //# sourceMappingURL=account-level-CAVVN4ZN.js.map
609
+ //# sourceMappingURL=account-level-6T2WAPF3.js.map
@@ -3,7 +3,7 @@ import {
3
3
  registerMetaListSchema,
4
4
  shapeMetaListRows,
5
5
  writeMetaListRows
6
- } from "./chunk-C4LZIBNP.js";
6
+ } from "./chunk-KUY26RCF.js";
7
7
  import {
8
8
  csvOrJson,
9
9
  handleMetaError,
@@ -72,4 +72,4 @@ Examples:
72
72
  export {
73
73
  activitiesCommand
74
74
  };
75
- //# sourceMappingURL=activities-CTGCJHLC.js.map
75
+ //# sourceMappingURL=activities-LKLPORDI.js.map
@@ -34,7 +34,7 @@ Full guides: __tooling__/docs/tools/baker/ads-<platform>.md (google|meta|linkedi
34
34
  },
35
35
  subCommands: {
36
36
  google: () => import("./google-ZZCSZR63.js").then((m) => m.googleCommand),
37
- meta: () => import("./meta-AHI2HVBM.js").then((m) => m.metaCommand),
37
+ meta: () => import("./meta-CUWDMZQH.js").then((m) => m.metaCommand),
38
38
  linkedin: () => import("./linkedin-A4U6IGZX.js").then((m) => m.linkedinCommand),
39
39
  x: () => import("./x-F5CSO2RN.js").then((m) => m.xCommand),
40
40
  chatgpt: () => import("./chatgpt-23X76OFD.js").then((m) => m.chatgptCommand),
@@ -45,4 +45,4 @@ Full guides: __tooling__/docs/tools/baker/ads-<platform>.md (google|meta|linkedi
45
45
  export {
46
46
  adsCommand
47
47
  };
48
- //# sourceMappingURL=ads-HH5YTV4O.js.map
48
+ //# sourceMappingURL=ads-CE3WX7VO.js.map
@@ -3,7 +3,7 @@ import {
3
3
  registerMetaListSchema,
4
4
  shapeMetaListRows,
5
5
  writeMetaListRows
6
- } from "./chunk-C4LZIBNP.js";
6
+ } from "./chunk-KUY26RCF.js";
7
7
  import {
8
8
  NAME_CONTAINS_ARG,
9
9
  csvOrJson,
@@ -92,15 +92,15 @@ Examples:
92
92
  },
93
93
  subCommands: {
94
94
  list: listCommand,
95
- create: () => import("./write-commands-S7AX24WF.js").then((m) => m.adsCreateCommand),
96
- update: () => import("./write-commands-S7AX24WF.js").then((m) => m.adsUpdateCommand),
97
- pause: () => import("./write-commands-S7AX24WF.js").then((m) => m.adsPauseCommand),
98
- resume: () => import("./write-commands-S7AX24WF.js").then((m) => m.adsResumeCommand),
99
- archive: () => import("./write-commands-S7AX24WF.js").then((m) => m.adsArchiveCommand),
100
- delete: () => import("./write-commands-S7AX24WF.js").then((m) => m.adsDeleteCommand),
101
- duplicate: () => import("./write-commands-S7AX24WF.js").then((m) => m.adsDuplicateCommand),
102
- copy: () => import("./copy-writes-OVCOZODC.js").then((m) => m.adsCopyCommand),
103
- retag: () => import("./write-commands-S7AX24WF.js").then((m) => m.adsRetagCommand)
95
+ create: () => import("./write-commands-2L7T43YO.js").then((m) => m.adsCreateCommand),
96
+ update: () => import("./write-commands-2L7T43YO.js").then((m) => m.adsUpdateCommand),
97
+ pause: () => import("./write-commands-2L7T43YO.js").then((m) => m.adsPauseCommand),
98
+ resume: () => import("./write-commands-2L7T43YO.js").then((m) => m.adsResumeCommand),
99
+ archive: () => import("./write-commands-2L7T43YO.js").then((m) => m.adsArchiveCommand),
100
+ delete: () => import("./write-commands-2L7T43YO.js").then((m) => m.adsDeleteCommand),
101
+ duplicate: () => import("./write-commands-2L7T43YO.js").then((m) => m.adsDuplicateCommand),
102
+ copy: () => import("./copy-writes-2XW7VCDE.js").then((m) => m.adsCopyCommand),
103
+ retag: () => import("./write-commands-2L7T43YO.js").then((m) => m.adsRetagCommand)
104
104
  },
105
105
  // `args` stays even though the parent has no `run`: citty scans rawArgs for the
106
106
  // subcommand name using THIS command's arg defs, so without them `--account-id act_1`
@@ -112,4 +112,4 @@ Examples:
112
112
  export {
113
113
  adsListCommand
114
114
  };
115
- //# sourceMappingURL=ads-WU4ITH6J.js.map
115
+ //# sourceMappingURL=ads-K2TIHZFC.js.map
@@ -7,10 +7,11 @@ import {
7
7
  } from "./chunk-G6XKD7QE.js";
8
8
  import {
9
9
  META_LIST_SHAPE_ARGS,
10
+ budgetUnitHints,
10
11
  registerMetaListSchema,
11
12
  shapeMetaListRows,
12
13
  writeMetaListRows
13
- } from "./chunk-C4LZIBNP.js";
14
+ } from "./chunk-KUY26RCF.js";
14
15
  import {
15
16
  NAME_CONTAINS_ARG,
16
17
  csvOrJson,
@@ -130,7 +131,10 @@ var listCommand = defineCommand({
130
131
  return;
131
132
  }
132
133
  const shaped = shapeMetaListRows("adsets", data, args);
133
- writeMetaListRows("adsets", shaped, csvOrJson(args), statusFilterHints(data, effectiveStatus, "ad sets"));
134
+ writeMetaListRows("adsets", shaped, csvOrJson(args), [
135
+ ...statusFilterHints(data, effectiveStatus, "ad sets"),
136
+ ...budgetUnitHints(data)
137
+ ]);
134
138
  } catch (err) {
135
139
  handleMetaError(err);
136
140
  }
@@ -156,14 +160,14 @@ Examples:
156
160
  },
157
161
  subCommands: {
158
162
  list: listCommand,
159
- create: () => import("./write-commands-S7AX24WF.js").then((m) => m.adSetsCreateCommand),
160
- update: () => import("./write-commands-S7AX24WF.js").then((m) => m.adSetsUpdateCommand),
161
- pause: () => import("./write-commands-S7AX24WF.js").then((m) => m.adSetsPauseCommand),
162
- resume: () => import("./write-commands-S7AX24WF.js").then((m) => m.adSetsResumeCommand),
163
- archive: () => import("./write-commands-S7AX24WF.js").then((m) => m.adSetsArchiveCommand),
164
- delete: () => import("./write-commands-S7AX24WF.js").then((m) => m.adSetsDeleteCommand),
165
- duplicate: () => import("./write-commands-S7AX24WF.js").then((m) => m.adSetsDuplicateCommand),
166
- copy: () => import("./copy-writes-OVCOZODC.js").then((m) => m.adSetsCopyCommand)
163
+ create: () => import("./write-commands-2L7T43YO.js").then((m) => m.adSetsCreateCommand),
164
+ update: () => import("./write-commands-2L7T43YO.js").then((m) => m.adSetsUpdateCommand),
165
+ pause: () => import("./write-commands-2L7T43YO.js").then((m) => m.adSetsPauseCommand),
166
+ resume: () => import("./write-commands-2L7T43YO.js").then((m) => m.adSetsResumeCommand),
167
+ archive: () => import("./write-commands-2L7T43YO.js").then((m) => m.adSetsArchiveCommand),
168
+ delete: () => import("./write-commands-2L7T43YO.js").then((m) => m.adSetsDeleteCommand),
169
+ duplicate: () => import("./write-commands-2L7T43YO.js").then((m) => m.adSetsDuplicateCommand),
170
+ copy: () => import("./copy-writes-2XW7VCDE.js").then((m) => m.adSetsCopyCommand)
167
171
  },
168
172
  // `args` stays even though the parent has no `run`: citty scans rawArgs for the
169
173
  // subcommand name using THIS command's arg defs, so without them `--account-id act_1`
@@ -175,4 +179,4 @@ Examples:
175
179
  export {
176
180
  adsetsCommand
177
181
  };
178
- //# sourceMappingURL=adsets-MMPN2SKX.js.map
182
+ //# sourceMappingURL=adsets-MTB4LNE3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/ads/meta/adsets.ts"],"sourcesContent":["import path from \"node:path\";\nimport { defineCommand } from \"citty\";\nimport { readAudienceNames } from \"../../../audience-names.ts\";\nimport { NO_CACHE_ARG } from \"../../../cache-flag.ts\";\nimport { apiGet } from \"../../../client.ts\";\nimport { rememberedJev } from \"../../../engine/lib/remembered-nouls.ts\";\nimport type { ReviewUsage } from \"../../../engine/nodes/local/lib/render-review.ts\";\nimport { findWorkspaceRoot } from \"../../canvas/normalize-paths.ts\";\nimport { holdUnbilledSpend } from \"../../canvas/unbilled-spend.ts\";\nimport { writeAdsOutput } from \"../output.ts\";\nimport { adSetViewerRows, audienceNamesOf, flattenViewerRows, VIEWER_TABLE_COLUMNS } from \"./adset-viewers.ts\";\nimport {\n budgetUnitHints,\n META_LIST_SHAPE_ARGS,\n registerMetaListSchema,\n shapeMetaListRows,\n writeMetaListRows,\n} from \"./list-rows.ts\";\nimport {\n csvOrJson,\n handleMetaError,\n NAME_CONTAINS_ARG,\n resolveAccountIdArg,\n resolveEffectiveStatus,\n statusFilterHints,\n} from \"./shared.ts\";\n\nconst listArgs = {\n \"account-id\": { type: \"string\", description: \"Meta ad account ID\" },\n \"campaign-id\": { type: \"string\", description: \"Filter to one campaign\" },\n \"effective-status\": { type: \"string\", description: \"Comma-separated effective_status filter (overrides default)\" },\n \"all-statuses\": { type: \"boolean\", description: \"Drop the default ACTIVE filter\" },\n \"name-contains\": NAME_CONTAINS_ARG,\n limit: { type: \"string\", description: \"Max rows (default 1000)\" },\n \"no-cache\": NO_CACHE_ARG,\n audience: {\n type: \"boolean\",\n description:\n \"Who each ad set reaches, instead of the compact row: a viewer per ad set — temperature (cold|warm|hot), what they already know (brand/offer/product), placements, and the reasons, read from its targeting, the account's audiences and the campaign objective. Start here before writing an ad for an ad set: baker ads meta adsets --campaign-id 6123 --audience --output json\",\n },\n ...META_LIST_SHAPE_ARGS,\n} as const;\n\ntype MetaRow = Record<string, unknown>;\n\n/**\n * The audience list and the campaign objectives only sharpen the read: without them\n * each audience is read from its name and the objective is left out, so a refused\n * read degrades the viewer rather than failing the listing.\n */\nasync function readOrEmpty(path: string, params: Record<string, string>, label: string, hints: string[]) {\n try {\n return await apiGet<MetaRow[]>(path, params);\n } catch (err) {\n const message = err instanceof Error ? err.message : \"unknown error\";\n hints.push(`Could not read the account's ${label} (${message}); the viewer was read without them.`);\n return [];\n }\n}\n\nasync function writeAdSetViewers(\n adSets: MetaRow[],\n accountParams: Record<string, string>,\n format: string,\n hints: string[],\n): Promise<void> {\n const [audiences, campaigns] = await Promise.all([\n readOrEmpty(\"/api/ads/meta/audiences\", accountParams, \"audiences\", hints),\n readOrEmpty(\"/api/ads/meta/campaigns\", accountParams, \"campaigns\", hints),\n ]);\n const root = findWorkspaceRoot(process.cwd()) ?? process.cwd();\n const cacheDir = path.join(root, \"canvas\", \".cache\");\n const spent: ReviewUsage[] = [];\n const readName = await readAudienceNames(\n audienceNamesOf(adSets, audiences),\n rememberedJev(path.join(cacheDir, \"audience-names.json\"), (u) => spent.push(u)),\n );\n await holdUnbilledSpend(cacheDir, spent).catch(() => undefined);\n const rows = adSetViewerRows(adSets, audiences, campaigns, readName);\n if (rows.length > 0) {\n hints.push(\n 'Write each ad for the viewer of the ad set it will run in, then record it in the creative\\'s _definition.md: targetAdSet: \"<ad set id>\" and viewer: { temperature, knows, placements, source }.',\n );\n }\n if (format === \"md\" || format === \"csv\") {\n writeAdsOutput(flattenViewerRows(rows), format, [...VIEWER_TABLE_COLUMNS], hints);\n return;\n }\n writeAdsOutput(rows as unknown as MetaRow[], format, undefined, hints);\n}\n\nregisterMetaListSchema(\n \"adsets\",\n \"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 — ask for it with --fields id,name,targeting (or --full). --audience replaces the row with who each ad set reaches (a viewer: temperature, what they already know, placements, reasons) — read it before writing an ad for an ad set. Start here: baker ads meta adsets --campaign-id 6123 --all-statuses. --output json returns the rows in the envelope.\",\n listArgs,\n);\n\nconst listCommand = defineCommand({\n meta: {\n name: \"list\",\n description:\n \"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\",\n },\n args: listArgs,\n run: async ({ args }) => {\n const accountId = resolveAccountIdArg(args);\n const effectiveStatus = resolveEffectiveStatus(args);\n try {\n const params: Record<string, string> = { \"account-id\": accountId };\n if (args[\"campaign-id\"]) params[\"campaign-id\"] = args[\"campaign-id\"] as string;\n if (effectiveStatus) params[\"effective-status\"] = effectiveStatus;\n if (args[\"name-contains\"]) params[\"name-contains\"] = args[\"name-contains\"] as string;\n if (args.limit) params.limit = args.limit as string;\n if (args[\"no-cache\"]) params[\"skip-cache\"] = \"true\";\n const data = await apiGet<Array<Record<string, unknown>>>(\"/api/ads/meta/adsets\", params);\n if (args.audience) {\n const hints = statusFilterHints(data, effectiveStatus, \"ad sets\");\n const accountParams: Record<string, string> = { \"account-id\": accountId };\n if (args[\"no-cache\"]) accountParams[\"skip-cache\"] = \"true\";\n await writeAdSetViewers(data, accountParams, csvOrJson(args), hints);\n return;\n }\n const shaped = shapeMetaListRows(\"adsets\", data, args);\n writeMetaListRows(\"adsets\", shaped, csvOrJson(args), [\n ...statusFilterHints(data, effectiveStatus, \"ad sets\"),\n ...budgetUnitHints(data),\n ]);\n } catch (err) {\n handleMetaError(err);\n }\n },\n});\n\nexport const adsetsCommand = defineCommand({\n meta: {\n name: \"adsets\",\n description: `List ad sets in a Meta ad account, or stage writes (create/update/pause/resume/archive/delete/duplicate/copy).\nDefaults to ACTIVE only. Write subcommands stage ops on this chat's draft.\n\nListings print a table by default: id, name, campaign_id, effective_status, optimization_goal, billing_event,\nbid_strategy, budgets, destination_type, is_dynamic_creative, learning_stage, end_time, created_time. Targeting\nis not in the compact row — ask for it with --fields (dotted paths) or --full. --output json returns the rows as JSON.\n\nExamples:\n baker ads meta adsets --account-id act_123\n baker ads meta adsets --campaign-id 6123456789\n baker ads meta adsets --account-id act_123 --all-statuses --name-contains retargeting — find one ad set by name\n baker ads meta adsets --campaign-id 6123456789 --fields id,name,targeting.geo_locations\n baker ads meta adsets --campaign-id 6123456789 --audience --output json — who each ad set reaches (viewer per ad set)\n 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`,\n },\n subCommands: {\n list: listCommand,\n create: () => import(\"./write-commands.ts\").then((m) => m.adSetsCreateCommand),\n update: () => import(\"./write-commands.ts\").then((m) => m.adSetsUpdateCommand),\n pause: () => import(\"./write-commands.ts\").then((m) => m.adSetsPauseCommand),\n resume: () => import(\"./write-commands.ts\").then((m) => m.adSetsResumeCommand),\n archive: () => import(\"./write-commands.ts\").then((m) => m.adSetsArchiveCommand),\n delete: () => import(\"./write-commands.ts\").then((m) => m.adSetsDeleteCommand),\n duplicate: () => import(\"./write-commands.ts\").then((m) => m.adSetsDuplicateCommand),\n copy: () => import(\"./copy-writes.ts\").then((m) => m.adSetsCopyCommand),\n },\n // `args` stays even though the parent has no `run`: citty scans rawArgs for the\n // subcommand name using THIS command's arg defs, so without them `--account-id act_1`\n // would read `act_1` as a subcommand. `default` (not `run`) dispatches the bare\n // invocation — citty falls through to `run` after a subcommand, double-executing it.\n args: listArgs,\n default: \"list\",\n});\n"],"mappings":"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","names":["path"]}
@@ -9,9 +9,9 @@ import {
9
9
  labelsDetachCommand,
10
10
  labelsRenameCommand,
11
11
  mediaDeleteCommand
12
- } from "./chunk-PRVX32SQ.js";
13
- import "./chunk-YIN6QNZD.js";
14
- import "./chunk-5B2WEPYR.js";
12
+ } from "./chunk-HH7B2L3Z.js";
13
+ import "./chunk-6R2BU3FJ.js";
14
+ import "./chunk-SQCALAI7.js";
15
15
  import "./chunk-GDFJOCDO.js";
16
16
  import "./chunk-B2POVFR2.js";
17
17
  import "./chunk-ERSX3MKH.js";
@@ -45,4 +45,4 @@ export {
45
45
  labelsRenameCommand,
46
46
  mediaDeleteCommand
47
47
  };
48
- //# sourceMappingURL=asset-writes-IE3HUPWM.js.map
48
+ //# sourceMappingURL=asset-writes-6QPHEAKF.js.map
@@ -3,19 +3,19 @@ import {
3
3
  customerListBatches,
4
4
  customerListFromFile,
5
5
  customerListUploadRefusal
6
- } from "./chunk-YGCRKABE.js";
6
+ } from "./chunk-SHLA4JF7.js";
7
7
  import {
8
8
  bareAccountId,
9
9
  failWriteValidation,
10
10
  repeatedListFlag,
11
11
  requireTarget,
12
12
  stageOp
13
- } from "./chunk-YIN6QNZD.js";
13
+ } from "./chunk-6R2BU3FJ.js";
14
14
  import {
15
15
  CUSTOMER_LIST_BATCH_ROWS,
16
16
  CUSTOMER_LIST_MAX_BATCHES,
17
17
  brandSafetyTargetingFields
18
- } from "./chunk-5B2WEPYR.js";
18
+ } from "./chunk-SQCALAI7.js";
19
19
  import "./chunk-GDFJOCDO.js";
20
20
  import {
21
21
  csvOrJson,
@@ -322,4 +322,4 @@ export {
322
322
  savedAudiencesCommand,
323
323
  targetingFromSavedAudience
324
324
  };
325
- //# sourceMappingURL=audience-writes-VXQTCSHH.js.map
325
+ //# sourceMappingURL=audience-writes-3PSC7LRY.js.map
@@ -67,11 +67,11 @@ Examples:
67
67
  },
68
68
  subCommands: {
69
69
  list: listCommand,
70
- create: () => import("./write-commands-S7AX24WF.js").then((m) => m.audiencesCreateCommand),
71
- update: () => import("./write-commands-S7AX24WF.js").then((m) => m.audiencesUpdateCommand),
72
- delete: () => import("./audience-writes-VXQTCSHH.js").then((m) => m.audiencesDeleteCommand),
73
- members: () => import("./audience-writes-VXQTCSHH.js").then((m) => m.audiencesMembersCommand),
74
- saved: () => import("./audience-writes-VXQTCSHH.js").then((m) => m.savedAudiencesCommand)
70
+ create: () => import("./write-commands-2L7T43YO.js").then((m) => m.audiencesCreateCommand),
71
+ update: () => import("./write-commands-2L7T43YO.js").then((m) => m.audiencesUpdateCommand),
72
+ delete: () => import("./audience-writes-3PSC7LRY.js").then((m) => m.audiencesDeleteCommand),
73
+ members: () => import("./audience-writes-3PSC7LRY.js").then((m) => m.audiencesMembersCommand),
74
+ saved: () => import("./audience-writes-3PSC7LRY.js").then((m) => m.savedAudiencesCommand)
75
75
  },
76
76
  // `args` stays even though the parent has no `run`: citty scans rawArgs for the
77
77
  // subcommand name using THIS command's arg defs, so without them `--account-id act_1`
@@ -83,4 +83,4 @@ Examples:
83
83
  export {
84
84
  audiencesCommand
85
85
  };
86
- //# sourceMappingURL=audiences-75WHI3A3.js.map
86
+ //# sourceMappingURL=audiences-UZ2V66OY.js.map
@@ -1,9 +1,10 @@
1
1
  import {
2
2
  META_LIST_SHAPE_ARGS,
3
+ budgetUnitHints,
3
4
  registerMetaListSchema,
4
5
  shapeMetaListRows,
5
6
  writeMetaListRows
6
- } from "./chunk-C4LZIBNP.js";
7
+ } from "./chunk-KUY26RCF.js";
7
8
  import {
8
9
  NAME_CONTAINS_ARG,
9
10
  csvOrJson,
@@ -71,7 +72,8 @@ var listCommand = defineCommand({
71
72
  const shaped = shapeMetaListRows("campaigns", data, args);
72
73
  writeMetaListRows("campaigns", shaped, csvOrJson(args), [
73
74
  ...statusFilterHints(data, effectiveStatus, "campaigns"),
74
- ...advantagePlusHints(data)
75
+ ...advantagePlusHints(data),
76
+ ...budgetUnitHints(data)
75
77
  ]);
76
78
  } catch (err) {
77
79
  handleMetaError(err);
@@ -105,14 +107,14 @@ Examples:
105
107
  },
106
108
  subCommands: {
107
109
  list: listCommand,
108
- create: () => import("./write-commands-S7AX24WF.js").then((m) => m.campaignsCreateCommand),
109
- update: () => import("./write-commands-S7AX24WF.js").then((m) => m.campaignsUpdateCommand),
110
- pause: () => import("./write-commands-S7AX24WF.js").then((m) => m.campaignsPauseCommand),
111
- resume: () => import("./write-commands-S7AX24WF.js").then((m) => m.campaignsResumeCommand),
112
- archive: () => import("./write-commands-S7AX24WF.js").then((m) => m.campaignsArchiveCommand),
113
- delete: () => import("./write-commands-S7AX24WF.js").then((m) => m.campaignsDeleteCommand),
114
- duplicate: () => import("./write-commands-S7AX24WF.js").then((m) => m.campaignsDuplicateCommand),
115
- copy: () => import("./copy-writes-OVCOZODC.js").then((m) => m.campaignsCopyCommand)
110
+ create: () => import("./write-commands-2L7T43YO.js").then((m) => m.campaignsCreateCommand),
111
+ update: () => import("./write-commands-2L7T43YO.js").then((m) => m.campaignsUpdateCommand),
112
+ pause: () => import("./write-commands-2L7T43YO.js").then((m) => m.campaignsPauseCommand),
113
+ resume: () => import("./write-commands-2L7T43YO.js").then((m) => m.campaignsResumeCommand),
114
+ archive: () => import("./write-commands-2L7T43YO.js").then((m) => m.campaignsArchiveCommand),
115
+ delete: () => import("./write-commands-2L7T43YO.js").then((m) => m.campaignsDeleteCommand),
116
+ duplicate: () => import("./write-commands-2L7T43YO.js").then((m) => m.campaignsDuplicateCommand),
117
+ copy: () => import("./copy-writes-2XW7VCDE.js").then((m) => m.campaignsCopyCommand)
116
118
  },
117
119
  // `args` stays even though the parent has no `run`: citty scans rawArgs for the
118
120
  // subcommand name using THIS command's arg defs, so without them `--account-id act_1`
@@ -125,4 +127,4 @@ export {
125
127
  advantagePlusHints,
126
128
  campaignsCommand
127
129
  };
128
- //# sourceMappingURL=campaigns-WHMJUFYV.js.map
130
+ //# sourceMappingURL=campaigns-XSAJ3XSB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/ads/meta/campaigns.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\nimport { NO_CACHE_ARG } from \"../../../cache-flag.ts\";\nimport { apiGet } from \"../../../client.ts\";\nimport {\n budgetUnitHints,\n META_LIST_SHAPE_ARGS,\n registerMetaListSchema,\n shapeMetaListRows,\n writeMetaListRows,\n} from \"./list-rows.ts\";\nimport {\n csvOrJson,\n handleMetaError,\n NAME_CONTAINS_ARG,\n resolveAccountIdArg,\n resolveEffectiveStatus,\n statusFilterHints,\n} from \"./shared.ts\";\n\n/**\n * Which listed campaigns Meta counts as Advantage+, read off the derived\n * `advantage_state_info` — a hint rather than a column, so the compact row of a\n * 100-campaign account stays small. Advantage+ is not a switch: it follows from\n * a campaign budget, Advantage+ audience and automatic placements.\n */\nexport function advantagePlusHints(rows: ReadonlyArray<Record<string, unknown>>): string[] {\n const named = rows.flatMap((row) => {\n const info = row.advantage_state_info as { advantage_state?: unknown } | undefined;\n const state = info?.advantage_state;\n return typeof state === \"string\" && state.startsWith(\"ADVANTAGE_PLUS_\")\n ? [`${String(row.id)} (${state.slice(\"ADVANTAGE_PLUS_\".length).toLowerCase()})`]\n : [];\n });\n return named.length > 0\n ? [\n `Advantage+ campaigns: ${named.join(\", \")}. Per-lever states (budget, audience, placements): --fields id,name,advantage_state_info.`,\n ]\n : [];\n}\n\nconst listArgs = {\n \"account-id\": { type: \"string\", description: \"Meta ad account ID\" },\n \"effective-status\": { type: \"string\", description: \"Comma-separated effective_status filter (overrides default)\" },\n \"all-statuses\": { type: \"boolean\", description: \"Drop the default ACTIVE filter and return everything\" },\n \"name-contains\": NAME_CONTAINS_ARG,\n limit: { type: \"string\", description: \"Max rows (default 1000)\" },\n \"no-cache\": NO_CACHE_ARG,\n ...META_LIST_SHAPE_ARGS,\n} as const;\n\nregisterMetaListSchema(\n \"campaigns\",\n \"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,advantage_state_info); --full returns every field Meta sent; --output json returns the rows in the envelope. A hint names the campaigns Meta counts as Advantage+.\",\n listArgs,\n);\n\nconst listCommand = defineCommand({\n meta: {\n name: \"list\",\n description:\n \"List campaigns for a Meta ad account. Runs by default when no subcommand is given. Example: baker ads meta campaigns --account-id act_123\",\n },\n args: listArgs,\n run: async ({ args }) => {\n const accountId = resolveAccountIdArg(args);\n const effectiveStatus = resolveEffectiveStatus(args);\n try {\n const params: Record<string, string> = { \"account-id\": accountId };\n if (effectiveStatus) params[\"effective-status\"] = effectiveStatus;\n if (args[\"name-contains\"]) params[\"name-contains\"] = args[\"name-contains\"] as string;\n if (args.limit) params.limit = args.limit as string;\n if (args[\"no-cache\"]) params[\"skip-cache\"] = \"true\";\n const data = await apiGet<Array<Record<string, unknown>>>(\"/api/ads/meta/campaigns\", params);\n const shaped = shapeMetaListRows(\"campaigns\", data, args);\n writeMetaListRows(\"campaigns\", shaped, csvOrJson(args), [\n ...statusFilterHints(data, effectiveStatus, \"campaigns\"),\n ...advantagePlusHints(data),\n ...budgetUnitHints(data),\n ]);\n } catch (err) {\n handleMetaError(err);\n }\n },\n});\n\nexport const campaignsCommand = defineCommand({\n meta: {\n name: \"campaigns\",\n description: `List campaigns for a Meta ad account, or stage writes (create/update/pause/resume/archive/delete/duplicate/copy).\nDefaults to ACTIVE only — pass --all-statuses to widen. Write subcommands stage ops on this chat's draft and\napply only when the chat is published.\n\nIn Meta's API \"campaign\" is the top-of-tree object (what marketers usually call a campaign group).\nThe dashboard shows effective_status: ACTIVE, PAUSED, DELETED, ARCHIVED, IN_PROCESS, WITH_ISSUES, etc.\n\nListings print a table by default: id, name, effective_status, daily/lifetime budget, created_date.\n--fields takes dotted paths for anything else (objective, bid_strategy, special_ad_categories, created_time,\nadvantage_state_info). A hint names the campaigns Meta counts as Advantage+ — a state Meta derives from a\ncampaign budget, Advantage+ audience and automatic placements on every ad set, not a setting;\n--full returns every field; --output json returns the same rows in the { ok, data } envelope.\n\nExamples:\n baker ads meta campaigns --account-id act_123 # ACTIVE only\n baker ads meta campaigns --account-id act_123 --all-statuses # everything\n baker ads meta campaigns --account-id act_123 --all-statuses --name-contains Q3 # find one by name\n baker ads meta campaigns --account-id act_123 --fields id,name,objective,bid_strategy,special_ad_categories\n baker ads meta campaigns --account-id act_123 --output json # rows as JSON\n baker ads meta campaigns create --account-id act_123 --name \"Q3\" --objective OUTCOME_LEADS --daily-budget 50\n baker ads meta campaigns pause 6123 --account-id act_123`,\n },\n subCommands: {\n list: listCommand,\n create: () => import(\"./write-commands.ts\").then((m) => m.campaignsCreateCommand),\n update: () => import(\"./write-commands.ts\").then((m) => m.campaignsUpdateCommand),\n pause: () => import(\"./write-commands.ts\").then((m) => m.campaignsPauseCommand),\n resume: () => import(\"./write-commands.ts\").then((m) => m.campaignsResumeCommand),\n archive: () => import(\"./write-commands.ts\").then((m) => m.campaignsArchiveCommand),\n delete: () => import(\"./write-commands.ts\").then((m) => m.campaignsDeleteCommand),\n duplicate: () => import(\"./write-commands.ts\").then((m) => m.campaignsDuplicateCommand),\n copy: () => import(\"./copy-writes.ts\").then((m) => m.campaignsCopyCommand),\n },\n // `args` stays even though the parent has no `run`: citty scans rawArgs for the\n // subcommand name using THIS command's arg defs, so without them `--account-id act_1`\n // would read `act_1` as a subcommand. `default` (not `run`) dispatches the bare\n // invocation — citty falls through to `run` after a subcommand, double-executing it.\n args: listArgs,\n default: \"list\",\n});\n"],"mappings":"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","names":[]}
@@ -7,10 +7,10 @@ import {
7
7
  requireTarget,
8
8
  stageOp,
9
9
  upper
10
- } from "./chunk-YIN6QNZD.js";
10
+ } from "./chunk-6R2BU3FJ.js";
11
11
  import {
12
12
  retailerIdFilter
13
- } from "./chunk-5B2WEPYR.js";
13
+ } from "./chunk-SQCALAI7.js";
14
14
  import "./chunk-GDFJOCDO.js";
15
15
  import {
16
16
  csvOrJson,
@@ -776,4 +776,4 @@ export {
776
776
  productFieldsFromArgs,
777
777
  productSetFilterFromArgs
778
778
  };
779
- //# sourceMappingURL=catalogs-ORSZM5SY.js.map
779
+ //# sourceMappingURL=catalogs-AIRFPJAJ.js.map
@@ -2,7 +2,7 @@ import {
2
2
  failWriteValidation,
3
3
  parseDateFlag,
4
4
  parseMoneyFlag
5
- } from "./chunk-YIN6QNZD.js";
5
+ } from "./chunk-6R2BU3FJ.js";
6
6
  import {
7
7
  repeatedValues
8
8
  } from "./chunk-ERSX3MKH.js";
@@ -284,4 +284,4 @@ export {
284
284
  clearFromFlags,
285
285
  clearArg
286
286
  };
287
- //# sourceMappingURL=chunk-GCLKAQUS.js.map
287
+ //# sourceMappingURL=chunk-5YFQPJVS.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  metaDraftOpInputSchema
3
- } from "./chunk-5B2WEPYR.js";
3
+ } from "./chunk-SQCALAI7.js";
4
4
  import {
5
5
  handleMetaError,
6
6
  resolveAccountIdArg
@@ -204,4 +204,4 @@ export {
204
204
  stageOps,
205
205
  stageStatusChange
206
206
  };
207
- //# sourceMappingURL=chunk-YIN6QNZD.js.map
207
+ //# sourceMappingURL=chunk-6R2BU3FJ.js.map
@@ -5,7 +5,7 @@ import {
5
5
  requireTarget,
6
6
  stageOp,
7
7
  stageOps
8
- } from "./chunk-YIN6QNZD.js";
8
+ } from "./chunk-6R2BU3FJ.js";
9
9
  import {
10
10
  repeatedValues
11
11
  } from "./chunk-ERSX3MKH.js";
@@ -216,4 +216,4 @@ export {
216
216
  labelsAttachCommand,
217
217
  labelsDetachCommand
218
218
  };
219
- //# sourceMappingURL=chunk-PRVX32SQ.js.map
219
+ //# sourceMappingURL=chunk-HH7B2L3Z.js.map
@@ -129,6 +129,14 @@ function compactActivity(row) {
129
129
  ...change !== void 0 ? { change } : {}
130
130
  };
131
131
  }
132
+ function budgetUnitHints(rows) {
133
+ const listed = rows.map((row) => Number(row.daily_budget ?? row.lifetime_budget)).find((amount) => Number.isFinite(amount) && amount > 0);
134
+ if (listed === void 0) return [];
135
+ const whole = listed / 100;
136
+ return [
137
+ `Budgets here are in the account currency's smallest unit, as Meta sends them: daily_budget ${listed} is ${whole} in EUR or USD (currencies without cents, such as JPY, are not divided). Money flags take whole currency: --daily-budget ${whole}, never ${listed}.`
138
+ ];
139
+ }
132
140
  var PROJECTIONS = {
133
141
  campaigns: { row: compactCampaign, columns: CAMPAIGN_COLUMNS, whenPresent: DIAGNOSTIC_COLUMNS },
134
142
  adsets: { row: compactAdSet, columns: ADSET_COLUMNS, whenPresent: DIAGNOSTIC_COLUMNS },
@@ -183,9 +191,10 @@ function registerMetaListSchema(kind, description, args) {
183
191
  }
184
192
 
185
193
  export {
194
+ budgetUnitHints,
186
195
  shapeMetaListRows,
187
196
  writeMetaListRows,
188
197
  META_LIST_SHAPE_ARGS,
189
198
  registerMetaListSchema
190
199
  };
191
- //# sourceMappingURL=chunk-C4LZIBNP.js.map
200
+ //# sourceMappingURL=chunk-KUY26RCF.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/ads/meta/list-rows.ts"],"sourcesContent":["import { registerSchema } from \"../../../schemas.ts\";\nimport { asRecord, type CompactProjection, type ShapedRows, shapeListRows } from \"../list-rows.ts\";\nimport { writeAdsOutput } from \"../output.ts\";\n\n/**\n * The compact row of each Meta listing. The backend asks Graph for every field a\n * write or an audit might need (targeting, tracking specs, three status fields),\n * and 100 campaigns or two days of activity passed through whole ran to 55–78 KB.\n * A compact row carries what an agent decides with; `--fields` reaches any other\n * path and `--full` returns the record Graph sent.\n *\n * `effective_status` is the one status kept: it is what Ads Manager shows, and\n * `status`/`configured_status` only restate the toggle it already folds in.\n *\n * Listings print a table by default: keyed JSON repeats every column name on\n * every row, and 100 campaigns stayed near 30 KB even compact. `--output json`\n * returns the same rows in the envelope.\n */\n\ntype MetaRow = Record<string, unknown>;\n\nexport type MetaListKind = \"campaigns\" | \"adsets\" | \"ads\" | \"activities\";\n\nfunction pick(row: MetaRow, keys: readonly string[]): MetaRow {\n const picked: MetaRow = {};\n for (const key of keys) {\n if (row[key] !== undefined) picked[key] = row[key];\n }\n return picked;\n}\n\n/**\n * An account's campaign list is the widest listing an agent reads (100+ rows), so\n * its row is the narrowest: what a campaign is called, whether it runs and what\n * it spends. Objective, bid strategy and Special Ad Category are one `--fields`\n * away; the creation day is enough to order by, and `--fields created_time` has\n * the timestamp.\n */\nconst CAMPAIGN_COLUMNS = [\"id\", \"name\", \"effective_status\", \"daily_budget\", \"lifetime_budget\", \"created_date\"] as const;\n\n/** Why delivery stops and what Meta suggests: columns only when a row has one. */\nconst DIAGNOSTIC_COLUMNS = [\"issues\", \"suggestions\"] as const;\n\nfunction compactCampaign(row: MetaRow): MetaRow {\n const created = row.created_time;\n return {\n ...pick(row, [\"id\", \"name\", \"effective_status\", \"daily_budget\", \"lifetime_budget\"]),\n ...(typeof created === \"string\" ? { created_date: created.slice(0, 10) } : {}),\n ...diagnostics(row),\n };\n}\n\nconst ADSET_KEYS = [\n \"id\",\n \"name\",\n \"campaign_id\",\n \"effective_status\",\n \"optimization_goal\",\n \"billing_event\",\n \"bid_strategy\",\n \"daily_budget\",\n \"lifetime_budget\",\n \"destination_type\",\n // A Dynamic Creative ad set refuses every new ad, which changes the plan before anything is staged.\n \"is_dynamic_creative\",\n] as const;\n\nconst ADSET_COLUMNS = [...ADSET_KEYS, \"learning_stage\", \"end_time\", \"created_time\"] as const;\n\nfunction compactAdSet(row: MetaRow): MetaRow {\n const learning = asRecord(row.learning_stage_info)?.status;\n return {\n ...pick(row, ADSET_KEYS),\n ...(typeof learning === \"string\" ? { learning_stage: learning } : {}),\n ...pick(row, [\"end_time\", \"created_time\"]),\n ...diagnostics(row),\n };\n}\n\nconst AD_COLUMNS = [\n \"id\",\n \"name\",\n \"adset_id\",\n \"campaign_id\",\n \"effective_status\",\n \"creative_id\",\n \"issues\",\n \"created_time\",\n] as const;\n\n/** Why an ad is WITH_ISSUES — the one reason to open `issues_info`, in its own words. */\nfunction adIssues(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return value.flatMap((entry) => {\n const issue = asRecord(entry);\n const text = issue?.error_summary ?? issue?.error_message;\n return typeof text === \"string\" && text ? [text] : [];\n });\n}\n\n/** Meta's suggestions for a campaign or ad set (`recommendations`), by their titles. */\nfunction suggestions(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return value.flatMap((entry) => {\n const recommendation = asRecord(entry);\n const text = recommendation?.title ?? recommendation?.message;\n return typeof text === \"string\" && text ? [text] : [];\n });\n}\n\n/** Why a campaign or ad set cannot deliver, and what Meta suggests — only when Meta says something. */\nfunction diagnostics(row: MetaRow): MetaRow {\n const issues = adIssues(row.issues_info);\n const suggested = suggestions(row.recommendations);\n return {\n ...(issues.length > 0 ? { issues } : {}),\n ...(suggested.length > 0 ? { suggestions: suggested } : {}),\n };\n}\n\nfunction compactAd(row: MetaRow): MetaRow {\n const creativeId = asRecord(row.creative)?.id;\n const issues = adIssues(row.issues_info);\n return {\n ...pick(row, [\"id\", \"name\", \"adset_id\", \"campaign_id\", \"effective_status\"]),\n ...(creativeId !== undefined ? { creative_id: creativeId } : {}),\n ...(issues.length > 0 ? { issues } : {}),\n ...pick(row, [\"created_time\"]),\n };\n}\n\nconst ACTIVITY_COLUMNS = [\n \"event_time\",\n \"event_type\",\n \"actor_name\",\n \"object_type\",\n \"object_name\",\n \"object_id\",\n \"change\",\n] as const;\n\nfunction isScalar(value: unknown): value is string | number | null {\n return value === null || typeof value === \"string\" || typeof value === \"number\";\n}\n\n/**\n * `extra_data` is a JSON string whose shape varies by event type and carries most\n * of an activity's bytes (image URLs, whole targeting specs). A status, name,\n * budget or goal change stores its before and after as two plain values — those\n * read as one line; any richer change stays behind `--fields extra_data`.\n */\nexport function activityChange(extraData: unknown): string | undefined {\n if (typeof extraData !== \"string\") return undefined;\n let parsed: unknown;\n try {\n parsed = JSON.parse(extraData);\n } catch {\n return undefined;\n }\n const data = asRecord(parsed);\n // An absent old_value is one this read did not observe, not an unset one — only `null` means \"none\".\n if (!data || !(\"new_value\" in data) || !(\"old_value\" in data)) return undefined;\n const { old_value: before, new_value: after } = data;\n if (!isScalar(before) || !isScalar(after)) return undefined;\n const show = (value: string | number | null) => (value === null ? \"(none)\" : String(value));\n return `${show(before)} → ${show(after)}`;\n}\n\nfunction compactActivity(row: MetaRow): MetaRow {\n const change = activityChange(row.extra_data);\n return {\n ...pick(row, [\"event_time\", \"event_type\", \"actor_name\", \"object_type\", \"object_name\", \"object_id\"]),\n ...(change !== undefined ? { change } : {}),\n };\n}\n\nconst PROJECTIONS: Record<MetaListKind, CompactProjection<MetaRow>> = {\n campaigns: { row: compactCampaign, columns: CAMPAIGN_COLUMNS, whenPresent: DIAGNOSTIC_COLUMNS },\n adsets: { row: compactAdSet, columns: ADSET_COLUMNS, whenPresent: DIAGNOSTIC_COLUMNS },\n ads: { row: compactAd, columns: AD_COLUMNS },\n activities: { row: compactActivity, columns: ACTIVITY_COLUMNS },\n};\n\nexport function shapeMetaListRows(kind: MetaListKind, rows: MetaRow[], args: Record<string, unknown>): ShapedRows {\n return shapeListRows(rows, args, PROJECTIONS[kind]);\n}\n\nconst NOUNS: Record<MetaListKind, string> = {\n campaigns: \"campaigns\",\n adsets: \"ad sets\",\n ads: \"ads\",\n activities: \"activities\",\n};\n\n/**\n * A table of no rows prints nothing at all, which reads as a failed call — so an empty\n * listing says so, and says why when a status filter may be hiding rows.\n */\nexport function writeMetaListRows(kind: MetaListKind, shaped: ShapedRows, format: string, hints: string[] = []): void {\n if (format === \"md\" && shaped.rows.length === 0) {\n process.stdout.write(`${hints.length > 0 ? hints.join(\"\\n\") : `No ${NOUNS[kind]} matched.`}\\n`);\n return;\n }\n writeAdsOutput(shaped.rows, format, shaped.fields, [...hints, ...(shaped.hints ?? [])]);\n}\n\n/** The projection flags every Meta listing shares, worded once for help and `baker schema`. */\nexport const META_LIST_SHAPE_ARGS = {\n fields: {\n type: \"string\",\n description: \"CSV of dotted paths to return instead of the compact row, e.g. id,name,targeting.geo_locations\",\n },\n full: { type: \"boolean\", description: \"Return every field Meta sent (targeting, tracking specs, raw extra_data)\" },\n output: {\n type: \"string\",\n description: \"md|json|csv|jsonl — md (default) prints a table; json returns the rows in the { ok, data } envelope\",\n default: \"md\",\n },\n} as const;\n\ninterface ListArgDef {\n type: string;\n description?: string;\n default?: unknown;\n}\n\n/**\n * `baker schema ads.meta.<list>`, read off the same arg defs the command parses,\n * so the introspection an agent checks before a call cannot promise a flag the\n * command refuses — `--full` on `adsets` was guessed three times in one Session.\n */\nexport function registerMetaListSchema(\n kind: MetaListKind,\n description: string,\n args: Record<string, ListArgDef>,\n): void {\n registerSchema({\n command: `ads.meta.${kind}`,\n description,\n args: Object.fromEntries(\n Object.entries(args).map(([name, def]) => [\n name,\n {\n type: def.type,\n description: def.description ?? \"\",\n required: false,\n ...(def.default !== undefined ? { default: def.default } : {}),\n },\n ]),\n ),\n });\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/commands/ads/meta/list-rows.ts"],"sourcesContent":["import { registerSchema } from \"../../../schemas.ts\";\nimport { asRecord, type CompactProjection, type ShapedRows, shapeListRows } from \"../list-rows.ts\";\nimport { writeAdsOutput } from \"../output.ts\";\n\n/**\n * The compact row of each Meta listing. The backend asks Graph for every field a\n * write or an audit might need (targeting, tracking specs, three status fields),\n * and 100 campaigns or two days of activity passed through whole ran to 55–78 KB.\n * A compact row carries what an agent decides with; `--fields` reaches any other\n * path and `--full` returns the record Graph sent.\n *\n * `effective_status` is the one status kept: it is what Ads Manager shows, and\n * `status`/`configured_status` only restate the toggle it already folds in.\n *\n * Listings print a table by default: keyed JSON repeats every column name on\n * every row, and 100 campaigns stayed near 30 KB even compact. `--output json`\n * returns the same rows in the envelope.\n */\n\ntype MetaRow = Record<string, unknown>;\n\nexport type MetaListKind = \"campaigns\" | \"adsets\" | \"ads\" | \"activities\";\n\nfunction pick(row: MetaRow, keys: readonly string[]): MetaRow {\n const picked: MetaRow = {};\n for (const key of keys) {\n if (row[key] !== undefined) picked[key] = row[key];\n }\n return picked;\n}\n\n/**\n * An account's campaign list is the widest listing an agent reads (100+ rows), so\n * its row is the narrowest: what a campaign is called, whether it runs and what\n * it spends. Objective, bid strategy and Special Ad Category are one `--fields`\n * away; the creation day is enough to order by, and `--fields created_time` has\n * the timestamp.\n */\nconst CAMPAIGN_COLUMNS = [\"id\", \"name\", \"effective_status\", \"daily_budget\", \"lifetime_budget\", \"created_date\"] as const;\n\n/** Why delivery stops and what Meta suggests: columns only when a row has one. */\nconst DIAGNOSTIC_COLUMNS = [\"issues\", \"suggestions\"] as const;\n\nfunction compactCampaign(row: MetaRow): MetaRow {\n const created = row.created_time;\n return {\n ...pick(row, [\"id\", \"name\", \"effective_status\", \"daily_budget\", \"lifetime_budget\"]),\n ...(typeof created === \"string\" ? { created_date: created.slice(0, 10) } : {}),\n ...diagnostics(row),\n };\n}\n\nconst ADSET_KEYS = [\n \"id\",\n \"name\",\n \"campaign_id\",\n \"effective_status\",\n \"optimization_goal\",\n \"billing_event\",\n \"bid_strategy\",\n \"daily_budget\",\n \"lifetime_budget\",\n \"destination_type\",\n // A Dynamic Creative ad set refuses every new ad, which changes the plan before anything is staged.\n \"is_dynamic_creative\",\n] as const;\n\nconst ADSET_COLUMNS = [...ADSET_KEYS, \"learning_stage\", \"end_time\", \"created_time\"] as const;\n\nfunction compactAdSet(row: MetaRow): MetaRow {\n const learning = asRecord(row.learning_stage_info)?.status;\n return {\n ...pick(row, ADSET_KEYS),\n ...(typeof learning === \"string\" ? { learning_stage: learning } : {}),\n ...pick(row, [\"end_time\", \"created_time\"]),\n ...diagnostics(row),\n };\n}\n\nconst AD_COLUMNS = [\n \"id\",\n \"name\",\n \"adset_id\",\n \"campaign_id\",\n \"effective_status\",\n \"creative_id\",\n \"issues\",\n \"created_time\",\n] as const;\n\n/** Why an ad is WITH_ISSUES — the one reason to open `issues_info`, in its own words. */\nfunction adIssues(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return value.flatMap((entry) => {\n const issue = asRecord(entry);\n const text = issue?.error_summary ?? issue?.error_message;\n return typeof text === \"string\" && text ? [text] : [];\n });\n}\n\n/** Meta's suggestions for a campaign or ad set (`recommendations`), by their titles. */\nfunction suggestions(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return value.flatMap((entry) => {\n const recommendation = asRecord(entry);\n const text = recommendation?.title ?? recommendation?.message;\n return typeof text === \"string\" && text ? [text] : [];\n });\n}\n\n/** Why a campaign or ad set cannot deliver, and what Meta suggests — only when Meta says something. */\nfunction diagnostics(row: MetaRow): MetaRow {\n const issues = adIssues(row.issues_info);\n const suggested = suggestions(row.recommendations);\n return {\n ...(issues.length > 0 ? { issues } : {}),\n ...(suggested.length > 0 ? { suggestions: suggested } : {}),\n };\n}\n\nfunction compactAd(row: MetaRow): MetaRow {\n const creativeId = asRecord(row.creative)?.id;\n const issues = adIssues(row.issues_info);\n return {\n ...pick(row, [\"id\", \"name\", \"adset_id\", \"campaign_id\", \"effective_status\"]),\n ...(creativeId !== undefined ? { creative_id: creativeId } : {}),\n ...(issues.length > 0 ? { issues } : {}),\n ...pick(row, [\"created_time\"]),\n };\n}\n\nconst ACTIVITY_COLUMNS = [\n \"event_time\",\n \"event_type\",\n \"actor_name\",\n \"object_type\",\n \"object_name\",\n \"object_id\",\n \"change\",\n] as const;\n\nfunction isScalar(value: unknown): value is string | number | null {\n return value === null || typeof value === \"string\" || typeof value === \"number\";\n}\n\n/**\n * `extra_data` is a JSON string whose shape varies by event type and carries most\n * of an activity's bytes (image URLs, whole targeting specs). A status, name,\n * budget or goal change stores its before and after as two plain values — those\n * read as one line; any richer change stays behind `--fields extra_data`.\n */\nexport function activityChange(extraData: unknown): string | undefined {\n if (typeof extraData !== \"string\") return undefined;\n let parsed: unknown;\n try {\n parsed = JSON.parse(extraData);\n } catch {\n return undefined;\n }\n const data = asRecord(parsed);\n // An absent old_value is one this read did not observe, not an unset one — only `null` means \"none\".\n if (!data || !(\"new_value\" in data) || !(\"old_value\" in data)) return undefined;\n const { old_value: before, new_value: after } = data;\n if (!isScalar(before) || !isScalar(after)) return undefined;\n const show = (value: string | number | null) => (value === null ? \"(none)\" : String(value));\n return `${show(before)} → ${show(after)}`;\n}\n\nfunction compactActivity(row: MetaRow): MetaRow {\n const change = activityChange(row.extra_data);\n return {\n ...pick(row, [\"event_time\", \"event_type\", \"actor_name\", \"object_type\", \"object_name\", \"object_id\"]),\n ...(change !== undefined ? { change } : {}),\n };\n}\n\n/**\n * The unit a listing's budgets are in, said once rather than as a column (a\n * 100-campaign table stays small). Meta lists money in the account currency's\n * smallest unit and Baker passes it through unchanged (published reports read\n * it that way), while every money flag takes whole currency. An agent that once\n * took a listed \"8000\" for the flag's unit staged 10,000 EUR a day instead of 100.\n */\nexport function budgetUnitHints(rows: ReadonlyArray<Record<string, unknown>>): string[] {\n const listed = rows\n .map((row) => Number(row.daily_budget ?? row.lifetime_budget))\n .find((amount) => Number.isFinite(amount) && amount > 0);\n if (listed === undefined) return [];\n const whole = listed / 100;\n return [\n `Budgets here are in the account currency's smallest unit, as Meta sends them: daily_budget ${listed} is ${whole} in EUR or USD (currencies without cents, such as JPY, are not divided). Money flags take whole currency: --daily-budget ${whole}, never ${listed}.`,\n ];\n}\n\nconst PROJECTIONS: Record<MetaListKind, CompactProjection<MetaRow>> = {\n campaigns: { row: compactCampaign, columns: CAMPAIGN_COLUMNS, whenPresent: DIAGNOSTIC_COLUMNS },\n adsets: { row: compactAdSet, columns: ADSET_COLUMNS, whenPresent: DIAGNOSTIC_COLUMNS },\n ads: { row: compactAd, columns: AD_COLUMNS },\n activities: { row: compactActivity, columns: ACTIVITY_COLUMNS },\n};\n\nexport function shapeMetaListRows(kind: MetaListKind, rows: MetaRow[], args: Record<string, unknown>): ShapedRows {\n return shapeListRows(rows, args, PROJECTIONS[kind]);\n}\n\nconst NOUNS: Record<MetaListKind, string> = {\n campaigns: \"campaigns\",\n adsets: \"ad sets\",\n ads: \"ads\",\n activities: \"activities\",\n};\n\n/**\n * A table of no rows prints nothing at all, which reads as a failed call — so an empty\n * listing says so, and says why when a status filter may be hiding rows.\n */\nexport function writeMetaListRows(kind: MetaListKind, shaped: ShapedRows, format: string, hints: string[] = []): void {\n if (format === \"md\" && shaped.rows.length === 0) {\n process.stdout.write(`${hints.length > 0 ? hints.join(\"\\n\") : `No ${NOUNS[kind]} matched.`}\\n`);\n return;\n }\n writeAdsOutput(shaped.rows, format, shaped.fields, [...hints, ...(shaped.hints ?? [])]);\n}\n\n/** The projection flags every Meta listing shares, worded once for help and `baker schema`. */\nexport const META_LIST_SHAPE_ARGS = {\n fields: {\n type: \"string\",\n description: \"CSV of dotted paths to return instead of the compact row, e.g. id,name,targeting.geo_locations\",\n },\n full: { type: \"boolean\", description: \"Return every field Meta sent (targeting, tracking specs, raw extra_data)\" },\n output: {\n type: \"string\",\n description: \"md|json|csv|jsonl — md (default) prints a table; json returns the rows in the { ok, data } envelope\",\n default: \"md\",\n },\n} as const;\n\ninterface ListArgDef {\n type: string;\n description?: string;\n default?: unknown;\n}\n\n/**\n * `baker schema ads.meta.<list>`, read off the same arg defs the command parses,\n * so the introspection an agent checks before a call cannot promise a flag the\n * command refuses — `--full` on `adsets` was guessed three times in one Session.\n */\nexport function registerMetaListSchema(\n kind: MetaListKind,\n description: string,\n args: Record<string, ListArgDef>,\n): void {\n registerSchema({\n command: `ads.meta.${kind}`,\n description,\n args: Object.fromEntries(\n Object.entries(args).map(([name, def]) => [\n name,\n {\n type: def.type,\n description: def.description ?? \"\",\n required: false,\n ...(def.default !== undefined ? { default: def.default } : {}),\n },\n ]),\n ),\n });\n}\n"],"mappings":"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","names":[]}
@@ -5,7 +5,7 @@ import {
5
5
  UNHASHED_CUSTOMER_LIST_KEYS,
6
6
  customAudienceMembersSchema,
7
7
  customerListBatchSchema
8
- } from "./chunk-5B2WEPYR.js";
8
+ } from "./chunk-SQCALAI7.js";
9
9
 
10
10
  // src/commands/ads/meta/customer-list.ts
11
11
  import { createHash } from "crypto";
@@ -388,4 +388,4 @@ export {
388
388
  customerListBatches,
389
389
  customerListUploadRefusal
390
390
  };
391
- //# sourceMappingURL=chunk-YGCRKABE.js.map
391
+ //# sourceMappingURL=chunk-SHLA4JF7.js.map
@@ -4157,11 +4157,14 @@ function createOp(kind, payload) {
4157
4157
  function updateOp(kind, payload) {
4158
4158
  return z12.object({ kind: z12.literal(kind), accountId: accountIdSchema, target: updateTargetSchema, payload });
4159
4159
  }
4160
+ function budgetUpdateOp(kind, payload) {
4161
+ return updateOp(kind, payload).extend({ confirmBudgetIncrease: z12.boolean().optional() });
4162
+ }
4160
4163
  var metaDraftOpInputSchema = z12.discriminatedUnion("kind", [
4161
4164
  createOp("campaign.create", campaignCreateSchema),
4162
- updateOp("campaign.update", campaignUpdateSchema),
4165
+ budgetUpdateOp("campaign.update", campaignUpdateSchema),
4163
4166
  createOp("adSet.create", adSetCreateSchema),
4164
- updateOp("adSet.update", adSetUpdateSchema),
4167
+ budgetUpdateOp("adSet.update", adSetUpdateSchema),
4165
4168
  createOp("adCreative.create", adCreativeCreateSchema),
4166
4169
  updateOp("adCreative.update", adCreativeUpdateSchema),
4167
4170
  createOp("ad.create", adCreateSchema),
@@ -4223,4 +4226,4 @@ export {
4223
4226
  metaTargetingSchema,
4224
4227
  metaDraftOpInputSchema
4225
4228
  };
4226
- //# sourceMappingURL=chunk-5B2WEPYR.js.map
4229
+ //# sourceMappingURL=chunk-SQCALAI7.js.map