@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":["../../api/src/ads-meta/adStudies.ts","../../api/src/ads-meta/limits.ts"],"sourcesContent":["/**\n * Meta A/B tests (ad studies, `POST /{business_id}/ad_studies`) — the staged contract.\n *\n * A split test divides one audience into non-overlapping groups and shows each\n * group one version — an ad set or a campaign — so the versions are compared\n * on people who saw only that one. Meta owns the split, the measurement and the\n * verdict; Baker stages the test and creates it at Publish.\n *\n * The payload keeps Meta's own shape — `cells[{name, treatment_percentage,\n * adsets|campaigns}]`, unix-second times, `confidence_level` as 0.8/0.9/0.95 —\n * so a test read with `baker ads meta studies --study-id` reads back the way it\n * was staged.\n *\n * Meta's API takes far more than Ads Manager does (live, v25.0, 2026-10-14: a\n * one-cell test, cells summing to 80, a 5% cell, a one-hour or 100-day test,\n * the same ad set in both cells, and an ad-set cell beside a campaign cell were\n * all created). Each of those is a test that cannot answer its question, so the\n * refusals below are Ads Manager's rules for an A/B test, not the API's, and\n * each one says why. The API's own refusals are marked \"live\".\n */\nimport { z } from \"zod\";\nimport { NUMERIC_ID_REGEX, TEMP_REF_REGEX } from \"./limits\";\n\nconst DAY_SECONDS = 86_400;\n\nconst entityRefSchema = z.string().refine((value) => NUMERIC_ID_REGEX.test(value) || TEMP_REF_REGEX.test(value), {\n message: \"expected a numeric Meta id or a meta_temp_* reference from this chat\",\n});\n\nexport const adStudyCellSchema = z.strictObject({\n name: z.string().min(1).max(100),\n /** Share of the audience that sees this version, in percent. */\n treatment_percentage: z.number().positive().max(100),\n /** A lift study: the share of the audience held out from the ads, so what they do is the baseline. */\n control_percentage: z.number().positive().max(100).optional(),\n adsets: z.array(entityRefSchema).min(1).max(100).optional(),\n campaigns: z.array(entityRefSchema).min(1).max(100).optional(),\n /** A creative test: the one ad this version runs. */\n ads: z.array(entityRefSchema).min(1).max(100).optional(),\n});\nexport type AdStudyCell = z.infer<typeof adStudyCellSchema>;\n\n/** Live: Meta refuses any other value (\"Confidence interval value must be 0.8, 0.9, or 0.95\"). */\nexport const AD_STUDY_CONFIDENCE_LEVELS = [0.8, 0.9, 0.95] as const;\nconst confidenceLevelSchema = z\n .number()\n .refine((value) => (AD_STUDY_CONFIDENCE_LEVELS as readonly number[]).includes(value), {\n message: \"confidence_level must be 0.8, 0.9 or 0.95 (80%, 90% or 95%)\",\n });\n\nconst eventSourceSchema = z.strictObject({\n id: z.string().regex(NUMERIC_ID_REGEX),\n /** Pixel or app events counted, e.g. Lead, Purchase. Meta stores pixel events by their standard name. */\n event_names: z.array(z.string().min(1)).min(1).optional(),\n});\n\n/** What a split test is decided on. Meta's other objective types (SALES, BRAND, …) belong to lift studies. */\nexport const AD_STUDY_OBJECTIVE_TYPES = [\n \"CONVERSIONS\",\n \"SALES\",\n \"NONSALES\",\n \"BRAND\",\n \"BRANDLIFT\",\n \"MAE\",\n \"MAI\",\n] as const;\n\nexport const adStudyObjectiveSchema = z.strictObject({\n name: z.string().min(1).max(100),\n /** A split test is decided on CONVERSIONS; a lift study may measure sales, brand, app events (Meta's types). */\n type: z.enum(AD_STUDY_OBJECTIVE_TYPES).default(\"CONVERSIONS\"),\n is_primary: z.boolean().optional(),\n adspixels: z.array(eventSourceSchema).min(1).optional(),\n customconversions: z.array(eventSourceSchema).min(1).optional(),\n applications: z.array(eventSourceSchema).min(1).optional(),\n offsite_datasets: z.array(eventSourceSchema).min(1).optional(),\n});\nexport type AdStudyObjective = z.infer<typeof adStudyObjectiveSchema>;\n\nconst OBJECTIVE_SOURCES = [\"adspixels\", \"customconversions\", \"applications\", \"offsite_datasets\"] as const;\n\nexport interface AdStudyIssue {\n path: PropertyKey[];\n message: string;\n}\n\n/** Ads Manager's limits; Meta's API documents up to 150 cells of up to 100 objects. */\nexport const AD_STUDY_MIN_CELLS = 2;\nexport const AD_STUDY_MAX_CELLS = 150;\n\n/** The ad sets, campaigns or ads a version runs. */\nexport function cellObjects(cell: Pick<AdStudyCell, \"adsets\" | \"campaigns\" | \"ads\">): string[] {\n return [...(cell.adsets ?? []), ...(cell.campaigns ?? []), ...(cell.ads ?? [])];\n}\n\nexport type AdStudyLevel = \"adsets\" | \"campaigns\" | \"ads\";\n\n/** What the versions are — ad sets, campaigns or ads — or undefined while they disagree. */\nexport function adStudyLevel(\n cells: readonly Pick<AdStudyCell, \"adsets\" | \"campaigns\" | \"ads\">[],\n): AdStudyLevel | undefined {\n const levels = new Set(\n cells.flatMap((cell) =>\n [cell.adsets ? \"adsets\" : [], cell.campaigns ? \"campaigns\" : [], cell.ads ? \"ads\" : []].flat(),\n ),\n );\n return levels.size === 1 ? ([...levels][0] as AdStudyLevel) : undefined;\n}\n\nfunction levelIssues(cells: readonly AdStudyCell[]): AdStudyIssue[] {\n const issues: AdStudyIssue[] = [];\n cells.forEach((cell, index) => {\n if (cellObjects(cell).length === 0) {\n issues.push({\n path: [\"cells\", index],\n message: `version \"${cell.name}\" runs nothing — give it the ad sets (adsets) or campaigns (campaigns) it shows`,\n });\n }\n });\n if (cells.some((cell) => cell.ads)) {\n issues.push({\n path: [\"cells\"],\n message:\n 'an A/B test compares ad sets or campaigns — to compare single ads of one ad set, stage a creative test (type \"SPLIT_TEST_V2\", `--type creative`)',\n });\n }\n const named = cells.filter((cell) => cellObjects(cell).length > 0);\n if (named.length > 0 && adStudyLevel(named) === undefined) {\n issues.push({\n path: [\"cells\"],\n message:\n \"the versions must be all ad sets or all campaigns — comparing an ad set with a campaign compares two different things\",\n });\n }\n return issues;\n}\n\nfunction duplicateObjectIssues(cells: readonly AdStudyCell[]): AdStudyIssue[] {\n const seen = new Map<string, number>();\n const issues: AdStudyIssue[] = [];\n cells.forEach((cell, index) => {\n for (const id of cellObjects(cell)) {\n const first = seen.get(id);\n if (first !== undefined && first !== index) {\n issues.push({\n path: [\"cells\", index],\n message: `${id} is in more than one version — each version must run its own ad sets or campaigns, or it is compared with itself`,\n });\n }\n seen.set(id, first ?? index);\n }\n });\n return issues;\n}\n\nfunction shareIssues(cells: readonly { treatment_percentage: number }[]): AdStudyIssue[] {\n const total = Math.round(cells.reduce((sum, cell) => sum + cell.treatment_percentage, 0) * 100) / 100;\n if (total === 100) {\n return [];\n }\n // Live: Meta refuses more than 100 (1840025) and creates anything under it.\n return [\n {\n path: [\"cells\"],\n message: `the versions' shares must add up to 100% (now ${total}%) — every person in the test sees exactly one version`,\n },\n ];\n}\n\nfunction cellIssues(cells: readonly AdStudyCell[]): AdStudyIssue[] {\n if (cells.length < AD_STUDY_MIN_CELLS) {\n return [\n {\n path: [\"cells\"],\n message: `an A/B test needs at least 2 versions (cells) — with ${cells.length} there is nothing to compare`,\n },\n ];\n }\n const issues: AdStudyIssue[] = [...shareIssues(cells)];\n issues.push(...levelIssues(cells), ...duplicateObjectIssues(cells));\n return issues;\n}\n\n/**\n * Ads Manager runs an A/B test for 1 to 30 days and recommends at least 7.\n * Meta's API created a one-hour and a 100-day test (live): neither is one Meta\n * can call — an hour reaches nobody, and past a month the audience the test\n * started with has changed under it.\n */\nexport const AD_STUDY_MIN_DAYS = 1;\nexport const AD_STUDY_MAX_DAYS = 30;\nexport const AD_STUDY_RECOMMENDED_DAYS = 7;\n\nexport function adStudyDays(startTime: number, endTime: number): number {\n return Math.round(((endTime - startTime) / DAY_SECONDS) * 10) / 10;\n}\n\nexport function scheduleIssues(startTime: number, endTime: number): AdStudyIssue[] {\n if (endTime <= startTime) {\n return [{ path: [\"end_time\"], message: \"the test ends before it starts — end_time must be after start_time\" }];\n }\n const days = adStudyDays(startTime, endTime);\n if (endTime - startTime < AD_STUDY_MIN_DAYS * DAY_SECONDS) {\n return [{ path: [\"end_time\"], message: `an A/B test runs for at least 1 day (this one: ${days} days)` }];\n }\n if (endTime - startTime > AD_STUDY_MAX_DAYS * DAY_SECONDS) {\n return [\n {\n path: [\"end_time\"],\n message: `an A/B test runs for at most 30 days, as in Ads Manager (this one: ${days} days) — split a longer question into two tests`,\n },\n ];\n }\n return [];\n}\n\nfunction objectiveIssues(objectives: readonly AdStudyObjective[] | undefined): AdStudyIssue[] {\n if (!objectives || objectives.length === 0) {\n return [];\n }\n const issues: AdStudyIssue[] = [];\n objectives.forEach((objective, index) => {\n if (!OBJECTIVE_SOURCES.some((source) => objective[source] !== undefined)) {\n issues.push({\n path: [\"objectives\", index],\n message: `measure \"${objective.name}\" counts nothing — give it a pixel event (adspixels), a custom conversion (customconversions) or an app event (applications)`,\n });\n }\n });\n const primaries = objectives.filter((objective) => objective.is_primary === true).length;\n const implicitPrimary = objectives.length === 1 && objectives[0]?.is_primary === undefined;\n if (primaries !== 1 && !implicitPrimary) {\n issues.push({\n path: [\"objectives\"],\n message: `a test is decided on exactly one primary measure (is_primary: true) — ${primaries} are marked`,\n });\n }\n return issues;\n}\n\n/**\n * A lift study measures what the ads ADD: each cell holds a share of its\n * audience out (`control_percentage`) and compares it with the share that\n * sees the ads. One cell is a whole study. Live on v26.0 (2026-10-15) Meta\n * created a one-cell 90/10 conversion lift study on a campaign of\n * act_1342210013621203 once it named `observation_end_time` (≥ the end,\n * 1840009) and `cooldown_start_time` (1840013) — Baker fills both.\n */\nexport const LIFT_MAX_DAYS = 90;\n\n/** Meta subcode 1840009: a lift study or creative test is read until it ends, at the least. */\nfunction observationEndIssues(\n study: Pick<AdStudyCreate, \"end_time\"> & Partial<Pick<AdStudyCreate, \"observation_end_time\">>,\n): AdStudyIssue[] {\n if (study.observation_end_time === undefined || study.observation_end_time >= study.end_time) return [];\n return [\n {\n path: [\"observation_end_time\"],\n message: \"observation_end_time must run at least until the study ends (end_time) — Meta reads results until then\",\n },\n ];\n}\n\nfunction liftIssues(\n study: Pick<AdStudyCreate, \"cells\" | \"start_time\" | \"end_time\" | \"objectives\"> &\n Partial<Pick<AdStudyCreate, \"observation_end_time\">>,\n): AdStudyIssue[] {\n const issues: AdStudyIssue[] = [];\n if (study.cells.length === 0) issues.push({ path: [\"cells\"], message: \"a lift study needs at least one cell\" });\n study.cells.forEach((cell, index) => {\n const total = cell.treatment_percentage + (cell.control_percentage ?? 0);\n if (cell.control_percentage === undefined) {\n issues.push({\n path: [\"cells\", index, \"control_percentage\"],\n message: `cell \"${cell.name}\" holds nobody out — give it a control_percentage (the people who do not see the ads)`,\n });\n } else if (total > 100) {\n issues.push({\n path: [\"cells\", index],\n message: `cell \"${cell.name}\" splits ${total}% of its audience — at most 100%`,\n });\n }\n if (cell.ads)\n issues.push({\n path: [\"cells\", index, \"ads\"],\n message: \"a lift study measures campaigns or ad sets, not single ads\",\n });\n else if (!cell.campaigns && !cell.adsets)\n issues.push({\n path: [\"cells\", index],\n message: `cell \"${cell.name}\" runs nothing — give it the campaigns (campaigns) or ad sets (adsets) whose lift it measures`,\n });\n });\n issues.push(...observationEndIssues(study));\n if (!study.objectives || study.objectives.length === 0) {\n issues.push({\n path: [\"objectives\"],\n message: \"a lift study needs a measure — the pixel event or conversion whose lift it reads\",\n });\n }\n if (study.end_time <= study.start_time) {\n issues.push({ path: [\"end_time\"], message: \"the study ends before it starts\" });\n } else if (study.end_time - study.start_time > LIFT_MAX_DAYS * DAY_SECONDS) {\n issues.push({ path: [\"end_time\"], message: \"a lift study runs for at most 90 days\" });\n }\n return [...issues, ...duplicateObjectIssues(study.cells), ...objectiveIssues(study.objectives)].filter(\n (issue, index, all) => all.findIndex((other) => other.message === issue.message) === index,\n );\n}\n\n/**\n * A creative test (`SPLIT_TEST_V2`): 2 to 5 ads of ONE ad set, each version\n * one ad, compared on a share of the ad set's budget (`testDailyBudget`, sent\n * as `creative_test_config.daily_budget`). Live on v26.0 (2026-10-15) Meta\n * created one over two paused ads of a €5/day ad set with a €2 test budget,\n * and refused `lifetime_budget_percentage` on that daily-budget ad set\n * (5024025 \"does not align with the campaign's budget\").\n */\nexport const CREATIVE_TEST_MIN_CELLS = 2;\nexport const CREATIVE_TEST_MAX_CELLS = 5;\n\nfunction creativeTestIssues(\n study: Pick<AdStudyCreate, \"cells\" | \"start_time\" | \"end_time\" | \"testDailyBudget\"> &\n Partial<Pick<AdStudyCreate, \"observation_end_time\">>,\n): AdStudyIssue[] {\n const issues: AdStudyIssue[] = [];\n if (study.cells.length < CREATIVE_TEST_MIN_CELLS || study.cells.length > CREATIVE_TEST_MAX_CELLS) {\n issues.push({ path: [\"cells\"], message: `a creative test compares 2 to 5 ads (now ${study.cells.length})` });\n }\n study.cells.forEach((cell, index) => {\n if (cell.ads?.length !== 1 || cell.adsets || cell.campaigns) {\n issues.push({ path: [\"cells\", index], message: `version \"${cell.name}\" runs exactly one ad (ads: [<ad id>])` });\n }\n });\n if (!study.testDailyBudget) {\n issues.push({\n path: [\"testDailyBudget\"],\n message: \"a creative test needs testDailyBudget — the part of the ad set's daily budget the test spends\",\n });\n }\n return [\n ...issues,\n ...shareIssues(study.cells),\n ...duplicateObjectIssues(study.cells),\n ...scheduleIssues(study.start_time, study.end_time),\n ...observationEndIssues(study),\n ];\n}\n\n/** Everything wrong with a test as it would be created, in the words a refusal reads. */\nexport function adStudyIssues(\n study: Pick<AdStudyCreate, \"cells\" | \"start_time\" | \"end_time\" | \"objectives\"> &\n Partial<Pick<AdStudyCreate, \"type\" | \"testDailyBudget\" | \"observation_end_time\">>,\n): AdStudyIssue[] {\n if (study.type === \"LIFT\") return liftIssues(study);\n if (study.type === \"SPLIT_TEST_V2\") return creativeTestIssues(study);\n return [\n ...cellIssues(study.cells),\n ...scheduleIssues(study.start_time, study.end_time),\n ...objectiveIssues(study.objectives),\n ];\n}\n\nfunction addIssues(issues: readonly AdStudyIssue[], ctx: z.RefinementCtx): void {\n for (const issue of issues) {\n ctx.addIssue({ code: \"custom\", path: issue.path, message: issue.message });\n }\n}\n\n/** A split (A/B) test, a lift study, or a creative test of single ads. */\nexport const AD_STUDY_TYPES = [\"SPLIT_TEST\", \"LIFT\", \"SPLIT_TEST_V2\"] as const;\n\nconst adStudyCreateBaseSchema = z.strictObject({\n name: z.string().min(1).max(255),\n description: z.string().max(1000).optional(),\n type: z.enum(AD_STUDY_TYPES).default(\"SPLIT_TEST\"),\n start_time: z.number().int().positive(),\n end_time: z.number().int().positive(),\n /** A lift study or creative test: when Meta stops counting results (≥ the end). Defaults to the end. */\n observation_end_time: z.number().int().positive().optional(),\n /** A creative test: the part of the ad set's daily budget it spends, major units. */\n testDailyBudget: z\n .strictObject({\n amount: z.string().regex(/^\\d+(\\.\\d{1,2})?$/, \"expected a decimal amount like 2 or 2.50\"),\n currencyCode: z.string().length(3).optional(),\n })\n .optional(),\n cells: z.array(adStudyCellSchema).max(AD_STUDY_MAX_CELLS),\n /** How sure Meta must be before it names a winner; Meta applies its own when none is sent. */\n confidence_level: confidenceLevelSchema.optional(),\n /** What the test is decided on. Without one, Meta compares cost per result on the campaigns' objective. */\n objectives: z.array(adStudyObjectiveSchema).max(10).optional(),\n /** The Business that owns the test — Meta creates studies on a Business. Filled by the backend from the ad account. */\n business_id: z.string().regex(NUMERIC_ID_REGEX).optional(),\n});\nexport type AdStudyCreate = z.infer<typeof adStudyCreateBaseSchema>;\n\nexport const adStudyCreateSchema = adStudyCreateBaseSchema.superRefine((study, ctx) =>\n addIssues(adStudyIssues(study), ctx),\n);\n\n/** Within this long of its start, a test may be published too late — Meta then refuses it (1840012). */\nconst START_SOON_SECONDS = 6 * 3600;\n\n/** Non-blocking notes on a staged test: things Meta takes but a marketer should know. */\nexport function adStudyWarnings(study: AdStudyCreate, nowSeconds: number): string[] {\n const warnings: string[] = [];\n if (study.end_time - study.start_time < AD_STUDY_RECOMMENDED_DAYS * DAY_SECONDS) {\n warnings.push(\n `this test runs ${adStudyDays(study.start_time, study.end_time)} days — Meta recommends at least 7 days for a result it can call`,\n );\n }\n if (study.start_time - nowSeconds < START_SOON_SECONDS) {\n warnings.push(\n \"this test starts within 6 hours — publish before then, or Meta refuses it because its start has passed\",\n );\n }\n for (const cell of study.cells) {\n if (cell.treatment_percentage < SMALL_VERSION_PERCENT) {\n warnings.push(\n `${cell.name} gets ${cell.treatment_percentage}% of the audience — Meta takes it, but a version under ${SMALL_VERSION_PERCENT}% rarely gathers enough results for Meta to call a winner (Meta's guidance is at least ${SMALL_VERSION_PERCENT}% per version)`,\n );\n }\n }\n return warnings;\n}\n\n/**\n * Below this share a version is warned about, not refused: live on v25.0\n * (2026-10-14) Meta created a test split 95/5, against its own guidance of at\n * least 10% per version.\n */\nconst SMALL_VERSION_PERCENT = 10;\n\n// --- Update ---\n\n/** A live version's new share, named by its cell id (`studies --study-id` lists them). */\nexport const adStudyCellShareSchema = z.strictObject({\n id: z.string().regex(NUMERIC_ID_REGEX),\n treatment_percentage: z.number().positive().max(100),\n});\n\n/**\n * What a live test takes, from Meta's update reference and what it answered\n * live. Once a test has started its start and its split are fixed (1840011,\n * live), so those are refused at staging against the test as it stands; its\n * name, description and end move freely, and the end can move later again\n * even after the test has ended (live).\n */\nconst adStudyUpdateBaseSchema = z.strictObject({\n name: z.string().min(1).max(255).optional(),\n description: z.string().max(1000).optional(),\n start_time: z.number().int().positive().optional(),\n end_time: z.number().int().positive().optional(),\n /** A lift study or creative test: when Meta stops counting results (≥ the end). Moved out with a later end on its own (`carryObservationEnd`). */\n observation_end_time: z.number().int().positive().optional(),\n /** End the test at publish: the end is set a few minutes after the change applies (Meta refuses an end in the past). */\n end_now: z.literal(true).optional(),\n confidence_level: confidenceLevelSchema.optional(),\n /** Every version's new share — Meta re-splits the whole audience at once, so name every cell. */\n cells: z.array(adStudyCellShareSchema).min(AD_STUDY_MIN_CELLS).optional(),\n /** Delete the test. Meta removes it, results and all; ending it keeps them. */\n status: z.literal(\"DELETED\").optional(),\n});\nexport type AdStudyUpdate = z.infer<typeof adStudyUpdateBaseSchema>;\n\nfunction updateShapeIssues(p: AdStudyUpdate): AdStudyIssue[] {\n const set = Object.entries(p).filter(([, value]) => value !== undefined);\n if (set.length === 0) {\n return [{ path: [], message: \"update needs at least one field\" }];\n }\n if (p.status === \"DELETED\" && set.length > 1) {\n return [{ path: [\"status\"], message: \"delete alone — a deleted test takes no other change\" }];\n }\n const issues: AdStudyIssue[] = [];\n if (p.end_now && p.end_time !== undefined) {\n issues.push({ path: [\"end_now\"], message: \"end now or set end_time, not both\" });\n }\n if (p.observation_end_time !== undefined && p.end_time !== undefined && p.observation_end_time < p.end_time) {\n issues.push({\n path: [\"observation_end_time\"],\n message: \"observation_end_time must run at least until the study ends (end_time) — Meta reads results until then\",\n });\n }\n if (p.cells) {\n issues.push(...shareIssues(p.cells));\n const ids = p.cells.map((cell) => cell.id);\n if (new Set(ids).size !== ids.length) {\n issues.push({ path: [\"cells\"], message: \"each version's share is given once\" });\n }\n }\n return issues;\n}\n\nexport const adStudyUpdateSchema = adStudyUpdateBaseSchema.superRefine((p, ctx) =>\n addIssues(updateShapeIssues(p), ctx),\n);\n\n/**\n * Room a publish needs between the check and Meta's call: the merge, the\n * workflow's queue and the ops staged ahead of the test all run first.\n */\nexport const AD_STUDY_PUBLISH_MARGIN_SECONDS = 600;\n\n/**\n * Why a staged test's times no longer hold at publish, or undefined. Staging\n * checked them against the moment it ran; a chat published a day later meets\n * Meta's own refusal (1840012) after the merge, when nothing can be fixed. So\n * publish holds the change back first, with what to do.\n */\nexport function adStudyPublishTimeBlocker(\n kind: \"adStudy.create\" | \"adStudy.update\",\n payload: Pick<AdStudyUpdate, \"start_time\" | \"end_time\">,\n nowSeconds: number,\n): string | undefined {\n const deadline = nowSeconds + AD_STUDY_PUBLISH_MARGIN_SECONDS;\n if (payload.start_time !== undefined && payload.start_time <= deadline) {\n return kind === \"adStudy.create\"\n ? \"this A/B test's start has passed (or is minutes away) since it was staged, and Meta refuses a test that starts in the past — re-stage it with a later start\"\n : \"this test's new start has passed (or is minutes away) since it was staged, and Meta refuses a start in the past — re-stage the change with a later start\";\n }\n if (payload.end_time !== undefined && payload.end_time <= deadline) {\n return \"this test's new end has passed (or is minutes away) since it was staged, and Meta refuses an end in the past — re-stage it with a later end, or end the test now (`studies end`)\";\n }\n return undefined;\n}\n\n// --- References, wire, reads ---\n\nexport type AdStudyRefEntity = \"adSet\" | \"campaign\" | \"ad\";\n\n/** The meta_temp_* refs a test's versions name — the ad sets and campaigns this chat creates first. */\nconst CELL_REF_ENTITIES = [\n [\"ads\", \"ad\"],\n [\"adsets\", \"adSet\"],\n [\"campaigns\", \"campaign\"],\n] as const;\n\nexport function adStudyTempRefs(\n cells: readonly Pick<AdStudyCell, \"adsets\" | \"campaigns\" | \"ads\">[] | undefined,\n): { ref: string; entity: AdStudyRefEntity }[] {\n return (cells ?? []).flatMap((cell) =>\n CELL_REF_ENTITIES.flatMap(([key, entity]) =>\n (cell[key] ?? []).filter((id) => TEMP_REF_REGEX.test(id)).map((ref) => ({ ref, entity })),\n ),\n );\n}\n\n/** A live cell as Meta returns it: id lists wrapped in `{data: [{id, name}]}`. */\ninterface WireCell {\n id?: unknown;\n name?: unknown;\n treatment_percentage?: unknown;\n control_percentage?: unknown;\n adsets?: { data?: { id?: unknown; name?: unknown }[] };\n campaigns?: { data?: { id?: unknown; name?: unknown }[] };\n ads?: { data?: { id?: unknown; name?: unknown }[] };\n}\n\n/** A live test in staged vocabulary, with the names of what its versions run. */\nexport interface AdStudySnapshot {\n id: string;\n name?: string;\n description?: string;\n type?: string;\n start_time?: number;\n end_time?: number;\n /** A lift study or creative test: when Meta stops counting results (≥ the end). */\n observation_end_time?: number;\n business_id?: string;\n cells: (AdStudyCell & { id: string })[];\n objectives?: AdStudyObjective[];\n names: Record<string, string>;\n}\n\n/** Meta's ISO time (`2026-10-16T14:28:53+0000`) as unix seconds. */\nexport function unixSeconds(value: unknown): number | undefined {\n if (typeof value === \"number\") {\n return value > 1e12 ? Math.floor(value / 1000) : value;\n }\n if (typeof value !== \"string\" || value === \"\") {\n return undefined;\n }\n const iso = value.replace(/([+-]\\d{2})(\\d{2})$/, \"$1:$2\");\n const ms = Date.parse(iso);\n return Number.isNaN(ms) ? undefined : Math.floor(ms / 1000);\n}\n\nfunction wireIds(edge: WireCell[\"adsets\"], names: Record<string, string>): string[] | undefined {\n const rows = edge?.data;\n if (!rows || rows.length === 0) {\n return undefined;\n }\n return rows.flatMap((row) => {\n if (typeof row.id !== \"string\") return [];\n if (typeof row.name === \"string\") names[row.id] = row.name;\n return [row.id];\n });\n}\n\nfunction text(value: unknown): string | undefined {\n return typeof value === \"string\" && value !== \"\" ? value : undefined;\n}\n\nfunction wireSources(edge: unknown): { id: string; event_names?: string[] }[] | undefined {\n const rows = (edge as { data?: { id?: unknown; event_names?: unknown }[] } | undefined)?.data;\n if (!rows || rows.length === 0) {\n return undefined;\n }\n return rows.map((row) => ({\n id: String(row.id ?? \"\"),\n ...(Array.isArray(row.event_names) && row.event_names.length > 0\n ? { event_names: row.event_names.map(String) }\n : {}),\n }));\n}\n\nfunction objectivesFromWire(edge: unknown): AdStudyObjective[] | undefined {\n const rows = (edge as { data?: Record<string, unknown>[] } | undefined)?.data;\n if (!rows || rows.length === 0) {\n return undefined;\n }\n return rows.map((row) => {\n const objective: AdStudyObjective = {\n name: String(row.name ?? \"\"),\n type: \"CONVERSIONS\",\n ...(typeof row.is_primary === \"boolean\" ? { is_primary: row.is_primary } : {}),\n };\n for (const source of OBJECTIVE_SOURCES) {\n const sources = wireSources(row[source]);\n if (sources) objective[source] = sources;\n }\n return objective;\n });\n}\n\nexport function adStudyFromWire(node: Record<string, unknown>): AdStudySnapshot {\n const names: Record<string, string> = {};\n const cellRows = ((node.cells as { data?: WireCell[] } | undefined)?.data ?? []) as WireCell[];\n const cells = cellRows.map((cell) => {\n const adsets = wireIds(cell.adsets, names);\n const campaigns = wireIds(cell.campaigns, names);\n const ads = wireIds(cell.ads, names);\n return {\n id: String(cell.id ?? \"\"),\n name: String(cell.name ?? \"\"),\n treatment_percentage: Number(cell.treatment_percentage ?? 0),\n ...(typeof cell.control_percentage === \"number\" ? { control_percentage: cell.control_percentage } : {}),\n ...(adsets ? { adsets } : {}),\n ...(campaigns ? { campaigns } : {}),\n ...(ads ? { ads } : {}),\n };\n });\n const out: AdStudySnapshot = { id: String(node.id ?? \"\"), cells, names };\n const fields: Array<[keyof AdStudySnapshot, unknown]> = [\n [\"name\", text(node.name)],\n [\"description\", text(node.description)],\n [\"type\", text(node.type)],\n [\"start_time\", unixSeconds(node.start_time)],\n [\"end_time\", unixSeconds(node.end_time)],\n [\"observation_end_time\", unixSeconds(node.observation_end_time)],\n [\"business_id\", text((node.business as { id?: unknown } | undefined)?.id)],\n [\"objectives\", objectivesFromWire(node.objectives)],\n ];\n for (const [key, value] of fields) {\n if (value !== undefined) (out as unknown as Record<string, unknown>)[key] = value;\n }\n return out;\n}\n\n/**\n * A staged test as Meta takes it on create: the Business is the path, not a\n * field, and a lone measure is the primary one — Meta decides on the primary.\n */\nexport function adStudyCreateToWire(p: AdStudyCreate): Record<string, unknown> {\n const { business_id: _business, objectives, testDailyBudget: _budget, observation_end_time, ...study } = p;\n const lonePrimary = objectives?.length === 1 && objectives[0]?.is_primary === undefined;\n // A lift study and a creative test both need these two; Meta's own\n // creative-test guide sets them to the start and the end.\n const windows =\n p.type === \"SPLIT_TEST\"\n ? {}\n : { cooldown_start_time: p.start_time, observation_end_time: observation_end_time ?? p.end_time };\n return {\n ...study,\n ...windows,\n ...(objectives ? { objectives: lonePrimary ? [{ ...objectives[0], is_primary: true }] : objectives } : {}),\n };\n}\n\n/**\n * \"End now\" lands this far after the change applies. Meta refuses an end in\n * the past, and refused one two seconds ahead (live) — the clock it checks\n * against runs ahead of the request.\n */\nexport const AD_STUDY_END_NOW_LEAD_SECONDS = 300;\n\n/** A staged change as Meta takes it on `POST /{study_id}`; `nowSeconds` places an \"end now\". */\n/**\n * A lift study or creative test counts results until its observation end, and\n * Meta refuses an end after it (1840009, as on create). So a later end moves\n * the observation end out with it, staged where the review shows it; an A/B\n * test has none, and an observation end the change names is kept.\n */\nexport function carryObservationEnd(\n update: AdStudyUpdate,\n live: Pick<AdStudySnapshot, \"type\" | \"observation_end_time\">,\n): AdStudyUpdate {\n const counting = live.observation_end_time;\n if (\n live.type === \"SPLIT_TEST\" ||\n counting === undefined ||\n update.observation_end_time !== undefined ||\n update.end_time === undefined ||\n update.end_time <= counting\n ) {\n return update;\n }\n return { ...update, observation_end_time: update.end_time };\n}\n\nexport function adStudyUpdateToWire(p: AdStudyUpdate, nowSeconds: number): Record<string, unknown> {\n const { end_now, status: _status, ...fields } = p;\n return end_now ? { ...fields, end_time: nowSeconds + AD_STUDY_END_NOW_LEAD_SECONDS } : fields;\n}\n","/**\n * Single source of truth for Meta Marketing API write constraints\n * (Graph API v25.0). Every zod schema in `ops.ts` reads from here — no\n * scattered literals. The naming follows Meta's object graph: Campaign →\n * Ad Set → Ad Creative → Ad, plus Custom Audiences and media.\n */\n\nexport const META_LIMITS = {\n /** Meta caps the labels on one object at 50 (`adlabels`, \"max 50\"); it documents no name length, so 255. */\n adLabel: {\n nameMax: 255,\n perObjectMax: 50,\n },\n campaign: {\n nameMax: 400,\n },\n adSet: {\n nameMax: 400,\n /**\n * Meta's own bounds for a minimum ROAS, as a multiple of spend (2 = 200%):\n * \"roas_average_floor … should be larger than or equal to 0.001 and smaller\n * than or equal to 1000\" (subcode 1815888, live on v25.0, 2026-10-14).\n */\n minRoasMin: 0.001,\n minRoasMax: 1000,\n /** Frequency caps: `interval_days` and `max_frequency` are each 1–90 (Meta's #100 refusal, live v25.0). */\n frequencyIntervalDaysMax: 90,\n frequencyMaxImpressionsMax: 90,\n /** \"You can set up a maximum of 50 high demand periods per campaign or ad set\" (High Demand Period reference). */\n budgetSchedulesMax: 50,\n },\n ad: {\n nameMax: 400,\n },\n creative: {\n nameMax: 400,\n /** Feed truncates the primary text past this with \"… See more\". */\n messageSoftMax: 125,\n messageHardMax: 5000,\n /** Below this, primary text reads as too thin to carry a hook + value + reason to act. */\n messageGoodMin: 40,\n headlineMax: 255,\n descriptionMax: 300,\n carouselCardsMin: 2,\n carouselCardsMax: 10,\n /** Carousels tell a fuller story and give Meta more to optimize at this many cards. */\n carouselCardsGoodMin: 3,\n dynamicTextsMin: 1,\n dynamicTextsMax: 5,\n /** Dynamic ads mix and match best with at least this many media assets. */\n dynamicAssetsGoodMin: 3,\n /**\n * `asset_feed_spec` limits (Meta's Asset Feed Spec Options, \"restrictions\"):\n * body text 1024 characters, titles and descriptions 255, at most 10\n * images and 10 videos, 30 assets in all (the ad format counts as one).\n */\n assetFeedBodyMax: 1024,\n assetFeedTitleMax: 255,\n assetFeedImagesMax: 10,\n assetFeedVideosMax: 10,\n assetFeedAssetsMax: 30,\n },\n audience: {\n nameMax: 100,\n /** Website/engagement audiences below this rarely serve. */\n minLookalikeSourceRows: 100,\n retentionDaysMax: 180,\n },\n customConversion: {\n nameMax: 100,\n descriptionMax: 500,\n /**\n * Meta's hard cap per ad account. It matters because deleting a custom\n * conversion archives it rather than removing it, so a chat that creates\n * one per campaign spends slots that only a person, in Events Manager, can\n * think about reclaiming.\n */\n perAccountMax: 100,\n },\n} as const;\n\n// --- Campaign ---\n\nexport const OBJECTIVES = [\n \"OUTCOME_TRAFFIC\",\n \"OUTCOME_ENGAGEMENT\",\n \"OUTCOME_LEADS\",\n \"OUTCOME_SALES\",\n \"OUTCOME_AWARENESS\",\n \"OUTCOME_APP_PROMOTION\",\n] as const;\nexport type MetaObjective = (typeof OBJECTIVES)[number];\n\nexport const SPECIAL_AD_CATEGORIES = [\n \"NONE\",\n \"HOUSING\",\n \"EMPLOYMENT\",\n /** Deprecated by Meta on 2025-01-14 — replaced by FINANCIAL_PRODUCTS_SERVICES. Still accepted as input and mapped on the wire. */\n \"CREDIT\",\n \"ISSUES_ELECTIONS_POLITICS\",\n \"FINANCIAL_PRODUCTS_SERVICES\",\n \"ONLINE_GAMBLING_AND_GAMING\",\n] as const;\nexport type MetaSpecialAdCategory = (typeof SPECIAL_AD_CATEGORIES)[number];\n\n/** ISO Alpha-2 country declaration is mandatory for these categories. */\nexport const SPECIAL_CATEGORIES_REQUIRING_COUNTRY: readonly MetaSpecialAdCategory[] = [\"ISSUES_ELECTIONS_POLITICS\"];\n\nexport const BUYING_TYPES = [\"AUCTION\", \"RESERVED\"] as const;\n\nexport const BID_STRATEGIES = [\n \"LOWEST_COST_WITHOUT_CAP\",\n \"LOWEST_COST_WITH_BID_CAP\",\n \"COST_CAP\",\n \"LOWEST_COST_WITH_MIN_ROAS\",\n] as const;\nexport type MetaBidStrategy = (typeof BID_STRATEGIES)[number];\n\n/** Bid strategies that require an explicit `bid_amount` on the ad set. */\nexport const BID_STRATEGIES_REQUIRING_AMOUNT: readonly MetaBidStrategy[] = [\"LOWEST_COST_WITH_BID_CAP\", \"COST_CAP\"];\n\n/**\n * Bid strategies that must NOT carry a `bid_amount` — Meta rejects one.\n * Auto-bid (`LOWEST_COST_WITHOUT_CAP`) has no cap; `LOWEST_COST_WITH_MIN_ROAS`\n * uses `bid_constraints.roas_average_floor` instead of a flat amount.\n */\n/**\n * Meta takes a minimum ROAS as `bid_constraints.roas_average_floor`, an integer\n * scaled 10000×: 10000 is 1.0× (100%), 23300 is 2.33×. Baker stages the\n * multiple itself and scales it on the wire, the way money is staged in major\n * units and converted there.\n */\nexport const ROAS_FLOOR_SCALE = 10000;\n\nexport const BID_STRATEGIES_FORBIDDING_AMOUNT: readonly MetaBidStrategy[] = [\n \"LOWEST_COST_WITHOUT_CAP\",\n \"LOWEST_COST_WITH_MIN_ROAS\",\n];\n\n// --- Ad set ---\n\nexport const BILLING_EVENTS = [\n \"APP_INSTALLS\",\n \"CLICKS\",\n \"IMPRESSIONS\",\n \"LINK_CLICKS\",\n \"NONE\",\n \"OFFER_CLAIMS\",\n \"PAGE_LIKES\",\n \"POST_ENGAGEMENT\",\n \"THRUPLAY\",\n \"PURCHASE\",\n \"LISTING_INTERACTION\",\n] as const;\nexport type MetaBillingEvent = (typeof BILLING_EVENTS)[number];\n\nexport const OPTIMIZATION_GOALS = [\n \"NONE\",\n \"APP_INSTALLS\",\n \"AD_RECALL_LIFT\",\n \"ENGAGED_USERS\",\n \"EVENT_RESPONSES\",\n \"IMPRESSIONS\",\n \"LEAD_GENERATION\",\n \"QUALITY_LEAD\",\n \"QUALITY_CALL\",\n \"LINK_CLICKS\",\n \"OFFSITE_CONVERSIONS\",\n \"LANDING_PAGE_VIEWS\",\n \"PAGE_LIKES\",\n \"POST_ENGAGEMENT\",\n \"REACH\",\n \"THRUPLAY\",\n \"VALUE\",\n \"CONVERSATIONS\",\n \"DERIVED_EVENTS\",\n // Added 2026-09-18 from Meta's own generated enum spec\n // (facebook-business-sdk-codegen › AdSet_optimization_goal). Every one of these\n // is a goal Meta accepts and Baker used to refuse at stage time — the messaging\n // and Instagram-profile goals are the ones that cost real campaigns, because a\n // click-to-WhatsApp ad set cannot be expressed without them.\n \"ADVERTISER_SILOED_VALUE\",\n \"APP_INSTALLS_AND_OFFSITE_CONVERSIONS\",\n \"AUTOMATIC_OBJECTIVE\",\n \"ENGAGED_PAGE_VIEWS\",\n \"IN_APP_VALUE\",\n \"MEANINGFUL_CALL_ATTEMPT\",\n \"MESSAGING_APPOINTMENT_CONVERSION\",\n \"MESSAGING_DEEP_CONVERSATION_AND_FOLLOW\",\n \"MESSAGING_PURCHASE_CONVERSION\",\n \"PROFILE_AND_PAGE_ENGAGEMENT\",\n \"PROFILE_VISIT\",\n \"REMINDERS_SET\",\n \"SUBSCRIBERS\",\n \"VISIT_INSTAGRAM_PROFILE\",\n] as const;\nexport type MetaOptimizationGoal = (typeof OPTIMIZATION_GOALS)[number];\n\n/**\n * Optimization goals Meta rejects without a `promoted_object.page_id` — the\n * lead-form and page goals where the promoted object *is* the page (instant\n * forms, page likes). Missing it fails publish with subcode 1815430\n * (\"Please select a promoted object for your ad set\").\n */\nexport const OPTIMIZATION_GOALS_REQUIRING_PAGE: readonly MetaOptimizationGoal[] = [\n \"LEAD_GENERATION\",\n \"QUALITY_LEAD\",\n \"PAGE_LIKES\",\n];\n\n/**\n * Web-conversion goals Meta rejects without `promoted_object.pixel_id` +\n * `custom_event_type` — the pixel/event the ad set optimizes toward. Meta docs:\n * \"For OFFSITE_CONVERSIONS: Requires pixel_id and custom_event_type.\"\n */\nexport const OPTIMIZATION_GOALS_REQUIRING_PIXEL: readonly MetaOptimizationGoal[] = [\"OFFSITE_CONVERSIONS\"];\n\n/**\n * Value-optimization goals need `custom_event_type` plus a conversion *source* —\n * `pixel_id` for web value optimization, or `application_id` for app value\n * optimization (AEO/VO). Requiring `pixel_id` unconditionally would reject a\n * legitimate app-based VALUE campaign, so we accept either source.\n */\nexport const OPTIMIZATION_GOALS_REQUIRING_CONVERSION_SOURCE: readonly MetaOptimizationGoal[] = [\"VALUE\"];\n\n/** App-promotion goals Meta rejects without `promoted_object.application_id`. */\nexport const OPTIMIZATION_GOALS_REQUIRING_APP: readonly MetaOptimizationGoal[] = [\"APP_INSTALLS\"];\n\n/**\n * `PHONE_CALL` is CONTESTED and deliberately kept. Meta's Destination Type page\n * documents it; Meta's own generated enum spec does not list it. Neither source\n * settles it and a create is the only thing that would, so it stays accepted —\n * removing a value Meta takes breaks a campaign shape, keeping one it refuses\n * costs a single publish error that names itself.\n */\nexport const DESTINATION_TYPES = [\n \"WEBSITE\",\n \"APP\",\n \"MESSENGER\",\n \"INSTAGRAM_DIRECT\",\n \"ON_AD\",\n \"ON_PAGE\",\n \"ON_POST\",\n \"ON_VIDEO\",\n \"WHATSAPP\",\n \"PHONE_CALL\",\n \"INSTAGRAM_PROFILE\",\n \"SHOP_AUTOMATIC\",\n // Added 2026-09-18 from adcampaign_destination_type. The four MESSAGING_* values\n // are the click-to-message destinations (Messenger / Instagram Direct / WhatsApp\n // in every combination Meta ships); without them Baker could not stage a\n // click-to-WhatsApp ad set at all.\n \"APPLINKS_AUTOMATIC\",\n \"FACEBOOK\",\n \"FACEBOOK_LIVE\",\n \"FACEBOOK_PAGE\",\n \"IMAGINE\",\n \"INSTAGRAM_LIVE\",\n \"INSTAGRAM_PROFILE_AND_FACEBOOK_PAGE\",\n \"MESSAGING_INSTAGRAM_DIRECT_MESSENGER\",\n \"MESSAGING_INSTAGRAM_DIRECT_MESSENGER_WHATSAPP\",\n \"MESSAGING_INSTAGRAM_DIRECT_WHATSAPP\",\n \"MESSAGING_MESSENGER_WHATSAPP\",\n \"ON_EVENT\",\n] as const;\nexport type MetaDestinationType = (typeof DESTINATION_TYPES)[number];\n\nexport const CUSTOM_EVENT_TYPES = [\n \"PURCHASE\",\n \"LEAD\",\n \"COMPLETE_REGISTRATION\",\n \"ADD_TO_CART\",\n \"ADD_PAYMENT_INFO\",\n \"INITIATED_CHECKOUT\",\n \"CONTENT_VIEW\",\n \"SEARCH\",\n \"SUBSCRIBE\",\n \"START_TRIAL\",\n \"CONTACT\",\n \"OTHER\",\n // Added 2026-09-18 from AdPromotedObject_custom_event_type. SCHEDULE,\n // SUBMIT_APPLICATION, SERVICE_BOOKING_REQUEST and\n // MESSAGING_CONVERSATION_STARTED_7D are the conversions service businesses and\n // click-to-message campaigns actually optimize toward.\n \"ACHIEVEMENT_UNLOCKED\",\n \"ADD_TO_WISHLIST\",\n \"AD_IMPRESSION\",\n \"CUSTOMIZE_PRODUCT\",\n \"D2_RETENTION\",\n \"D7_RETENTION\",\n \"DONATE\",\n \"FIND_LOCATION\",\n \"LEVEL_ACHIEVED\",\n \"LISTING_INTERACTION\",\n \"MESSAGING_CONVERSATION_STARTED_7D\",\n \"RATE\",\n \"SCHEDULE\",\n \"SERVICE_BOOKING_REQUEST\",\n \"SPENT_CREDITS\",\n \"SUBMIT_APPLICATION\",\n \"TUTORIAL_COMPLETION\",\n] as const;\n\n/**\n * The only goals Meta lets an ad set cap frequency on: \"Writes to this field are\n * only available in ad sets where REACH and THRUPLAY are the performance goal\"\n * (Ad Account Ad Sets reference); anything else is subcode 1815211, live v25.0.\n */\nexport const OPTIMIZATION_GOALS_WITH_FREQUENCY_CAP: readonly MetaOptimizationGoal[] = [\"REACH\", \"THRUPLAY\"];\n\n/**\n * What a frequency cap counts — the values Meta's own refusal lists on v25.0.\n * Not all of them work: see `validateFrequencyCap` (VIDEO_VIEWS fails with an\n * unknown error, VIDEO_VIEWS_6S is REACH-only).\n */\nexport const FREQUENCY_CAP_EVENTS = [\n \"IMPRESSIONS\",\n \"VIDEO_VIEWS\",\n \"VIDEO_VIEWS_2S\",\n \"VIDEO_VIEWS_15S\",\n \"VIDEO_VIEWS_6S\",\n] as const;\n\n/**\n * CAP holds people at or below the number; TARGET aims at it — reach-and-frequency\n * only: live on v25.0 an auction ad set's TARGET cap passed the dry run and was\n * refused at create for having no prediction (subcode 3858652), so staging\n * refuses it (`validateFrequencyCap`). Kept so a live ad set carrying one reads.\n */\nexport const FREQUENCY_CAP_TYPES = [\"CAP\", \"TARGET\"] as const;\n\n/**\n * How an ad set spends through its day. `standard` spreads the budget evenly;\n * `no_pacing` (Ads Manager's accelerated delivery) spends as fast as it can and\n * only works on a bid cap; `day_parting` runs only in the hours `adset_schedule`\n * names. Sent as Meta's one-element `pacing_type` list.\n */\nexport const PACING_TYPES = [\"standard\", \"no_pacing\", \"day_parting\"] as const;\nexport type MetaPacingType = (typeof PACING_TYPES)[number];\n\n/** Whose clock an ad schedule follows: the viewer's (USER) or the ad account's (ADVERTISER). */\nexport const SCHEDULE_TIMEZONE_TYPES = [\"USER\", \"ADVERTISER\"] as const;\n\nexport const ATTRIBUTION_EVENT_TYPES = [\"CLICK_THROUGH\", \"VIEW_THROUGH\", \"ENGAGED_VIDEO_VIEW\"] as const;\nexport const ATTRIBUTION_WINDOW_DAYS = [1, 7] as const;\n\n/**\n * The longest window Meta still takes per event, live on v25.0 (2026-10-14):\n * a 28-day click is refused for every goal (\"supported values is/are\n * attribution window of 1, 7 day(s)\", subcode 1885423), a view or an engaged\n * video view only counts for one day (\"supported combination of click-through\n * and view-through attribution window values are: (1, 0), (1, 1), (7, 0),\n * (7, 1)\", subcode 1885501). Which combinations a given goal takes is narrower\n * still and Meta's to say — the stage-time dry run asks it.\n */\nexport const ATTRIBUTION_MAX_WINDOW_DAYS: Readonly<Record<(typeof ATTRIBUTION_EVENT_TYPES)[number], number>> = {\n CLICK_THROUGH: 7,\n VIEW_THROUGH: 1,\n ENGAGED_VIDEO_VIEW: 1,\n};\n\n// --- Advantage+ Audience (targeting_automation.advantage_audience) ---\n\n/**\n * With Advantage+ Audience on (`advantage_audience: 1`, the Meta v23+ default\n * when age/gender/custom-audience/detailed inclusions are default or omitted),\n * age & gender become mere suggestions: `age_max` is pinned to 65 and `age_min`\n * is limited to 18–25. Setting a narrower `age_max`, an `age_min` above 25, or a\n * single-gender restriction is rejected (subcode 1870189, \"add a lower maximum\n * age as a suggestion instead\"). To enforce a HARD age/gender limit you must set\n * `advantage_audience: 0`.\n */\nexport const ADVANTAGE_AUDIENCE_OPEN_AGE_MAX = 65;\nexport const ADVANTAGE_AUDIENCE_MAX_HARD_AGE_MIN = 25;\n\n// --- EU Digital Services Act (DSA) ---\n\n/**\n * When an ad set targets any EU country, Meta requires `dsa_beneficiary` and\n * `dsa_payor` (who benefits from / pays for the ad) for Digital Services Act\n * compliance — the create is rejected without them. The backend auto-fills both\n * from the ad account's business name when the caller omits them.\n */\nexport const EU_DSA_COUNTRIES = new Set([\n \"AT\",\n \"BE\",\n \"BG\",\n \"HR\",\n \"CY\",\n \"CZ\",\n \"DK\",\n \"EE\",\n \"FI\",\n \"FR\",\n \"DE\",\n \"GR\",\n \"HU\",\n \"IE\",\n \"IT\",\n \"LV\",\n \"LT\",\n \"LU\",\n \"MT\",\n \"NL\",\n \"PL\",\n \"PT\",\n \"RO\",\n \"SK\",\n \"SI\",\n \"ES\",\n \"SE\",\n]);\n\n// --- Ad creative ---\n\n/**\n * Every button Meta accepts on `object_story_spec.link_data.call_to_action.type`\n * — a single ad, a video ad, and each card of a carousel.\n *\n * Read off Meta itself on 2026-09-01 by posting an invalid type and keeping the\n * list its 400 enumerates, because the published reference and the live\n * validator disagree: `SEE_DETAILS` is missing from the docs page and accepted\n * by the API, and it is the button three of one client's live ads actually use.\n * This list used to be a hand-picked 27, so those ads could not be rebuilt\n * through Baker at all — the button was the thing that stopped them.\n *\n * Meta keeps a SECOND, different list for `asset_feed_spec.call_to_action_types`\n * ({@link ASSET_FEED_CTA_TYPES}). Neither contains the other:\n * `SEE_DETAILS` is link-only, `GET_STARTED` and `VIEW_CART` are feed-only. A\n * value in the wrong slot is refused at creation, so the two are kept apart\n * rather than unioned.\n */\nexport const CTA_TYPES = [\n \"BOOK_TRAVEL\",\n \"CONTACT_US\",\n \"DONATE\",\n \"DONATE_NOW\",\n \"DOWNLOAD\",\n \"GET_DIRECTIONS\",\n \"GO_LIVE\",\n \"INTERESTED\",\n \"LEARN_MORE\",\n \"SEE_DETAILS\",\n \"LIKE_PAGE\",\n \"MESSAGE_PAGE\",\n \"RAISE_MONEY\",\n \"SAVE\",\n \"SEND_TIP\",\n \"SHOP_NOW\",\n \"SIGN_UP\",\n \"VIEW_INSTAGRAM_PROFILE\",\n \"INSTAGRAM_MESSAGE\",\n \"LOYALTY_LEARN_MORE\",\n \"PURCHASE_GIFT_CARDS\",\n \"PAY_TO_ACCESS\",\n \"SEE_MORE\",\n \"TRY_IN_CAMERA\",\n \"WHATSAPP_LINK\",\n \"GET_IN_TOUCH\",\n \"TRY_NOW\",\n \"ASK_A_QUESTION\",\n \"START_A_CHAT\",\n \"CHAT_NOW\",\n \"ASK_US\",\n \"CHAT_WITH_US\",\n \"BOOK_NOW\",\n \"CHECK_AVAILABILITY\",\n \"ORDER_NOW\",\n \"WHATSAPP_MESSAGE\",\n \"GET_MOBILE_APP\",\n \"INSTALL_MOBILE_APP\",\n \"USE_MOBILE_APP\",\n \"INSTALL_APP\",\n \"USE_APP\",\n \"PLAY_GAME\",\n \"TRY_DEMO\",\n \"WATCH_VIDEO\",\n \"WATCH_MORE\",\n \"OPEN_LINK\",\n \"NO_BUTTON\",\n \"LISTEN_MUSIC\",\n \"MOBILE_DOWNLOAD\",\n \"GET_OFFER\",\n \"GET_OFFER_VIEW\",\n \"BUY_NOW\",\n \"BUY_TICKETS\",\n \"UPDATE_APP\",\n \"BET_NOW\",\n \"ADD_TO_CART\",\n \"SELL_NOW\",\n \"GET_SHOWTIMES\",\n \"LISTEN_NOW\",\n \"GET_EVENT_TICKETS\",\n \"REMIND_ME\",\n \"SEARCH_MORE\",\n \"PRE_REGISTER\",\n \"SWIPE_UP_PRODUCT\",\n \"SWIPE_UP_SHOP\",\n \"PLAY_GAME_ON_FACEBOOK\",\n \"VISIT_WORLD\",\n \"OPEN_INSTANT_APP\",\n \"JOIN_GROUP\",\n \"GET_PROMOTIONS\",\n \"SEND_UPDATES\",\n \"INQUIRE_NOW\",\n \"VISIT_PROFILE\",\n \"CHAT_ON_WHATSAPP\",\n \"EXPLORE_MORE\",\n \"CONFIRM\",\n \"JOIN_CHANNEL\",\n \"MAKE_AN_APPOINTMENT\",\n \"ASK_ABOUT_SERVICES\",\n \"BOOK_A_CONSULTATION\",\n \"GET_A_QUOTE\",\n \"BUY_VIA_MESSAGE\",\n \"ASK_FOR_MORE_INFO\",\n \"VIEW_PRODUCT\",\n \"VIEW_CHANNEL\",\n \"WATCH_LIVE_VIDEO\",\n \"JOIN_LIVE_VIDEO\",\n \"IMAGINE\",\n \"CALL\",\n \"MISSED_CALL\",\n \"CALL_NOW\",\n \"CALL_ME\",\n \"APPLY_NOW\",\n \"BUY\",\n \"GET_QUOTE\",\n \"SUBSCRIBE\",\n \"RECORD_NOW\",\n \"VOTE_NOW\",\n \"GIVE_FREE_RIDES\",\n \"REGISTER_NOW\",\n \"OPEN_MESSENGER_EXT\",\n \"EVENT_RSVP\",\n \"CIVIC_ACTION\",\n \"SEND_INVITES\",\n \"REFER_FRIENDS\",\n \"REQUEST_TIME\",\n \"SEE_MENU\",\n \"SEARCH\",\n \"TRY_IT\",\n \"TRY_ON\",\n \"LINK_CARD\",\n \"DIAL_CODE\",\n \"FIND_YOUR_GROUPS\",\n \"START_ORDER\",\n // Added 2026-09-18 from Meta's generated enum spec\n // (AdCreative_call_to_action_type). Additive on purpose: 37 of the values above\n // are absent from that spec and present in the live 400, which is the\n // disagreement the note above is about — so the spec widens this list and never\n // prunes it.\n \"AUDIO_CALL\",\n \"BROWSE_SHOP\",\n \"CONTACT\",\n \"FIND_A_GROUP\",\n \"FIND_OUT_MORE\",\n \"FOLLOW_NEWS_STORYLINE\",\n \"FOLLOW_PAGE\",\n \"FOLLOW_USER\",\n \"GET_DETAILS\",\n \"GET_STARTED\",\n \"SAY_THANKS\",\n \"SEE_SHOP\",\n \"SEND_A_GIFT\",\n \"SEND_GIFT_MONEY\",\n \"SHARE\",\n \"SHOP_WITH_AI\",\n \"SOTTO_SUBSCRIBE\",\n \"TRY_ON_WITH_AI\",\n \"VIDEO_ANNOTATION\",\n \"VIDEO_CALL\",\n \"VIEW_CART\",\n \"VIEW_IN_CART\",\n \"VISIT_PAGES_FEED\",\n \"VISIT_WEBSITE\",\n \"WOODHENGE_SUPPORT\",\n] as const;\nexport type MetaCtaType = (typeof CTA_TYPES)[number];\n\n/**\n * The buttons a dynamic / flexible creative may list in\n * `asset_feed_spec.call_to_action_types`. Read off Meta the same way and on the\n * same day as {@link CTA_TYPES}, and deliberately a separate list — see the\n * note there.\n */\nexport const ASSET_FEED_CTA_TYPES = [\n \"OPEN_LINK\",\n \"LIKE_PAGE\",\n \"SHOP_NOW\",\n \"PLAY_GAME\",\n \"INSTALL_APP\",\n \"USE_APP\",\n \"CALL\",\n \"CALL_ME\",\n \"VIDEO_CALL\",\n \"INSTALL_MOBILE_APP\",\n \"USE_MOBILE_APP\",\n \"MOBILE_DOWNLOAD\",\n \"BOOK_TRAVEL\",\n \"LISTEN_MUSIC\",\n \"WATCH_VIDEO\",\n \"LEARN_MORE\",\n \"SIGN_UP\",\n \"DOWNLOAD\",\n \"WATCH_MORE\",\n \"NO_BUTTON\",\n \"VISIT_PAGES_FEED\",\n \"CALL_NOW\",\n \"APPLY_NOW\",\n \"CONTACT\",\n \"BUY_NOW\",\n \"GET_OFFER\",\n \"GET_OFFER_VIEW\",\n \"BUY_TICKETS\",\n \"UPDATE_APP\",\n \"GET_DIRECTIONS\",\n \"BUY\",\n \"SEND_UPDATES\",\n \"MESSAGE_PAGE\",\n \"DONATE\",\n \"SUBSCRIBE\",\n \"SAY_THANKS\",\n \"SELL_NOW\",\n \"SHARE\",\n \"DONATE_NOW\",\n \"GET_QUOTE\",\n \"CONTACT_US\",\n \"ORDER_NOW\",\n \"START_ORDER\",\n \"ADD_TO_CART\",\n \"VIEW_CART\",\n \"VIEW_IN_CART\",\n \"VIDEO_ANNOTATION\",\n \"RECORD_NOW\",\n \"INQUIRE_NOW\",\n \"CONFIRM\",\n \"REFER_FRIENDS\",\n \"REQUEST_TIME\",\n \"GET_SHOWTIMES\",\n \"LISTEN_NOW\",\n \"TRY_DEMO\",\n \"WOODHENGE_SUPPORT\",\n \"SOTTO_SUBSCRIBE\",\n \"FOLLOW_USER\",\n \"RAISE_MONEY\",\n \"SEE_SHOP\",\n \"GET_DETAILS\",\n \"FIND_OUT_MORE\",\n \"VISIT_WEBSITE\",\n \"BROWSE_SHOP\",\n \"EVENT_RSVP\",\n \"WHATSAPP_MESSAGE\",\n \"FOLLOW_NEWS_STORYLINE\",\n \"SEE_MORE\",\n \"BOOK_NOW\",\n \"FIND_A_GROUP\",\n \"FIND_YOUR_GROUPS\",\n \"PAY_TO_ACCESS\",\n \"PURCHASE_GIFT_CARDS\",\n \"FOLLOW_PAGE\",\n \"SEND_A_GIFT\",\n \"SWIPE_UP_SHOP\",\n \"SWIPE_UP_PRODUCT\",\n \"SEND_GIFT_MONEY\",\n \"PLAY_GAME_ON_FACEBOOK\",\n \"GET_STARTED\",\n \"OPEN_INSTANT_APP\",\n \"AUDIO_CALL\",\n \"GET_PROMOTIONS\",\n \"JOIN_CHANNEL\",\n \"MAKE_AN_APPOINTMENT\",\n \"ASK_ABOUT_SERVICES\",\n \"BOOK_A_CONSULTATION\",\n \"GET_A_QUOTE\",\n \"BUY_VIA_MESSAGE\",\n \"ASK_FOR_MORE_INFO\",\n \"CHAT_WITH_US\",\n \"VIEW_PRODUCT\",\n \"VIEW_CHANNEL\",\n \"GET_IN_TOUCH\",\n \"ASK_A_QUESTION\",\n \"START_A_CHAT\",\n \"CHAT_NOW\",\n \"ASK_US\",\n \"WATCH_LIVE_VIDEO\",\n \"JOIN_LIVE_VIDEO\",\n \"SHOP_WITH_AI\",\n \"TRY_ON_WITH_AI\",\n] as const;\nexport type MetaAssetFeedCtaType = (typeof ASSET_FEED_CTA_TYPES)[number];\n\n/**\n * The buttons Meta allows on a creative that opens an instant form. Meta's\n * lead-ads guide names exactly these six for `link_data.call_to_action`, and\n * anything else is refused at creation with \"Invalid value field\n * lead_gen_form_id for CTA type: <TYPE>\" (subcode 1856030) — which is a publish\n * failure, after the ad's siblings have already been created on the account.\n * One real chat staged six instant-form creatives, two of them on CONTACT_US:\n * both creatives were rejected and both of their ads were skipped, leaving four\n * of six ads live and nobody able to tell why from Meta's sentence.\n */\nexport const LEAD_FORM_CTA_TYPES = [\n \"APPLY_NOW\",\n \"DOWNLOAD\",\n \"GET_QUOTE\",\n \"LEARN_MORE\",\n \"SIGN_UP\",\n \"SUBSCRIBE\",\n] as const satisfies readonly MetaCtaType[];\n\n/** `asset_feed_spec.ad_formats` (Asset Feed Spec Options): `AUTOMATIC_FORMAT` mixes pictures and videos. */\nexport const AD_FORMATS = [\"SINGLE_IMAGE\", \"CAROUSEL\", \"SINGLE_VIDEO\", \"AUTOMATIC_FORMAT\"] as const;\nexport type MetaAdFormat = (typeof AD_FORMATS)[number];\n\n/** Advantage+ Creative enroll state (case-sensitive) — set per individual feature. */\nexport const ENROLL_STATUSES = [\"OPT_IN\", \"OPT_OUT\"] as const;\nexport type MetaEnrollStatus = (typeof ENROLL_STATUSES)[number];\n\n/**\n * Meta deprecated the `standard_enhancements` bundle key at Marketing API v22.0\n * — including it in `creative_features_spec` now hard-fails (error subcode\n * 3858504: \"Including standard enhancements field in creative has been\n * deprecated. Please choose to set individual features instead.\"). The bundle is\n * replaced by these individual feature keys, opted in/out one at a time.\n *\n * Meta does NOT publish a per-media eligibility matrix and validates features\n * server-side, so we expand our master toggle into ONLY keys confirmed present\n * in the current `AdCreativeFeaturesSpec`, scoped to the creative's media type.\n * Callers needing a specific feature pass it explicitly via `enhancements.features`.\n */\nexport const STANDARD_ENHANCEMENT_IMAGE_FEATURES = [\n \"image_templates\",\n \"image_touchups\",\n \"text_optimizations\",\n \"inline_comment\",\n] as const;\n/** Video keeps only the universally-valid text/comment enhancements (visual crop keys aren't in the confirmed spec list). */\nexport const STANDARD_ENHANCEMENT_VIDEO_FEATURES = [\"text_optimizations\", \"inline_comment\"] as const;\n\n/**\n * Advantage+ Creative features that change the picture or video itself —\n * adding frames, re-cropping, AI outpainting, animating a still, generating\n * music, cutting a video. Read off a live creative's\n * `degrees_of_freedom_spec.creative_features_spec` (82 keys, v25.0,\n * 2026-10-14) and every one accepted as OPT_OUT by a validate-only create.\n *\n * Every composed creative sends them all OPT_OUT, so Meta changes nobody's\n * pixels by default; one is switched on only when the user asked for it by name.\n */\nexport const VISUAL_ENHANCEMENT_FEATURES = {\n adapt_to_placement: \"Adapt the picture to each placement\",\n add_text_overlay: \"Add text on top of the media\",\n audio: \"Add audio\",\n carousel_to_video: \"Turn the carousel into a video\",\n creative_stickers: \"Add stickers\",\n cv_transformation: \"Visual transformations\",\n image_animation: \"Animate the picture\",\n image_auto_crop: \"Crop the picture automatically\",\n image_background_gen: \"Generate a new background\",\n image_banner: \"Add a banner\",\n image_brightness_and_contrast: \"Adjust brightness and contrast\",\n image_end_card: \"Add an end card\",\n image_enhancement: \"Enhance the picture\",\n image_templates: \"Put the picture in a template frame\",\n image_text_translation: \"Translate text in the picture\",\n image_touchups: \"Touch up the picture\",\n image_uncrop: \"Expand the picture with AI\",\n media_liquidity_animated_image: \"Animate the picture\",\n media_type_automation: \"Turn the picture into a video\",\n multi_photo_to_video: \"Turn several pictures into a video\",\n music_generation: \"Generate music\",\n pac_genai_recomposition: \"Recompose the media with AI per placement\",\n pac_recomposition: \"Recompose the media per placement\",\n replace_media_text: \"Replace text in the media\",\n reveal_details_over_time: \"Reveal details over time\",\n text_overlay_translation: \"Translate text overlays\",\n translate_voiceover: \"Translate the voiceover\",\n video_auto_crop: \"Crop the video automatically\",\n video_filtering: \"Filter the video\",\n video_highlight: \"Cut a highlight from the video\",\n video_highlights: \"Cut highlights from the video\",\n video_to_image: \"Turn the video into a picture\",\n video_uncrop: \"Expand the video with AI\",\n video_uncrop_9x16_to_9x18: \"Expand a vertical video\",\n ig_video_native_subtitle: \"Add subtitles to the video\",\n} as const satisfies Record<string, string>;\nexport type VisualEnhancementFeature = keyof typeof VISUAL_ENHANCEMENT_FEATURES;\n\n/** The features that change the media which these enhancements switch on, in the reviewer's words. */\nexport function visualEnhancementsOn(enhancements: { features?: Record<string, string> } | undefined): string[] {\n return Object.entries(enhancements?.features ?? {})\n .filter(([key, status]) => status === \"OPT_IN\" && key in VISUAL_ENHANCEMENT_FEATURES)\n .map(([key]) => VISUAL_ENHANCEMENT_FEATURES[key as VisualEnhancementFeature]);\n}\n\n/** What the enhancements switch turns on or off: suggestions to the words, never to the media. */\nexport const TEXT_ENHANCEMENT_FEATURES = [\"text_optimizations\", \"inline_comment\"] as const;\n\n// --- Statuses ---\n\nexport const ENTITY_STATUSES = [\"ACTIVE\", \"PAUSED\", \"DELETED\", \"ARCHIVED\"] as const;\nexport type MetaEntityStatus = (typeof ENTITY_STATUSES)[number];\n\n/** Statuses a create op may request (Meta forbids launching straight to DELETED/ARCHIVED). */\nexport const STAGEABLE_CREATE_STATUSES = [\"ACTIVE\", \"PAUSED\"] as const;\n/**\n * Statuses a campaign, ad set or ad update op may set. ARCHIVED keeps the entity\n * readable in Ads Manager (and counts toward Meta's archived-object limit);\n * DELETED removes it for good and cannot be undone. The CLI stages DELETED only\n * through its `delete` command; `update --status` refuses it.\n */\nexport const UPDATE_STATUSES = [\"ACTIVE\", \"PAUSED\", \"ARCHIVED\", \"DELETED\"] as const;\n/**\n * Statuses a creative update may set. DELETED is how a creative is deleted —\n * `POST /{creative_id}` with `status: DELETED` (live on v25.0, 2026-10-14) —\n * and Meta refuses it for a creative an ad still uses.\n */\nexport const CREATIVE_UPDATE_STATUSES = [\"ACTIVE\", \"PAUSED\", \"ARCHIVED\", \"DELETED\"] as const;\n\n// --- Custom audiences ---\n\nexport const CUSTOM_AUDIENCE_SUBTYPES = [\"CUSTOM\", \"WEBSITE\", \"ENGAGEMENT\", \"LOOKALIKE\"] as const;\nexport type MetaCustomAudienceSubtype = (typeof CUSTOM_AUDIENCE_SUBTYPES)[number];\n\n/**\n * Where the rows of a customer-file audience came from. Meta publishes exactly\n * these three, and the field is a data-provenance declaration about personal\n * data — the one place in this file where a free string was the wrong type.\n */\nexport const CUSTOMER_FILE_SOURCES = [\n \"USER_PROVIDED_ONLY\",\n \"PARTNER_PROVIDED_ONLY\",\n \"BOTH_USER_AND_PARTNER_PROVIDED\",\n] as const;\nexport type MetaCustomerFileSource = (typeof CUSTOMER_FILE_SOURCES)[number];\n\n// --- Media ---\n\nexport const MEDIA_KINDS = [\"image\", \"video\"] as const;\nexport type MetaMediaKind = (typeof MEDIA_KINDS)[number];\n\n// --- Money ---\n\n// Minor-unit conversion for the wire lives in the backend's single source of\n// truth, `ads/meta/currency.ts` (Meta's own offset table: whole-unit and\n// hundredth currencies, an unlisted one refused). It is intentionally NOT duplicated here.\n\n/**\n * Indicative per-currency daily-budget floors (Meta enforces the authoritative\n * per-account `min_daily_budget` at stage time; these only catch obvious\n * mistakes offline). Amounts in major units.\n */\nexport const CURRENCY_MINIMUMS: Record<string, { dailyBudgetMin: number }> = {\n USD: { dailyBudgetMin: 1 },\n EUR: { dailyBudgetMin: 1 },\n GBP: { dailyBudgetMin: 1 },\n};\nexport const DEFAULT_CURRENCY_MINIMUM = { dailyBudgetMin: 1 };\n\n// --- Refs / ids ---\n\nexport const TEMP_REF_PREFIX = \"meta_temp_\";\nexport const TEMP_REF_REGEX = /^meta_temp_[A-Za-z0-9_-]{4,}$/;\n/** Meta node ids are bare numeric strings (the `act_` prefix is stripped for scoping). */\nexport const NUMERIC_ID_REGEX = /^\\d+$/;\n/** Ad-image hashes are hex; be lenient on length across Graph versions. */\nexport const IMAGE_HASH_REGEX = /^[A-Fa-f0-9]{16,}$/;\nexport const SIMULATED_ID_PREFIX = \"sim_meta_\";\n"],"mappings":"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AA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AASO,IAAM,uBAAuB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA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","names":[]}
@@ -3,7 +3,7 @@ import {
3
3
  parseDefinitionDelivery,
4
4
  resolveDelivery,
5
5
  resolveFormatList
6
- } from "./chunk-AVNSH2JE.js";
6
+ } from "./chunk-KOXDXSKN.js";
7
7
  import {
8
8
  AD_PLACEMENTS
9
9
  } from "./chunk-MCJ5I5LR.js";
