@koda-sl/baker-cli 0.489.0 → 0.490.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 (311) hide show
  1. package/README.md +169 -7
  2. package/dist/{account-Z65CPOWE.js → account-3H6BZO5H.js} +2 -2
  3. package/dist/account-IKFDY52P.js +138 -0
  4. package/dist/account-IKFDY52P.js.map +1 -0
  5. package/dist/account-assets-LKZVWZAR.js +289 -0
  6. package/dist/account-assets-LKZVWZAR.js.map +1 -0
  7. package/dist/account-level-UJOZDVXY.js +608 -0
  8. package/dist/account-level-UJOZDVXY.js.map +1 -0
  9. package/dist/{account-writes-4N2MA2ZR.js → account-writes-AE5IJGGW.js} +2 -2
  10. package/dist/{accounts-UA2ZWRN4.js → accounts-K4INATCW.js} +2 -2
  11. package/dist/{activities-IQPJPP4B.js → activities-T253KK4Q.js} +4 -4
  12. package/dist/{ad-group-writes-EUTMPBMK.js → ad-group-writes-VRSBI2Z2.js} +2 -2
  13. package/dist/{ad-groups-OVPAI5RM.js → ad-groups-IEBVEAMS.js} +6 -6
  14. package/dist/{ad-writes-DACTYFEO.js → ad-writes-ALV4KFPZ.js} +2 -2
  15. package/dist/{ads-L65JIKCD.js → ads-CQZHD7FC.js} +7 -7
  16. package/dist/{ads-G6AS5L7G.js → ads-QIKZ6O2N.js} +5 -5
  17. package/dist/{ads-HXX2IAFF.js → ads-ZEY72UBN.js} +14 -13
  18. package/dist/ads-ZEY72UBN.js.map +1 -0
  19. package/dist/{adsets-LPN6WFGF.js → adsets-5H3MOT3D.js} +15 -14
  20. package/dist/{adsets-LPN6WFGF.js.map → adsets-5H3MOT3D.js.map} +1 -1
  21. package/dist/{analytics-QKP3A5F3.js → analytics-ALOZ7ZZ4.js} +1 -1
  22. package/dist/asset-writes-L5TMKIZC.js +47 -0
  23. package/dist/audience-writes-X52VG35Y.js +324 -0
  24. package/dist/audience-writes-X52VG35Y.js.map +1 -0
  25. package/dist/{audiences-RPLVMO4H.js → audiences-AAZH56WD.js} +2 -2
  26. package/dist/{audiences-XEZHACKH.js → audiences-X3RLGOVM.js} +12 -6
  27. package/dist/audiences-X3RLGOVM.js.map +1 -0
  28. package/dist/{avatars-MXTI74VC.js → avatars-YSFFRHDK.js} +1 -1
  29. package/dist/{brief-BN4UGUXF.js → brief-7S6XCJIA.js} +15 -15
  30. package/dist/{businesses-PRRYPR7H.js → businesses-H3HIDQX6.js} +2 -2
  31. package/dist/{campaign-writes-BAFB5E7A.js → campaign-writes-7ZF57KLH.js} +3 -3
  32. package/dist/campaign-writes-7ZF57KLH.js.map +1 -0
  33. package/dist/{campaign-writes-U5LTDTYK.js → campaign-writes-U5PUVSMT.js} +2 -2
  34. package/dist/{campaigns-4SOLY7OR.js → campaigns-AV6G3AUU.js} +32 -15
  35. package/dist/campaigns-AV6G3AUU.js.map +1 -0
  36. package/dist/{campaigns-TFEQTSO3.js → campaigns-JEIKY2M4.js} +6 -6
  37. package/dist/{campaigns-NR6TNQFN.js → campaigns-VTRMKSAT.js} +5 -5
  38. package/dist/{canvas-GJAQAVS6.js → canvas-SVJEQO4V.js} +13 -13
  39. package/dist/{catalog-USZL4SGX.js → catalog-S32MX453.js} +5 -5
  40. package/dist/{catalogs-A7XMEEEP.js → catalogs-OCVXZLIF.js} +2 -2
  41. package/dist/catalogs-RXJTZTVX.js +778 -0
  42. package/dist/catalogs-RXJTZTVX.js.map +1 -0
  43. package/dist/{chatgpt-4PEWDJKP.js → chatgpt-QVF2FD3E.js} +12 -12
  44. package/dist/{chats-INN2OHSH.js → chats-QG72JB6Y.js} +22 -8
  45. package/dist/chats-QG72JB6Y.js.map +1 -0
  46. package/dist/{check-MMJGFFZS.js → check-SLNHVYGS.js} +4 -4
  47. package/dist/{chunk-7RBJ2Z7Z.js → chunk-2C7AHPM4.js} +25 -6
  48. package/dist/chunk-2C7AHPM4.js.map +1 -0
  49. package/dist/{chunk-KPYDTIAI.js → chunk-2WZI36D3.js} +2 -2
  50. package/dist/{chunk-FUKDI2UK.js → chunk-3W6G6ARX.js} +2 -2
  51. package/dist/{chunk-JWSEPW7F.js → chunk-46GWHUKN.js} +2 -2
  52. package/dist/{chunk-3TZVZXM6.js → chunk-4KJMLYCD.js} +6 -6
  53. package/dist/{chunk-6JWEGFM5.js → chunk-5C35OW7L.js} +38 -7
  54. package/dist/chunk-5C35OW7L.js.map +1 -0
  55. package/dist/chunk-5GQCN2QZ.js +391 -0
  56. package/dist/chunk-5GQCN2QZ.js.map +1 -0
  57. package/dist/{chunk-KIGGMKAE.js → chunk-65Y3RCWP.js} +4 -2
  58. package/dist/chunk-65Y3RCWP.js.map +1 -0
  59. package/dist/{chunk-R3EKM2P2.js → chunk-6NCJGU6I.js} +5 -5
  60. package/dist/chunk-A4MVVPJ2.js +4204 -0
  61. package/dist/chunk-A4MVVPJ2.js.map +1 -0
  62. package/dist/{chunk-LPXSM2DI.js → chunk-AO45BX6Q.js} +3 -3
  63. package/dist/{chunk-3UXMQ3K2.js → chunk-AQM4JH62.js} +2 -2
  64. package/dist/chunk-AQM4JH62.js.map +1 -0
  65. package/dist/{chunk-NPMAATZG.js → chunk-C7NWUCLQ.js} +2 -2
  66. package/dist/chunk-CP4P6YKM.js +287 -0
  67. package/dist/chunk-CP4P6YKM.js.map +1 -0
  68. package/dist/{chunk-OWA7ZLC4.js → chunk-D4CKCNGW.js} +4 -4
  69. package/dist/{chunk-H5HDZ7IC.js → chunk-DCBZ5CHZ.js} +4 -4
  70. package/dist/{chunk-C6EYCD5J.js → chunk-FVHJCERJ.js} +5 -5
  71. package/dist/{chunk-BITS62MF.js → chunk-G6XKD7QE.js} +2 -2
  72. package/dist/{chunk-QE3JEJXF.js → chunk-GSZZLW5Q.js} +4 -4
  73. package/dist/chunk-HLVRHBKL.js +1078 -0
  74. package/dist/chunk-HLVRHBKL.js.map +1 -0
  75. package/dist/{chunk-TPANP5A2.js → chunk-JKJQWRLO.js} +2 -2
  76. package/dist/{chunk-62JQQUAU.js → chunk-JQH5VG6F.js} +2 -2
  77. package/dist/{chunk-6WXV5GTA.js → chunk-JVH5A3XC.js} +2 -2
  78. package/dist/{chunk-AVNSH2JE.js → chunk-KOXDXSKN.js} +7 -7
  79. package/dist/{chunk-2XRMPSEV.js → chunk-LXQB4ZGE.js} +2 -2
  80. package/dist/{chunk-ZL23HA4N.js → chunk-M6PN3VH6.js} +2 -2
  81. package/dist/{chunk-TZEVD4Q6.js → chunk-P5FRWPG7.js} +2 -2
  82. package/dist/{chunk-CSZFZKVX.js → chunk-PQJXIY64.js} +5 -5
  83. package/dist/{chunk-OP7DNHD2.js → chunk-QTOZ32SU.js} +27 -1
  84. package/dist/chunk-QTOZ32SU.js.map +1 -0
  85. package/dist/chunk-SVAB6KV5.js +219 -0
  86. package/dist/chunk-SVAB6KV5.js.map +1 -0
  87. package/dist/{chunk-LBO2YAZY.js → chunk-UNX6BS4U.js} +15 -15
  88. package/dist/{chunk-UWXDNVS5.js → chunk-ZJSGGJ5R.js} +2 -2
  89. package/dist/cli.js +20 -20
  90. package/dist/{connect-WBGCBBFJ.js → connect-S54TJ6OV.js} +3 -3
  91. package/dist/{conversion-writes-JU7Q2MUO.js → conversion-writes-ECZBVY7D.js} +2 -2
  92. package/dist/{conversions-3ISBR3TS.js → conversions-5QCSCRLI.js} +3 -3
  93. package/dist/copy-writes-D2RTHAL6.js +167 -0
  94. package/dist/copy-writes-D2RTHAL6.js.map +1 -0
  95. package/dist/{creatives-VQO2TKE3.js → creatives-5I3G5YP3.js} +2 -2
  96. package/dist/{creatives-YJ3CXZQC.js → creatives-MZ6ICNSY.js} +5 -4
  97. package/dist/{creatives-YJ3CXZQC.js.map → creatives-MZ6ICNSY.js.map} +1 -1
  98. package/dist/{creatives-S5QUWUL6.js → creatives-PCAGWPW3.js} +10 -10
  99. package/dist/{critique-5LCG5TYF.js → critique-NRHUPIWF.js} +7 -7
  100. package/dist/{custom-conversions-YRYE65PU.js → custom-conversions-FIP6ZS34.js} +5 -3
  101. package/dist/{custom-conversions-YRYE65PU.js.map → custom-conversions-FIP6ZS34.js.map} +1 -1
  102. package/dist/{draft-Y2QJE2NM.js → draft-34CGWUVA.js} +2 -2
  103. package/dist/{draft-GPN3HOAG.js → draft-4P3YO67N.js} +9 -5
  104. package/dist/draft-4P3YO67N.js.map +1 -0
  105. package/dist/{draft-EWDOIXSH.js → draft-L45PGCYZ.js} +7 -3
  106. package/dist/draft-L45PGCYZ.js.map +1 -0
  107. package/dist/engine/index.js +4 -4
  108. package/dist/{experiment-G3FQVAJU.js → experiment-7N4QFRWV.js} +4 -4
  109. package/dist/{feedback-CAOZPGTT.js → feedback-O3H42V4I.js} +10 -10
  110. package/dist/{feedback-record-EXV5H6OS.js → feedback-record-FAPN2GBS.js} +12 -12
  111. package/dist/{find-EVY4XEIQ.js → find-FSQAEGGF.js} +4 -4
  112. package/dist/{flows-Z7355RMD.js → flows-T22B77J3.js} +3 -3
  113. package/dist/{funnel-2B3JXJPX.js → funnel-7OA33VRP.js} +5 -5
  114. package/dist/{ga4-2BL5YAYN.js → ga4-LPDIBNYP.js} +1 -1
  115. package/dist/{google-7STODZQR.js → google-5ESVO76E.js} +5 -5
  116. package/dist/{gsc-UU3T2C6B.js → gsc-FIZTQX3N.js} +1 -1
  117. package/dist/{history-IQ33J5PB.js → history-QKDYBSYM.js} +2 -2
  118. package/dist/{icon-GB7UH5RF.js → icon-CSVAZ7NE.js} +4 -4
  119. package/dist/{ideas-F6CIGTVU.js → ideas-JQT422P7.js} +4 -4
  120. package/dist/{images-WCKTD6Z2.js → images-WBNWK2ZH.js} +6 -6
  121. package/dist/{insights-4HT2NAYP.js → insights-YWVJMATY.js} +4 -3
  122. package/dist/{insights-4HT2NAYP.js.map → insights-YWVJMATY.js.map} +1 -1
  123. package/dist/{inspiration-XQYHBJY2.js → inspiration-IX5N724J.js} +1 -1
  124. package/dist/instant-experiences-NQ2GWIWL.js +257 -0
  125. package/dist/instant-experiences-NQ2GWIWL.js.map +1 -0
  126. package/dist/{landing-WUILAWDS.js → landing-Y6QCTXCZ.js} +2 -2
  127. package/dist/leads-THI37ZMD.js +537 -0
  128. package/dist/leads-THI37ZMD.js.map +1 -0
  129. package/dist/{learn-CC6Q5IK2.js → learn-3BDZUWDT.js} +5 -5
  130. package/dist/{linkedin-XKVPSCLV.js → linkedin-UGMAFSGO.js} +2 -2
  131. package/dist/{locations-YA7NZY44.js → locations-HM56X2MK.js} +2 -2
  132. package/dist/locations-HM56X2MK.js.map +1 -0
  133. package/dist/{logo-YSNUUT33.js → logo-VHXH4J6A.js} +3 -3
  134. package/dist/{make-ED7HBLH3.js → make-W2PYZXYF.js} +39 -39
  135. package/dist/media-H6B7VDON.js +18 -0
  136. package/dist/media-H6B7VDON.js.map +1 -0
  137. package/dist/{media-sources-PEHUMH7C.js → media-sources-EZKAJNVD.js} +1 -1
  138. package/dist/meta-YHDTGJQ6.js +122 -0
  139. package/dist/meta-YHDTGJQ6.js.map +1 -0
  140. package/dist/{options-6FCNFWUF.js → options-NSCZSQ5P.js} +3 -3
  141. package/dist/page-photos-CXRG4AXV.js +115 -0
  142. package/dist/page-photos-CXRG4AXV.js.map +1 -0
  143. package/dist/{pages-FTI44OSH.js → pages-PTWRXAZT.js} +2 -2
  144. package/dist/{pixels-6IUB3Y3H.js → pixels-MYT3TCHZ.js} +2 -2
  145. package/dist/{pixels-MBKR4XPX.js → pixels-ZZCQUS3J.js} +2 -2
  146. package/dist/{preview-V4YBD45S.js → preview-XOXAAPMQ.js} +73 -27
  147. package/dist/preview-XOXAAPMQ.js.map +1 -0
  148. package/dist/{rerun-A2XHGFZS.js → rerun-5THJLQQJ.js} +18 -18
  149. package/dist/{research-BLDY5UWH.js → research-JHDWWFL7.js} +1 -1
  150. package/dist/rule-writes-6ZCAJDYZ.js +522 -0
  151. package/dist/rule-writes-6ZCAJDYZ.js.map +1 -0
  152. package/dist/rules-BMYOY2BM.js +216 -0
  153. package/dist/rules-BMYOY2BM.js.map +1 -0
  154. package/dist/{rules-SK5DFFPY.js → rules-YLLFDZEM.js} +3 -3
  155. package/dist/{rules-add-YQNYSME7.js → rules-add-U2GU4AGP.js} +4 -4
  156. package/dist/{run-KBN5K7LE.js → run-V5YQB6TH.js} +18 -18
  157. package/dist/{scaffold-ad-6BN5LWQH.js → scaffold-ad-H4GJOKAW.js} +12 -12
  158. package/dist/{scaffold-static-ad-VVZRAWBR.js → scaffold-static-ad-2YIFHCTL.js} +25 -25
  159. package/dist/{scaffold-video-LFIYI4GP.js → scaffold-video-3EJLKR2O.js} +14 -14
  160. package/dist/{select-QBU6ED4K.js → select-I22NPSIW.js} +9 -9
  161. package/dist/{set-prompt-TL64CRBQ.js → set-prompt-S75OMQ7L.js} +8 -8
  162. package/dist/{shared-NDRFKAH7.js → shared-3IBNDEFL.js} +2 -2
  163. package/dist/{sources-RMNFV4CA.js → sources-VA23PDND.js} +1 -1
  164. package/dist/{stale-ITFCPOER.js → stale-MHTU2NQJ.js} +8 -8
  165. package/dist/{stats-RCLQE4HJ.js → stats-ZAGJH4AD.js} +1 -1
  166. package/dist/{stock-ECRBD7RP.js → stock-6SHHLSKG.js} +5 -5
  167. package/dist/studies-4NIV4D5Y.js +249 -0
  168. package/dist/studies-4NIV4D5Y.js.map +1 -0
  169. package/dist/{studio-MARZ22J2.js → studio-ZLCGXFAN.js} +1 -1
  170. package/dist/study-writes-L2AA2PGL.js +467 -0
  171. package/dist/study-writes-L2AA2PGL.js.map +1 -0
  172. package/dist/{sync-definition-C6ROLKJ4.js → sync-definition-2EBSQA6A.js} +11 -11
  173. package/dist/{tag-manager-G3LBQZUL.js → tag-manager-3CJ66GKJ.js} +1 -1
  174. package/dist/targeting-LNDQV4EK.js +759 -0
  175. package/dist/targeting-LNDQV4EK.js.map +1 -0
  176. package/dist/{testimonials-YMMA5YWL.js → testimonials-GR6TIS5S.js} +2 -2
  177. package/dist/{translate-OXVIMYHE.js → translate-GEFUP6KQ.js} +18 -18
  178. package/dist/{validate-ZS2M5Q3V.js → validate-NOWIOAHE.js} +11 -11
  179. package/dist/{videos-I6YXFBFT.js → videos-XMTDEHEJ.js} +1 -1
  180. package/dist/{viewer-check-7ZG7KHEN.js → viewer-check-U4XZMMS7.js} +6 -6
  181. package/dist/viewer-check-U4XZMMS7.js.map +1 -0
  182. package/dist/{winning-ads-ABN5OULS.js → winning-ads-QOAYIR5U.js} +1 -1
  183. package/dist/{write-commands-HCQI4Y27.js → write-commands-PEJBTME6.js} +485 -57
  184. package/dist/write-commands-PEJBTME6.js.map +1 -0
  185. package/dist/{x-WK2VQDPF.js → x-VCSMV7T5.js} +4 -4
  186. package/package.json +1 -1
  187. package/dist/account-7LUQWY6Q.js +0 -49
  188. package/dist/account-7LUQWY6Q.js.map +0 -1
  189. package/dist/ads-HXX2IAFF.js.map +0 -1
  190. package/dist/audiences-XEZHACKH.js.map +0 -1
  191. package/dist/campaign-writes-BAFB5E7A.js.map +0 -1
  192. package/dist/campaigns-4SOLY7OR.js.map +0 -1
  193. package/dist/chats-INN2OHSH.js.map +0 -1
  194. package/dist/chunk-3UXMQ3K2.js.map +0 -1
  195. package/dist/chunk-6JWEGFM5.js.map +0 -1
  196. package/dist/chunk-7RBJ2Z7Z.js.map +0 -1
  197. package/dist/chunk-GOJXKIFQ.js +0 -1605
  198. package/dist/chunk-GOJXKIFQ.js.map +0 -1
  199. package/dist/chunk-KIGGMKAE.js.map +0 -1
  200. package/dist/chunk-OP7DNHD2.js.map +0 -1
  201. package/dist/draft-EWDOIXSH.js.map +0 -1
  202. package/dist/draft-GPN3HOAG.js.map +0 -1
  203. package/dist/leads-2XOSAYP4.js +0 -293
  204. package/dist/leads-2XOSAYP4.js.map +0 -1
  205. package/dist/locations-YA7NZY44.js.map +0 -1
  206. package/dist/media-ES2UBGYW.js +0 -15
  207. package/dist/media-ES2UBGYW.js.map +0 -1
  208. package/dist/meta-AOIPEDV5.js +0 -69
  209. package/dist/meta-AOIPEDV5.js.map +0 -1
  210. package/dist/preview-V4YBD45S.js.map +0 -1
  211. package/dist/write-commands-HCQI4Y27.js.map +0 -1
  212. /package/dist/{account-Z65CPOWE.js.map → account-3H6BZO5H.js.map} +0 -0
  213. /package/dist/{account-writes-4N2MA2ZR.js.map → account-writes-AE5IJGGW.js.map} +0 -0
  214. /package/dist/{accounts-UA2ZWRN4.js.map → accounts-K4INATCW.js.map} +0 -0
  215. /package/dist/{activities-IQPJPP4B.js.map → activities-T253KK4Q.js.map} +0 -0
  216. /package/dist/{ad-group-writes-EUTMPBMK.js.map → ad-group-writes-VRSBI2Z2.js.map} +0 -0
  217. /package/dist/{ad-groups-OVPAI5RM.js.map → ad-groups-IEBVEAMS.js.map} +0 -0
  218. /package/dist/{ad-writes-DACTYFEO.js.map → ad-writes-ALV4KFPZ.js.map} +0 -0
  219. /package/dist/{ads-L65JIKCD.js.map → ads-CQZHD7FC.js.map} +0 -0
  220. /package/dist/{ads-G6AS5L7G.js.map → ads-QIKZ6O2N.js.map} +0 -0
  221. /package/dist/{analytics-QKP3A5F3.js.map → analytics-ALOZ7ZZ4.js.map} +0 -0
  222. /package/dist/{connect-WBGCBBFJ.js.map → asset-writes-L5TMKIZC.js.map} +0 -0
  223. /package/dist/{audiences-RPLVMO4H.js.map → audiences-AAZH56WD.js.map} +0 -0
  224. /package/dist/{avatars-MXTI74VC.js.map → avatars-YSFFRHDK.js.map} +0 -0
  225. /package/dist/{brief-BN4UGUXF.js.map → brief-7S6XCJIA.js.map} +0 -0
  226. /package/dist/{businesses-PRRYPR7H.js.map → businesses-H3HIDQX6.js.map} +0 -0
  227. /package/dist/{campaign-writes-U5LTDTYK.js.map → campaign-writes-U5PUVSMT.js.map} +0 -0
  228. /package/dist/{campaigns-TFEQTSO3.js.map → campaigns-JEIKY2M4.js.map} +0 -0
  229. /package/dist/{campaigns-NR6TNQFN.js.map → campaigns-VTRMKSAT.js.map} +0 -0
  230. /package/dist/{canvas-GJAQAVS6.js.map → canvas-SVJEQO4V.js.map} +0 -0
  231. /package/dist/{catalog-USZL4SGX.js.map → catalog-S32MX453.js.map} +0 -0
  232. /package/dist/{catalogs-A7XMEEEP.js.map → catalogs-OCVXZLIF.js.map} +0 -0
  233. /package/dist/{chatgpt-4PEWDJKP.js.map → chatgpt-QVF2FD3E.js.map} +0 -0
  234. /package/dist/{check-MMJGFFZS.js.map → check-SLNHVYGS.js.map} +0 -0
  235. /package/dist/{chunk-KPYDTIAI.js.map → chunk-2WZI36D3.js.map} +0 -0
  236. /package/dist/{chunk-FUKDI2UK.js.map → chunk-3W6G6ARX.js.map} +0 -0
  237. /package/dist/{chunk-JWSEPW7F.js.map → chunk-46GWHUKN.js.map} +0 -0
  238. /package/dist/{chunk-3TZVZXM6.js.map → chunk-4KJMLYCD.js.map} +0 -0
  239. /package/dist/{chunk-R3EKM2P2.js.map → chunk-6NCJGU6I.js.map} +0 -0
  240. /package/dist/{chunk-LPXSM2DI.js.map → chunk-AO45BX6Q.js.map} +0 -0
  241. /package/dist/{chunk-NPMAATZG.js.map → chunk-C7NWUCLQ.js.map} +0 -0
  242. /package/dist/{chunk-OWA7ZLC4.js.map → chunk-D4CKCNGW.js.map} +0 -0
  243. /package/dist/{chunk-H5HDZ7IC.js.map → chunk-DCBZ5CHZ.js.map} +0 -0
  244. /package/dist/{chunk-C6EYCD5J.js.map → chunk-FVHJCERJ.js.map} +0 -0
  245. /package/dist/{chunk-BITS62MF.js.map → chunk-G6XKD7QE.js.map} +0 -0
  246. /package/dist/{chunk-QE3JEJXF.js.map → chunk-GSZZLW5Q.js.map} +0 -0
  247. /package/dist/{chunk-TPANP5A2.js.map → chunk-JKJQWRLO.js.map} +0 -0
  248. /package/dist/{chunk-62JQQUAU.js.map → chunk-JQH5VG6F.js.map} +0 -0
  249. /package/dist/{chunk-6WXV5GTA.js.map → chunk-JVH5A3XC.js.map} +0 -0
  250. /package/dist/{chunk-AVNSH2JE.js.map → chunk-KOXDXSKN.js.map} +0 -0
  251. /package/dist/{chunk-2XRMPSEV.js.map → chunk-LXQB4ZGE.js.map} +0 -0
  252. /package/dist/{chunk-ZL23HA4N.js.map → chunk-M6PN3VH6.js.map} +0 -0
  253. /package/dist/{chunk-TZEVD4Q6.js.map → chunk-P5FRWPG7.js.map} +0 -0
  254. /package/dist/{chunk-CSZFZKVX.js.map → chunk-PQJXIY64.js.map} +0 -0
  255. /package/dist/{chunk-LBO2YAZY.js.map → chunk-UNX6BS4U.js.map} +0 -0
  256. /package/dist/{chunk-UWXDNVS5.js.map → chunk-ZJSGGJ5R.js.map} +0 -0
  257. /package/dist/{ideas-F6CIGTVU.js.map → connect-S54TJ6OV.js.map} +0 -0
  258. /package/dist/{conversion-writes-JU7Q2MUO.js.map → conversion-writes-ECZBVY7D.js.map} +0 -0
  259. /package/dist/{conversions-3ISBR3TS.js.map → conversions-5QCSCRLI.js.map} +0 -0
  260. /package/dist/{creatives-VQO2TKE3.js.map → creatives-5I3G5YP3.js.map} +0 -0
  261. /package/dist/{creatives-S5QUWUL6.js.map → creatives-PCAGWPW3.js.map} +0 -0
  262. /package/dist/{critique-5LCG5TYF.js.map → critique-NRHUPIWF.js.map} +0 -0
  263. /package/dist/{draft-Y2QJE2NM.js.map → draft-34CGWUVA.js.map} +0 -0
  264. /package/dist/{experiment-G3FQVAJU.js.map → experiment-7N4QFRWV.js.map} +0 -0
  265. /package/dist/{feedback-CAOZPGTT.js.map → feedback-O3H42V4I.js.map} +0 -0
  266. /package/dist/{feedback-record-EXV5H6OS.js.map → feedback-record-FAPN2GBS.js.map} +0 -0
  267. /package/dist/{find-EVY4XEIQ.js.map → find-FSQAEGGF.js.map} +0 -0
  268. /package/dist/{flows-Z7355RMD.js.map → flows-T22B77J3.js.map} +0 -0
  269. /package/dist/{funnel-2B3JXJPX.js.map → funnel-7OA33VRP.js.map} +0 -0
  270. /package/dist/{ga4-2BL5YAYN.js.map → ga4-LPDIBNYP.js.map} +0 -0
  271. /package/dist/{google-7STODZQR.js.map → google-5ESVO76E.js.map} +0 -0
  272. /package/dist/{gsc-UU3T2C6B.js.map → gsc-FIZTQX3N.js.map} +0 -0
  273. /package/dist/{history-IQ33J5PB.js.map → history-QKDYBSYM.js.map} +0 -0
  274. /package/dist/{icon-GB7UH5RF.js.map → icon-CSVAZ7NE.js.map} +0 -0
  275. /package/dist/{logo-YSNUUT33.js.map → ideas-JQT422P7.js.map} +0 -0
  276. /package/dist/{images-WCKTD6Z2.js.map → images-WBNWK2ZH.js.map} +0 -0
  277. /package/dist/{inspiration-XQYHBJY2.js.map → inspiration-IX5N724J.js.map} +0 -0
  278. /package/dist/{landing-WUILAWDS.js.map → landing-Y6QCTXCZ.js.map} +0 -0
  279. /package/dist/{learn-CC6Q5IK2.js.map → learn-3BDZUWDT.js.map} +0 -0
  280. /package/dist/{linkedin-XKVPSCLV.js.map → linkedin-UGMAFSGO.js.map} +0 -0
  281. /package/dist/{run-KBN5K7LE.js.map → logo-VHXH4J6A.js.map} +0 -0
  282. /package/dist/{make-ED7HBLH3.js.map → make-W2PYZXYF.js.map} +0 -0
  283. /package/dist/{media-sources-PEHUMH7C.js.map → media-sources-EZKAJNVD.js.map} +0 -0
  284. /package/dist/{options-6FCNFWUF.js.map → options-NSCZSQ5P.js.map} +0 -0
  285. /package/dist/{pages-FTI44OSH.js.map → pages-PTWRXAZT.js.map} +0 -0
  286. /package/dist/{pixels-6IUB3Y3H.js.map → pixels-MYT3TCHZ.js.map} +0 -0
  287. /package/dist/{pixels-MBKR4XPX.js.map → pixels-ZZCQUS3J.js.map} +0 -0
  288. /package/dist/{rerun-A2XHGFZS.js.map → rerun-5THJLQQJ.js.map} +0 -0
  289. /package/dist/{research-BLDY5UWH.js.map → research-JHDWWFL7.js.map} +0 -0
  290. /package/dist/{rules-SK5DFFPY.js.map → rules-YLLFDZEM.js.map} +0 -0
  291. /package/dist/{rules-add-YQNYSME7.js.map → rules-add-U2GU4AGP.js.map} +0 -0
  292. /package/dist/{shared-NDRFKAH7.js.map → run-V5YQB6TH.js.map} +0 -0
  293. /package/dist/{scaffold-ad-6BN5LWQH.js.map → scaffold-ad-H4GJOKAW.js.map} +0 -0
  294. /package/dist/{scaffold-static-ad-VVZRAWBR.js.map → scaffold-static-ad-2YIFHCTL.js.map} +0 -0
  295. /package/dist/{scaffold-video-LFIYI4GP.js.map → scaffold-video-3EJLKR2O.js.map} +0 -0
  296. /package/dist/{select-QBU6ED4K.js.map → select-I22NPSIW.js.map} +0 -0
  297. /package/dist/{set-prompt-TL64CRBQ.js.map → set-prompt-S75OMQ7L.js.map} +0 -0
  298. /package/dist/{sync-definition-C6ROLKJ4.js.map → shared-3IBNDEFL.js.map} +0 -0
  299. /package/dist/{sources-RMNFV4CA.js.map → sources-VA23PDND.js.map} +0 -0
  300. /package/dist/{stale-ITFCPOER.js.map → stale-MHTU2NQJ.js.map} +0 -0
  301. /package/dist/{stats-RCLQE4HJ.js.map → stats-ZAGJH4AD.js.map} +0 -0
  302. /package/dist/{stock-ECRBD7RP.js.map → stock-6SHHLSKG.js.map} +0 -0
  303. /package/dist/{studio-MARZ22J2.js.map → studio-ZLCGXFAN.js.map} +0 -0
  304. /package/dist/{viewer-check-7ZG7KHEN.js.map → sync-definition-2EBSQA6A.js.map} +0 -0
  305. /package/dist/{tag-manager-G3LBQZUL.js.map → tag-manager-3CJ66GKJ.js.map} +0 -0
  306. /package/dist/{testimonials-YMMA5YWL.js.map → testimonials-GR6TIS5S.js.map} +0 -0
  307. /package/dist/{translate-OXVIMYHE.js.map → translate-GEFUP6KQ.js.map} +0 -0
  308. /package/dist/{validate-ZS2M5Q3V.js.map → validate-NOWIOAHE.js.map} +0 -0
  309. /package/dist/{videos-I6YXFBFT.js.map → videos-XMTDEHEJ.js.map} +0 -0
  310. /package/dist/{winning-ads-ABN5OULS.js.map → winning-ads-QOAYIR5U.js.map} +0 -0
  311. /package/dist/{x-WK2VQDPF.js.map → x-VCSMV7T5.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/ads/meta/write-commands.ts","../src/commands/ads/meta/creative-flags.ts"],"sourcesContent":["import { buildCustomConversionRule } from \"@baker/api/ads-meta\";\nimport { defineCommand } from \"citty\";\nimport { repeatedValues } from \"../../../lib/repeatedFlags.ts\";\nimport {\n carouselFlags,\n conversationAndAppCta,\n creativeEnhancementsFromFlags,\n welcomeMessageFromFlags,\n} from \"./creative-flags.ts\";\nimport {\n adSetDeliveryArgs,\n adSetDeliveryFromFlags,\n boostEditArgs,\n boostEditsFromFlags,\n budgetBoostArg,\n budgetBoostsFromFlags,\n clearArg,\n clearFromFlags,\n} from \"./delivery-flags.ts\";\nimport {\n bareAccountId,\n failWriteValidation,\n listFlag,\n loadJsonFileArg,\n mergePayload,\n numberFlag,\n parseDateFlag,\n parseMoneyFlag,\n refuseDeleteByUpdate,\n repeatedListFlag,\n requireTarget,\n stageOp,\n stageStatusChange,\n upper,\n} from \"./write-shared.ts\";\n\n/**\n * Staged Meta write subcommands. None of these touch the Meta Graph API — they\n * stage ops on this chat's draft; ops appear in the dashboard as pending Meta\n * changes and apply sequentially when the chat is published. Review with\n * `baker ads meta draft`, undo with `draft remove <ref>`.\n *\n * Full object graph: campaign → ad set → ad creative → ad, plus custom\n * audiences and media uploads. Chain creates with meta_temp_* refs.\n */\n\nconst STAGED_NOTE = \"Staged until publish — review with `baker ads meta draft`.\";\n\nconst accountArgs = {\n \"account-id\": { type: \"string\", description: \"Numeric account ID or act_N\" },\n} as const;\n\n// --- Campaigns ---\n\nfunction campaignPayloadFromFlags(args: Record<string, unknown>): Record<string, unknown> {\n return {\n name: args.name,\n objective: upper(args.objective),\n status: upper(args.status),\n special_ad_categories: listFlag(args[\"special-ad-categories\"])?.map((c) => c.toUpperCase()),\n special_ad_category_country: listFlag(args[\"special-ad-category-country\"])?.map((c) => c.toUpperCase()),\n buying_type: upper(args[\"buying-type\"]),\n bid_strategy: upper(args[\"bid-strategy\"]),\n dailyBudget: parseMoneyFlag(args[\"daily-budget\"], args.currency, \"--daily-budget\"),\n lifetimeBudget: parseMoneyFlag(args[\"lifetime-budget\"], args.currency, \"--lifetime-budget\"),\n spendCap: parseMoneyFlag(args[\"spend-cap\"], args.currency, \"--spend-cap\"),\n adSetBudgetSharing: args[\"adset-budget-sharing\"] === undefined ? undefined : Boolean(args[\"adset-budget-sharing\"]),\n start_time: parseDateFlag(args.start, \"--start\"),\n stop_time: parseDateFlag(args.stop, \"--stop\"),\n promoted_object: args[\"catalog-id\"] ? { product_catalog_id: String(args[\"catalog-id\"]) } : undefined,\n };\n}\n\nconst campaignBudgetArgs = {\n \"daily-budget\": { type: \"string\", description: \"Daily budget (Advantage campaign budget / CBO)\" },\n \"lifetime-budget\": { type: \"string\", description: \"Lifetime budget\" },\n \"spend-cap\": { type: \"string\", description: \"Campaign spend cap\" },\n currency: { type: \"string\", description: \"3-letter currency (defaults to the account currency)\" },\n \"bid-strategy\": {\n type: \"string\",\n description: \"LOWEST_COST_WITHOUT_CAP|LOWEST_COST_WITH_BID_CAP|COST_CAP|LOWEST_COST_WITH_MIN_ROAS\",\n },\n start: { type: \"string\", description: \"Start time (ISO date or epoch ms)\" },\n stop: { type: \"string\", description: \"Stop time\" },\n ...budgetBoostArg,\n} as const;\n\nexport const campaignsCreateCommand = defineCommand({\n meta: {\n name: \"create\",\n description: `Stage a new campaign. ${STAGED_NOTE}\nExample: baker ads meta campaigns create --name \"Q3 Prospecting\" --objective OUTCOME_LEADS --daily-budget 50\nAdvantage+ (Meta's own \"Advantage+ campaign\" state) is not a setting: it follows from a campaign budget here, Advantage+ audience (targeting_automation.advantage_audience 1) and automatic placements (no placement lists) on every ad set. Read it back with \\`baker ads meta campaigns --fields id,name,advantage_state_info\\`.\nBlack Friday boost: baker ads meta campaigns create --name \"BF\" --objective OUTCOME_SALES --daily-budget 50 --budget-boost 2027-11-27T00:00Z..2027-11-28T00:00Z=+100%`,\n },\n args: {\n ...accountArgs,\n name: { type: \"string\", description: \"Campaign name\" },\n objective: {\n type: \"string\",\n description:\n \"OUTCOME_TRAFFIC|OUTCOME_ENGAGEMENT|OUTCOME_LEADS|OUTCOME_SALES|OUTCOME_AWARENESS|OUTCOME_APP_PROMOTION\",\n },\n status: { type: \"string\", description: \"ACTIVE|PAUSED (default PAUSED)\" },\n \"special-ad-categories\": { type: \"string\", description: \"CSV: NONE|HOUSING|EMPLOYMENT|CREDIT|… (default NONE)\" },\n \"special-ad-category-country\": { type: \"string\", description: \"CSV of 2-letter country codes\" },\n \"buying-type\": { type: \"string\", description: \"AUCTION|RESERVED (default AUCTION)\" },\n \"adset-budget-sharing\": {\n type: \"boolean\",\n description:\n \"Let ad sets lend up to 20% of their budget to each other (off unless set; ignored with a campaign budget)\",\n },\n ...campaignBudgetArgs,\n \"catalog-id\": {\n type: \"string\",\n description:\n \"Advantage+ catalog ads: the product catalog the campaign sells from (OUTCOME_SALES) — from `baker ads meta catalogs`. Fixed at creation; each ad set then names one of its product sets with --product-set-id\",\n },\n file: { type: \"string\", description: \"JSON file with the full payload; flags override file keys\" },\n },\n run: async ({ args, rawArgs }) => {\n const accountId = bareAccountId(args as Record<string, unknown>);\n const payload = mergePayload(loadJsonFileArg(args.file), {\n ...campaignPayloadFromFlags(args as Record<string, unknown>),\n budgetSchedules: budgetBoostsFromFlags(args as Record<string, unknown>, rawArgs),\n });\n await stageOp({ kind: \"campaign.create\", accountId, payload });\n },\n});\n\nexport const campaignsUpdateCommand = defineCommand({\n meta: {\n name: \"update\",\n description: `Stage changes to a campaign. ${STAGED_NOTE}\nPass a meta_temp_* ref to amend a campaign staged in this chat. Example: baker ads meta campaigns update 6123 --daily-budget 80\nBudget boosts on a live campaign need its daily budget restated in the same command (Meta reads it from the request): baker ads meta campaigns update 6123 --daily-budget 50 --budget-boost 2027-11-27T00:00Z..2027-11-28T00:00Z=+25\nA boost is ADDED to the ones the campaign has (Meta keeps them, even overlapping); take them all away with --clear boosts, or one at a time with --remove-boost / --move-boost (ids from \\`baker ads meta high-demand-periods --campaign-id 6123\\`): baker ads meta campaigns update 6123 --move-boost 1633135568548763=2027-11-27T06:00Z..2027-11-27T12:00Z`,\n },\n args: {\n id: { type: \"positional\", description: \"Campaign id or meta_temp_* ref\", required: true },\n ...accountArgs,\n name: { type: \"string\", description: \"New name\" },\n status: { type: \"string\", description: \"ACTIVE|PAUSED|ARCHIVED\" },\n ...campaignBudgetArgs,\n clear: { type: \"string\", description: \"boosts — take away every budget boost the campaign has now\" },\n ...boostEditArgs,\n file: { type: \"string\", description: \"JSON file with fields to change\" },\n },\n run: async ({ args, rawArgs }) => {\n const accountId = bareAccountId(args as Record<string, unknown>);\n const payload = mergePayload(loadJsonFileArg(args.file), {\n name: args.name,\n status: upper(args.status),\n budgetSchedules: budgetBoostsFromFlags(args as Record<string, unknown>, rawArgs),\n clear: clearOrFail(rawArgs, \"campaign\"),\n ...boostEditsFromFlags(args as Record<string, unknown>, rawArgs),\n bid_strategy: upper(args[\"bid-strategy\"]),\n dailyBudget: parseMoneyFlag(args[\"daily-budget\"], args.currency, \"--daily-budget\"),\n lifetimeBudget: parseMoneyFlag(args[\"lifetime-budget\"], args.currency, \"--lifetime-budget\"),\n spendCap: parseMoneyFlag(args[\"spend-cap\"], args.currency, \"--spend-cap\"),\n start_time: parseDateFlag(args.start, \"--start\"),\n stop_time: parseDateFlag(args.stop, \"--stop\"),\n });\n refuseDeleteByUpdate(payload, \"campaigns\");\n await stageOp({\n kind: \"campaign.update\",\n accountId,\n target: requireTarget(args as Record<string, unknown>, \"campaign\"),\n payload,\n });\n },\n});\n\n// --- Ad sets ---\n\nfunction clearOrFail(rawArgs: readonly string[] | undefined, entity: \"adSet\" | \"campaign\"): string[] | undefined {\n try {\n return clearFromFlags(rawArgs, entity);\n } catch (err) {\n failWriteValidation(err instanceof Error ? err.message : String(err));\n }\n}\n\nfunction adSetPayloadFromFlags(\n args: Record<string, unknown>,\n rawArgs: readonly string[] | undefined,\n file: Record<string, unknown>,\n): Record<string, unknown> {\n const promotedObject = args[\"promoted-object-file\"]\n ? loadJsonFileArg(args[\"promoted-object-file\"])\n : buildPromotedObject(args);\n return {\n ...adSetDeliveryFromFlags(args, rawArgs),\n budgetSchedules: budgetBoostsFromFlags(args, rawArgs),\n name: args.name,\n campaign_id: args.campaign,\n status: upper(args.status),\n optimization_goal: upper(args[\"optimization-goal\"]),\n billing_event: upper(args[\"billing-event\"]),\n destination_type: upper(args[\"destination-type\"]),\n dailyBudget: parseMoneyFlag(args[\"daily-budget\"], args.currency, \"--daily-budget\"),\n lifetimeBudget: parseMoneyFlag(args[\"lifetime-budget\"], args.currency, \"--lifetime-budget\"),\n bidAmount: parseMoneyFlag(args[\"bid-amount\"], args.currency, \"--bid-amount\"),\n bid_strategy: upper(args[\"bid-strategy\"]),\n start_time: parseDateFlag(args.start, \"--start\"),\n end_time: parseDateFlag(args.end, \"--end\"),\n targeting: targetingFromFlags(args, rawArgs, targetingOf(file)),\n rf_prediction_id: args.reservation,\n promoted_object: promotedObject && Object.keys(promotedObject).length > 0 ? promotedObject : undefined,\n };\n}\n\nfunction targetingOf(file: Record<string, unknown>): Record<string, unknown> | undefined {\n const targeting = file.targeting;\n return targeting && typeof targeting === \"object\" && !Array.isArray(targeting)\n ? (targeting as Record<string, unknown>)\n : undefined;\n}\n\n/**\n * The targeting file — or else the `--file` payload's own targeting — with the\n * brand-safety flags laid over it (`brandSafety.ts`), so a safety flag joins the\n * audience rather than replacing it with safety keys alone.\n */\nexport function targetingFromFlags(\n args: Record<string, unknown>,\n rawArgs: readonly string[] | undefined,\n fileTargeting?: Record<string, unknown>,\n): Record<string, unknown> | undefined {\n const file = args[\"targeting-file\"] ? loadJsonFileArg(args[\"targeting-file\"]) : undefined;\n const base = file ?? fileTargeting;\n const lists = repeatedValues(rawArgs, \"block-list\", args[\"block-list\"]);\n const filters = repeatedValues(rawArgs, \"content-filter\", args[\"content-filter\"]).map((value) => value.toUpperCase());\n const categories = repeatedValues(rawArgs, \"exclude-publisher-category\", args[\"exclude-publisher-category\"]).map(\n (value) => value.toLowerCase(),\n );\n const safety = {\n ...(lists.length > 0 ? { excluded_publisher_list_ids: lists } : {}),\n ...(filters.length > 0 ? { brand_safety_content_filter_levels: filters } : {}),\n ...(categories.length > 0 ? { excluded_publisher_categories: categories } : {}),\n };\n if (Object.keys(safety).length === 0) return file;\n return { ...(base ?? {}), ...safety };\n}\n\nfunction buildPromotedObject(args: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n if (args[\"page-id\"]) out.page_id = String(args[\"page-id\"]);\n if (args[\"pixel-id\"]) out.pixel_id = String(args[\"pixel-id\"]);\n if (args[\"custom-event-type\"]) out.custom_event_type = upper(args[\"custom-event-type\"]);\n if (args[\"custom-conversion-id\"]) out.custom_conversion_id = String(args[\"custom-conversion-id\"]);\n if (args[\"product-set-id\"]) out.product_set_id = String(args[\"product-set-id\"]);\n if (args[\"app-id\"]) out.application_id = String(args[\"app-id\"]);\n if (args[\"app-store-url\"]) out.object_store_url = String(args[\"app-store-url\"]);\n if (args[\"whatsapp-number\"]) out.whatsapp_phone_number = String(args[\"whatsapp-number\"]);\n return out;\n}\n\n// --- Custom conversions ---\n\n/**\n * The rule, from the flags that cover the conversion people actually create.\n *\n * `--url-contains` is the whole common case (\"count a Lead when somebody\n * reaches /gracias\") and produces the exact shape Events Manager writes.\n * `--rule-file` is the escape hatch for anything Meta's filter language can\n * express and these flags cannot. Requiring one and refusing both keeps a\n * half-specified conversion — which Meta accepts, and which then counts\n * everything or nothing — off the draft.\n */\nexport function customConversionRuleFromFlags(args: Record<string, unknown>): Record<string, unknown> {\n const urlContains = args[\"url-contains\"];\n const ruleFile = args[\"rule-file\"];\n if (urlContains && ruleFile) {\n failWriteValidation(\n \"pass either --url-contains or --rule-file, not both — they are two ways to say the same thing\",\n );\n }\n if (ruleFile) {\n return loadJsonFileArg(ruleFile);\n }\n if (!urlContains) {\n failWriteValidation(\n \"a custom conversion needs a rule — pass --url-contains '/thank-you' (the common case), or --rule-file with Meta's filter JSON\",\n );\n }\n return buildCustomConversionRule({\n event: args.event ? String(args.event) : undefined,\n urlContains: String(urlContains),\n });\n}\n\nexport const customConversionsCreateCommand = defineCommand({\n meta: {\n name: \"create\",\n description: `Stage a new Custom Conversion — a pixel event narrowed by a rule, which an ad set can then optimize toward. ${STAGED_NOTE}\nMeta caps an account at 100 and its delete only archives one, so a duplicate is permanent: check \\`baker ads meta custom-conversions\\` first.\nChain an ad set to it in the same chat with --custom-conversion-id meta_temp_*.\nExample: baker ads meta custom-conversions create --name \"Lead formulario\" --pixel-id 645971030024859 --custom-event-type LEAD --url-contains \"/gracias\"`,\n },\n args: {\n ...accountArgs,\n name: { type: \"string\", description: \"What the marketer will see in Events Manager and in reports\" },\n \"pixel-id\": { type: \"string\", description: \"The pixel it counts from — from `baker ads meta pixels`\" },\n \"custom-event-type\": {\n type: \"string\",\n description: \"Event category Meta files it under: LEAD|PURCHASE|COMPLETE_REGISTRATION|CONTACT|…\",\n },\n \"url-contains\": {\n type: \"string\",\n description: \"Count the event when the URL contains this, e.g. '/gracias'. The common case.\",\n },\n event: { type: \"string\", description: \"Pixel event the URL narrows (default PageView)\" },\n \"rule-file\": { type: \"string\", description: \"JSON file with Meta's raw filter, instead of --url-contains\" },\n description: { type: \"string\", description: \"Free-text note shown in Events Manager\" },\n value: { type: \"string\", description: \"Default value of one conversion, when the site sends no value\" },\n },\n run: async ({ args }) => {\n const accountId = bareAccountId(args as Record<string, unknown>);\n await stageOp({\n kind: \"customConversion.create\",\n accountId,\n payload: {\n name: args.name,\n description: args.description,\n pixel_id: args[\"pixel-id\"] ? String(args[\"pixel-id\"]) : undefined,\n custom_event_type: upper(args[\"custom-event-type\"]),\n rule: customConversionRuleFromFlags(args as Record<string, unknown>),\n default_conversion_value: numberFlag(args.value, \"--value\"),\n },\n });\n },\n});\n\nconst adSetWriteArgs = {\n ...accountArgs,\n name: { type: \"string\", description: \"Ad set name\" },\n status: { type: \"string\", description: \"ACTIVE|PAUSED|ARCHIVED\" },\n \"optimization-goal\": { type: \"string\", description: \"LINK_CLICKS|OFFSITE_CONVERSIONS|REACH|LEAD_GENERATION|…\" },\n \"billing-event\": { type: \"string\", description: \"IMPRESSIONS|LINK_CLICKS|THRUPLAY|…\" },\n \"destination-type\": { type: \"string\", description: \"WEBSITE|APP|MESSENGER|ON_AD|WHATSAPP|…\" },\n \"daily-budget\": { type: \"string\", description: \"Daily budget (ABO; omit if the campaign uses CBO)\" },\n \"lifetime-budget\": { type: \"string\", description: \"Lifetime budget (needs --end)\" },\n \"bid-amount\": { type: \"string\", description: \"Bid amount (required for COST_CAP / bid-cap strategies)\" },\n \"bid-strategy\": {\n type: \"string\",\n description:\n \"LOWEST_COST_WITHOUT_CAP (auto-bid) | LOWEST_COST_WITH_BID_CAP | COST_CAP — needs --bid-amount | LOWEST_COST_WITH_MIN_ROAS — needs --min-roas. Omit and Baker sets auto-bid (or min-ROAS when --min-roas is given); never leave it to Meta, whose default is a bid cap that then fails without an amount.\",\n },\n ...adSetDeliveryArgs,\n currency: { type: \"string\", description: \"3-letter currency (defaults to the account currency)\" },\n start: { type: \"string\", description: \"Start time\" },\n end: { type: \"string\", description: \"End time\" },\n \"targeting-file\": {\n type: \"string\",\n description:\n \"JSON file with the full Meta targeting spec. Ids, never names: look them up with `baker ads meta targeting search|geo|locales` and size it with `targeting estimate`\",\n },\n \"block-list\": {\n type: \"string\",\n description:\n \"Repeatable. Keep the ad set off a publisher block list — an id from `baker ads meta block-lists` or a meta_temp_* ref. On update without --targeting-file, the rest of the live targeting is kept\",\n },\n \"content-filter\": {\n type: \"string\",\n description:\n \"Repeatable, one per family: FEED_|FACEBOOK_|AN_ + RELAXED|STANDARD|STRICT — how strict Meta's content filter next to the ad is (feeds, in-stream/Reels, Audience Network)\",\n },\n \"exclude-publisher-category\": {\n type: \"string\",\n description:\n \"Repeatable: dating|gambling (and, for Audience Network / in-stream, debated_social_issues|mature_audiences|tragedy_and_conflict)\",\n },\n reservation: {\n type: \"string\",\n description:\n \"Create only: a reach-and-frequency reservation this ad set is bought on (id or meta_temp_* from `reach-frequency reserve`); its campaign is --buying-type RESERVED and it takes no budget\",\n },\n \"promoted-object-file\": { type: \"string\", description: \"JSON file with the promoted_object\" },\n \"page-id\": {\n type: \"string\",\n description: \"promoted_object.page_id shortcut (required for LEAD_GENERATION / QUALITY_LEAD / PAGE_LIKES goals)\",\n },\n \"pixel-id\": { type: \"string\", description: \"promoted_object.pixel_id shortcut\" },\n \"custom-event-type\": { type: \"string\", description: \"promoted_object.custom_event_type (PURCHASE|LEAD|…)\" },\n \"custom-conversion-id\": {\n type: \"string\",\n description:\n \"Optimize toward a Custom Conversion — the id from `baker ads meta custom-conversions`. Use it instead of --pixel-id/--custom-event-type, not alongside: Baker reads the conversion off Meta and fills its pixel, event category and rule.\",\n },\n \"product-set-id\": {\n type: \"string\",\n description:\n \"Advantage+ catalog ads: the product set this ad set shows (promoted_object.product_set_id) — from `baker ads meta catalogs --catalog-id <id>`. With OFFSITE_CONVERSIONS pass --custom-event-type (PURCHASE, ADD_TO_CART…); no pixel needed\",\n },\n \"app-id\": {\n type: \"string\",\n description:\n \"App ads: the app to promote (promoted_object.application_id) — from `baker ads meta apps`; needs --app-store-url\",\n },\n \"app-store-url\": {\n type: \"string\",\n description: \"App ads: the app's App Store / Google Play page (promoted_object.object_store_url)\",\n },\n \"whatsapp-number\": {\n type: \"string\",\n description:\n \"Click-to-WhatsApp: the WhatsApp Business number connected to the Page (promoted_object.whatsapp_phone_number)\",\n },\n file: { type: \"string\", description: \"JSON file with the full payload; flags override\" },\n} as const;\n\nexport const adSetsCreateCommand = defineCommand({\n meta: {\n name: \"create\",\n description: `Stage a new ad set. ${STAGED_NOTE}\nChain to a campaign with --campaign (real id or meta_temp_* ref).\nLead-form goals (LEAD_GENERATION, QUALITY_LEAD) and PAGE_LIKES need --page-id (the Facebook Page the leads/likes belong to).\nConversion goals take EITHER --pixel-id + --custom-event-type (a standard event) OR --custom-conversion-id (the marketer's own conversion, from 'baker ads meta custom-conversions').\nExample: 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\nDelivery controls: --min-roas (ROAS goal bidding), --frequency-cap 2/7 (REACH/THRUPLAY), --schedule \"Mon-Fri 09-18\" (dayparting, lifetime budget only), --pacing no_pacing (bid cap only), --daily-spend-cap/--daily-min-spend (an ad set's share of a campaign budget), --budget-boost (high-demand periods), --attribution 7d_click,1d_view, --dynamic-creative (create only).\nExample: baker ads meta adsets create --campaign 6123 --name \"Reach ES\" --optimization-goal REACH --billing-event IMPRESSIONS --lifetime-budget 300 --end 2027-02-01 --frequency-cap 2/7 --schedule \"Mon-Fri 09-18\" --targeting-file t.json`,\n },\n args: {\n campaign: { type: \"string\", description: \"Parent campaign id or meta_temp_* ref\" },\n ...adSetWriteArgs,\n \"budget-boost\": {\n type: \"string\",\n description:\n \"Raise this ad set's daily budget for a high-demand period, repeatable (on a live ad set, `adsets update --budget-boost` adds one beside those it has): START..END=+AMOUNT or START..END=+PERCENT% (max 800%), at least 3 hours, on quarter hours, all amounts or all percentages. Needs --daily-budget. Example: --budget-boost 2027-11-27T00:00Z..2027-11-28T00:00Z=+50%\",\n },\n \"dynamic-creative\": {\n type: \"boolean\",\n description:\n \"Make this a Dynamic Creative ad set: its ONE ad runs a creativeType dynamic creative (Meta mixes the images, videos and texts). Create-only — Meta fixes it for the ad set's life.\",\n },\n \"saved-audience\": {\n type: \"string\",\n description:\n \"Start from a saved audience's targeting (id from `baker ads meta audiences saved`) — copied into the ad set; instead of --targeting-file, and --block-list / --content-filter / --exclude-publisher-category join it\",\n },\n },\n run: async ({ args, rawArgs }) => {\n const accountId = bareAccountId(args as Record<string, unknown>);\n const file = loadJsonFileArg(args.file);\n const payload = mergePayload(file, adSetPayloadFromFlags(args as Record<string, unknown>, rawArgs, file));\n if (args[\"saved-audience\"]) {\n const { savedAudienceTargeting, targetingFromSavedAudience } = await import(\"./audience-writes.ts\");\n const saved = await savedAudienceTargeting(accountId, String(args[\"saved-audience\"]));\n const merged = targetingFromSavedAudience(saved, payload.targeting as Record<string, unknown> | undefined);\n if (\"refusal\" in merged) failWriteValidation(merged.refusal);\n payload.targeting = merged.targeting;\n }\n await stageOp({ kind: \"adSet.create\", accountId, payload });\n },\n});\n\nexport const adSetsUpdateCommand = defineCommand({\n meta: {\n name: \"update\",\n description: `Stage changes to an ad set. ${STAGED_NOTE}\nSwitching --optimization-goal to a lead-form goal (LEAD_GENERATION, QUALITY_LEAD) or PAGE_LIKES needs --page-id in the same change.\nTake a control away with --clear: baker ads meta adsets update 6123 --clear daily-spend-cap,schedule\nBudget boosts on a live ad set with its own daily budget: add with --budget-boost, take one away with --remove-boost, re-time one with --move-boost (ids from \\`baker ads meta high-demand-periods --campaign-id <ad set id>\\`).\nExample: baker ads meta adsets update 6123 --daily-budget 80`,\n },\n args: {\n id: { type: \"positional\", description: \"Ad set id or meta_temp_* ref\", required: true },\n ...adSetWriteArgs,\n \"budget-boost\": {\n type: \"string\",\n description:\n \"Add a budget boost to this ad set (its own daily budget is raised for a high-demand period), repeatable: START..END=+AMOUNT or START..END=+PERCENT% (max 800%), at least 3 hours, on quarter hours. Sent to Meta's boost list for the ad set, so the budget need not be restated. Example: --budget-boost 2027-11-27T00:00Z..2027-11-28T00:00Z=+50%\",\n },\n ...boostEditArgs,\n ...clearArg,\n },\n run: async ({ args, rawArgs }) => {\n const accountId = bareAccountId(args as Record<string, unknown>);\n const file = loadJsonFileArg(args.file);\n const {\n campaign_id: _drop,\n billing_event: _be,\n ...payload\n } = adSetPayloadFromFlags(args as Record<string, unknown>, rawArgs, file);\n const merged = mergePayload(file, {\n ...payload,\n ...boostEditsFromFlags(args as Record<string, unknown>, rawArgs),\n clear: clearOrFail(rawArgs, \"adSet\"),\n });\n refuseDeleteByUpdate(merged, \"adsets\");\n await stageOp({\n kind: \"adSet.update\",\n accountId,\n target: requireTarget(args as Record<string, unknown>, \"ad set\"),\n payload: merged,\n });\n },\n});\n\n// --- Ad creatives ---\n\nfunction creativePayloadFromFlags(args: Record<string, unknown>, rawArgs: readonly string[]): Record<string, unknown> {\n const enhancements = creativeEnhancementsFromFlags(args, rawArgs);\n return {\n // Leave undefined when --type is omitted so a --file's creativeType survives\n // mergePayload (any defined flag overrides the file). Defaulted after merge.\n creativeType: args.type ? String(args.type) : undefined,\n name: args.name,\n page_id: args.page,\n instagram_user_id: args[\"instagram-user\"],\n message: args.message,\n link: args.link,\n headline: args.headline,\n description: args.description,\n caption: args.caption,\n call_to_action: creativeCta(args),\n welcome_message: welcomeMessageFromFlags(args, rawArgs),\n applink_treatment: args[\"applink-treatment\"],\n product_set_id: args[\"product-set-id\"],\n canvas_id: args[\"canvas-id\"],\n format: args.format,\n imageHash: args[\"image-hash\"],\n imageRef: args[\"image-ref\"],\n videoId: args[\"video-id\"],\n videoRef: args[\"video-ref\"],\n thumbnailHash: args[\"thumbnail-hash\"],\n thumbnailRef: args[\"thumbnail-ref\"],\n url_tags: args[\"url-tags\"],\n shop_destination: args[\"shop-destination\"],\n multi_advertiser: args[\"multi-advertiser\"],\n partner: partnerFromFlags(args),\n object_story_id: args[\"post-id\"],\n source_instagram_media_id: args[\"instagram-media-id\"],\n instagram_ad_code: args[\"ad-code\"],\n collection_thumbnails: collectionThumbnailsFromFlags(rawArgs, args[\"collection-thumbnail\"]),\n enhancements,\n ...carouselFlags(args),\n };\n}\n\n/** `--collection-thumbnail <element id>[:<product index>]`, repeatable — the four pictures under a collection's hero. */\nexport function collectionThumbnailsFromFlags(\n rawArgs: readonly string[] | undefined,\n parsed: unknown,\n): Array<{ element_id: string; element_child_index?: number }> | undefined {\n const values = repeatedValues(rawArgs, \"collection-thumbnail\", parsed);\n if (values.length === 0) return undefined;\n return values.map((value) => {\n const [elementId = \"\", index] = value.split(\":\");\n return index === undefined\n ? { element_id: elementId }\n : { element_id: elementId, element_child_index: Number(index) };\n });\n}\n\n/** A partnership ad's second identity, from `--partner-page` / `--partner-instagram` / `--partner-format`. */\nexport function partnerFromFlags(args: Record<string, unknown>): Record<string, unknown> | undefined {\n const partner = {\n facebook_page_id: args[\"partner-page\"],\n instagram_user_id: args[\"partner-instagram\"],\n ad_format: args[\"partner-format\"],\n };\n return Object.values(partner).some((value) => value !== undefined) ? partner : undefined;\n}\n\n/**\n * Only the call-to-action fields the caller actually named. `--lead-form` is the\n * only way to name an instant form: the ad set says leads are collected on the\n * ad but never WHICH form, so a creative without this makes Meta reject every ad\n * in that ad set.\n *\n * Partial on purpose. On `update` this becomes a patch over the creative already\n * staged, and a complete object here would silently undo the other half —\n * `--cta LEARN_MORE` would drop a form the creative already names (re-creating\n * the very publish failure this exists to stop), and `--lead-form <id>` would\n * rewrite an already-chosen button to SIGN_UP.\n */\nexport function ctaPatchFromFlags(args: Record<string, unknown>): Record<string, string> | undefined {\n const patch = {\n ...(args.cta ? { type: String(upper(args.cta)) } : {}),\n ...(args[\"lead-form\"] === undefined ? {} : { lead_gen_form_id: String(args[\"lead-form\"]) }),\n ...conversationAndAppCta(args),\n };\n return Object.keys(patch).length > 0 ? patch : undefined;\n}\n\n/**\n * The call-to-action for a NEW creative, where there is nothing to patch over.\n * Defaults the type to SIGN_UP when a form is named and no --cta is: an\n * instant-form ad has to have a button, and that is the one Meta suggests.\n */\nexport function creativeCta(args: Record<string, unknown>): Record<string, string> | undefined {\n const patch = ctaPatchFromFlags(args);\n if (!patch) return undefined;\n // An instant form's button defaults to SIGN_UP; a conversation's, to the one that opens it.\n const opener = Object.entries({\n MESSENGER: \"MESSAGE_PAGE\",\n WHATSAPP: \"WHATSAPP_MESSAGE\",\n INSTAGRAM_DIRECT: \"INSTAGRAM_MESSAGE\",\n }).find(([app]) => app === patch.app_destination)?.[1];\n return { type: opener ?? (patch.app_link || patch.application ? \"INSTALL_MOBILE_APP\" : \"SIGN_UP\"), ...patch };\n}\n\n/**\n * The content patch for `creatives update`, merged rather than assigned at both\n * levels. `mergePayload` and the backend's `mergeAmendPayload` are both shallow\n * top-level merges, so building a fresh `content` here would throw away every\n * other field a `--file` supplied — silently, which is the failure shape this\n * whole change is about.\n */\nexport function creativeContentPatch(file: Record<string, unknown>, args: Record<string, unknown>): unknown {\n const cta = ctaPatchFromFlags(args);\n if (!cta) {\n return undefined;\n }\n const fileContent = (file.content ?? {}) as Record<string, unknown>;\n const fileCta = (fileContent.call_to_action ?? {}) as Record<string, unknown>;\n return { ...fileContent, call_to_action: { ...fileCta, ...cta } };\n}\n\nexport const adCreativesCreateCommand = defineCommand({\n meta: {\n name: \"create\",\n description: `Stage a new ad creative. ${STAGED_NOTE}\nSingle-image/video via flags; carousel/dynamic via --file (creativeType carousel|dynamic).\nClick-to-message: --cta MESSAGE_PAGE|WHATSAPP_MESSAGE|INSTAGRAM_MESSAGE (opens Messenger|WhatsApp|Instagram Direct) + --greeting \"Hi!\" --ice-breaker \"Prices? => From 99 EUR.\" (ad set: --destination-type MESSENGER --optimization-goal CONVERSATIONS --page-id).\nApp ads: --link <App Store / Google Play URL> --cta INSTALL_MOBILE_APP|USE_MOBILE_APP --deep-link myapp://x --app-id <id> --applink-treatment deeplink_with_appstore_fallback.\nCatalog (Advantage+ catalog ads): --type catalog --product-set-id <id> --message \"{{product.name}}\" --headline \"{{product.price}}\" --link https://shop.example --format carousel|single|slideshow.\nInstant Experience / collection: --type instant_experience --canvas-id <id or meta_temp_*> --message … --image-hash … [--format collection] (build one with \\`baker ads meta instant-experiences create\\`).\nReference media by --image-hash (already on Meta) or --image-ref meta_temp_* (a staged media upload).\nExample: baker ads meta creatives create --page 555 --message \"Save now\" --link https://x.com --headline \"Best cover\" --image-hash abc123… --cta SHOP_NOW`,\n },\n args: {\n ...accountArgs,\n type: {\n type: \"string\",\n description: \"single|carousel|dynamic|existing_post|catalog|instant_experience (default single)\",\n },\n \"product-set-id\": {\n type: \"string\",\n description:\n \"--type catalog: the product set the template shows — from `baker ads meta catalogs --catalog-id <id>`\",\n },\n \"canvas-id\": {\n type: \"string\",\n description:\n \"--type instant_experience: the Instant Experience the ad opens — an id from `baker ads meta instant-experiences --page-id <id>` (published) or the meta_temp_* ref of one this chat creates\",\n },\n format: {\n type: \"string\",\n description:\n \"--type catalog: carousel (default) | single (one product per ad) | slideshow. --type instant_experience: standard (default) | collection (products or photos under the ad)\",\n },\n greeting: {\n type: \"string\",\n description: \"Click-to-message: the first message the person reads when the conversation opens (≤300 chars)\",\n },\n \"ice-breaker\": {\n type: \"string\",\n description:\n 'Click-to-message, repeatable (max 4): a question the person can tap and your answer — \"Question => Answer\"',\n },\n autofill: {\n type: \"string\",\n description: \"Click-to-message (instead of ice breakers): a message pre-filled for the person to send\",\n },\n \"app-destination\": {\n type: \"string\",\n description:\n \"Click-to-message: MESSENGER|WHATSAPP|INSTAGRAM_DIRECT — implied by --cta MESSAGE_PAGE|WHATSAPP_MESSAGE|INSTAGRAM_MESSAGE\",\n },\n \"deep-link\": {\n type: \"string\",\n description:\n \"App ads: where the button opens inside the installed app (e.g. myapp://product/12). --link must be the App Store / Google Play page\",\n },\n \"app-id\": {\n type: \"string\",\n description: \"App ads: the app the button installs or opens — from `baker ads meta apps`\",\n },\n \"applink-treatment\": {\n type: \"string\",\n description:\n \"App ads: how a deep link opens — deeplink_with_web_fallback|deeplink_with_appstore_fallback|web_only|automatic\",\n },\n name: { type: \"string\", description: \"Creative name\" },\n page: { type: \"string\", description: \"Facebook Page id (identity)\" },\n \"instagram-user\": {\n type: \"string\",\n description: \"Instagram account id for IG placements — from `baker ads meta instagram-accounts`\",\n },\n message: { type: \"string\", description: \"Primary text\" },\n link: { type: \"string\", description: \"Destination URL (https)\" },\n headline: { type: \"string\", description: \"Headline\" },\n description: { type: \"string\", description: \"Description\" },\n caption: { type: \"string\", description: \"Display URL / caption\" },\n cta: { type: \"string\", description: \"Call-to-action type (SHOP_NOW|LEARN_MORE|SIGN_UP|…)\" },\n \"lead-form\": {\n type: \"string\",\n description:\n \"Instant form id or meta_temp_* ref from `baker ads meta lead-forms create` — REQUIRED for an ad set that collects leads on the ad. With a form, --cta must be APPLY_NOW|DOWNLOAD|GET_QUOTE|LEARN_MORE|SIGN_UP|SUBSCRIBE\",\n },\n \"image-hash\": { type: \"string\", description: \"Meta ad-image hash (already uploaded)\" },\n \"image-ref\": { type: \"string\", description: \"meta_temp_* ref of a staged media upload\" },\n \"video-id\": { type: \"string\", description: \"Meta video id (already uploaded)\" },\n \"video-ref\": { type: \"string\", description: \"meta_temp_* ref of a staged video upload\" },\n \"thumbnail-hash\": {\n type: \"string\",\n description:\n \"Cover for a video ad: a picture hash already in the ad account (Meta's own frame is used when no cover is given)\",\n },\n \"thumbnail-ref\": {\n type: \"string\",\n description:\n \"Cover for a video ad: meta_temp_* ref of a staged `media upload --kind image` — how a cover picked from the library is used\",\n },\n \"url-tags\": { type: \"string\", description: \"URL tracking params (utm_source=fb&…)\" },\n \"shop-destination\": {\n type: \"string\",\n description:\n \"website_only keeps a shop advertiser's ad on the website (Meta's v26 default also sends it to the shop); website_and_shop asks for both\",\n },\n \"standard-enhancements\": {\n type: \"string\",\n description: \"Meta's suggestions to the ad's TEXT on|off — never changes the picture or video\",\n },\n \"multi-advertiser\": {\n type: \"string\",\n description:\n \"opt_out keeps the ad from being shown beside other advertisers' ads after someone engages (Meta opts every new ad IN by default); opt_in asks for it\",\n },\n \"partner-page\": {\n type: \"string\",\n description:\n \"Partnership ad: the partner's (creator's or other brand's) Facebook Page id, shown beside yours. Needs --instagram-user on the ad and the partner's approval before it runs\",\n },\n \"partner-instagram\": { type: \"string\", description: \"Partnership ad: the partner's Instagram account id\" },\n \"partner-format\": {\n type: \"string\",\n description: \"Partnership ad: both (default — both identities) | first_only | auto (Meta picks, Instagram only)\",\n },\n \"collection-thumbnail\": {\n type: \"string\",\n description:\n \"--format collection over a photo experience, repeat 4 times: an element id of the live experience (`instant-experiences --page-id`), or <product-set element id>:<product index>\",\n },\n \"post-id\": {\n type: \"string\",\n description:\n \"--type existing_post: the Facebook post to boost, <page_id>_<post_id> — from `baker ads meta page-posts --page-id <id>`\",\n },\n \"instagram-media-id\": {\n type: \"string\",\n description:\n \"--type existing_post: the Instagram post to boost (with --page and --instagram-user) — from `baker ads meta instagram-media`\",\n },\n \"ad-code\": {\n type: \"string\",\n description: \"--type existing_post: a creator's partnership ad code for their Instagram post (with --page)\",\n },\n \"card-order\": {\n type: \"string\",\n description:\n \"Carousel only: fixed (default — every card, in the order built) or optimized (Meta reorders by performance and may show only the top 5)\",\n },\n \"end-card\": {\n type: \"string\",\n description: \"Carousel only: on adds Meta's card linking to the Page after the last card (default off)\",\n },\n \"visual-enhancement\": {\n type: \"string\",\n description:\n \"Repeatable. Let Meta change the media with this feature (e.g. image_uncrop, image_animation, music_generation) — ONLY when the user asked for it by name; every such feature is off otherwise\",\n },\n file: { type: \"string\", description: \"JSON file with the full creative payload (carousel cards / dynamic assets)\" },\n },\n run: async ({ args, rawArgs }) => {\n const accountId = bareAccountId(args as Record<string, unknown>);\n const payload = mergePayload(\n loadJsonFileArg(args.file),\n creativePayloadFromFlags(args as Record<string, unknown>, rawArgs),\n );\n // Flag-only creatives default to a single-image ad; a --file that declares\n // its own creativeType (carousel/dynamic/existing_post) is left untouched.\n if (payload.creativeType === undefined) {\n payload.creativeType = \"single\";\n }\n await stageOp({ kind: \"adCreative.create\", accountId, payload });\n },\n});\n\nexport const adCreativesUpdateCommand = defineCommand({\n meta: {\n name: \"update\",\n description: `Stage name/status changes to an ad creative. ${STAGED_NOTE}\nMeta creatives are immutable — to change content, stage a new creative and repoint the ad.\nAmending a staged (meta_temp_*) creative merges fields into the create. Example: baker ads meta creatives update 998 --name \"Renamed\"`,\n },\n args: {\n id: { type: \"positional\", description: \"Creative id or meta_temp_* ref\", required: true },\n ...accountArgs,\n name: { type: \"string\", description: \"New name\" },\n status: { type: \"string\", description: \"ACTIVE|PAUSED|ARCHIVED\" },\n cta: { type: \"string\", description: \"Call-to-action type (staged creatives only)\" },\n \"lead-form\": {\n type: \"string\",\n description: \"Instant form id the button opens (staged creatives only) — `baker ads meta lead-forms` lists them\",\n },\n file: {\n type: \"string\",\n description: \"JSON file with fields to change (content only merges into a staged creative)\",\n },\n },\n run: async ({ args }) => {\n const accountId = bareAccountId(args as Record<string, unknown>);\n const file = loadJsonFileArg(args.file);\n const payload = mergePayload(file, {\n name: args.name,\n status: upper(args.status),\n // A creative's content is immutable on Meta, so this only ever lands on a\n // creative still staged in this chat — which is exactly the fix path when\n // staging an ad refuses it for naming no instant form.\n content: creativeContentPatch(file, args as Record<string, unknown>),\n });\n if (payload.status === \"DELETED\") {\n failWriteValidation(\n \"update does not delete — use `baker ads meta creatives delete <id>` if the user asked to delete it\",\n );\n }\n await stageOp({\n kind: \"adCreative.update\",\n accountId,\n target: requireTarget(args as Record<string, unknown>, \"creative\"),\n payload,\n });\n },\n});\n\n// --- Ads ---\n\nexport const adsCreateCommand = defineCommand({\n meta: {\n name: \"create\",\n description: `Stage a new ad linking an ad set to a creative. ${STAGED_NOTE}\nExample: baker ads meta ads create --name \"Ad 1\" --adset meta_temp_as01 --creative meta_temp_cr01`,\n },\n args: {\n ...accountArgs,\n name: { type: \"string\", description: \"Ad name\" },\n adset: { type: \"string\", description: \"Ad set id or meta_temp_* ref\" },\n creative: { type: \"string\", description: \"Creative id or meta_temp_* ref\" },\n status: { type: \"string\", description: \"ACTIVE|PAUSED (default PAUSED)\" },\n \"tracking-file\": { type: \"string\", description: \"JSON file with tracking_specs\" },\n \"conversion-domain\": {\n type: \"string\",\n description:\n \"The website domain conversions are counted on (example.com — no www., no https://). Meta fills it from the link when left out; set it when the site and the pixel's domain differ\",\n },\n file: { type: \"string\", description: \"JSON file with the full payload\" },\n },\n run: async ({ args }) => {\n const accountId = bareAccountId(args as Record<string, unknown>);\n const tracking = args[\"tracking-file\"] ? loadJsonFileArg(args[\"tracking-file\"]).tracking_specs : undefined;\n const payload = mergePayload(loadJsonFileArg(args.file), {\n name: args.name,\n adset_id: args.adset,\n creative: args.creative ? { creative_id: String(args.creative) } : undefined,\n status: upper(args.status),\n tracking_specs: tracking,\n conversion_domain: args[\"conversion-domain\"],\n });\n await stageOp({ kind: \"ad.create\", accountId, payload });\n },\n});\n\nexport const adsUpdateCommand = defineCommand({\n meta: {\n name: \"update\",\n description: `Stage changes to an ad (name/status, or swap its creative). ${STAGED_NOTE}\nExample: baker ads meta ads update 6123 --creative meta_temp_cr02`,\n },\n args: {\n id: { type: \"positional\", description: \"Ad id or meta_temp_* ref\", required: true },\n ...accountArgs,\n name: { type: \"string\", description: \"New name\" },\n status: { type: \"string\", description: \"ACTIVE|PAUSED|ARCHIVED\" },\n creative: { type: \"string\", description: \"New creative id or meta_temp_* ref\" },\n file: { type: \"string\", description: \"JSON file with fields to change\" },\n },\n run: async ({ args }) => {\n const accountId = bareAccountId(args as Record<string, unknown>);\n const payload = mergePayload(loadJsonFileArg(args.file), {\n name: args.name,\n status: upper(args.status),\n creative: args.creative ? { creative_id: String(args.creative) } : undefined,\n });\n refuseDeleteByUpdate(payload, \"ads\");\n await stageOp({\n kind: \"ad.update\",\n accountId,\n target: requireTarget(args as Record<string, unknown>, \"ad\"),\n payload,\n });\n },\n});\n\nexport const adsRetagCommand = defineCommand({\n meta: {\n name: \"retag\",\n description: `Stage new URL tracking parameters on a LIVE ad — the fix for a wrong utm_medium, a missing ad id, or any tag already running. ${STAGED_NOTE}\nStart here when a report attributes paid traffic to the wrong channel: --set rewrites only the keys you name and leaves the rest of the string alone.\nBaker clones the ad's own creative behind the scenes, so every button, text variant and enhancement is carried across exactly as Meta holds them — nothing is retyped.\nExample: baker ads meta ads retag 120252158038400247 --set \"utm_medium=paid-social&utm_placement={{placement}}\"\nExample: baker ads meta ads retag 120252158038400247 --url-tags \"utm_source={{site_source_name}}&utm_medium=paid-social&ad_id={{ad.id}}\"`,\n },\n args: {\n id: { type: \"positional\", description: \"Ad id (a live ad — not a meta_temp_* ref)\", required: true },\n ...accountArgs,\n \"url-tags\": { type: \"string\", description: \"Replace the WHOLE tracking string\" },\n set: {\n type: \"string\",\n description:\n 'Rewrite only these keys, keeping the rest: \"utm_medium=paid-social&ad_id={{ad.id}}\" (repeatable: --set a=1 --set b=2)',\n },\n },\n run: async ({ args, rawArgs }) => {\n const { apiPost } = await import(\"../../../client.ts\");\n const { requireChatId } = await import(\"../../../env.ts\");\n const { writeJsonEnvelope } = await import(\"../output.ts\");\n const { handleMetaError } = await import(\"./shared.ts\");\n try {\n const accountId = bareAccountId(args as Record<string, unknown>);\n const urlTags = typeof args[\"url-tags\"] === \"string\" ? args[\"url-tags\"] : undefined;\n const setRaw = typeof args.set === \"string\" ? args.set : undefined;\n if ((urlTags === undefined) === (setRaw === undefined)) {\n failWriteValidation(\"pass either --url-tags (the whole string) or --set (the keys to change), not both\");\n }\n const response = await apiPost(\"/api/ads/meta/draft/retag\", {\n chatId: requireChatId(),\n accountId,\n adId: requireTarget(args as Record<string, unknown>, \"ad\"),\n urlTags,\n set: setRaw === undefined ? undefined : retagSetPairs(rawArgs, setRaw),\n });\n writeJsonEnvelope(response as Record<string, unknown>);\n } catch (err) {\n handleMetaError(err);\n }\n },\n});\n\n/**\n * Every `--set`, whether joined by `&` or given as the flag repeated. citty keeps\n * only a repeated flag's last value, and a retag that silently loses all but one\n * key still publishes — so the command line is read directly.\n */\nexport function retagSetPairs(rawArgs: readonly string[] | undefined, parsed: unknown): Record<string, string> {\n return parseSetPairs(repeatedValues(rawArgs, \"set\", parsed).join(\"&\"));\n}\n\nfunction parseSetPairs(raw: string): Record<string, string> {\n const pairs: Record<string, string> = {};\n for (const part of raw.replace(/^[?&]+/, \"\").split(\"&\")) {\n if (part.length === 0) continue;\n const eq = part.indexOf(\"=\");\n if (eq <= 0) {\n failWriteValidation(`--set expects key=value pairs joined by & — could not read \"${part}\"`);\n }\n pairs[part.slice(0, eq)] = part.slice(eq + 1);\n }\n if (Object.keys(pairs).length === 0) {\n failWriteValidation(\"--set needs at least one key=value pair\");\n }\n return pairs;\n}\n\n// --- Custom audiences ---\n\nexport const audiencesCreateCommand = defineCommand({\n meta: {\n name: \"create\",\n description: `Stage a new custom audience. ${STAGED_NOTE}\nCustomer list: --subtype CUSTOM --customer-file-source USER_PROVIDED_ONLY, then put people in it with \\`audiences members add <ref> --file list.csv\\` (hashed on this machine). --value-based for a list where each person carries a value (needs the account's value-based terms).\nLookalike: --subtype LOOKALIKE --lookalike-of <seed audience> --ratio 0.02 --country ES (or --countries ES,PT; --starting-ratio 0.01 for the 1%–2% band). The seed needs 100+ people in those countries. Or seed it from the people who converted in live campaigns: --lookalike-of-conversions <campaign or ad set id,…>.\nWEBSITE/ENGAGEMENT: the rule via --file. A rule carries its own window in retention_seconds, so --retention-days is refused next to one, and one audience covers one kind of event source (a Page and an Instagram profile are two audiences).\nExample: baker ads meta audiences create --name \"Site visitors 30d\" --subtype WEBSITE --file rule.json\nExample: baker ads meta audiences create --name \"Customers\" --subtype CUSTOM --customer-file-source USER_PROVIDED_ONLY`,\n },\n args: {\n ...accountArgs,\n name: { type: \"string\", description: \"Audience name\" },\n subtype: { type: \"string\", description: \"CUSTOM|WEBSITE|ENGAGEMENT|LOOKALIKE\" },\n description: { type: \"string\", description: \"Description\" },\n \"retention-days\": {\n type: \"string\",\n description: \"Retention window in days — customer-file audiences only; a rule carries its own retention_seconds\",\n },\n \"customer-file-source\": {\n type: \"string\",\n description:\n \"Customer list: where its people came from — USER_PROVIDED_ONLY (collected from customers directly) | PARTNER_PROVIDED_ONLY | BOTH_USER_AND_PARTNER_PROVIDED\",\n },\n \"value-based\": {\n type: \"boolean\",\n description: \"Customer list where each person carries a value (LOOKALIKE_VALUE column)\",\n },\n \"lookalike-of\": {\n type: \"string\",\n description: \"Lookalike: the seed audience id (a live audience — one this chat creates cannot be a seed yet)\",\n },\n \"lookalike-of-conversions\": {\n type: \"string\",\n description:\n \"Lookalike seeded from the people who converted in live campaigns or ad sets (ids, comma-separated or repeated) instead of an audience. Meta wants 100+ conversions in the lookalike's countries.\",\n },\n ratio: { type: \"string\", description: \"Lookalike size: 0.01–0.20 of the country, in 0.01 steps\" },\n \"starting-ratio\": {\n type: \"string\",\n description: \"Lookalike band start, below --ratio (0.01 with --ratio 0.03 = the 1%–3% band)\",\n },\n country: { type: \"string\", description: \"Lookalike: one country (ES)\" },\n countries: { type: \"string\", description: \"Lookalike: several countries (ES,PT — comma-separated or repeated)\" },\n \"allow-international-seeds\": {\n type: \"boolean\",\n description: \"Lookalike: let Meta use seed people from other countries when the seed is thin in these\",\n },\n file: { type: \"string\", description: \"JSON file with lookalike_spec / rule / full payload\" },\n },\n run: async ({ args, rawArgs }) => {\n const accountId = bareAccountId(args as Record<string, unknown>);\n const file = loadJsonFileArg(args.file);\n const payload = mergePayload(file, {\n name: args.name,\n subtype: upper(args.subtype),\n description: args.description,\n retention_days: numberFlag(args[\"retention-days\"], \"--retention-days\"),\n customer_file_source: upper(args[\"customer-file-source\"]),\n is_value_based: args[\"value-based\"] ? true : undefined,\n lookalike_spec: lookalikeSpecFromFlags(args as Record<string, unknown>, file.lookalike_spec, rawArgs),\n });\n await stageOp({ kind: \"customAudience.create\", accountId, payload });\n },\n});\n\n/** The lookalike flags folded over a spec from --file; undefined when neither names one. */\nexport function lookalikeSpecFromFlags(\n args: Record<string, unknown>,\n fromFile: unknown,\n rawArgs?: readonly string[],\n): Record<string, unknown> | undefined {\n const base = fromFile && typeof fromFile === \"object\" ? (fromFile as Record<string, unknown>) : {};\n const flags = {\n origin: typeof args[\"lookalike-of\"] === \"string\" ? [{ id: args[\"lookalike-of\"] }] : undefined,\n conversions_of: repeatedListFlag(rawArgs, \"lookalike-of-conversions\", args[\"lookalike-of-conversions\"]),\n ratio: numberFlag(args.ratio, \"--ratio\"),\n starting_ratio: numberFlag(args[\"starting-ratio\"], \"--starting-ratio\"),\n country: typeof args.country === \"string\" ? args.country.toUpperCase() : undefined,\n countries: repeatedListFlag(rawArgs, \"countries\", args.countries)?.map((code) => code.toUpperCase()),\n allow_international_seeds: args[\"allow-international-seeds\"] ? true : undefined,\n };\n const merged = mergePayload(base, flags);\n return Object.keys(merged).length > 0 ? merged : undefined;\n}\n\nexport const audiencesUpdateCommand = defineCommand({\n meta: {\n name: \"update\",\n description: `Stage changes to a custom audience: name, description, where a customer list came from, its opt-out link, or a website/engagement rule (--file {\"rule\": …}). A customer list's retention and a lookalike's seed and size are fixed — a different one is a new audience. Delete with \\`audiences delete\\`. ${STAGED_NOTE}`,\n },\n args: {\n id: { type: \"positional\", description: \"Audience id or meta_temp_* ref\", required: true },\n ...accountArgs,\n name: { type: \"string\", description: \"New name\" },\n description: { type: \"string\", description: \"New description\" },\n \"customer-file-source\": {\n type: \"string\",\n description: \"USER_PROVIDED_ONLY | PARTNER_PROVIDED_ONLY | BOTH_USER_AND_PARTNER_PROVIDED\",\n },\n \"opt-out-link\": { type: \"string\", description: \"https link where people can opt out of this audience\" },\n file: { type: \"string\", description: \"JSON file with fields to change (rule for a website/engagement audience)\" },\n },\n run: async ({ args }) => {\n const accountId = bareAccountId(args as Record<string, unknown>);\n const payload = mergePayload(loadJsonFileArg(args.file), {\n name: args.name,\n description: args.description,\n customer_file_source: upper(args[\"customer-file-source\"]),\n opt_out_link: args[\"opt-out-link\"],\n });\n if (payload.status === \"DELETED\") {\n failWriteValidation(\n \"update does not delete — use `baker ads meta audiences delete <id>` if the user asked to delete it\",\n );\n }\n await stageOp({\n kind: \"customAudience.update\",\n accountId,\n target: requireTarget(args as Record<string, unknown>, \"audience\"),\n payload,\n });\n },\n});\n\n// --- Media upload ---\n\nexport const mediaUploadCommand = defineCommand({\n meta: {\n name: \"upload\",\n description: `Stage a Baker library image/video upload to Meta. Publishes the hash/id a creative references by --image-ref/--video-ref. ${STAGED_NOTE}\nExample: baker ads meta media upload --kind image --image-id <bakerImageId>`,\n },\n args: {\n ...accountArgs,\n kind: { type: \"string\", description: \"image|video\" },\n \"image-id\": { type: \"string\", description: \"Baker library image id (for --kind image)\" },\n \"video-id\": { type: \"string\", description: \"Baker library video id (for --kind video)\" },\n name: { type: \"string\", description: \"Display name / filename hint\" },\n },\n run: async ({ args }) => {\n const accountId = bareAccountId(args as Record<string, unknown>);\n const kind = String(args.kind ?? \"\").toLowerCase();\n if (kind !== \"image\" && kind !== \"video\") {\n failWriteValidation(\"--kind must be image or video\");\n }\n await stageOp({\n kind: \"media.upload\",\n accountId,\n payload: { kind, bakerImageId: args[\"image-id\"], bakerVideoId: args[\"video-id\"], name: args.name },\n });\n },\n});\n\n// --- Status-change + duplicate factories ---\n\ntype StatusKind = \"campaign.update\" | \"adSet.update\" | \"ad.update\";\n\nconst STATUS_BY_COMMAND = { pause: \"PAUSED\", resume: \"ACTIVE\", archive: \"ARCHIVED\", delete: \"DELETED\" } as const;\n\nconst STATUS_COMMAND_NOTE: Partial<Record<keyof typeof STATUS_BY_COMMAND, string>> = {\n archive: \"Archived stays readable in Ads Manager and can be found with --effective-status ARCHIVED.\",\n delete:\n \"Deleting is permanent and cannot be undone — Meta removes it and everything under it. Prefer pause or archive unless the user asked to delete.\",\n};\n\nfunction statusCommand(name: keyof typeof STATUS_BY_COMMAND, kind: StatusKind, label: string) {\n const status = STATUS_BY_COMMAND[name];\n const note = STATUS_COMMAND_NOTE[name];\n return defineCommand({\n meta: { name, description: `Stage ${name} for a ${label}. ${note ? `${note} ` : \"\"}${STAGED_NOTE}` },\n args: { id: { type: \"positional\", description: `${label} id`, required: true }, ...accountArgs },\n run: async ({ args }) => {\n const accountId = bareAccountId(args as Record<string, unknown>);\n await stageStatusChange({\n kind,\n accountId,\n target: requireTarget(args as Record<string, unknown>, label),\n status,\n });\n },\n });\n}\n\nfunction duplicateCommand(entity: \"campaign\" | \"adSet\" | \"ad\", label: string) {\n return defineCommand({\n meta: {\n name: \"duplicate\",\n description: `Stage a paused copy of an existing ${label} (reconstructed from its live snapshot). ${STAGED_NOTE}\n--replace also stages a pause of the original, gated on the copy publishing.`,\n },\n args: {\n id: { type: \"positional\", description: `Source ${label} id`, required: true },\n ...accountArgs,\n name: { type: \"string\", description: \"Override the copy's name\" },\n replace: { type: \"boolean\", description: \"Pause the original once the copy publishes\" },\n },\n run: async ({ args }) => {\n const { apiPost } = await import(\"../../../client.ts\");\n const { requireChatId } = await import(\"../../../env.ts\");\n const { writeJsonEnvelope } = await import(\"../output.ts\");\n const { handleMetaError } = await import(\"./shared.ts\");\n try {\n const accountId = bareAccountId(args as Record<string, unknown>);\n const chatId = requireChatId();\n const response = await apiPost(\"/api/ads/meta/draft/duplicate\", {\n chatId,\n accountId,\n entity,\n sourceId: requireTarget(args as Record<string, unknown>, label),\n overrides: args.name ? { name: args.name } : undefined,\n replace: Boolean(args.replace),\n });\n writeJsonEnvelope(response as Record<string, unknown>);\n } catch (err) {\n handleMetaError(err);\n }\n },\n });\n}\n\nexport const campaignsPauseCommand = statusCommand(\"pause\", \"campaign.update\", \"campaign\");\nexport const campaignsResumeCommand = statusCommand(\"resume\", \"campaign.update\", \"campaign\");\nexport const campaignsArchiveCommand = statusCommand(\"archive\", \"campaign.update\", \"campaign\");\nexport const campaignsDeleteCommand = statusCommand(\"delete\", \"campaign.update\", \"campaign\");\nexport const campaignsDuplicateCommand = duplicateCommand(\"campaign\", \"campaign\");\n\nexport const adSetsPauseCommand = statusCommand(\"pause\", \"adSet.update\", \"ad set\");\nexport const adSetsResumeCommand = statusCommand(\"resume\", \"adSet.update\", \"ad set\");\nexport const adSetsArchiveCommand = statusCommand(\"archive\", \"adSet.update\", \"ad set\");\nexport const adSetsDeleteCommand = statusCommand(\"delete\", \"adSet.update\", \"ad set\");\nexport const adSetsDuplicateCommand = duplicateCommand(\"adSet\", \"ad set\");\n\nexport const adsPauseCommand = statusCommand(\"pause\", \"ad.update\", \"ad\");\nexport const adsResumeCommand = statusCommand(\"resume\", \"ad.update\", \"ad\");\nexport const adsArchiveCommand = statusCommand(\"archive\", \"ad.update\", \"ad\");\nexport const adsDeleteCommand = statusCommand(\"delete\", \"ad.update\", \"ad\");\nexport const adsDuplicateCommand = duplicateCommand(\"ad\", \"ad\");\n","import { VISUAL_ENHANCEMENT_FEATURES } from \"@baker/api/ads-meta/limits\";\nimport { repeatedValues } from \"../../../lib/repeatedFlags.ts\";\nimport { failWriteValidation } from \"./write-shared.ts\";\n\ntype Args = Record<string, unknown>;\n\nfunction parseEnroll(value: unknown): \"OPT_IN\" | \"OPT_OUT\" {\n const raw = String(value).toLowerCase();\n if (raw === \"on\" || raw === \"true\" || raw === \"opt_in\") return \"OPT_IN\";\n if (raw === \"off\" || raw === \"false\" || raw === \"opt_out\") return \"OPT_OUT\";\n failWriteValidation(\"--standard-enhancements must be on|off\");\n}\n\n/**\n * The creative's Advantage+ enhancements from its flags. `--standard-enhancements`\n * is Meta's suggestions to the text; every feature that changes the picture or\n * video stays off unless named with `--visual-enhancement <feature>`.\n */\nexport function creativeEnhancementsFromFlags(\n args: Args,\n rawArgs: readonly string[] | undefined,\n): { standardEnhancements?: \"OPT_IN\" | \"OPT_OUT\"; features?: Record<string, \"OPT_IN\"> } | undefined {\n const visual = repeatedValues(rawArgs, \"visual-enhancement\", args[\"visual-enhancement\"]);\n const unknown = visual.filter((feature) => !(feature in VISUAL_ENHANCEMENT_FEATURES));\n if (unknown.length > 0) {\n failWriteValidation(\n `--visual-enhancement ${unknown.join(\", \")} is not a feature that changes the media — one of ${Object.keys(VISUAL_ENHANCEMENT_FEATURES).join(\", \")}`,\n );\n }\n const standard = args[\"standard-enhancements\"] !== undefined ? parseEnroll(args[\"standard-enhancements\"]) : undefined;\n if (!standard && visual.length === 0) return undefined;\n return {\n ...(standard ? { standardEnhancements: standard } : {}),\n ...(visual.length > 0\n ? { features: Object.fromEntries(visual.map((feature) => [feature, \"OPT_IN\" as const])) }\n : {}),\n };\n}\n\n/** A carousel's card order and end card — Meta's `multi_share_optimized` / `multi_share_end_card`. */\nexport function carouselFlags(args: Args): { card_order?: string; end_card?: boolean } {\n const order = args[\"card-order\"];\n if (order !== undefined && order !== \"fixed\" && order !== \"optimized\") {\n failWriteValidation(\"--card-order must be fixed (the order you built) or optimized (Meta reorders)\");\n }\n const endCard = args[\"end-card\"];\n return {\n ...(order !== undefined ? { card_order: String(order) } : {}),\n ...(endCard !== undefined ? { end_card: parseEnroll(endCard) === \"OPT_IN\" } : {}),\n };\n}\n\n/**\n * A click-to-message greeting from `--greeting`, every `--ice-breaker\n * \"Question => Answer\"` (repeatable) and `--autofill`.\n */\nexport function welcomeMessageFromFlags(\n args: Args,\n rawArgs: readonly string[] | undefined,\n): { greeting?: string; iceBreakers?: { question: string; answer: string }[]; autofill?: string } | undefined {\n const breakers = repeatedValues(rawArgs, \"ice-breaker\", args[\"ice-breaker\"]).map((entry) => {\n const [question, ...rest] = entry.split(\"=>\");\n const answer = rest.join(\"=>\").trim();\n if (!question?.trim() || !answer) {\n failWriteValidation(`--ice-breaker takes \"Question => Answer\" — got \"${entry}\"`);\n }\n return { question: question.trim(), answer };\n });\n if (args.greeting === undefined && breakers.length === 0 && args.autofill === undefined) return undefined;\n return {\n ...(args.greeting !== undefined ? { greeting: String(args.greeting) } : {}),\n ...(breakers.length > 0 ? { iceBreakers: breakers } : {}),\n ...(args.autofill !== undefined ? { autofill: String(args.autofill) } : {}),\n };\n}\n\n/** The app each messaging button opens (Meta's click-to-* guides). */\nconst BUTTON_OPENS: Record<string, string> = {\n MESSAGE_PAGE: \"MESSENGER\",\n WHATSAPP_MESSAGE: \"WHATSAPP\",\n INSTAGRAM_MESSAGE: \"INSTAGRAM_DIRECT\",\n};\n\n/**\n * The button fields of a click-to-message or app ad: which app a conversation\n * opens in (`--app-destination`, implied by a messaging `--cta`), the deep link\n * (`--deep-link`) and the app (`--app-id`).\n */\nexport function conversationAndAppCta(args: Args): Record<string, string> {\n const cta = args.cta === undefined ? undefined : String(args.cta).toUpperCase();\n const destination =\n args[\"app-destination\"] !== undefined\n ? String(args[\"app-destination\"]).toUpperCase()\n : cta\n ? BUTTON_OPENS[cta]\n : undefined;\n return {\n ...(destination ? { app_destination: destination } : {}),\n ...(args[\"deep-link\"] !== undefined ? { app_link: String(args[\"deep-link\"]) } : {}),\n ...(args[\"app-id\"] !== undefined ? { application: String(args[\"app-id\"]) } : {}),\n };\n}\n"],"mappings":"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","names":[]}