@@ -88,4 +88,4 @@ export {
88
88
  deliveryDefinitionFields,
89
89
  deliveryNote
90
90
  };
91
- //# sourceMappingURL=chunk-TPANP5A2.js.map
91
+ //# sourceMappingURL=chunk-JKJQWRLO.js.map
@@ -40,7 +40,7 @@ import {
40
40
  } from "./chunk-MCJ5I5LR.js";
41
41
  import {
42
42
  marketCountryName
43
- } from "./chunk-KPYDTIAI.js";
43
+ } from "./chunk-2WZI36D3.js";
44
44
  import {
45
45
  ASSET_KINDS,
46
46
  BackendHttpError,
@@ -5365,4 +5365,4 @@ export {
5365
5365
  canSpellNumbers,
5366
5366
  spellNumber
5367
5367
  };
5368
- //# sourceMappingURL=chunk-62JQQUAU.js.map
5368
+ //# sourceMappingURL=chunk-JQH5VG6F.js.map
@@ -47,7 +47,7 @@ import {
47
47
  usesTextColour,
48
48
  validateCanvas,
49
49
  validateCanvasDeep
50
- } from "./chunk-62JQQUAU.js";
50
+ } from "./chunk-JQH5VG6F.js";
51
51
  import {
52
52
  FRAME_CUT,
53
53
  bandViolations,
@@ -8911,4 +8911,4 @@ export {
8911
8911
  defaultRegistry,
8912
8912
  createEngineFromEnv
8913
8913
  };
8914
- //# sourceMappingURL=chunk-6WXV5GTA.js.map
8914
+ //# sourceMappingURL=chunk-JVH5A3XC.js.map
@@ -1,11 +1,8 @@
1
- import {
2
- readInsights
3
- } from "./chunk-EOY6BK4C.js";
4
1
  import {
5
2
  heldRules,
6
3
  readAdWords,
7
4
  ruleGate
8
- } from "./chunk-2XRMPSEV.js";
5
+ } from "./chunk-LXQB4ZGE.js";
9
6
  import {
10
7
  avatarRelation,
11
8
  castCompany
@@ -13,6 +10,9 @@ import {
13
10
  import {
14
11
  readAvatars
15
12
  } from "./chunk-LCW3U4EA.js";
13
+ import {
14
+ readInsights
15
+ } from "./chunk-EOY6BK4C.js";
16
16
  import {
17
17
  frontmatterOf,
18
18
  sourcesClaims
@@ -98,7 +98,7 @@ import {
98
98
  staticRenderNodes,
99
99
  trimmedRenderBand,
100
100
  wordCount
101
- } from "./chunk-62JQQUAU.js";
101
+ } from "./chunk-JQH5VG6F.js";
102
102
  import {
103
103
  blockingArea
104
104
  } from "./chunk-E2RFM6R2.js";
@@ -182,7 +182,7 @@ import {
182
182
  import {
183
183
  AWARENESS_VALUES,
184
184
  marketFromCompanyDoc
185
- } from "./chunk-KPYDTIAI.js";
185
+ } from "./chunk-2WZI36D3.js";
186
186
  import {
187
187
  JEV_MODEL,
188
188
  askJev,
@@ -8936,4 +8936,4 @@ export {
8936
8936
  prepareCanvas,
8937
8937
  exitOnPrepareError
8938
8938
  };
8939
- //# sourceMappingURL=chunk-AVNSH2JE.js.map
8939
+ //# sourceMappingURL=chunk-KOXDXSKN.js.map
@@ -22,7 +22,7 @@ import {
22
22
  } from "./chunk-4AMIHNNP.js";
23
23
  import {
24
24
  marketFromCompanyDoc
25
- } from "./chunk-KPYDTIAI.js";
25
+ } from "./chunk-2WZI36D3.js";
26
26
 
27
27
  // src/engine/creative-context/ad-words.ts
28
28
  import { readdir, readFile } from "fs/promises";
@@ -139,4 +139,4 @@ export {
139
139
  heldRules,
140
140
  ruleGate
141
141
  };
142
- //# sourceMappingURL=chunk-2XRMPSEV.js.map
142
+ //# sourceMappingURL=chunk-LXQB4ZGE.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  latestVersion
3
- } from "./chunk-FUKDI2UK.js";
3
+ } from "./chunk-3W6G6ARX.js";
4
4
  import {
5
5
  canvasOutputsRoot
6
6
  } from "./chunk-23H4ZJRP.js";
@@ -16,4 +16,4 @@ async function versionOf(slug, run) {
16
16
  export {
17
17
  versionOf
18
18
  };
19
- //# sourceMappingURL=chunk-ZL23HA4N.js.map
19
+ //# sourceMappingURL=chunk-M6PN3VH6.js.map
@@ -24,7 +24,7 @@ import {
24
24
  } from "./chunk-IKCP5NCE.js";
25
25
  import {
26
26
  marketFromCompanyDoc
27
- } from "./chunk-KPYDTIAI.js";
27
+ } from "./chunk-2WZI36D3.js";
28
28
  import {
29
29
  registerSchema,
30
30
  writeJson
@@ -157,4 +157,4 @@ export {
157
157
  ideasReport,
158
158
  ideasCommand
159
159
  };
160
- //# sourceMappingURL=chunk-TZEVD4Q6.js.map
160
+ //# sourceMappingURL=chunk-P5FRWPG7.js.map
@@ -1,11 +1,11 @@
1
+ import {
2
+ leadVersion,
3
+ writeSeriesMemberCanvas
4
+ } from "./chunk-FVHJCERJ.js";
1
5
  import {
2
6
  claimNewCreativeInWorkspace,
3
7
  creativeLimitRefusal
4
8
  } from "./chunk-XZ4YMCZK.js";
5
- import {
6
- leadVersion,
7
- writeSeriesMemberCanvas
8
- } from "./chunk-C6EYCD5J.js";
9
9
  import {
10
10
  definitionFieldsOf,
11
11
  setDefinitionFields,
@@ -94,4 +94,4 @@ export {
94
94
  makeSeriesAd,
95
95
  seriesMadeEnvelope
96
96
  };
97
- //# sourceMappingURL=chunk-CSZFZKVX.js.map
97
+ //# sourceMappingURL=chunk-PQJXIY64.js.map
@@ -11,9 +11,35 @@ import {
11
11
  getEnv
12
12
  } from "./chunk-EE72SSB2.js";
13
13
 
14
+ // ../api/src/ads-meta/permissionGates.ts
15
+ var META_PERMISSION_NOT_ENABLED_MESSAGE = {
16
+ catalog: "Catalog changes need the Catalog permission for Meta \u2014 ask a Baker admin to turn it on, then reconnect Meta. Everything else on Meta keeps working: tell the user, and carry on with the rest of the job.",
17
+ pagePosts: "Facebook Page posts need the Page posts permission for Meta \u2014 ask a Baker admin to turn it on, then reconnect Meta. Everything else on Meta keeps working: tell the user, and carry on with the rest of the job."
18
+ };
19
+ var META_PERMISSION_RECONNECT_MESSAGE = {
20
+ catalog: "Catalog changes need the Catalog permission for Meta. It is turned on for this company, but this Meta connection was made before, so it does not hold it \u2014 ask the user to reconnect Meta in the dashboard, then try again. Everything else on Meta keeps working meanwhile.",
21
+ pagePosts: "Facebook Page posts need the Page posts permission for Meta. It is turned on for this company, but this Meta connection was made before, so it does not hold it \u2014 ask the user to reconnect Meta in the dashboard, then try again. Everything else on Meta keeps working meanwhile."
22
+ };
23
+ var META_UNREQUESTED_PERMISSION_MESSAGE = {
24
+ comments: "Reading and moderating comments on ads needs Meta permissions Baker's Meta connection does not ask for yet (reading people's comments and managing them on the Page). Tell the user that comment moderation happens in Meta Business Suite for now, and carry on with the rest of the job.",
25
+ instagramMedia: "Listing an Instagram account's posts needs a Meta permission Baker's Meta connection does not ask for yet. Ask the user for the post's link or id instead, or boost it from Meta Business Suite, and carry on."
26
+ };
27
+ var META_PAGE_ADS_PERMISSION_REMEDY = "A Baker admin turns it on with the lead ads switch for this company; then the user reconnects Meta in the dashboard. Tell the user, and carry on with the rest of the job.";
28
+ function isMetaPermissionGateRefusal(message) {
29
+ return [
30
+ ...Object.values(META_PERMISSION_NOT_ENABLED_MESSAGE),
31
+ ...Object.values(META_PERMISSION_RECONNECT_MESSAGE),
32
+ ...Object.values(META_UNREQUESTED_PERMISSION_MESSAGE),
33
+ META_PAGE_ADS_PERMISSION_REMEDY
34
+ ].some((refusal) => message.includes(refusal));
35
+ }
36
+
14
37
  // src/commands/ads/meta/shared.ts
15
38
  var DAY_MS = 864e5;
16
39
  function metaForbiddenFix(message) {
40
+ if (isMetaPermissionGateRefusal(message)) {
41
+ return { action: "reject", explanation: message };
42
+ }
17
43
  if (message.includes("has not accepted Meta's Lead Generation Terms")) {
18
44
  return {
19
45
  action: "reject",
@@ -134,4 +160,4 @@ export {
134
160
  resolveEffectiveStatus,
135
161
  statusFilterHints
136
162
  };
137
- //# sourceMappingURL=chunk-OP7DNHD2.js.map
163
+ //# sourceMappingURL=chunk-QTOZ32SU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../api/src/ads-meta/permissionGates.ts","../src/commands/ads/meta/shared.ts"],"sourcesContent":["/**\n * The refusals Baker writes for Meta work that needs a permission the baseline\n * connection does not ask for — managing catalogs (`catalog_management`) and\n * posting to a Facebook Page (`pages_manage_posts`). Shared verbatim by the\n * backend that throws them and the CLI that explains them, for the same reason\n * as `leadAds.ts`: these name their own cause and remedy, so the CLI must not\n * append Meta's ambiguous \"maybe reconnect, maybe an unassigned asset\" advice.\n */\n\nexport type MetaPermissionGate = \"catalog\" | \"pagePosts\";\n\n/** Everything a person or the agent can see about one per-company Meta permission. */\nexport interface MetaPermissionState {\n /** A Baker admin switched it on for this company, so the consent screen asks for it. */\n enabled: boolean;\n /** The current Meta connection holds it. */\n granted: boolean;\n /** Switched on, but the connection predates it — reconnecting Meta is the fix. */\n reconnectNeeded: boolean;\n}\n\nexport type MetaPermissionStates = Record<\"leadAds\" | MetaPermissionGate, MetaPermissionState>;\n\nexport const META_PERMISSION_NOT_ENABLED_MESSAGE: Record<MetaPermissionGate, string> = {\n catalog:\n \"Catalog changes need the Catalog permission for Meta — ask a Baker admin to turn it on, then reconnect Meta. \" +\n \"Everything else on Meta keeps working: tell the user, and carry on with the rest of the job.\",\n pagePosts:\n \"Facebook Page posts need the Page posts permission for Meta — ask a Baker admin to turn it on, then reconnect \" +\n \"Meta. Everything else on Meta keeps working: tell the user, and carry on with the rest of the job.\",\n};\n\nexport const META_PERMISSION_RECONNECT_MESSAGE: Record<MetaPermissionGate, string> = {\n catalog:\n \"Catalog changes need the Catalog permission for Meta. It is turned on for this company, but this Meta \" +\n \"connection was made before, so it does not hold it — ask the user to reconnect Meta in the dashboard, then \" +\n \"try again. Everything else on Meta keeps working meanwhile.\",\n pagePosts:\n \"Facebook Page posts need the Page posts permission for Meta. It is turned on for this company, but this Meta \" +\n \"connection was made before, so it does not hold it — ask the user to reconnect Meta in the dashboard, then \" +\n \"try again. Everything else on Meta keeps working meanwhile.\",\n};\n\n/**\n * Work that needs a Meta permission Baker's connection does not ask for at all\n * (no switch turns it on): reading and moderating comments on ads\n * (`pages_read_user_content`, `pages_manage_engagement`) and listing an\n * Instagram account's posts (`instagram_basic`). Live on v26.0 (2026-10-15)\n * Meta refused both with code 10.\n */\nexport const META_UNREQUESTED_PERMISSION_MESSAGE = {\n comments:\n \"Reading and moderating comments on ads needs Meta permissions Baker's Meta connection does not ask for yet \" +\n \"(reading people's comments and managing them on the Page). Tell the user that comment moderation happens in \" +\n \"Meta Business Suite for now, and carry on with the rest of the job.\",\n instagramMedia:\n \"Listing an Instagram account's posts needs a Meta permission Baker's Meta connection does not ask for yet. \" +\n \"Ask the user for the post's link or id instead, or boost it from Meta Business Suite, and carry on.\",\n} as const;\n\nconst META_PAGE_ADS_PERMISSION_REMEDY =\n \"A Baker admin turns it on with the lead ads switch for this company; then the user reconnects Meta in the dashboard. \" +\n \"Tell the user, and carry on with the rest of the job.\";\n\n/**\n * Click-to-message ads and Instant Experiences need Meta's Page ads permission\n * (`pages_manage_ads`), which only the lead ads switch adds to the consent\n * screen. `work` names what was refused (\"Click-to-message ads\").\n */\nexport function metaPageAdsPermissionMessage(work: string): string {\n return `${work} need Meta's Page ads permission, and this Meta connection does not have it. ${META_PAGE_ADS_PERMISSION_REMEDY}`;\n}\n\n/**\n * Whether a `FORBIDDEN` message carries one of these refusals. `includes`, not\n * equality: a stage-time refusal may lead with what the op was trying to do.\n */\nexport function isMetaPermissionGateRefusal(message: string): boolean {\n return [\n ...Object.values(META_PERMISSION_NOT_ENABLED_MESSAGE),\n ...Object.values(META_PERMISSION_RECONNECT_MESSAGE),\n ...Object.values(META_UNREQUESTED_PERMISSION_MESSAGE),\n META_PAGE_ADS_PERMISSION_REMEDY,\n ].some((refusal) => message.includes(refusal));\n}\n","import { isMetaPermissionGateRefusal } from \"@baker/api/ads-meta/permissionGates\";\nimport { ApiError } from \"../../../client.ts\";\nimport { getEnv } from \"../../../env.ts\";\nimport { handleConnectionError, isOrganizationReadRefusal, needsConnectionFix } from \"../../../error-handler.ts\";\nimport { writeAdsJson } from \"../output.ts\";\nimport type { AdsErrorEnvelope, QueryFix } from \"../types.ts\";\n\nconst DAY_MS = 86_400_000;\n\n/**\n * Meta answers a permission refusal (Graph codes 200/10/294) with a bare\n * \"Permissions error\" that covers two causes needing opposite remedies: a\n * consent grant the connection never got — nothing validates Meta's granted\n * scopes after connect, unlike HubSpot's `requireCapability` — or a role the\n * user lacks on one asset, since a Pixel/Dataset, Page or catalog lives in a\n * Business and is assigned separately from the ad account. Only the blast radius\n * separates them, so hand the agent that test rather than a verdict: guessing\n * \"reconnect\" wastes the user's time on an unassigned asset, and ruling it out\n * strands a connection that really is short a scope.\n */\nexport function metaForbiddenFix(message: string): QueryFix {\n // Baker's own refusal already names the switch or the reconnect; Meta's\n // two-cause advice under it would contradict it.\n if (isMetaPermissionGateRefusal(message)) {\n return { action: \"reject\", explanation: message };\n }\n if (message.includes(\"has not accepted Meta's Lead Generation Terms\")) {\n return {\n action: \"reject\",\n explanation: `${message}\\n\\nMeta confirmed the Page's terms status using its Page access. Give the Page owner the terms link in the error and ask them to accept it before trying the form or lead ad set again. Do not suggest reconnecting Meta for this refusal; continue with other work that does not require the form or ad set.`,\n };\n }\n return {\n action: \"reject\",\n explanation: [\n message,\n \"This is a permission refusal, not a dead connection, and Meta returns the same code for two causes with opposite remedies. Tell them apart by how much else works before you answer.\",\n \"If other reads on this account are ALSO refused (campaigns, ad sets, insights), the connection is short a permission it was never granted. Only the user can widen it, by reconnecting Meta from the dashboard.\",\n \"If those reads work and only this object is refused, the asset (pixel/dataset, Page, or catalog) belongs to a Business the connected user holds no role in. Ad-account access does not carry asset access and reconnecting cannot grant it — the client assigns that asset to the connected user or partner in Meta Business settings, under the asset's own section (Data sources → Datasets for a pixel).\",\n \"Either way do not retry the same call, and do not abort the wider job. Continue with what you can read, and state in your answer that this specific check could not run and why — never present the task as verified when this step was skipped.\",\n ].join(\"\\n\\n\"),\n };\n}\n\nexport function handleMetaError(err: unknown): never {\n if (err instanceof ApiError) {\n if (needsConnectionFix(err.code, err.message)) {\n handleConnectionError(\"meta_ads\", err.message);\n }\n const envelope: AdsErrorEnvelope = {\n ok: false,\n error: {\n code: err.code,\n message: err.message,\n fix:\n err.code === \"FORBIDDEN\" && !isOrganizationReadRefusal(err.message)\n ? metaForbiddenFix(err.message)\n : { action: \"reject\", explanation: err.message },\n retryable: err.code === \"RATE_LIMITED\" || err.code === \"UNAVAILABLE\" || err.code === \"INTERNAL_ERROR\",\n },\n };\n writeAdsJson(envelope);\n process.exit(1);\n }\n const message = err instanceof Error ? err.message : \"Unexpected error\";\n writeAdsJson({ ok: false, error: { code: \"NETWORK_ERROR\", message } });\n process.exit(1);\n}\n\nconst ACCOUNT_ID_RE = /^(act_)?[0-9]+$/;\n\n/** Pull the default Meta ad account ID from `--account-id` arg or `BAKER_META_AD_ACCOUNT_ID` env. */\nexport function resolveAccountIdArg(args: Record<string, unknown>): string {\n const fromArgs = args[\"account-id\"] as string | undefined;\n const id = fromArgs || getEnv().BAKER_META_AD_ACCOUNT_ID;\n if (!id) {\n writeAdsJson({\n ok: false,\n error: {\n code: \"MISSING_ACCOUNT_ID\",\n message: \"Pass --account-id or set BAKER_META_AD_ACCOUNT_ID. Run `baker ads meta accounts` to find IDs.\",\n },\n });\n process.exit(1);\n }\n if (!ACCOUNT_ID_RE.test(id)) {\n writeAdsJson({\n ok: false,\n error: {\n code: \"INVALID_ACCOUNT_ID\",\n message: `Invalid account ID \"${id}\". Expected numeric ID, optionally prefixed with \"act_\".`,\n },\n });\n process.exit(1);\n }\n return id.startsWith(\"act_\") ? id : `act_${id}`;\n}\n\nexport function getDateRange(args: Record<string, unknown>): { datePreset?: string; since?: string; until?: string } {\n const datePreset = args[\"date-preset\"] as string | undefined;\n const since = args.since as string | undefined;\n const until = args.until as string | undefined;\n if (since && until) return { since, until };\n return { datePreset: datePreset ?? \"last_7d\" };\n}\n\nexport function todayIso(): string {\n return new Date().toISOString().slice(0, 10);\n}\n\nexport function daysAgoIso(days: number): string {\n return new Date(Date.now() - days * DAY_MS).toISOString().slice(0, 10);\n}\n\nexport function csvOrJson(args: Record<string, unknown>): string {\n return (args.output as string | undefined) ?? \"json\";\n}\n\n/**\n * Matched by Meta itself, so finding one entity by name reads only the rows that\n * match instead of the whole account.\n */\nexport const NAME_CONTAINS_ARG = {\n type: \"string\",\n description:\n \"Only rows whose name contains this text, matched by Meta before anything is returned. Start here to find one entity by name: --name-contains octubre --all-statuses\",\n} as const;\n\n/**\n * Default to ACTIVE-only on listings — that's almost always what an AI agent or\n * a human glance wants. Pass `--effective-status ACTIVE,PAUSED` to override, or\n * `--all-statuses` to drop the filter entirely.\n */\nexport function resolveEffectiveStatus(args: Record<string, unknown>): string | undefined {\n if (args[\"all-statuses\"]) {\n return undefined;\n }\n const explicit = args[\"effective-status\"] as string | undefined;\n if (explicit) {\n return explicit;\n }\n return \"ACTIVE\";\n}\n\n/**\n * An empty listing under a status filter reads exactly like \"nothing exists\":\n * a paused campaign's ad sets are CAMPAIGN_PAUSED, so the ACTIVE default hides\n * every one of them. Say which filter produced the empty list and how to widen it.\n */\nexport function statusFilterHints(\n rows: ReadonlyArray<unknown>,\n effectiveStatus: string | undefined,\n noun: string,\n): string[] {\n if (rows.length > 0 || effectiveStatus === undefined) return [];\n if (effectiveStatus === \"ACTIVE\") {\n return [\n `No ACTIVE ${noun}. The ACTIVE filter hides paused, archived and in-review ones (under a paused campaign or ad set that is all of them), so this does NOT mean none exist. Re-run with --all-statuses before concluding there are none.`,\n ];\n }\n return [\n `No ${noun} with effective_status ${effectiveStatus}. Re-run with --all-statuses to see every status before concluding there are none.`,\n ];\n}\n"],"mappings":"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","names":[]}