@@ -27,21 +27,21 @@ Full guide: __tooling__/docs/tools/baker/ads-x.md`
27
27
  subCommands: {
28
28
  accounts: () => import("./accounts-E4TVYTUR.js").then((m) => m.accountsCommand),
29
29
  funding: () => import("./funding-ULBMKUMW.js").then((m) => m.fundingCommand),
30
- campaigns: () => import("./campaigns-NR6TNQFN.js").then((m) => m.campaignsCommand),
30
+ campaigns: () => import("./campaigns-VTRMKSAT.js").then((m) => m.campaignsCommand),
31
31
  "line-items": () => import("./line-items-CKUD2UU4.js").then((m) => m.lineItemsCommand),
32
32
  "promoted-tweets": () => import("./promoted-tweets-7MXVZRBI.js").then((m) => m.promotedTweetsCommand),
33
33
  tweets: () => import("./tweets-C3QUKS3I.js").then((m) => m.tweetsCommand),
34
34
  cards: () => import("./cards-WHMCSRZX.js").then((m) => m.cardsCommand),
35
- draft: () => import("./draft-GPN3HOAG.js").then((m) => m.draftCommand),
35
+ draft: () => import("./draft-4P3YO67N.js").then((m) => m.draftCommand),
36
36
  media: () => import("./media-MPXEXN4O.js").then((m) => m.mediaCommand),
37
37
  audiences: () => import("./audiences-3LRCLHTQ.js").then((m) => m.audiencesCommand),
38
38
  "targeting-criteria": () => import("./targeting-criteria-EU65WUUF.js").then((m) => m.targetingCriteriaCommand),
39
39
  "targeting-constants": () => import("./targeting-constants-KEKYU5JQ.js").then((m) => m.targetingConstantsCommand),
40
40
  "active-entities": () => import("./active-entities-MCL7UEGV.js").then((m) => m.activeEntitiesCommand),
41
- stats: () => import("./stats-RCLQE4HJ.js").then((m) => m.statsCommand)
41
+ stats: () => import("./stats-ZAGJH4AD.js").then((m) => m.statsCommand)
42
42
  }
43
43
  });
44
44
  export {
45
45
  xCommand
46
46
  };
47
- //# sourceMappingURL=x-WK2VQDPF.js.map
47
+ //# sourceMappingURL=x-VCSMV7T5.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@koda-sl/baker-cli",
3
- "version": "0.489.0",
3
+ "version": "0.490.0",
4
4
  "description": "AI-agent-first CLI for interacting with Baker, including the Baker creative canvas.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,49 +0,0 @@
1
- import {
2
- handleMetaError,
3
- resolveAccountIdArg
4
- } from "./chunk-OP7DNHD2.js";
5
- import {
6
- writeAdsJson
7
- } from "./chunk-SWL4AAPP.js";
8
- import {
9
- NO_CACHE_ARG
10
- } from "./chunk-K3TNTBZJ.js";
11
- import {
12
- apiGet
13
- } from "./chunk-XDZVBX6L.js";
14
- import "./chunk-N5O67GK5.js";
15
- import "./chunk-EE72SSB2.js";
16
- import "./chunk-WNSE7N75.js";
17
- import "./chunk-YQSBHWOI.js";
18
-
19
- // src/commands/ads/meta/account.ts
20
- import { defineCommand } from "citty";
21
- var accountCommand = defineCommand({
22
- meta: {
23
- name: "account",
24
- description: `Show single Meta ad account detail (currency, timezone, balance, business).
25
-
26
- Examples:
27
- baker ads meta account --account-id act_123
28
- BAKER_META_AD_ACCOUNT_ID=act_123 baker ads meta account`
29
- },
30
- args: {
31
- "account-id": { type: "string", description: "Meta ad account ID (act_...)" },
32
- "no-cache": NO_CACHE_ARG
33
- },
34
- run: async ({ args }) => {
35
- const accountId = resolveAccountIdArg(args);
36
- try {
37
- const params = { "account-id": accountId };
38
- if (args["no-cache"]) params["skip-cache"] = "true";
39
- const data = await apiGet("/api/ads/meta/account", params);
40
- writeAdsJson({ ok: true, data });
41
- } catch (err) {
42
- handleMetaError(err);
43
- }
44
- }
45
- });
46
- export {
47
- accountCommand
48
- };
49
- //# sourceMappingURL=account-7LUQWY6Q.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/ads/meta/account.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\nimport { NO_CACHE_ARG } from \"../../../cache-flag.ts\";\nimport { apiGet } from \"../../../client.ts\";\nimport { writeAdsJson } from \"../output.ts\";\nimport { handleMetaError, resolveAccountIdArg } from \"./shared.ts\";\n\nexport const accountCommand = defineCommand({\n meta: {\n name: \"account\",\n description: `Show single Meta ad account detail (currency, timezone, balance, business).\n\nExamples:\n baker ads meta account --account-id act_123\n BAKER_META_AD_ACCOUNT_ID=act_123 baker ads meta account`,\n },\n args: {\n \"account-id\": { type: \"string\", description: \"Meta ad account ID (act_...)\" },\n \"no-cache\": NO_CACHE_ARG,\n },\n run: async ({ args }) => {\n const accountId = resolveAccountIdArg(args);\n try {\n const params: Record<string, string> = { \"account-id\": accountId };\n if (args[\"no-cache\"]) params[\"skip-cache\"] = \"true\";\n const data = await apiGet<Record<string, unknown>>(\"/api/ads/meta/account\", params);\n writeAdsJson({ ok: true, data });\n } catch (err) {\n handleMetaError(err);\n }\n },\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA,SAAS,qBAAqB;AAMvB,IAAM,iBAAiB,cAAc;AAAA,EAC1C,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA,EAKf;AAAA,EACA,MAAM;AAAA,IACJ,cAAc,EAAE,MAAM,UAAU,aAAa,+BAA+B;AAAA,IAC5E,YAAY;AAAA,EACd;AAAA,EACA,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,UAAM,YAAY,oBAAoB,IAAI;AAC1C,QAAI;AACF,YAAM,SAAiC,EAAE,cAAc,UAAU;AACjE,UAAI,KAAK,UAAU,EAAG,QAAO,YAAY,IAAI;AAC7C,YAAM,OAAO,MAAM,OAAgC,yBAAyB,MAAM;AAClF,mBAAa,EAAE,IAAI,MAAM,KAAK,CAAC;AAAA,IACjC,SAAS,KAAK;AACZ,sBAAgB,GAAG;AAAA,IACrB;AAAA,EACF;AACF,CAAC;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/ads/meta/ads.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\nimport { NO_CACHE_ARG } from \"../../../cache-flag.ts\";\nimport { apiGet } from \"../../../client.ts\";\nimport { META_LIST_SHAPE_ARGS, registerMetaListSchema, shapeMetaListRows, writeMetaListRows } 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 \"adset-id\": { type: \"string\", description: \"Filter to one adset\" },\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 ...META_LIST_SHAPE_ARGS,\n} as const;\n\nregisterMetaListSchema(\n \"ads\",\n \"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.\",\n listArgs,\n);\n\nconst listCommand = defineCommand({\n meta: {\n name: \"list\",\n description:\n \"List ads in a Meta ad account. Runs by default when no subcommand is given. Example: baker ads meta ads --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[\"adset-id\"]) params[\"adset-id\"] = args[\"adset-id\"] as string;\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/ads\", params);\n const shaped = shapeMetaListRows(\"ads\", data, args);\n writeMetaListRows(\"ads\", shaped, csvOrJson(args), statusFilterHints(data, effectiveStatus, \"ads\"));\n } catch (err) {\n handleMetaError(err);\n }\n },\n});\n\nexport const adsListCommand = defineCommand({\n meta: {\n name: \"ads\",\n description: `List ads in a Meta ad account, or stage writes (create/update/pause/resume/archive/delete/duplicate/retag).\nDefaults to ACTIVE only — pass --all-statuses to widen. Write subcommands stage ops on this chat's draft.\n\nThe dashboard shows effective_status (e.g. WITH_ISSUES, PENDING_REVIEW, DISAPPROVED, ADSET_PAUSED), not status.\n\nListings print a table by default: id, name, adset_id, campaign_id, effective_status, creative_id, issues\n(why an ad is WITH_ISSUES), created_time. --fields takes dotted paths (e.g. tracking_specs,\npreview_shareable_link); --full returns every field; --output json returns the rows as JSON.\n\nExamples:\n baker ads meta ads --account-id act_123\n baker ads meta ads --adset-id 6123\n baker ads meta ads --account-id act_123 --all-statuses --name-contains octubre --fields id,name,adset_id,creative_id — find one ad by name\n baker ads meta ads --adset-id 6123 --fields id,name,preview_shareable_link\n baker ads meta ads create --name \"Ad 1\" --adset meta_temp_as01 --creative meta_temp_cr01\n baker ads meta ads pause 6123 --account-id act_123\n baker ads meta ads retag 6123 --set \"utm_medium=paid-social\" — fix tracking on a LIVE ad, keeping everything else`,\n },\n subCommands: {\n list: listCommand,\n create: () => import(\"./write-commands.ts\").then((m) => m.adsCreateCommand),\n update: () => import(\"./write-commands.ts\").then((m) => m.adsUpdateCommand),\n pause: () => import(\"./write-commands.ts\").then((m) => m.adsPauseCommand),\n resume: () => import(\"./write-commands.ts\").then((m) => m.adsResumeCommand),\n archive: () => import(\"./write-commands.ts\").then((m) => m.adsArchiveCommand),\n delete: () => import(\"./write-commands.ts\").then((m) => m.adsDeleteCommand),\n duplicate: () => import(\"./write-commands.ts\").then((m) => m.adsDuplicateCommand),\n retag: () => import(\"./write-commands.ts\").then((m) => m.adsRetagCommand),\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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,qBAAqB;AAa9B,IAAM,WAAW;AAAA,EACf,cAAc,EAAE,MAAM,UAAU,aAAa,qBAAqB;AAAA,EAClE,YAAY,EAAE,MAAM,UAAU,aAAa,sBAAsB;AAAA,EACjE,eAAe,EAAE,MAAM,UAAU,aAAa,yBAAyB;AAAA,EACvE,oBAAoB,EAAE,MAAM,UAAU,aAAa,8DAA8D;AAAA,EACjH,gBAAgB,EAAE,MAAM,WAAW,aAAa,iCAAiC;AAAA,EACjF,iBAAiB;AAAA,EACjB,OAAO,EAAE,MAAM,UAAU,aAAa,0BAA0B;AAAA,EAChE,YAAY;AAAA,EACZ,GAAG;AACL;AAEA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,cAAc,cAAc;AAAA,EAChC,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aACE;AAAA,EACJ;AAAA,EACA,MAAM;AAAA,EACN,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,UAAM,YAAY,oBAAoB,IAAI;AAC1C,UAAM,kBAAkB,uBAAuB,IAAI;AACnD,QAAI;AACF,YAAM,SAAiC,EAAE,cAAc,UAAU;AACjE,UAAI,KAAK,UAAU,EAAG,QAAO,UAAU,IAAI,KAAK,UAAU;AAC1D,UAAI,KAAK,aAAa,EAAG,QAAO,aAAa,IAAI,KAAK,aAAa;AACnE,UAAI,gBAAiB,QAAO,kBAAkB,IAAI;AAClD,UAAI,KAAK,eAAe,EAAG,QAAO,eAAe,IAAI,KAAK,eAAe;AACzE,UAAI,KAAK,MAAO,QAAO,QAAQ,KAAK;AACpC,UAAI,KAAK,UAAU,EAAG,QAAO,YAAY,IAAI;AAC7C,YAAM,OAAO,MAAM,OAAuC,qBAAqB,MAAM;AACrF,YAAM,SAAS,kBAAkB,OAAO,MAAM,IAAI;AAClD,wBAAkB,OAAO,QAAQ,UAAU,IAAI,GAAG,kBAAkB,MAAM,iBAAiB,KAAK,CAAC;AAAA,IACnG,SAAS,KAAK;AACZ,sBAAgB,GAAG;AAAA,IACrB;AAAA,EACF;AACF,CAAC;AAEM,IAAM,iBAAiB,cAAc;AAAA,EAC1C,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBf;AAAA,EACA,aAAa;AAAA,IACX,MAAM;AAAA,IACN,QAAQ,MAAM,OAAO,8BAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,gBAAgB;AAAA,IAC1E,QAAQ,MAAM,OAAO,8BAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,gBAAgB;AAAA,IAC1E,OAAO,MAAM,OAAO,8BAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,eAAe;AAAA,IACxE,QAAQ,MAAM,OAAO,8BAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,gBAAgB;AAAA,IAC1E,SAAS,MAAM,OAAO,8BAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,iBAAiB;AAAA,IAC5E,QAAQ,MAAM,OAAO,8BAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,gBAAgB;AAAA,IAC1E,WAAW,MAAM,OAAO,8BAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,mBAAmB;AAAA,IAChF,OAAO,MAAM,OAAO,8BAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,eAAe;AAAA,EAC1E;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM;AAAA,EACN,SAAS;AACX,CAAC;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/ads/meta/audiences.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\nimport { NO_CACHE_ARG } from \"../../../cache-flag.ts\";\nimport { apiGet } from \"../../../client.ts\";\nimport { writeAdsJson, writeAdsOutput } from \"../output.ts\";\nimport { csvOrJson, handleMetaError, resolveAccountIdArg } from \"./shared.ts\";\n\nconst listArgs = {\n \"account-id\": { type: \"string\", description: \"Meta ad account ID\" },\n limit: { type: \"string\", description: \"Max rows\" },\n \"no-cache\": NO_CACHE_ARG,\n output: { type: \"string\", description: \"Output format\", default: \"json\" },\n} as const;\n\nconst listCommand = defineCommand({\n meta: {\n name: \"list\",\n description:\n \"List custom audiences. Runs by default when no subcommand is given. Example: baker ads meta audiences --account-id act_123\",\n },\n args: listArgs,\n run: async ({ args }) => {\n const accountId = resolveAccountIdArg(args);\n try {\n const params: Record<string, string> = { \"account-id\": accountId };\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/audiences\", params);\n const fmt = csvOrJson(args);\n if (fmt !== \"json\") {\n writeAdsOutput(data, fmt);\n return;\n }\n writeAdsJson({ ok: true, data });\n } catch (err) {\n handleMetaError(err);\n }\n },\n});\n\nexport const audiencesCommand = defineCommand({\n meta: {\n name: \"audiences\",\n description: `List custom audiences, or stage writes (create/update). Write subcommands stage ops on this chat's draft.\nIncludes lookalikes, website-pixel audiences, customer-file audiences. Meta hides exact size when count < 1000.\n\nExamples:\n baker ads meta audiences --account-id act_123\n baker ads meta audiences create --name \"Site 30d\" --subtype WEBSITE --file rule.json`,\n },\n subCommands: {\n list: listCommand,\n create: () => import(\"./write-commands.ts\").then((m) => m.audiencesCreateCommand),\n update: () => import(\"./write-commands.ts\").then((m) => m.audiencesUpdateCommand),\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":";;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,qBAAqB;AAM9B,IAAM,WAAW;AAAA,EACf,cAAc,EAAE,MAAM,UAAU,aAAa,qBAAqB;AAAA,EAClE,OAAO,EAAE,MAAM,UAAU,aAAa,WAAW;AAAA,EACjD,YAAY;AAAA,EACZ,QAAQ,EAAE,MAAM,UAAU,aAAa,iBAAiB,SAAS,OAAO;AAC1E;AAEA,IAAM,cAAc,cAAc;AAAA,EAChC,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aACE;AAAA,EACJ;AAAA,EACA,MAAM;AAAA,EACN,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,UAAM,YAAY,oBAAoB,IAAI;AAC1C,QAAI;AACF,YAAM,SAAiC,EAAE,cAAc,UAAU;AACjE,UAAI,KAAK,MAAO,QAAO,QAAQ,KAAK;AACpC,UAAI,KAAK,UAAU,EAAG,QAAO,YAAY,IAAI;AAC7C,YAAM,OAAO,MAAM,OAAuC,2BAA2B,MAAM;AAC3F,YAAM,MAAM,UAAU,IAAI;AAC1B,UAAI,QAAQ,QAAQ;AAClB,uBAAe,MAAM,GAAG;AACxB;AAAA,MACF;AACA,mBAAa,EAAE,IAAI,MAAM,KAAK,CAAC;AAAA,IACjC,SAAS,KAAK;AACZ,sBAAgB,GAAG;AAAA,IACrB;AAAA,EACF;AACF,CAAC;AAEM,IAAM,mBAAmB,cAAc;AAAA,EAC5C,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMf;AAAA,EACA,aAAa;AAAA,IACX,MAAM;AAAA,IACN,QAAQ,MAAM,OAAO,8BAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,sBAAsB;AAAA,IAChF,QAAQ,MAAM,OAAO,8BAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,sBAAsB;AAAA,EAClF;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM;AAAA,EACN,SAAS;AACX,CAAC;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/ads/x/campaign-writes.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\nimport { registerSchema } from \"../../../schemas.ts\";\nimport {\n compact,\n microsFromArg,\n requireTarget,\n requireTargets,\n stageAccountId,\n stageXOp,\n stageXOps,\n} from \"./write-shared.ts\";\n\n/**\n * Staged campaign writes. Nothing here calls X: each command appends an op to\n * this chat's draft, which applies when the chat publishes.\n */\n\nconst BUDGET_ARGS = {\n \"daily-budget\": { type: \"string\", description: \"Daily budget in account currency, e.g. 12.50\" },\n \"total-budget\": { type: \"string\", description: \"Lifetime budget in account currency — must exceed the daily budget\" },\n} as const;\n\nregisterSchema({\n command: \"ads.x.campaigns.create\",\n description:\n \"Stage a new X campaign on this chat's draft. Needs a funding instrument (`baker ads x funding`). Defaults to PAUSED — an ACTIVE campaign starts spending the moment the chat publishes.\",\n args: {\n \"account-id\": { type: \"string\", description: \"X Ads account ID\", required: false },\n name: { type: \"string\", description: \"Campaign name\", required: true },\n \"funding-instrument-id\": { type: \"string\", description: \"From `baker ads x funding`\", required: true },\n status: { type: \"string\", description: \"ACTIVE | PAUSED | DRAFT (default PAUSED)\", required: false },\n \"daily-budget\": { type: \"string\", description: \"Daily budget in account currency\", required: false },\n \"total-budget\": { type: \"string\", description: \"Lifetime budget in account currency\", required: false },\n \"budget-optimization\": { type: \"string\", description: \"CAMPAIGN | LINE_ITEM\", required: false },\n },\n});\n\nexport const campaignsCreateCommand = defineCommand({\n meta: {\n name: \"create\",\n description: `Stage a new campaign (applies when the chat is published).\n\nExamples:\n baker ads x campaigns create --name \"zz-baker-harness\" --funding-instrument-id vtbot --daily-budget 5`,\n },\n args: {\n \"account-id\": { type: \"string\", description: \"X Ads account ID\" },\n name: { type: \"string\", description: \"Campaign name\", required: true },\n \"funding-instrument-id\": { type: \"string\", description: \"Funding instrument id\", required: true },\n status: { type: \"string\", description: \"ACTIVE | PAUSED | DRAFT (default PAUSED)\" },\n ...BUDGET_ARGS,\n \"budget-optimization\": { type: \"string\", description: \"CAMPAIGN | LINE_ITEM\" },\n },\n run: async ({ args }) => {\n const accountId = await stageAccountId(args);\n await stageXOp({\n kind: \"campaign.create\",\n accountId,\n payload: compact({\n name: args.name,\n fundingInstrumentId: args[\"funding-instrument-id\"],\n entityStatus: args.status,\n budgetOptimization: args[\"budget-optimization\"],\n dailyBudgetAmountLocalMicro: microsFromArg(args[\"daily-budget\"], \"--daily-budget\"),\n totalBudgetAmountLocalMicro: microsFromArg(args[\"total-budget\"], \"--total-budget\"),\n }),\n });\n },\n});\n\nregisterSchema({\n command: \"ads.x.campaigns.update\",\n description:\n \"Stage a change to an existing X campaign. Staging the same campaign twice amends the staged change in place rather than queueing two writes.\",\n args: {\n id: { type: \"string\", description: \"Campaign id\", required: true },\n \"account-id\": { type: \"string\", description: \"X Ads account ID\", required: false },\n name: { type: \"string\", description: \"New name\", required: false },\n status: { type: \"string\", description: \"ACTIVE | PAUSED\", required: false },\n \"daily-budget\": { type: \"string\", description: \"Daily budget in account currency\", required: false },\n \"total-budget\": { type: \"string\", description: \"Lifetime budget in account currency\", required: false },\n \"budget-optimization\": { type: \"string\", description: \"CAMPAIGN | LINE_ITEM\", required: false },\n },\n});\n\nexport const campaignsUpdateCommand = defineCommand({\n meta: {\n name: \"update\",\n description: `Stage a change to a campaign.\n\nExamples:\n baker ads x campaigns update oilf0 --daily-budget 20\n baker ads x campaigns update oilf0 --name \"Spring push\"`,\n },\n args: {\n id: { type: \"positional\", description: \"Campaign id\", required: true },\n \"account-id\": { type: \"string\", description: \"X Ads account ID\" },\n name: { type: \"string\", description: \"New name\" },\n status: { type: \"string\", description: \"ACTIVE | PAUSED\" },\n ...BUDGET_ARGS,\n \"budget-optimization\": { type: \"string\", description: \"CAMPAIGN | LINE_ITEM\" },\n },\n run: async ({ args }) => {\n const accountId = await stageAccountId(args);\n await stageXOp({\n kind: \"campaign.update\",\n accountId,\n target: requireTarget(args, \"id\"),\n payload: compact({\n name: args.name,\n entityStatus: args.status,\n budgetOptimization: args[\"budget-optimization\"],\n dailyBudgetAmountLocalMicro: microsFromArg(args[\"daily-budget\"], \"--daily-budget\"),\n totalBudgetAmountLocalMicro: microsFromArg(args[\"total-budget\"], \"--total-budget\"),\n }),\n });\n },\n});\n\nfunction statusCommand(name: \"pause\" | \"resume\", status: \"PAUSED\" | \"ACTIVE\") {\n registerSchema({\n command: `ads.x.campaigns.${name}`,\n description: `Stage ${name === \"pause\" ? \"a pause\" : \"a resume\"} for one or more X campaigns. Pass every id in one call.`,\n args: {\n ids: { type: \"string\", description: \"Campaign ids, comma-separated\", required: true },\n \"account-id\": { type: \"string\", description: \"X Ads account ID\", required: false },\n },\n });\n return defineCommand({\n meta: {\n name,\n description: `Stage ${name === \"pause\" ? \"pausing\" : \"resuming\"} campaigns.\n\nExample:\n baker ads x campaigns ${name} oilf0,omyq3`,\n },\n args: {\n ids: { type: \"positional\", description: \"Campaign ids, comma-separated\", required: true },\n \"account-id\": { type: \"string\", description: \"X Ads account ID\" },\n },\n run: async ({ args }) => {\n const accountId = await stageAccountId(args);\n await stageXOps(\n requireTargets(args, \"ids\").map((id) => ({\n kind: \"campaign.update\",\n accountId,\n target: id,\n payload: { entityStatus: status },\n })),\n );\n },\n });\n}\n\nexport const campaignsPauseCommand = statusCommand(\"pause\", \"PAUSED\");\nexport const campaignsResumeCommand = statusCommand(\"resume\", \"ACTIVE\");\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
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 { META_LIST_SHAPE_ARGS, registerMetaListSchema, shapeMetaListRows, writeMetaListRows } 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 \"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); --full returns every field Meta sent; --output json returns the rows in the envelope.\",\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), statusFilterHints(data, effectiveStatus, \"campaigns\"));\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).\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);\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 },\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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,qBAAqB;AAa9B,IAAM,WAAW;AAAA,EACf,cAAc,EAAE,MAAM,UAAU,aAAa,qBAAqB;AAAA,EAClE,oBAAoB,EAAE,MAAM,UAAU,aAAa,8DAA8D;AAAA,EACjH,gBAAgB,EAAE,MAAM,WAAW,aAAa,uDAAuD;AAAA,EACvG,iBAAiB;AAAA,EACjB,OAAO,EAAE,MAAM,UAAU,aAAa,0BAA0B;AAAA,EAChE,YAAY;AAAA,EACZ,GAAG;AACL;AAEA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,cAAc,cAAc;AAAA,EAChC,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aACE;AAAA,EACJ;AAAA,EACA,MAAM;AAAA,EACN,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,UAAM,YAAY,oBAAoB,IAAI;AAC1C,UAAM,kBAAkB,uBAAuB,IAAI;AACnD,QAAI;AACF,YAAM,SAAiC,EAAE,cAAc,UAAU;AACjE,UAAI,gBAAiB,QAAO,kBAAkB,IAAI;AAClD,UAAI,KAAK,eAAe,EAAG,QAAO,eAAe,IAAI,KAAK,eAAe;AACzE,UAAI,KAAK,MAAO,QAAO,QAAQ,KAAK;AACpC,UAAI,KAAK,UAAU,EAAG,QAAO,YAAY,IAAI;AAC7C,YAAM,OAAO,MAAM,OAAuC,2BAA2B,MAAM;AAC3F,YAAM,SAAS,kBAAkB,aAAa,MAAM,IAAI;AACxD,wBAAkB,aAAa,QAAQ,UAAU,IAAI,GAAG,kBAAkB,MAAM,iBAAiB,WAAW,CAAC;AAAA,IAC/G,SAAS,KAAK;AACZ,sBAAgB,GAAG;AAAA,IACrB;AAAA,EACF;AACF,CAAC;AAEM,IAAM,mBAAmB,cAAc;AAAA,EAC5C,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBf;AAAA,EACA,aAAa;AAAA,IACX,MAAM;AAAA,IACN,QAAQ,MAAM,OAAO,8BAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,sBAAsB;AAAA,IAChF,QAAQ,MAAM,OAAO,8BAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,sBAAsB;AAAA,IAChF,OAAO,MAAM,OAAO,8BAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,qBAAqB;AAAA,IAC9E,QAAQ,MAAM,OAAO,8BAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,sBAAsB;AAAA,IAChF,SAAS,MAAM,OAAO,8BAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,uBAAuB;AAAA,IAClF,QAAQ,MAAM,OAAO,8BAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,sBAAsB;AAAA,IAChF,WAAW,MAAM,OAAO,8BAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,yBAAyB;AAAA,EACxF;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM;AAAA,EACN,SAAS;AACX,CAAC;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/chats/index.ts"],"sourcesContent":["import type { ChatsDiffResponse, ChatsListResponse, ChatsTranscriptResponse, ChatsViewResponse } from \"@baker/api\";\nimport { defineCommand } from \"citty\";\nimport { apiPost } from \"../../client.ts\";\nimport { getEnv } from \"../../env.ts\";\nimport { writeJson } from \"../../output.ts\";\nimport { registerSchema } from \"../../schemas.ts\";\nimport { failApi } from \"../actions/shared.ts\";\n\nconst STATUS_GROUPS = [\"active\", \"archived\", \"all\"] as const;\nconst REPO_SURFACES = [\"knowledge\", \"company\", \"brand\", \"landings\", \"flows\", \"creatives\"] as const;\n\nfunction parseBoundedInt(raw: string | undefined, name: string, min: number, max: number): number | undefined {\n if (raw === undefined) {\n return undefined;\n }\n const value = Number.parseInt(raw, 10);\n if (Number.isNaN(value) || value < min || value > max) {\n throw new Error(`--${name} must be an integer between ${min} and ${max}`);\n }\n return value;\n}\n\nregisterSchema({\n command: \"chats.list\",\n description:\n \"Start here: list other Sessions on this account (newest first) so you can reuse what was done before. Each row shows the Session id, title, status, and a count of what it produced (creatives, landings, actions, flows, reports…). Then drill in with `baker chats view <id>`, `baker chats transcript <id>`, or `baker chats diff <id>`. Read-only.\",\n args: {\n status: { type: \"string\", description: \"Filter: active|archived|all (default: all)\", required: false },\n limit: { type: \"string\", description: \"Max Sessions to return, 1-100 (default: 20)\", required: false },\n full: { type: \"boolean\", description: \"Include each Session's full change list\", required: false, default: false },\n },\n});\n\nconst listCommand = defineCommand({\n meta: { name: \"list\", description: \"List other Sessions on this account, newest first.\" },\n args: {\n status: { type: \"string\", description: \"Filter: active|archived|all (default: all)\", required: false },\n limit: { type: \"string\", description: \"Max Sessions (1-100, default 20)\", required: false },\n full: { type: \"boolean\", description: \"Include each Session's full change list\", required: false, default: false },\n },\n run: async ({ args }) => {\n try {\n const body: Record<string, unknown> = {};\n if (args.status) {\n if (!(STATUS_GROUPS as readonly string[]).includes(args.status)) {\n throw new Error(`--status must be one of: ${STATUS_GROUPS.join(\"|\")}`);\n }\n body.status = args.status;\n }\n const limit = parseBoundedInt(args.limit, \"limit\", 1, 100);\n if (limit !== undefined) {\n body.limit = limit;\n }\n if (args.full) {\n body.full = true;\n }\n // Exclude our own Session so we never list ourselves as a reusable \"other\".\n const selfChatId = getEnv().BAKER_CHAT_ID;\n if (selfChatId) {\n body.excludeChatId = selfChatId;\n }\n const response = await apiPost<ChatsListResponse>(\"/api/chats/list\", body);\n writeJson({\n ...response,\n meta: { count: response.data.chats.length },\n ...(response.data.chats.length === 0\n ? { hints: [\"No Sessions matched. Widen with --status all or a larger --limit.\"] }\n : {\n hints: [\n \"Drill in: `baker chats view <id>` for outputs, `chats transcript <id>` for the conversation, `chats diff <id>` for the real file changes.\",\n ],\n }),\n });\n } catch (err) {\n failApi(err);\n }\n },\n});\n\nregisterSchema({\n command: \"chats.view\",\n description:\n \"Inspect one Session's FULL picture of what it changed — the unified `effects`: git content (landings, creatives, flows, knowledge, brand), plus DB-only effects that never touch the repo — Actions, Scheduled agents, Tags, Tag Manager, Google Analytics, ad-platform writes, the funnel (`funnel`: which steps it added, changed or removed, and which ways in it added or removed in `triggersAdded`/`triggersRemoved`), what counts as a conversion (`conversions`), conversion sends, event sources, and every other staged or already-applied change (`otherChanges`: A/B tests, recipes, library images) — each resolved to real detail (names, descriptions, priorities, tag types, ad operations) and, once published, its `outcome`. Also `publish` (what each external surface actually did, with the provider's own error), `activity` (the chat's own timeline: status changes, publish start/fail, workspace recoveries, timeouts), `usage` (per-thread cost and the Session's token totals), the kickoff (how it was asked), threads, and commits. Effects are `staged` (in-progress draft) or applied. A completed Session is NOT proof its external changes landed — read `publish`. Use after `baker chats list` to decide whether to reuse it. Read-only.\",\n args: {\n id: { type: \"positional\", description: \"The Session id (from `baker chats list`)\", required: true },\n full: {\n type: \"boolean\",\n description: \"Untruncated effect lists and full activity metadata (compact caps each list at 25)\",\n required: false,\n default: false,\n },\n },\n});\n\nconst viewCommand = defineCommand({\n meta: {\n name: \"view\",\n description: \"Inspect one Session's full effects — git content + actions/tags/ads, kickoff, commits.\",\n },\n args: {\n id: { type: \"positional\", description: \"The Session id\", required: true },\n full: { type: \"boolean\", description: \"Include full detail\", required: false, default: false },\n },\n run: async ({ args }) => {\n try {\n const response = await apiPost<ChatsViewResponse>(\"/api/chats/view\", {\n chatId: args.id,\n ...(args.full ? { full: true } : {}),\n });\n const hints: string[] = [];\n // The most dangerous thing a reader can conclude from this command is\n // that a completed Session published everything it staged. It usually\n // did; better than one published draft in three did not.\n if (response.data.publish && !response.data.publish.complete) {\n const failed = response.data.publish.failedTotal;\n hints.push(\n `This Session's publish left ${failed} change${failed === 1 ? \"\" : \"s\"} behind — see \\`publish.surfaces\\` for the platform's own words. Do not report those changes as live.`,\n );\n }\n if (response.data.diffAvailable) {\n hints.push(\"See the real file-level diff of the git content with `baker chats diff <id> --full`.\");\n } else if (response.data.status === \"in_progress\" || response.data.status === \"publishing\") {\n hints.push(\n \"This Session is still in progress — read its current file changes with `baker chats diff <id> --live`.\",\n );\n }\n hints.push(\"Read the conversation with `baker chats transcript <id>`.\");\n writeJson({ ...response, hints });\n } catch (err) {\n failApi(err);\n }\n },\n});\n\nregisterSchema({\n command: \"chats.transcript\",\n description:\n \"Read another Session's conversation (user + agent turns), most-recent first-capped. Use to see exactly how a past request was phrased and iterated before replaying it for a new goal. Compact truncates long messages; add --full for verbatim text. Read-only.\",\n args: {\n id: { type: \"positional\", description: \"The Session id\", required: true },\n limit: { type: \"string\", description: \"Max messages to return, 1-1000 (default: 100)\", required: false },\n full: {\n type: \"boolean\",\n description: \"Return verbatim (untruncated) message text\",\n required: false,\n default: false,\n },\n },\n});\n\nconst transcriptCommand = defineCommand({\n meta: { name: \"transcript\", description: \"Read another Session's conversation.\" },\n args: {\n id: { type: \"positional\", description: \"The Session id\", required: true },\n limit: { type: \"string\", description: \"Max messages (1-1000, default 100)\", required: false },\n full: { type: \"boolean\", description: \"Verbatim message text\", required: false, default: false },\n },\n run: async ({ args }) => {\n try {\n const body: Record<string, unknown> = { chatId: args.id };\n const limit = parseBoundedInt(args.limit, \"limit\", 1, 1000);\n if (limit !== undefined) {\n body.limit = limit;\n }\n if (args.full) {\n body.full = true;\n }\n const response = await apiPost<ChatsTranscriptResponse>(\"/api/chats/transcript\", body);\n writeJson({\n ...response,\n meta: { count: response.data.entries.length },\n ...(response.data.truncated\n ? { hints: [\"Older messages were dropped to fit --limit. Raise --limit to see more.\"] }\n : {}),\n });\n } catch (err) {\n failApi(err);\n }\n },\n});\n\nregisterSchema({\n command: \"chats.diff\",\n description:\n \"See the real file-level changes a Session made (landings, creatives, brand, flows, knowledge). Published Sessions read from git; for an in-progress (unpublished) Session pass --live to read its changes straight from its running workspace. Without --live, an unpublished Session returns available:false — use `baker chats view` for the staged summary. Compact lists changed files with +/- counts; add --full for the actual diff text. Read-only.\",\n args: {\n id: { type: \"positional\", description: \"The Session id\", required: true },\n surface: {\n type: \"string\",\n description: \"Filter to one surface: knowledge|company|brand|landings|flows|creatives\",\n required: false,\n },\n full: {\n type: \"boolean\",\n description: \"Include the unified-diff patch text per file\",\n required: false,\n default: false,\n },\n live: {\n type: \"boolean\",\n description:\n \"For an in-progress Session, read its changes from the live workspace (slower; resumes the paused Runtime). Ignored for published Sessions.\",\n required: false,\n default: false,\n },\n },\n});\n\nconst diffCommand = defineCommand({\n meta: { name: \"diff\", description: \"See a published Session's real file-level changes.\" },\n args: {\n id: { type: \"positional\", description: \"The Session id\", required: true },\n surface: {\n type: \"string\",\n description: \"Filter: knowledge|company|brand|landings|flows|creatives\",\n required: false,\n },\n full: { type: \"boolean\", description: \"Include the diff patch text per file\", required: false, default: false },\n live: {\n type: \"boolean\",\n description: \"Read an in-progress Session's changes from its live workspace (slower)\",\n required: false,\n default: false,\n },\n },\n run: async ({ args }) => {\n try {\n const body: Record<string, unknown> = { chatId: args.id };\n if (args.surface) {\n if (!(REPO_SURFACES as readonly string[]).includes(args.surface)) {\n throw new Error(`--surface must be one of: ${REPO_SURFACES.join(\"|\")}`);\n }\n body.surface = args.surface;\n }\n if (args.full) {\n body.full = true;\n }\n if (args.live) {\n body.live = true;\n }\n const response = await apiPost<ChatsDiffResponse>(\"/api/chats/diff\", body);\n writeJson({\n ...response,\n meta: { count: response.data.files.length },\n ...(!response.data.available && response.data.reason ? { hints: [response.data.reason] } : {}),\n ...(response.data.available && !args.full && response.data.files.length > 0\n ? { hints: [\"Add --full to read the actual diff text for each file.\"] }\n : {}),\n });\n } catch (err) {\n failApi(err);\n }\n },\n});\n\nexport const chatsCommand = defineCommand({\n meta: {\n name: \"chats\",\n description: `Inspect other Sessions on this account (read-only): list them, view what they produced, read their conversation, and see their real file changes — so you can reuse past work for a new goal.\nFull guide: __tooling__/docs/tools/baker/chats.md`,\n },\n subCommands: {\n list: listCommand,\n view: viewCommand,\n transcript: transcriptCommand,\n diff: diffCommand,\n },\n});\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/ads/chatgpt/write-shared.ts"],"sourcesContent":["import { type ChatgptDraftStageResponse, chatgptDraftOpInputSchema } from \"@baker/api/ads-chatgpt\";\nimport { defineCommand } from \"citty\";\nimport { ApiError, apiPost } from \"../../../client.ts\";\nimport { requireChatId } from \"../../../env.ts\";\nimport { registerSchema } from \"../../../schemas.ts\";\nimport { writeJsonEnvelope } from \"../output.ts\";\nimport type { AdsErrorEnvelope } from \"../types.ts\";\nimport { chatgptFailure } from \"./shared.ts\";\n\n/**\n * Shared plumbing for the staged ChatGPT Ads write commands.\n *\n * Writes never reach ChatGPT Ads from here: every command stages an op on this\n * chat's draft (`/api/ads/chatgpt/draft/stage`), the dashboard shows it as a\n * pending change, and it applies only when the chat is published.\n */\n\nfunction fail(envelope: AdsErrorEnvelope): never {\n writeJsonEnvelope({ ...envelope });\n process.exit(1);\n}\n\nexport function failWriteValidation(message: string): never {\n fail({\n ok: false,\n error: {\n code: \"VALIDATION_ERROR\",\n message,\n fix: { action: \"add_required_field\", explanation: `${message}. Nothing was staged.` },\n retryable: false,\n },\n });\n}\n\n/** A write failure, as the agent should act on it; a missing chat is not a network error. */\nfunction writeFailure(err: unknown, reference: string): AdsErrorEnvelope {\n if (!(err instanceof ApiError) && err instanceof Error && err.message.includes(\"BAKER_CHAT_ID\")) {\n return {\n ok: false,\n error: {\n code: \"NO_CHAT\",\n message: err.message,\n fix: {\n action: \"reject\",\n explanation:\n \"ChatGPT Ads changes are staged on a chat and apply when it is published; run this from the chat.\",\n },\n retryable: false,\n },\n };\n }\n return chatgptFailure(err, reference);\n}\n\n/**\n * Digits after the decimal point, read off the written amount: `String(0.0000005)`\n * is `\"5e-7\"`, whose mantissa has no decimals at all.\n */\nfunction decimalPlaces(value: unknown): number {\n const [mantissa, exponent] = String(value).trim().split(/e/i);\n const written = (mantissa?.split(\".\")[1] ?? \"\").length;\n return Math.max(0, written - (exponent ? Number(exponent) : 0));\n}\n\nexport type ChatgptMoneyParse = { ok: true; micros: number | undefined } | { ok: false; reason: string };\n\n/**\n * ChatGPT Ads takes money as integer micros of the account currency; the CLI\n * takes the amount a person writes. Counting decimals instead of comparing\n * `amount * 1e6` with its rounding is exact at every magnitude.\n */\nexport function parseChatgptMoney(value: unknown): ChatgptMoneyParse {\n if (value === undefined || value === \"\") {\n return { ok: true, micros: undefined };\n }\n const amount = Number(value);\n if (!Number.isFinite(amount) || amount <= 0) {\n return { ok: false, reason: \"must be a positive amount, for example 12.50\" };\n }\n if (decimalPlaces(value) > 6) {\n return { ok: false, reason: \"is finer than ChatGPT Ads can express\" };\n }\n return { ok: true, micros: Math.round(amount * 1_000_000) };\n}\n\nexport function microsFromArg(value: unknown, flag: string): number | undefined {\n const parsed = parseChatgptMoney(value);\n if (!parsed.ok) {\n failWriteValidation(`${flag} ${parsed.reason}`);\n }\n return parsed.micros;\n}\n\nexport function csvArg(value: unknown): string[] | undefined {\n if (typeof value !== \"string\" || value.trim().length === 0) {\n return undefined;\n }\n const parts = value\n .split(\",\")\n .map((part) => part.trim())\n .filter(Boolean);\n return parts.length > 0 ? parts : undefined;\n}\n\ninterface CliArg {\n type: string;\n description: string;\n required?: boolean;\n}\n\n/**\n * The `baker schema` entry for a command, read off the flags it really takes,\n * so the introspection an agent plans from cannot drift from the command.\n */\nexport function schemaArgs(args: Record<string, CliArg>) {\n return Object.fromEntries(\n Object.entries(args).map(([name, arg]) => [\n name,\n {\n type: arg.type === \"positional\" ? \"string\" : arg.type,\n description: arg.description,\n required: arg.required === true,\n },\n ]),\n );\n}\n\n/** A flag naming one of ChatGPT Ads' lowercase values, taken in whatever case it was typed. */\nexport function lowerArg(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim() !== \"\" ? value.trim().toLowerCase() : undefined;\n}\n\n/** A comma-separated list of those values. */\nexport function lowerCsvArg(value: unknown): string[] | undefined {\n return csvArg(value)?.map((part) => part.toLowerCase());\n}\n\n/** Drop unset keys so an omitted flag never stages as an explicit value. */\nexport function compact(payload: Record<string, unknown>): Record<string, unknown> {\n return Object.fromEntries(Object.entries(payload).filter(([, value]) => value !== undefined && value !== \"\"));\n}\n\nexport function requireTarget(args: Record<string, unknown>, name: string): string {\n const value = args[name];\n if (typeof value !== \"string\" || value.trim().length === 0) {\n failWriteValidation(`${name} is required`);\n }\n return value.trim();\n}\n\nexport function requireTargets(args: Record<string, unknown>, name: string): string[] {\n const ids = csvArg(args[name]);\n if (!ids) {\n failWriteValidation(`${name} is required — pass one or more ids, comma-separated`);\n }\n return ids;\n}\n\n/** The op, checked against the same schema the backend applies, before anything is sent. */\nfunction preflight(raw: Record<string, unknown>) {\n const parsed = chatgptDraftOpInputSchema.safeParse(raw);\n if (parsed.success) {\n return parsed.data;\n }\n const fields = parsed.error.issues.map((issue) => ({ path: issue.path.join(\".\"), message: issue.message }));\n const message = fields.map((field) => (field.path ? `${field.path}: ${field.message}` : field.message)).join(\"; \");\n return fail({\n ok: false,\n error: {\n code: \"VALIDATION_ERROR\",\n message,\n fix: {\n action: \"retry_with_modified_query\",\n explanation:\n \"Fix the named fields and stage again. Nothing was staged — the draft is as it was before this call.\",\n },\n retryable: false,\n },\n });\n}\n\n/** The ChatGPT Ads routes answer with the payload itself; the envelope is the CLI's to add. */\nasync function postStage(chatId: string, op: ReturnType<typeof preflight>): Promise<ChatgptDraftStageResponse> {\n return await apiPost<ChatgptDraftStageResponse>(\"/api/ads/chatgpt/draft/stage\", { chatId, op });\n}\n\n/** Stage one op and print what was staged; `hintsFor` names the obvious next step. */\nexport async function stageChatgptOp(\n raw: Record<string, unknown>,\n reference: string,\n hintsFor?: (staged: ChatgptDraftStageResponse) => string[],\n): Promise<void> {\n const op = preflight(raw);\n try {\n const staged = await postStage(requireChatId(), op);\n const hints = hintsFor?.(staged) ?? [];\n writeJsonEnvelope({ ok: true, data: staged, ...(hints.length > 0 ? { hints } : {}) });\n } catch (err) {\n fail(writeFailure(err, reference));\n }\n}\n\n/**\n * Stage the same change on several entities (a pause across campaigns). Each is\n * its own op; when one is refused, the ones already staged are named so the\n * agent neither re-stages nor loses them.\n */\nexport async function stageChatgptOps(raws: Array<Record<string, unknown>>, reference: string): Promise<void> {\n if (raws.length === 1 && raws[0]) {\n await stageChatgptOp(raws[0], reference);\n return;\n }\n const ops = raws.map(preflight);\n const staged: ChatgptDraftStageResponse[] = [];\n try {\n const chatId = requireChatId();\n for (const op of ops) {\n staged.push(await postStage(chatId, op));\n }\n writeJsonEnvelope({ ok: true, data: staged });\n } catch (err) {\n const failure = writeFailure(err, reference);\n if (staged.length > 0) {\n failure.error.message = `${failure.error.message} (already staged: ${staged.map((s) => s.summary).join(\"; \")})`;\n }\n fail(failure);\n }\n}\n\n/** On an update, `none` empties a list — ChatGPT Ads' way to clear exclusions, audiences or regions. */\nexport function clearableCsvArg(value: unknown): string[] | undefined {\n return typeof value === \"string\" && value.trim().toLowerCase() === \"none\" ? [] : csvArg(value);\n}\n\n/** On an update, `none` removes the value — a tracking template. */\nexport function clearableArg(value: unknown): string | null | undefined {\n if (typeof value !== \"string\" || value.trim() === \"\") {\n return undefined;\n }\n return value.trim().toLowerCase() === \"none\" ? null : value.trim();\n}\n\n/** A crop as `x,y,width,height`, each a share of the image from 0 to 1. */\nexport function cropArg(\n value: unknown,\n flag: string,\n): { x: number; y: number; width: number; height: number } | undefined {\n const parts = csvArg(value);\n if (!parts) {\n return undefined;\n }\n const numbers = parts.map(Number);\n const [x, y, width, height] = numbers;\n if (\n numbers.length !== 4 ||\n numbers.some(Number.isNaN) ||\n x === undefined ||\n y === undefined ||\n width === undefined ||\n height === undefined\n ) {\n failWriteValidation(`${flag} takes four shares of the image, x,y,width,height — e.g. 0.1,0,0.8,0.8`);\n }\n return { x, y, width, height };\n}\n\ntype StatusEntity = \"campaign\" | \"adGroup\" | \"ad\";\ntype StatusVerb = \"pause\" | \"resume\" | \"archive\";\n\nconst STATUS_OF: Record<StatusVerb, \"paused\" | \"active\" | \"archived\"> = {\n pause: \"paused\",\n resume: \"active\",\n archive: \"archived\",\n};\n\nexport function statusOps(entity: StatusEntity, ids: readonly string[], status: \"paused\" | \"active\" | \"archived\") {\n return ids.map((id) => ({ kind: `${entity}.update`, target: id, payload: { status } }));\n}\n\nconst STATUS_NOUN: Record<StatusEntity, { command: string; plural: string; example: string }> = {\n campaign: { command: \"campaigns\", plural: \"campaigns\", example: \"cmpn_123,cmpn_456\" },\n adGroup: { command: \"ad-groups\", plural: \"ad groups\", example: \"adgrp_123,adgrp_456\" },\n ad: { command: \"ads\", plural: \"cards\", example: \"ad_123,ad_456\" },\n};\n\nconst STATUS_DOING: Record<StatusVerb, string> = { pause: \"pausing\", resume: \"resuming\", archive: \"archiving\" };\n\n/** `pause`, `resume` or `archive` for every id passed, staged as one change each. */\nexport function statusCommand(entity: StatusEntity, verb: StatusVerb, reference: string) {\n const noun = STATUS_NOUN[entity];\n const args = {\n ids: { type: \"positional\", description: `${noun.plural} ids, comma-separated`, required: true },\n } as const;\n const forGood =\n verb === \"archive\"\n ? ` Archiving is for good: ChatGPT Ads cannot bring archived ${noun.plural} back, and their results stay in reports. Pause instead unless the user asked to archive.`\n : \"\";\n registerSchema({\n command: `ads.chatgpt.${noun.command}.${verb}`,\n description: `Stage ${STATUS_DOING[verb]} one or more ChatGPT Ads ${noun.plural}. Pass every id in one call.${forGood}`,\n args: schemaArgs(args),\n });\n return defineCommand({\n meta: {\n name: verb,\n description: `Stage ${STATUS_DOING[verb]} ${noun.plural}.${forGood}\n\nExample:\n baker ads chatgpt ${noun.command} ${verb} ${noun.example}`,\n },\n args,\n run: async ({ args: parsed }) => {\n await stageChatgptOps(statusOps(entity, requireTargets(parsed, \"ids\"), STATUS_OF[verb]), reference);\n },\n });\n}\n\n/**\n * Product filters as a marketer writes them: `brand in Acme|Baker; price lte 5000`\n * — conditions split by `;`, each field, operator and values (several joined\n * with `|`). `none` is no filter: the whole catalog.\n */\nexport function productFiltersArg(\n value: unknown,\n): Array<{ field: string; operator: string; values: string[] }> | undefined {\n if (typeof value !== \"string\" || value.trim() === \"\") {\n return undefined;\n }\n if (value.trim().toLowerCase() === \"none\") {\n return [];\n }\n return value\n .split(\";\")\n .map((condition) => condition.trim())\n .filter(Boolean)\n .map((condition) => {\n const match = /^(\\S+)\\s+(\\S+)\\s+(.+)$/.exec(condition);\n if (!match?.[1] || !match[2] || !match[3]) {\n failWriteValidation(\n `\"${condition}\" is not a product filter — write field operator values, e.g. price lte 5000`,\n );\n }\n return {\n field: match[1],\n operator: match[2].toLowerCase(),\n values: match[3]\n .split(\"|\")\n .map((part) => part.trim())\n .filter(Boolean),\n };\n });\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/ads/meta/write-shared.ts"],"sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { type MetaDraftStageResponse, metaDraftOpInputSchema } from \"@baker/api/ads-meta\";\nimport { apiPost } from \"../../../client.ts\";\nimport { requireChatId } from \"../../../env.ts\";\nimport { capabilityFix } from \"../../capabilities/fix.ts\";\nimport { booleanWordPositionalError } from \"../boolean-word-positional.ts\";\nimport { adCopyHints } from \"../copy-hints.ts\";\nimport { withHints } from \"../hints.ts\";\nimport { writeJsonEnvelope } from \"../output.ts\";\nimport { handleMetaError, resolveAccountIdArg } from \"./shared.ts\";\n\n/**\n * Shared plumbing for the staged Meta write commands. Writes NEVER hit Meta\n * directly: every command stages an op against this chat's draft\n * (`/api/ads/meta/draft/stage`), the dashboard shows it as a pending Meta\n * change, and it applies when the chat is published.\n */\n\n/** Backend account ids are bare numeric — strip the `act_` prefix resolveAccountIdArg adds. */\nexport function bareAccountId(args: Record<string, unknown>): string {\n return resolveAccountIdArg(args).replace(/^act_/, \"\");\n}\n\nexport function failWriteValidation(message: string): never {\n writeJsonEnvelope({ ok: false, error: { code: \"VALIDATION_ERROR\", message } });\n process.exit(1);\n}\n\n/** Deleting is permanent, so it only stages through `delete`, whose description carries that warning. */\nexport function refuseDeleteByUpdate(payload: Record<string, unknown>, group: \"campaigns\" | \"adsets\" | \"ads\"): void {\n if (payload.status === \"DELETED\") {\n failWriteValidation(\n `update does not delete — deleting is permanent. Use \\`baker ads meta ${group} delete <id>\\` if the user asked to delete; otherwise pause or archive.`,\n );\n }\n}\n\nexport function loadJsonFileArg(path: unknown): Record<string, unknown> {\n if (typeof path !== \"string\" || path.length === 0) {\n return {};\n }\n try {\n const parsed = JSON.parse(readFileSync(path, \"utf8\")) as unknown;\n if (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n failWriteValidation(`${path} must contain a JSON object`);\n }\n return parsed as Record<string, unknown>;\n } catch (err) {\n if (err instanceof SyntaxError) {\n failWriteValidation(`${path} is not valid JSON: ${err.message}`);\n }\n throw err;\n }\n}\n\n/** Flags override file keys — the file is the base, flags are the overrides. */\nexport function mergePayload(file: Record<string, unknown>, flags: Record<string, unknown>): Record<string, unknown> {\n const merged: Record<string, unknown> = { ...file };\n for (const [key, value] of Object.entries(flags)) {\n if (value !== undefined) {\n merged[key] = value;\n }\n }\n return merged;\n}\n\nexport function parseMoneyFlag(\n amount: unknown,\n currency: unknown,\n flag: string,\n): { amount: string; currencyCode?: string } | undefined {\n if (amount === undefined || amount === null || amount === \"\") {\n return undefined;\n }\n if (currency === undefined || currency === null || currency === \"\") {\n // Meta ad accounts are single-currency — the backend fills it in.\n return { amount: String(amount) };\n }\n if (typeof currency !== \"string\" || currency.length !== 3) {\n failWriteValidation(`${flag} got an invalid --currency (expected a 3-letter code like USD)`);\n }\n return { amount: String(amount), currencyCode: currency.toUpperCase() };\n}\n\n/** Accepts ISO dates (2026-07-10), ISO datetimes, or epoch millis. */\nexport function parseDateFlag(value: unknown, flag: string): number | undefined {\n if (value === undefined || value === null || value === \"\") {\n return undefined;\n }\n const raw = String(value);\n if (/^\\d{10,}$/.test(raw)) {\n return Number(raw);\n }\n const parsed = Date.parse(raw);\n if (Number.isNaN(parsed)) {\n failWriteValidation(`${flag} must be an ISO date (2026-07-10) or epoch milliseconds`);\n }\n return parsed;\n}\n\n/** Split a comma-separated flag into a trimmed, non-empty array. */\nexport function listFlag(value: unknown): string[] | undefined {\n if (typeof value !== \"string\" || value.trim().length === 0) {\n return undefined;\n }\n const items = value\n .split(\",\")\n .map((item) => item.trim())\n .filter(Boolean);\n return items.length > 0 ? items : undefined;\n}\n\nexport function upper(value: unknown): string | undefined {\n return typeof value === \"string\" && value.length > 0 ? value.toUpperCase() : undefined;\n}\n\nexport function numberFlag(value: unknown, flag: string): number | undefined {\n if (value === undefined || value === null || value === \"\") {\n return undefined;\n }\n const n = Number(value);\n if (!Number.isFinite(n)) {\n failWriteValidation(`${flag} must be a number`);\n }\n return n;\n}\n\n/**\n * Accepts whichever positional the command declared (`id`, `target`, `ref`) or the raw positional.\n *\n * `--flag false` is refused first: citty turns it into the flag set to TRUE plus a stray positional,\n * so on `campaigns duplicate 6123 --replace false` the copy stages AND the live original is staged\n * for pause — the opposite of what was typed, with an \"ok\" receipt. This is the only place on this\n * surface that reads positionals, and every target-taking command goes through it.\n */\nexport function requireTarget(args: Record<string, unknown>, entity: string): string {\n const inverted = booleanWordPositionalError(args, entity);\n if (inverted !== undefined) {\n failWriteValidation(inverted);\n }\n const positional = Array.isArray(args._) ? args._[0] : undefined;\n const target = args.id ?? args.target ?? args.ref ?? positional;\n if (typeof target !== \"string\" || target.length === 0) {\n failWriteValidation(`pass the ${entity} id as the positional argument`);\n }\n return target;\n}\n\ninterface StageEnvelope extends Record<string, unknown> {\n ok: true;\n data: MetaDraftStageResponse;\n}\n\n/**\n * Preflight-validates the op against the shared `@baker/api/ads-meta` contract\n * (same schema the backend enforces), then stages it. Prints the staged\n * envelope — ref, mode (always `live`: publishing reaches the real ad account),\n * summary, warnings.\n */\nexport async function stageOp(raw: Record<string, unknown>): Promise<void> {\n const preflight = metaDraftOpInputSchema.safeParse(raw);\n if (!preflight.success) {\n const fields = preflight.error.issues.map((issue) => ({ path: issue.path.join(\".\"), message: issue.message }));\n writeJsonEnvelope({\n ok: false,\n error: {\n code: \"VALIDATION_ERROR\",\n message: fields.map((field) => (field.path ? `${field.path}: ${field.message}` : field.message)).join(\"; \"),\n fields,\n fix: capabilityFix(\"meta-ads\"),\n },\n });\n process.exit(1);\n }\n try {\n const chatId = requireChatId();\n const response = await apiPost<StageEnvelope>(\"/api/ads/meta/draft/stage\", { chatId, op: preflight.data });\n const copyHints = await adCopyHints(preflight.data);\n writeJsonEnvelope(withHints(response, copyHints));\n } catch (err) {\n handleMetaError(err);\n }\n}\n\nexport async function stageStatusChange(input: {\n kind: \"campaign.update\" | \"adSet.update\" | \"adCreative.update\" | \"ad.update\" | \"customAudience.update\";\n accountId: string;\n target: string;\n status: \"ACTIVE\" | \"PAUSED\" | \"ARCHIVED\" | \"DELETED\";\n}): Promise<void> {\n await stageOp({\n kind: input.kind,\n accountId: input.accountId,\n target: input.target,\n payload: { status: input.status },\n });\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
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\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 };\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 };\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\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 },\n adsets: { row: compactAdSet, columns: ADSET_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":";;;;;;;;;;;;AAuBA,SAAS,KAAK,KAAc,MAAkC;AAC5D,QAAM,SAAkB,CAAC;AACzB,aAAW,OAAO,MAAM;AACtB,QAAI,IAAI,GAAG,MAAM,OAAW,QAAO,GAAG,IAAI,IAAI,GAAG;AAAA,EACnD;AACA,SAAO;AACT;AASA,IAAM,mBAAmB,CAAC,MAAM,QAAQ,oBAAoB,gBAAgB,mBAAmB,cAAc;AAE7G,SAAS,gBAAgB,KAAuB;AAC9C,QAAM,UAAU,IAAI;AACpB,SAAO;AAAA,IACL,GAAG,KAAK,KAAK,CAAC,MAAM,QAAQ,oBAAoB,gBAAgB,iBAAiB,CAAC;AAAA,IAClF,GAAI,OAAO,YAAY,WAAW,EAAE,cAAc,QAAQ,MAAM,GAAG,EAAE,EAAE,IAAI,CAAC;AAAA,EAC9E;AACF;AAEA,IAAM,aAAa;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AACF;AAEA,IAAM,gBAAgB,CAAC,GAAG,YAAY,kBAAkB,YAAY,cAAc;AAElF,SAAS,aAAa,KAAuB;AAC3C,QAAM,WAAW,SAAS,IAAI,mBAAmB,GAAG;AACpD,SAAO;AAAA,IACL,GAAG,KAAK,KAAK,UAAU;AAAA,IACvB,GAAI,OAAO,aAAa,WAAW,EAAE,gBAAgB,SAAS,IAAI,CAAC;AAAA,IACnE,GAAG,KAAK,KAAK,CAAC,YAAY,cAAc,CAAC;AAAA,EAC3C;AACF;AAEA,IAAM,aAAa;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGA,SAAS,SAAS,OAA0B;AAC1C,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO,CAAC;AACnC,SAAO,MAAM,QAAQ,CAAC,UAAU;AAC9B,UAAM,QAAQ,SAAS,KAAK;AAC5B,UAAM,OAAO,OAAO,iBAAiB,OAAO;AAC5C,WAAO,OAAO,SAAS,YAAY,OAAO,CAAC,IAAI,IAAI,CAAC;AAAA,EACtD,CAAC;AACH;AAEA,SAAS,UAAU,KAAuB;AACxC,QAAM,aAAa,SAAS,IAAI,QAAQ,GAAG;AAC3C,QAAM,SAAS,SAAS,IAAI,WAAW;AACvC,SAAO;AAAA,IACL,GAAG,KAAK,KAAK,CAAC,MAAM,QAAQ,YAAY,eAAe,kBAAkB,CAAC;AAAA,IAC1E,GAAI,eAAe,SAAY,EAAE,aAAa,WAAW,IAAI,CAAC;AAAA,IAC9D,GAAI,OAAO,SAAS,IAAI,EAAE,OAAO,IAAI,CAAC;AAAA,IACtC,GAAG,KAAK,KAAK,CAAC,cAAc,CAAC;AAAA,EAC/B;AACF;AAEA,IAAM,mBAAmB;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,SAAS,SAAS,OAAiD;AACjE,SAAO,UAAU,QAAQ,OAAO,UAAU,YAAY,OAAO,UAAU;AACzE;AAQO,SAAS,eAAe,WAAwC;AACrE,MAAI,OAAO,cAAc,SAAU,QAAO;AAC1C,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,SAAS;AAAA,EAC/B,QAAQ;AACN,WAAO;AAAA,EACT;AACA,QAAM,OAAO,SAAS,MAAM;AAE5B,MAAI,CAAC,QAAQ,EAAE,eAAe,SAAS,EAAE,eAAe,MAAO,QAAO;AACtE,QAAM,EAAE,WAAW,QAAQ,WAAW,MAAM,IAAI;AAChD,MAAI,CAAC,SAAS,MAAM,KAAK,CAAC,SAAS,KAAK,EAAG,QAAO;AAClD,QAAM,OAAO,CAAC,UAAmC,UAAU,OAAO,WAAW,OAAO,KAAK;AACzF,SAAO,GAAG,KAAK,MAAM,CAAC,WAAM,KAAK,KAAK,CAAC;AACzC;AAEA,SAAS,gBAAgB,KAAuB;AAC9C,QAAM,SAAS,eAAe,IAAI,UAAU;AAC5C,SAAO;AAAA,IACL,GAAG,KAAK,KAAK,CAAC,cAAc,cAAc,cAAc,eAAe,eAAe,WAAW,CAAC;AAAA,IAClG,GAAI,WAAW,SAAY,EAAE,OAAO,IAAI,CAAC;AAAA,EAC3C;AACF;AAEA,IAAM,cAAgE;AAAA,EACpE,WAAW,EAAE,KAAK,iBAAiB,SAAS,iBAAiB;AAAA,EAC7D,QAAQ,EAAE,KAAK,cAAc,SAAS,cAAc;AAAA,EACpD,KAAK,EAAE,KAAK,WAAW,SAAS,WAAW;AAAA,EAC3C,YAAY,EAAE,KAAK,iBAAiB,SAAS,iBAAiB;AAChE;AAEO,SAAS,kBAAkB,MAAoB,MAAiB,MAA2C;AAChH,SAAO,cAAc,MAAM,MAAM,YAAY,IAAI,CAAC;AACpD;AAEA,IAAM,QAAsC;AAAA,EAC1C,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,KAAK;AAAA,EACL,YAAY;AACd;AAMO,SAAS,kBAAkB,MAAoB,QAAoB,QAAgB,QAAkB,CAAC,GAAS;AACpH,MAAI,WAAW,QAAQ,OAAO,KAAK,WAAW,GAAG;AAC/C,YAAQ,OAAO,MAAM,GAAG,MAAM,SAAS,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,MAAM,IAAI,CAAC,WAAW;AAAA,CAAI;AAC9F;AAAA,EACF;AACA,iBAAe,OAAO,MAAM,QAAQ,OAAO,QAAQ,CAAC,GAAG,OAAO,GAAI,OAAO,SAAS,CAAC,CAAE,CAAC;AACxF;AAGO,IAAM,uBAAuB;AAAA,EAClC,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AAAA,EACA,MAAM,EAAE,MAAM,WAAW,aAAa,2EAA2E;AAAA,EACjH,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,EACX;AACF;AAaO,SAAS,uBACd,MACA,aACA,MACM;AACN,iBAAe;AAAA,IACb,SAAS,YAAY,IAAI;AAAA,IACzB;AAAA,IACA,MAAM,OAAO;AAAA,MACX,OAAO,QAAQ,IAAI,EAAE,IAAI,CAAC,CAAC,MAAM,GAAG,MAAM;AAAA,QACxC;AAAA,QACA;AAAA,UACE,MAAM,IAAI;AAAA,UACV,aAAa,IAAI,eAAe;AAAA,UAChC,UAAU;AAAA,UACV,GAAI,IAAI,YAAY,SAAY,EAAE,SAAS,IAAI,QAAQ,IAAI,CAAC;AAAA,QAC9D;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AACH;","names":[]}