@koda-sl/baker-cli 0.513.0 → 0.514.0-dev.555f7007e

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 (1156) hide show
  1. package/README.md +19 -2
  2. package/dist/account-QX4G4BJ7.js +82 -0
  3. package/dist/account-QX4G4BJ7.js.map +1 -0
  4. package/dist/account-UFYZS3K6.js +82 -0
  5. package/dist/account-UFYZS3K6.js.map +1 -0
  6. package/dist/account-assets-J5Z4URLQ.js +290 -0
  7. package/dist/account-level-4SBYYHRS.js +611 -0
  8. package/dist/account-level-4SBYYHRS.js.map +1 -0
  9. package/dist/account-reads-FOEVPWDP.js +219 -0
  10. package/dist/account-users-UTIF7MIT.js +64 -0
  11. package/dist/account-users-UTIF7MIT.js.map +1 -0
  12. package/dist/account-writes-QAQXRIEY.js +68 -0
  13. package/dist/account-writes-QAQXRIEY.js.map +1 -0
  14. package/dist/accounts-JK3OAS5U.js +701 -0
  15. package/dist/accounts-JK3OAS5U.js.map +1 -0
  16. package/dist/accounts-OE33CKWD.js +80 -0
  17. package/dist/accounts-OE33CKWD.js.map +1 -0
  18. package/dist/actions-QZDSLFFK.js +55 -0
  19. package/dist/activecampaign-U6TKRR45.js +938 -0
  20. package/dist/activecampaign-U6TKRR45.js.map +1 -0
  21. package/dist/ad-group-writes-XY5JYTKT.js +172 -0
  22. package/dist/ad-group-writes-XY5JYTKT.js.map +1 -0
  23. package/dist/ad-groups-YEO5ZS5U.js +70 -0
  24. package/dist/ad-groups-YEO5ZS5U.js.map +1 -0
  25. package/dist/ad-writes-XRCPK4SP.js +176 -0
  26. package/dist/ad-writes-XRCPK4SP.js.map +1 -0
  27. package/dist/add-2EF7S4NK.js +305 -0
  28. package/dist/add-2EF7S4NK.js.map +1 -0
  29. package/dist/add-YCJ6RXPG.js +107 -0
  30. package/dist/add-YCJ6RXPG.js.map +1 -0
  31. package/dist/ads-AYJAYLFR.js +48 -0
  32. package/dist/ads-H7H7H2CM.js +79 -0
  33. package/dist/ads-H7H7H2CM.js.map +1 -0
  34. package/dist/ads-MAOI7S6V.js +115 -0
  35. package/dist/adsets-QRKICEFD.js +182 -0
  36. package/dist/advertisers-JLSU3G35.js +123 -0
  37. package/dist/advertisers-JLSU3G35.js.map +1 -0
  38. package/dist/analytics-ADIWEM6G.js +2437 -0
  39. package/dist/analytics-ADIWEM6G.js.map +1 -0
  40. package/dist/analytics-XB6FRNVJ.js +447 -0
  41. package/dist/analytics-XB6FRNVJ.js.map +1 -0
  42. package/dist/animate-HRWFVE2N.js +480 -0
  43. package/dist/asset-writes-JLVUAVUZ.js +50 -0
  44. package/dist/assign-IWZ2OPFL.js +80 -0
  45. package/dist/assign-IWZ2OPFL.js.map +1 -0
  46. package/dist/audience-size-P5L6MZ4C.js +76 -0
  47. package/dist/audience-size-P5L6MZ4C.js.map +1 -0
  48. package/dist/audience-writes-CDKQB3SM.js +327 -0
  49. package/dist/audience-writes-CDKQB3SM.js.map +1 -0
  50. package/dist/audiences-CDDI5HR5.js +86 -0
  51. package/dist/audiences-XKERWKKE.js +280 -0
  52. package/dist/audiences-XKERWKKE.js.map +1 -0
  53. package/dist/audit-SEADLC6F.js +154 -0
  54. package/dist/audit-SEADLC6F.js.map +1 -0
  55. package/dist/autocomplete-AJQBJS5R.js +114 -0
  56. package/dist/autocomplete-AJQBJS5R.js.map +1 -0
  57. package/dist/avatars-4HCGWBOL.js +38 -0
  58. package/dist/bid-pricing-NWSUO3VM.js +103 -0
  59. package/dist/bid-pricing-NWSUO3VM.js.map +1 -0
  60. package/dist/brand-C6OB6Q4U.js +22 -0
  61. package/dist/brief-LCWWQ4OC.js +543 -0
  62. package/dist/brief-LCWWQ4OC.js.map +1 -0
  63. package/dist/campaign-groups-PH64UXZJ.js +99 -0
  64. package/dist/campaign-groups-PH64UXZJ.js.map +1 -0
  65. package/dist/campaign-writes-BN3EGDK5.js +168 -0
  66. package/dist/campaign-writes-BN3EGDK5.js.map +1 -0
  67. package/dist/campaign-writes-CLV5ZSUK.js +176 -0
  68. package/dist/campaign-writes-CLV5ZSUK.js.map +1 -0
  69. package/dist/campaigns-5XRY27JZ.js +78 -0
  70. package/dist/campaigns-5XRY27JZ.js.map +1 -0
  71. package/dist/campaigns-HES5MDUG.js +130 -0
  72. package/dist/campaigns-JF4TYYUP.js +113 -0
  73. package/dist/campaigns-JF4TYYUP.js.map +1 -0
  74. package/dist/campaigns-ZYU4BXDP.js +111 -0
  75. package/dist/canvas-AI34UBGU.js +46 -0
  76. package/dist/capabilities-TRHAPTUU.js +147 -0
  77. package/dist/capabilities-TRHAPTUU.js.map +1 -0
  78. package/dist/catalog-ZY3MFT55.js +65 -0
  79. package/dist/catalogs-6XLBWAUS.js +130 -0
  80. package/dist/catalogs-6XLBWAUS.js.map +1 -0
  81. package/dist/catalogs-TGLSJEK5.js +781 -0
  82. package/dist/catalogs-TGLSJEK5.js.map +1 -0
  83. package/dist/changes-OOUVQDBY.js +135 -0
  84. package/dist/chatgpt-NAXIFWXV.js +47 -0
  85. package/dist/chats-I5RHBRS5.js +279 -0
  86. package/dist/chats-I5RHBRS5.js.map +1 -0
  87. package/dist/check-3E64VBUE.js +107 -0
  88. package/dist/check-3E64VBUE.js.map +1 -0
  89. package/dist/chunk-3CHYJYSS.js +319 -0
  90. package/dist/chunk-3G3GC5N4.js +429 -0
  91. package/dist/chunk-3M45PYU7.js +274 -0
  92. package/dist/chunk-3QHXF3QI.js +23 -0
  93. package/dist/chunk-3XPHUMLJ.js +3868 -0
  94. package/dist/chunk-45EERHDB.js +783 -0
  95. package/dist/chunk-4FGTANFK.js +387 -0
  96. package/dist/chunk-4IHWT7PH.js +167 -0
  97. package/dist/chunk-4LF4AYPT.js +846 -0
  98. package/dist/chunk-4UQRXKYJ.js +219 -0
  99. package/dist/chunk-5JJD33Y2.js +455 -0
  100. package/dist/chunk-5K4QYYOJ.js +831 -0
  101. package/dist/chunk-5LJ6E4YU.js +163 -0
  102. package/dist/chunk-5T73MMBL.js +275 -0
  103. package/dist/chunk-64MAHLTK.js +363 -0
  104. package/dist/chunk-6OIKNJ7G.js +26 -0
  105. package/dist/chunk-6ZFSDYWV.js +131 -0
  106. package/dist/chunk-7BUIOP36.js +287 -0
  107. package/dist/chunk-7I6ZVBLM.js +358 -0
  108. package/dist/chunk-7I6ZVBLM.js.map +1 -0
  109. package/dist/chunk-AN4OEQXE.js +122 -0
  110. package/dist/chunk-AULSX5ZA.js +5368 -0
  111. package/dist/chunk-AVYUFJQQ.js +46 -0
  112. package/dist/chunk-B4YF7VQF.js +97 -0
  113. package/dist/chunk-BDOYNGUL.js +98 -0
  114. package/dist/chunk-BJOK7QD4.js +207 -0
  115. package/dist/chunk-CMCGFSUS.js +197 -0
  116. package/dist/chunk-DMJUIUAL.js +676 -0
  117. package/dist/chunk-DUCUOZLS.js +225 -0
  118. package/dist/chunk-EW7JSTRZ.js +24026 -0
  119. package/dist/chunk-EW7JSTRZ.js.map +1 -0
  120. package/dist/chunk-F3CZFUXZ.js +3187 -0
  121. package/dist/chunk-F3CZFUXZ.js.map +1 -0
  122. package/dist/chunk-FJZYOVSW.js +843 -0
  123. package/dist/chunk-FKP4ECJY.js +19 -0
  124. package/dist/chunk-G4FG5EQO.js +110 -0
  125. package/dist/chunk-G4FG5EQO.js.map +1 -0
  126. package/dist/chunk-GAYRBIEF.js +712 -0
  127. package/dist/chunk-GAYRBIEF.js.map +1 -0
  128. package/dist/chunk-GNMEOU46.js +8954 -0
  129. package/dist/chunk-GYKYXWUQ.js +156 -0
  130. package/dist/chunk-GYPLRU4Y.js +297 -0
  131. package/dist/chunk-I43ZEWJQ.js +285 -0
  132. package/dist/chunk-IZABTTW5.js +228 -0
  133. package/dist/chunk-JOE42ZW6.js +2984 -0
  134. package/dist/chunk-JOE42ZW6.js.map +1 -0
  135. package/dist/chunk-K7IE6UYV.js +1646 -0
  136. package/dist/chunk-KH5YHHJV.js +604 -0
  137. package/dist/chunk-KMY7AD3N.js +51 -0
  138. package/dist/chunk-KPCHWDJM.js +8914 -0
  139. package/dist/chunk-KTZCLJ2D.js +148 -0
  140. package/dist/chunk-MKUA54QE.js +638 -0
  141. package/dist/chunk-MTV2RSGY.js +63 -0
  142. package/dist/chunk-MUS2UTWU.js +4254 -0
  143. package/dist/chunk-MUS2UTWU.js.map +1 -0
  144. package/dist/chunk-N2QX57K3.js +392 -0
  145. package/dist/chunk-NB2FU6EZ.js +179 -0
  146. package/dist/chunk-NEYWS2DQ.js +479 -0
  147. package/dist/chunk-NKQWDEB7.js +115 -0
  148. package/dist/chunk-NKQWDEB7.js.map +1 -0
  149. package/dist/chunk-NWF2LRKO.js +188 -0
  150. package/dist/chunk-NZ34KM46.js +7211 -0
  151. package/dist/chunk-NZ34KM46.js.map +1 -0
  152. package/dist/chunk-OTC6UMJ2.js +191 -0
  153. package/dist/chunk-OUY2IAWL.js +224 -0
  154. package/dist/chunk-PJXNCRMR.js +344 -0
  155. package/dist/chunk-PYQ3GF7R.js +91 -0
  156. package/dist/chunk-Q3EIVZAR.js +170 -0
  157. package/dist/chunk-Q3GSVLE5.js +4274 -0
  158. package/dist/chunk-Q3GSVLE5.js.map +1 -0
  159. package/dist/chunk-QDQZ62FL.js +207 -0
  160. package/dist/chunk-QHZE62GP.js +1919 -0
  161. package/dist/chunk-RGR6TSTJ.js +103 -0
  162. package/dist/chunk-SAAXU7QR.js +203 -0
  163. package/dist/chunk-SHTKLRI6.js +66 -0
  164. package/dist/chunk-SIKCVWM3.js +76 -0
  165. package/dist/chunk-SOPVIIUW.js +68 -0
  166. package/dist/chunk-SOPVIIUW.js.map +1 -0
  167. package/dist/chunk-SSXG53CZ.js +89 -0
  168. package/dist/chunk-TBWAM577.js +547 -0
  169. package/dist/chunk-TGPGQTZA.js +169 -0
  170. package/dist/chunk-UMIX2BMM.js +1518 -0
  171. package/dist/chunk-URMAEVZO.js +150 -0
  172. package/dist/chunk-VBO3ZVUU.js +61 -0
  173. package/dist/chunk-VFLYMHTO.js +592 -0
  174. package/dist/chunk-VGYIVXIZ.js +249 -0
  175. package/dist/chunk-VIB7R533.js +57 -0
  176. package/dist/chunk-WLESMH4J.js +45 -0
  177. package/dist/chunk-WVWLPXBO.js +910 -0
  178. package/dist/chunk-XEH5XAP6.js +494 -0
  179. package/dist/chunk-XEOKVL4E.js +142 -0
  180. package/dist/chunk-XOGQJYXH.js +64 -0
  181. package/dist/chunk-XOQNM7I4.js +396 -0
  182. package/dist/chunk-XOQNM7I4.js.map +1 -0
  183. package/dist/chunk-XUXRA7IB.js +942 -0
  184. package/dist/claim-FIK2YTLM.js +200 -0
  185. package/dist/claim-FIK2YTLM.js.map +1 -0
  186. package/dist/cli.js +34 -33
  187. package/dist/cli.js.map +1 -1
  188. package/dist/companies-KMMV6EJW.js +198 -0
  189. package/dist/companies-KMMV6EJW.js.map +1 -0
  190. package/dist/company-B54URPJG.js +308 -0
  191. package/dist/company-B54URPJG.js.map +1 -0
  192. package/dist/complete-PPCWEXS3.js +84 -0
  193. package/dist/complete-PPCWEXS3.js.map +1 -0
  194. package/dist/connect-IAXSZPGA.js +45 -0
  195. package/dist/conversation-KHTZBGX2.js +96 -0
  196. package/dist/conversation-KHTZBGX2.js.map +1 -0
  197. package/dist/conversion-report-U66HW6JM.js +127 -0
  198. package/dist/conversion-report-U66HW6JM.js.map +1 -0
  199. package/dist/conversion-upload-command-IHFKVX2M.js +439 -0
  200. package/dist/conversion-writes-RSGDOAET.js +122 -0
  201. package/dist/conversion-writes-RSGDOAET.js.map +1 -0
  202. package/dist/conversions-BVOL43W4.js +78 -0
  203. package/dist/conversions-BVOL43W4.js.map +1 -0
  204. package/dist/conversions-SUMZAV2T.js +140 -0
  205. package/dist/conversions-SUMZAV2T.js.map +1 -0
  206. package/dist/copy-writes-CIHIFLY6.js +170 -0
  207. package/dist/copy-writes-CIHIFLY6.js.map +1 -0
  208. package/dist/create-732HQL3C.js +210 -0
  209. package/dist/create-732HQL3C.js.map +1 -0
  210. package/dist/create-TFR6R2KF.js +239 -0
  211. package/dist/create-TFR6R2KF.js.map +1 -0
  212. package/dist/create-UC57ULRL.js +62 -0
  213. package/dist/create-UC57ULRL.js.map +1 -0
  214. package/dist/create-UL2OYXOA.js +135 -0
  215. package/dist/create-UL2OYXOA.js.map +1 -0
  216. package/dist/creatives-BB6S2OF6.js +89 -0
  217. package/dist/creatives-BZEVJ6ER.js +58 -0
  218. package/dist/creatives-FU3YELGU.js +223 -0
  219. package/dist/creatives-FU3YELGU.js.map +1 -0
  220. package/dist/credentials-AYV5YQE4.js +290 -0
  221. package/dist/credentials-AYV5YQE4.js.map +1 -0
  222. package/dist/critique-FKIJB72I.js +1451 -0
  223. package/dist/critique-FKIJB72I.js.map +1 -0
  224. package/dist/critique-IQYNDXCN.js +232 -0
  225. package/dist/critique-IQYNDXCN.js.map +1 -0
  226. package/dist/crm-ILQMNJPX.js +323 -0
  227. package/dist/crm-ILQMNJPX.js.map +1 -0
  228. package/dist/crm-MQQRBITZ.js +227 -0
  229. package/dist/crm-MQQRBITZ.js.map +1 -0
  230. package/dist/currency-CGKO5GKH.js +88 -0
  231. package/dist/custom-conversions-HAGG72LF.js +128 -0
  232. package/dist/customers-NKKU6S7G.js +59 -0
  233. package/dist/delete-2TCCNRMH.js +57 -0
  234. package/dist/delete-2TCCNRMH.js.map +1 -0
  235. package/dist/delete-HCZTISBT.js +69 -0
  236. package/dist/delete-HCZTISBT.js.map +1 -0
  237. package/dist/delete-UIKB5ZXS.js +67 -0
  238. package/dist/delete-UIKB5ZXS.js.map +1 -0
  239. package/dist/demographics-ABZODD45.js +141 -0
  240. package/dist/demographics-ABZODD45.js.map +1 -0
  241. package/dist/discard-V3K5PZ4W.js +69 -0
  242. package/dist/discard-V3K5PZ4W.js.map +1 -0
  243. package/dist/discover-VM3O7CQM.js +172 -0
  244. package/dist/domain-A66DHOTQ.js +101 -0
  245. package/dist/domain-A66DHOTQ.js.map +1 -0
  246. package/dist/download-LSAZD5JO.js +172 -0
  247. package/dist/download-LSAZD5JO.js.map +1 -0
  248. package/dist/draft-5UUJC675.js +335 -0
  249. package/dist/draft-5UUJC675.js.map +1 -0
  250. package/dist/draft-BATA5CVI.js +283 -0
  251. package/dist/draft-BATA5CVI.js.map +1 -0
  252. package/dist/draft-CRDBU6LF.js +308 -0
  253. package/dist/draft-P7IDMXWR.js +310 -0
  254. package/dist/draft-P7IDMXWR.js.map +1 -0
  255. package/dist/draft-YBNL4ZZA.js +220 -0
  256. package/dist/draft-YBNL4ZZA.js.map +1 -0
  257. package/dist/engine/index.js +7 -7
  258. package/dist/experiments-MLLTHMMS.js +236 -0
  259. package/dist/experiments-MLLTHMMS.js.map +1 -0
  260. package/dist/facets-KSHR3MBE.js +117 -0
  261. package/dist/facets-KSHR3MBE.js.map +1 -0
  262. package/dist/feedback-4GCPXZSI.js +111 -0
  263. package/dist/feedback-4GCPXZSI.js.map +1 -0
  264. package/dist/feedback-record-VEFHUIUJ.js +265 -0
  265. package/dist/feedback-record-VEFHUIUJ.js.map +1 -0
  266. package/dist/fetch-42QL56JC.js +179 -0
  267. package/dist/fetch-42QL56JC.js.map +1 -0
  268. package/dist/fit-Q5GRVF2O.js +65 -0
  269. package/dist/flows-M3WBZQET.js +250 -0
  270. package/dist/flows-M3WBZQET.js.map +1 -0
  271. package/dist/fonts-GD4YRXQU.js +39 -0
  272. package/dist/forecast-HT46MFL4.js +121 -0
  273. package/dist/forecast-HT46MFL4.js.map +1 -0
  274. package/dist/forecast-ONVS2QAI.js +169 -0
  275. package/dist/funnel-76BAD64Q.js +397 -0
  276. package/dist/funnel-76BAD64Q.js.map +1 -0
  277. package/dist/generate-VBEY3N3L.js +263 -0
  278. package/dist/get-4KFAO475.js +82 -0
  279. package/dist/get-4KFAO475.js.map +1 -0
  280. package/dist/get-QV5NIADE.js +59 -0
  281. package/dist/get-QV5NIADE.js.map +1 -0
  282. package/dist/google-7EZP7I6J.js +3267 -0
  283. package/dist/google-ads-J7WHTJO4.js +198 -0
  284. package/dist/google-ads-J7WHTJO4.js.map +1 -0
  285. package/dist/history-EULKWQUS.js +136 -0
  286. package/dist/history-EULKWQUS.js.map +1 -0
  287. package/dist/history-FEBJHFHJ.js +69 -0
  288. package/dist/history-FEBJHFHJ.js.map +1 -0
  289. package/dist/history-RDVV7KBN.js +102 -0
  290. package/dist/history-RDVV7KBN.js.map +1 -0
  291. package/dist/hubspot-A3RQNMYN.js +782 -0
  292. package/dist/hubspot-A3RQNMYN.js.map +1 -0
  293. package/dist/ideas-WX7EBPSF.js +45 -0
  294. package/dist/images-4AXF4LAC.js +92 -0
  295. package/dist/ingest-AM5YDTRH.js +110 -0
  296. package/dist/ingest-AM5YDTRH.js.map +1 -0
  297. package/dist/ingest-C3M4GUO6.js +26 -0
  298. package/dist/insights-UTCMSWSC.js +132 -0
  299. package/dist/insights-UTCMSWSC.js.map +1 -0
  300. package/dist/insights-XZL2EM53.js +439 -0
  301. package/dist/insights-XZL2EM53.js.map +1 -0
  302. package/dist/inspect-DWCLRZGR.js +192 -0
  303. package/dist/inspect-DWCLRZGR.js.map +1 -0
  304. package/dist/instant-experiences-RM4MLJTL.js +260 -0
  305. package/dist/instant-experiences-RM4MLJTL.js.map +1 -0
  306. package/dist/intent-ZMYMFGB4.js +95 -0
  307. package/dist/keyword-gap-XSJO2R77.js +130 -0
  308. package/dist/keyword-metrics-M46FCTAS.js +200 -0
  309. package/dist/keyword-metrics-M46FCTAS.js.map +1 -0
  310. package/dist/keywords-for-site-XNSLX7EA.js +131 -0
  311. package/dist/keywords-for-site-XNSLX7EA.js.map +1 -0
  312. package/dist/landing-MUNYZQNA.js +28 -0
  313. package/dist/languages-DIQ3OG3E.js +40 -0
  314. package/dist/lead-routes-XBO2GOBL.js +608 -0
  315. package/dist/lead-routes-XBO2GOBL.js.map +1 -0
  316. package/dist/leads-LAATTW5G.js +115 -0
  317. package/dist/leads-LAATTW5G.js.map +1 -0
  318. package/dist/leads-ULYHTG22.js +540 -0
  319. package/dist/leads-ULYHTG22.js.map +1 -0
  320. package/dist/learn-3GLY4G3H.js +207 -0
  321. package/dist/learn-3GLY4G3H.js.map +1 -0
  322. package/dist/line-item-writes-XJTTA3X5.js +211 -0
  323. package/dist/line-item-writes-XJTTA3X5.js.map +1 -0
  324. package/dist/line-items-JR25T2C5.js +107 -0
  325. package/dist/link-7DSLIF3I.js +67 -0
  326. package/dist/link-7DSLIF3I.js.map +1 -0
  327. package/dist/linkedin-W5BJ6HEH.js +1316 -0
  328. package/dist/linkedin-W5BJ6HEH.js.map +1 -0
  329. package/dist/linkedin-person-2ZYSOHYR.js +139 -0
  330. package/dist/linkedin-person-2ZYSOHYR.js.map +1 -0
  331. package/dist/list-3653DIYB.js +67 -0
  332. package/dist/list-3653DIYB.js.map +1 -0
  333. package/dist/list-G66HVYCR.js +306 -0
  334. package/dist/list-G66HVYCR.js.map +1 -0
  335. package/dist/list-Z4M53MS5.js +154 -0
  336. package/dist/list-Z4M53MS5.js.map +1 -0
  337. package/dist/locations-HTVYJSDJ.js +40 -0
  338. package/dist/locations-M2B5XDU4.js +69 -0
  339. package/dist/locations-M2B5XDU4.js.map +1 -0
  340. package/dist/log-2RJU5BOW.js +95 -0
  341. package/dist/log-2RJU5BOW.js.map +1 -0
  342. package/dist/lookup-S5VG7AWH.js +23 -0
  343. package/dist/make-MJ6JMU5T.js +1370 -0
  344. package/dist/make-MJ6JMU5T.js.map +1 -0
  345. package/dist/map-27IPOBY6.js +436 -0
  346. package/dist/map-27IPOBY6.js.map +1 -0
  347. package/dist/mcp-TFQTME4P.js +717 -0
  348. package/dist/mcp-TFQTME4P.js.map +1 -0
  349. package/dist/media-P4T4ZBNS.js +18 -0
  350. package/dist/media-sources-P246GM7W.js +35 -0
  351. package/dist/members-KOKBTUC2.js +47 -0
  352. package/dist/members-KOKBTUC2.js.map +1 -0
  353. package/dist/meta-IPLWNYC7.js +122 -0
  354. package/dist/metrics-WYWUX6Y5.js +152 -0
  355. package/dist/models-HJ7Y55AH.js +155 -0
  356. package/dist/normalize-GXBUNTYJ.js +144 -0
  357. package/dist/normalize-GXBUNTYJ.js.map +1 -0
  358. package/dist/options-MA25RNXF.js +125 -0
  359. package/dist/options-MA25RNXF.js.map +1 -0
  360. package/dist/organization-NLEVNGKQ.js +949 -0
  361. package/dist/organization-NLEVNGKQ.js.map +1 -0
  362. package/dist/page-photos-OQ5QATQH.js +118 -0
  363. package/dist/page-photos-OQ5QATQH.js.map +1 -0
  364. package/dist/performance-34EUP5KL.js +5541 -0
  365. package/dist/performance-34EUP5KL.js.map +1 -0
  366. package/dist/performance-J3DLNI2W.js +27 -0
  367. package/dist/pixels-THEGYRXT.js +62 -0
  368. package/dist/pixels-THEGYRXT.js.map +1 -0
  369. package/dist/plan-7UF76Q6U.js +208 -0
  370. package/dist/plan-7UF76Q6U.js.map +1 -0
  371. package/dist/preview-LRJOQ7LM.js +218 -0
  372. package/dist/preview-LRJOQ7LM.js.map +1 -0
  373. package/dist/promoted-tweet-writes-SBXWKO23.js +183 -0
  374. package/dist/promoted-tweet-writes-SBXWKO23.js.map +1 -0
  375. package/dist/promoted-tweets-W42FNWS7.js +119 -0
  376. package/dist/publish-YG76GOA7.js +344 -0
  377. package/dist/publish-YG76GOA7.js.map +1 -0
  378. package/dist/query-IQICLABN.js +62 -0
  379. package/dist/questionnaire-DWEH5II4.js +94 -0
  380. package/dist/questionnaire-DWEH5II4.js.map +1 -0
  381. package/dist/reddit-X4CERXYF.js +29 -0
  382. package/dist/refresh-A36GA7JN.js +97 -0
  383. package/dist/refresh-A36GA7JN.js.map +1 -0
  384. package/dist/release-3NCMZIDI.js +63 -0
  385. package/dist/release-3NCMZIDI.js.map +1 -0
  386. package/dist/relevant-pages-UDDQOYLD.js +99 -0
  387. package/dist/remove-6LE3XNRG.js +53 -0
  388. package/dist/remove-6LE3XNRG.js.map +1 -0
  389. package/dist/reopen-XLADJ2UU.js +66 -0
  390. package/dist/reopen-XLADJ2UU.js.map +1 -0
  391. package/dist/rerun-QVMFJZA2.js +95 -0
  392. package/dist/rerun-QVMFJZA2.js.map +1 -0
  393. package/dist/research-D5UUJF74.js +72 -0
  394. package/dist/research-QCI5ISUE.js +265 -0
  395. package/dist/research-QCI5ISUE.js.map +1 -0
  396. package/dist/reset-DD37KDXQ.js +57 -0
  397. package/dist/reset-DD37KDXQ.js.map +1 -0
  398. package/dist/reset-FLZPKY2N.js +57 -0
  399. package/dist/reset-FLZPKY2N.js.map +1 -0
  400. package/dist/resolve-KRKIJKT7.js +124 -0
  401. package/dist/resolve-KRKIJKT7.js.map +1 -0
  402. package/dist/retry-ALXYEKFV.js +65 -0
  403. package/dist/retry-ALXYEKFV.js.map +1 -0
  404. package/dist/retry-MIXKW4EW.js +63 -0
  405. package/dist/retry-MIXKW4EW.js.map +1 -0
  406. package/dist/revenue-UBZUTSXN.js +91 -0
  407. package/dist/revenue-UBZUTSXN.js.map +1 -0
  408. package/dist/rule-writes-UAVWT4XS.js +525 -0
  409. package/dist/rule-writes-UAVWT4XS.js.map +1 -0
  410. package/dist/rules-SO6P44B6.js +99 -0
  411. package/dist/rules-SO6P44B6.js.map +1 -0
  412. package/dist/rules-ZVS2MWED.js +217 -0
  413. package/dist/rules-add-XN3BZKFO.js +465 -0
  414. package/dist/rules-add-XN3BZKFO.js.map +1 -0
  415. package/dist/run-K2DOMOAN.js +69 -0
  416. package/dist/run-K2DOMOAN.js.map +1 -0
  417. package/dist/run-T7XAH2W5.js +70 -0
  418. package/dist/scaffold-ad-TWIT7R4U.js +1516 -0
  419. package/dist/scaffold-ad-TWIT7R4U.js.map +1 -0
  420. package/dist/scaffold-static-ad-GPJKOGOI.js +1015 -0
  421. package/dist/scaffold-static-ad-GPJKOGOI.js.map +1 -0
  422. package/dist/scaffold-video-7BQNOJ4S.js +888 -0
  423. package/dist/scaffold-video-7BQNOJ4S.js.map +1 -0
  424. package/dist/schedule-UTRVEWPE.js +64 -0
  425. package/dist/schedule-UTRVEWPE.js.map +1 -0
  426. package/dist/scheduled-agents-ZGCUZ6SB.js +55 -0
  427. package/dist/schema-D6BMZAPB.js +69 -0
  428. package/dist/schema-DSMF6ELE.js +135 -0
  429. package/dist/schema-DSMF6ELE.js.map +1 -0
  430. package/dist/search-2P72GSKY.js +177 -0
  431. package/dist/search-2P72GSKY.js.map +1 -0
  432. package/dist/select-N7VWQ2ZQ.js +106 -0
  433. package/dist/select-N7VWQ2ZQ.js.map +1 -0
  434. package/dist/sends-LAY5C74B.js +349 -0
  435. package/dist/sends-LAY5C74B.js.map +1 -0
  436. package/dist/set-prompt-3N3HMHT6.js +198 -0
  437. package/dist/set-prompt-3N3HMHT6.js.map +1 -0
  438. package/dist/setup-links-I5RFZTS4.js +144 -0
  439. package/dist/setup-links-I5RFZTS4.js.map +1 -0
  440. package/dist/shopify-LXSR37XI.js +3958 -0
  441. package/dist/shopify-LXSR37XI.js.map +1 -0
  442. package/dist/site-AI3BFWRK.js +180 -0
  443. package/dist/site-AI3BFWRK.js.map +1 -0
  444. package/dist/sources-AOF2YDYX.js +457 -0
  445. package/dist/sources-AOF2YDYX.js.map +1 -0
  446. package/dist/sources-DVMJEXEX.js +30 -0
  447. package/dist/stale-P4GGOLIB.js +76 -0
  448. package/dist/stale-P4GGOLIB.js.map +1 -0
  449. package/dist/status-O25MXHU4.js +65 -0
  450. package/dist/status-O25MXHU4.js.map +1 -0
  451. package/dist/studies-EPO2AM4M.js +250 -0
  452. package/dist/studio-5Z4NMA4K.js +49 -0
  453. package/dist/study-writes-7FP443QQ.js +470 -0
  454. package/dist/study-writes-7FP443QQ.js.map +1 -0
  455. package/dist/sync-2AI7LKKN.js +57 -0
  456. package/dist/sync-2AI7LKKN.js.map +1 -0
  457. package/dist/sync-definition-F3CXG6KG.js +69 -0
  458. package/dist/tags-SEZ2CQJM.js +26 -0
  459. package/dist/tags-TJDZXOXS.js +227 -0
  460. package/dist/tags-TJDZXOXS.js.map +1 -0
  461. package/dist/tags-YSC7ZILI.js +23 -0
  462. package/dist/tags-YSC7ZILI.js.map +1 -0
  463. package/dist/tags-Z6EALYOS.js +23 -0
  464. package/dist/tags-Z6EALYOS.js.map +1 -0
  465. package/dist/tags-ZXSVW6XO.js +23 -0
  466. package/dist/tags-ZXSVW6XO.js.map +1 -0
  467. package/dist/targeting-NKZFEZD7.js +762 -0
  468. package/dist/targeting-NKZFEZD7.js.map +1 -0
  469. package/dist/targeting-criteria-AU5CSMAU.js +113 -0
  470. package/dist/targets-IOIH5JYS.js +106 -0
  471. package/dist/targets-IOIH5JYS.js.map +1 -0
  472. package/dist/testimonials-Y6PUV6AL.js +32 -0
  473. package/dist/themes-PGPIAKAO.js +95 -0
  474. package/dist/top-companies-FSITN3ZR.js +111 -0
  475. package/dist/top-companies-FSITN3ZR.js.map +1 -0
  476. package/dist/transcript-CGPX7Y37.js +165 -0
  477. package/dist/transcript-CGPX7Y37.js.map +1 -0
  478. package/dist/translate-QCBMGOKR.js +609 -0
  479. package/dist/translate-QCBMGOKR.js.map +1 -0
  480. package/dist/triggers-MONMZSKT.js +144 -0
  481. package/dist/triggers-MONMZSKT.js.map +1 -0
  482. package/dist/unlink-I7QFQQKO.js +70 -0
  483. package/dist/unlink-I7QFQQKO.js.map +1 -0
  484. package/dist/unstage-JXG5AU5Q.js +88 -0
  485. package/dist/unstage-JXG5AU5Q.js.map +1 -0
  486. package/dist/unstage-ZA3WQBEA.js +96 -0
  487. package/dist/unstage-ZA3WQBEA.js.map +1 -0
  488. package/dist/update-BVZGM54I.js +66 -0
  489. package/dist/update-BVZGM54I.js.map +1 -0
  490. package/dist/update-EI2BHUM2.js +101 -0
  491. package/dist/update-EI2BHUM2.js.map +1 -0
  492. package/dist/update-RZSV4NYP.js +155 -0
  493. package/dist/update-RZSV4NYP.js.map +1 -0
  494. package/dist/update-WLDNOZ5U.js +192 -0
  495. package/dist/update-WLDNOZ5U.js.map +1 -0
  496. package/dist/upload-BP3YEQSF.js +129 -0
  497. package/dist/upload-BP3YEQSF.js.map +1 -0
  498. package/dist/url-options-63DED6CR.js +131 -0
  499. package/dist/url-options-63DED6CR.js.map +1 -0
  500. package/dist/url-params-TRFI2PMD.js +101 -0
  501. package/dist/url-params-TRFI2PMD.js.map +1 -0
  502. package/dist/validate-SNCR25A7.js +122 -0
  503. package/dist/validate-SNCR25A7.js.map +1 -0
  504. package/dist/videos-SVZV5YYC.js +41 -0
  505. package/dist/viewer-check-LUAEGV6H.js +83 -0
  506. package/dist/web-MJQEK7BB.js +143 -0
  507. package/dist/web-MJQEK7BB.js.map +1 -0
  508. package/dist/winning-ads-KNLJHHCO.js +86 -0
  509. package/dist/write-commands-NVCX7IAU.js +1502 -0
  510. package/dist/write-commands-NVCX7IAU.js.map +1 -0
  511. package/dist/write-commands-OGVDWWBV.js +1172 -0
  512. package/dist/write-commands-OGVDWWBV.js.map +1 -0
  513. package/dist/x-ZQNHYIDU.js +47 -0
  514. package/package.json +1 -1
  515. package/dist/account-UUAEQWO3.js +0 -80
  516. package/dist/account-UUAEQWO3.js.map +0 -1
  517. package/dist/account-WLQBAQMD.js +0 -80
  518. package/dist/account-WLQBAQMD.js.map +0 -1
  519. package/dist/account-assets-O7IA37RE.js +0 -290
  520. package/dist/account-level-EU7BWCO7.js +0 -609
  521. package/dist/account-level-EU7BWCO7.js.map +0 -1
  522. package/dist/account-reads-SNOWDHHF.js +0 -219
  523. package/dist/account-users-NV37Z2XJ.js +0 -62
  524. package/dist/account-users-NV37Z2XJ.js.map +0 -1
  525. package/dist/account-writes-TU3WJRSI.js +0 -66
  526. package/dist/account-writes-TU3WJRSI.js.map +0 -1
  527. package/dist/accounts-MZ6SETJJ.js +0 -78
  528. package/dist/accounts-MZ6SETJJ.js.map +0 -1
  529. package/dist/accounts-U7ZBEAY6.js +0 -699
  530. package/dist/accounts-U7ZBEAY6.js.map +0 -1
  531. package/dist/actions-4JYHXRFH.js +0 -55
  532. package/dist/activecampaign-IDBV26HH.js +0 -936
  533. package/dist/activecampaign-IDBV26HH.js.map +0 -1
  534. package/dist/ad-group-writes-HLBWN4E4.js +0 -170
  535. package/dist/ad-group-writes-HLBWN4E4.js.map +0 -1
  536. package/dist/ad-groups-33NZD6J3.js +0 -68
  537. package/dist/ad-groups-33NZD6J3.js.map +0 -1
  538. package/dist/ad-writes-7ZDNDZ2E.js +0 -174
  539. package/dist/ad-writes-7ZDNDZ2E.js.map +0 -1
  540. package/dist/add-AF42LQQQ.js +0 -105
  541. package/dist/add-AF42LQQQ.js.map +0 -1
  542. package/dist/add-LJRZYJ7I.js +0 -303
  543. package/dist/add-LJRZYJ7I.js.map +0 -1
  544. package/dist/ads-KBE5JXCH.js +0 -115
  545. package/dist/ads-LXWXOQHX.js +0 -48
  546. package/dist/ads-X3AM6M7L.js +0 -77
  547. package/dist/ads-X3AM6M7L.js.map +0 -1
  548. package/dist/adsets-YWBJFPAZ.js +0 -182
  549. package/dist/advertisers-6FOCN2W3.js +0 -121
  550. package/dist/advertisers-6FOCN2W3.js.map +0 -1
  551. package/dist/analytics-64HBRJJE.js +0 -2435
  552. package/dist/analytics-64HBRJJE.js.map +0 -1
  553. package/dist/analytics-VY5NL2GL.js +0 -445
  554. package/dist/analytics-VY5NL2GL.js.map +0 -1
  555. package/dist/animate-2BMHZ4FM.js +0 -480
  556. package/dist/asset-writes-72DEVXGO.js +0 -48
  557. package/dist/assign-N2I2BM67.js +0 -78
  558. package/dist/assign-N2I2BM67.js.map +0 -1
  559. package/dist/audience-size-H5DEZXJN.js +0 -74
  560. package/dist/audience-size-H5DEZXJN.js.map +0 -1
  561. package/dist/audience-writes-KCHLNFSI.js +0 -325
  562. package/dist/audience-writes-KCHLNFSI.js.map +0 -1
  563. package/dist/audiences-QAH42HIM.js +0 -86
  564. package/dist/audiences-WCDWN64L.js +0 -268
  565. package/dist/audiences-WCDWN64L.js.map +0 -1
  566. package/dist/audit-2AAF6AOX.js +0 -152
  567. package/dist/audit-2AAF6AOX.js.map +0 -1
  568. package/dist/autocomplete-3GSKRNCZ.js +0 -112
  569. package/dist/autocomplete-3GSKRNCZ.js.map +0 -1
  570. package/dist/avatars-N6W6HUPP.js +0 -38
  571. package/dist/bid-pricing-IMITXHXN.js +0 -101
  572. package/dist/bid-pricing-IMITXHXN.js.map +0 -1
  573. package/dist/brand-ITWQVZD2.js +0 -22
  574. package/dist/brief-JJNEYPYB.js +0 -541
  575. package/dist/brief-JJNEYPYB.js.map +0 -1
  576. package/dist/campaign-groups-TTQLP32Q.js +0 -97
  577. package/dist/campaign-groups-TTQLP32Q.js.map +0 -1
  578. package/dist/campaign-writes-MAKPHQ3V.js +0 -166
  579. package/dist/campaign-writes-MAKPHQ3V.js.map +0 -1
  580. package/dist/campaign-writes-XO74BALZ.js +0 -174
  581. package/dist/campaign-writes-XO74BALZ.js.map +0 -1
  582. package/dist/campaigns-5BIDXYSR.js +0 -111
  583. package/dist/campaigns-LS65QM6W.js +0 -76
  584. package/dist/campaigns-LS65QM6W.js.map +0 -1
  585. package/dist/campaigns-XZOQ2VTK.js +0 -130
  586. package/dist/campaigns-XZPXCS7I.js +0 -111
  587. package/dist/campaigns-XZPXCS7I.js.map +0 -1
  588. package/dist/canvas-SL3RMOY5.js +0 -46
  589. package/dist/capabilities-LSR5GCE6.js +0 -145
  590. package/dist/capabilities-LSR5GCE6.js.map +0 -1
  591. package/dist/catalog-TZLU5NWI.js +0 -65
  592. package/dist/catalogs-JLCSFZYC.js +0 -779
  593. package/dist/catalogs-JLCSFZYC.js.map +0 -1
  594. package/dist/catalogs-T23RKYFC.js +0 -128
  595. package/dist/catalogs-T23RKYFC.js.map +0 -1
  596. package/dist/changes-36C754R4.js +0 -135
  597. package/dist/chatgpt-3WFOPURY.js +0 -47
  598. package/dist/chats-GGYTXNJS.js +0 -277
  599. package/dist/chats-GGYTXNJS.js.map +0 -1
  600. package/dist/check-P7UPBBG7.js +0 -105
  601. package/dist/check-P7UPBBG7.js.map +0 -1
  602. package/dist/chunk-2TOIY2WN.js +0 -4254
  603. package/dist/chunk-2TOIY2WN.js.map +0 -1
  604. package/dist/chunk-3YJNSUNF.js +0 -131
  605. package/dist/chunk-4D46PS6J.js +0 -344
  606. package/dist/chunk-4GAEB6NK.js +0 -228
  607. package/dist/chunk-5XTGG4PV.js +0 -274
  608. package/dist/chunk-6JCX3YLM.js +0 -249
  609. package/dist/chunk-6KWEF6HF.js +0 -8914
  610. package/dist/chunk-7HZSORAB.js +0 -843
  611. package/dist/chunk-7J3NZBPV.js +0 -2982
  612. package/dist/chunk-7J3NZBPV.js.map +0 -1
  613. package/dist/chunk-A3IQAONL.js +0 -638
  614. package/dist/chunk-ALMYGH5U.js +0 -479
  615. package/dist/chunk-AQKRSEBQ.js +0 -103
  616. package/dist/chunk-ASRS37QE.js +0 -710
  617. package/dist/chunk-ASRS37QE.js.map +0 -1
  618. package/dist/chunk-BL6RTOK3.js +0 -297
  619. package/dist/chunk-C6CBBZBO.js +0 -203
  620. package/dist/chunk-CCEDZTP7.js +0 -391
  621. package/dist/chunk-CCEDZTP7.js.map +0 -1
  622. package/dist/chunk-CKQTJ2LV.js +0 -89
  623. package/dist/chunk-D3KLDIPQ.js +0 -45
  624. package/dist/chunk-DL2UJNJ7.js +0 -8954
  625. package/dist/chunk-DQ54POZN.js +0 -363
  626. package/dist/chunk-EDLZGTGN.js +0 -216
  627. package/dist/chunk-EDLZGTGN.js.map +0 -1
  628. package/dist/chunk-EXSHBYNQ.js +0 -349
  629. package/dist/chunk-EXSHBYNQ.js.map +0 -1
  630. package/dist/chunk-F4YQ5PVR.js +0 -1518
  631. package/dist/chunk-FFFJBNHA.js +0 -63
  632. package/dist/chunk-FFG2OYVV.js +0 -64
  633. package/dist/chunk-FKQK22IX.js +0 -51
  634. package/dist/chunk-FLK6QHOY.js +0 -142
  635. package/dist/chunk-GACSA5A6.js +0 -1646
  636. package/dist/chunk-HJKYTNAZ.js +0 -61
  637. package/dist/chunk-HML3VQIW.js +0 -225
  638. package/dist/chunk-INUU3752.js +0 -392
  639. package/dist/chunk-IQHO2ABF.js +0 -197
  640. package/dist/chunk-J3UWMBOP.js +0 -547
  641. package/dist/chunk-JAC6JVCI.js +0 -26
  642. package/dist/chunk-JDR3HUEL.js +0 -191
  643. package/dist/chunk-JI77AKT6.js +0 -19
  644. package/dist/chunk-JNURZHZJ.js +0 -942
  645. package/dist/chunk-JSNMKTFM.js +0 -592
  646. package/dist/chunk-K4FLWDEX.js +0 -122
  647. package/dist/chunk-KBRJSPIM.js +0 -676
  648. package/dist/chunk-LAC6YHHX.js +0 -97
  649. package/dist/chunk-LRV6M2WB.js +0 -1919
  650. package/dist/chunk-M7HD42M6.js +0 -24017
  651. package/dist/chunk-M7HD42M6.js.map +0 -1
  652. package/dist/chunk-MCJ5I5LR.js +0 -3187
  653. package/dist/chunk-MCJ5I5LR.js.map +0 -1
  654. package/dist/chunk-MGYC2IRC.js +0 -783
  655. package/dist/chunk-MI4HXE7M.js +0 -23
  656. package/dist/chunk-MJ7RNDD4.js +0 -910
  657. package/dist/chunk-MVD7QIXI.js +0 -46
  658. package/dist/chunk-MZPS46OR.js +0 -76
  659. package/dist/chunk-OBJCNGZL.js +0 -207
  660. package/dist/chunk-OJGYYH6K.js +0 -179
  661. package/dist/chunk-OLBLXJNI.js +0 -224
  662. package/dist/chunk-PFTYKINE.js +0 -207
  663. package/dist/chunk-PLBITHV6.js +0 -846
  664. package/dist/chunk-PX3PUDK7.js +0 -167
  665. package/dist/chunk-Q6JMMBSQ.js +0 -831
  666. package/dist/chunk-RAQHUMKS.js +0 -169
  667. package/dist/chunk-SA22KXWT.js +0 -163
  668. package/dist/chunk-SIXU5PDF.js +0 -66
  669. package/dist/chunk-SWN6OHXG.js +0 -148
  670. package/dist/chunk-SXMK5AEJ.js +0 -494
  671. package/dist/chunk-TTLD66NI.js +0 -319
  672. package/dist/chunk-TVAIOC77.js +0 -287
  673. package/dist/chunk-TVTSA4EN.js +0 -188
  674. package/dist/chunk-TX7CQTD4.js +0 -5368
  675. package/dist/chunk-UKSSNYLU.js +0 -98
  676. package/dist/chunk-V5NHJU3M.js +0 -604
  677. package/dist/chunk-VIPKDXGU.js +0 -4229
  678. package/dist/chunk-VIPKDXGU.js.map +0 -1
  679. package/dist/chunk-W4D7C74B.js +0 -387
  680. package/dist/chunk-WF25CCLD.js +0 -170
  681. package/dist/chunk-WQPUX3BA.js +0 -275
  682. package/dist/chunk-WR3FR3K3.js +0 -156
  683. package/dist/chunk-XDNJC62G.js +0 -91
  684. package/dist/chunk-XE6N4SZI.js +0 -429
  685. package/dist/chunk-XGPU2VDU.js +0 -219
  686. package/dist/chunk-XUJZO7MZ.js +0 -57
  687. package/dist/chunk-Y67LUJBE.js +0 -455
  688. package/dist/chunk-Y7XSDJEA.js +0 -3868
  689. package/dist/chunk-YNYAT2TZ.js +0 -285
  690. package/dist/chunk-ZNNQK366.js +0 -7198
  691. package/dist/chunk-ZNNQK366.js.map +0 -1
  692. package/dist/chunk-ZNRGH4NS.js +0 -150
  693. package/dist/claim-4KUETSW3.js +0 -198
  694. package/dist/claim-4KUETSW3.js.map +0 -1
  695. package/dist/companies-XFO6WPVT.js +0 -196
  696. package/dist/companies-XFO6WPVT.js.map +0 -1
  697. package/dist/company-OJGISG7K.js +0 -306
  698. package/dist/company-OJGISG7K.js.map +0 -1
  699. package/dist/complete-CXOST5J3.js +0 -82
  700. package/dist/complete-CXOST5J3.js.map +0 -1
  701. package/dist/connect-HPQ32KGV.js +0 -43
  702. package/dist/conversation-D5HKCTDA.js +0 -94
  703. package/dist/conversation-D5HKCTDA.js.map +0 -1
  704. package/dist/conversion-report-DKXFHLLX.js +0 -125
  705. package/dist/conversion-report-DKXFHLLX.js.map +0 -1
  706. package/dist/conversion-upload-command-KTYAY7IG.js +0 -439
  707. package/dist/conversion-writes-7ODJDAUP.js +0 -120
  708. package/dist/conversion-writes-7ODJDAUP.js.map +0 -1
  709. package/dist/conversions-BKVGNNC6.js +0 -76
  710. package/dist/conversions-BKVGNNC6.js.map +0 -1
  711. package/dist/conversions-SYNDEB6D.js +0 -138
  712. package/dist/conversions-SYNDEB6D.js.map +0 -1
  713. package/dist/copy-writes-P4WK6OPM.js +0 -168
  714. package/dist/copy-writes-P4WK6OPM.js.map +0 -1
  715. package/dist/create-7D4VD4TC.js +0 -208
  716. package/dist/create-7D4VD4TC.js.map +0 -1
  717. package/dist/create-7QDEAWZS.js +0 -133
  718. package/dist/create-7QDEAWZS.js.map +0 -1
  719. package/dist/create-IQSYEC4M.js +0 -60
  720. package/dist/create-IQSYEC4M.js.map +0 -1
  721. package/dist/create-TQSCM7MG.js +0 -237
  722. package/dist/create-TQSCM7MG.js.map +0 -1
  723. package/dist/creatives-JPKA2RHU.js +0 -89
  724. package/dist/creatives-RNOL4F4E.js +0 -58
  725. package/dist/creatives-RXI27T2D.js +0 -221
  726. package/dist/creatives-RXI27T2D.js.map +0 -1
  727. package/dist/credentials-PYW55B52.js +0 -288
  728. package/dist/credentials-PYW55B52.js.map +0 -1
  729. package/dist/critique-2SYHNAW5.js +0 -1449
  730. package/dist/critique-2SYHNAW5.js.map +0 -1
  731. package/dist/critique-72GFZSHA.js +0 -230
  732. package/dist/critique-72GFZSHA.js.map +0 -1
  733. package/dist/crm-EATDSXXB.js +0 -225
  734. package/dist/crm-EATDSXXB.js.map +0 -1
  735. package/dist/crm-XXP3VBYD.js +0 -321
  736. package/dist/crm-XXP3VBYD.js.map +0 -1
  737. package/dist/currency-R4ORE2U3.js +0 -88
  738. package/dist/custom-conversions-5HJBB5XL.js +0 -128
  739. package/dist/customers-OFZTEXST.js +0 -57
  740. package/dist/delete-FGVZIK4R.js +0 -55
  741. package/dist/delete-FGVZIK4R.js.map +0 -1
  742. package/dist/delete-HBZZL4UA.js +0 -67
  743. package/dist/delete-HBZZL4UA.js.map +0 -1
  744. package/dist/delete-JOUXMRIX.js +0 -65
  745. package/dist/delete-JOUXMRIX.js.map +0 -1
  746. package/dist/demographics-SB7NBYOI.js +0 -139
  747. package/dist/demographics-SB7NBYOI.js.map +0 -1
  748. package/dist/discard-YYGIRDII.js +0 -67
  749. package/dist/discard-YYGIRDII.js.map +0 -1
  750. package/dist/discover-GSJRZUOC.js +0 -172
  751. package/dist/domain-3KRAJAUH.js +0 -99
  752. package/dist/domain-3KRAJAUH.js.map +0 -1
  753. package/dist/download-QCBKJ6OR.js +0 -170
  754. package/dist/download-QCBKJ6OR.js.map +0 -1
  755. package/dist/draft-7CGFFZTH.js +0 -333
  756. package/dist/draft-7CGFFZTH.js.map +0 -1
  757. package/dist/draft-BI4NW6AU.js +0 -308
  758. package/dist/draft-BI4NW6AU.js.map +0 -1
  759. package/dist/draft-LPVK6YHI.js +0 -281
  760. package/dist/draft-LPVK6YHI.js.map +0 -1
  761. package/dist/draft-QF5JEUTH.js +0 -218
  762. package/dist/draft-QF5JEUTH.js.map +0 -1
  763. package/dist/draft-WYDMLNYA.js +0 -308
  764. package/dist/experiments-ZCEYRP3H.js +0 -234
  765. package/dist/experiments-ZCEYRP3H.js.map +0 -1
  766. package/dist/facets-G7ZDPI5Q.js +0 -115
  767. package/dist/facets-G7ZDPI5Q.js.map +0 -1
  768. package/dist/feedback-3U3CL2VB.js +0 -109
  769. package/dist/feedback-3U3CL2VB.js.map +0 -1
  770. package/dist/feedback-record-4ZHPENIP.js +0 -263
  771. package/dist/feedback-record-4ZHPENIP.js.map +0 -1
  772. package/dist/fetch-PNVNNWTP.js +0 -177
  773. package/dist/fetch-PNVNNWTP.js.map +0 -1
  774. package/dist/fit-53DGYRFD.js +0 -63
  775. package/dist/flows-JXLQBP5Q.js +0 -248
  776. package/dist/flows-JXLQBP5Q.js.map +0 -1
  777. package/dist/fonts-LFMBUT4R.js +0 -37
  778. package/dist/forecast-4AG5F7YC.js +0 -169
  779. package/dist/forecast-VZAXI74O.js +0 -119
  780. package/dist/forecast-VZAXI74O.js.map +0 -1
  781. package/dist/funnel-EACC35UD.js +0 -395
  782. package/dist/funnel-EACC35UD.js.map +0 -1
  783. package/dist/generate-NWHPM2GQ.js +0 -263
  784. package/dist/get-AXBVYGAC.js +0 -57
  785. package/dist/get-AXBVYGAC.js.map +0 -1
  786. package/dist/get-D6A27Q4E.js +0 -80
  787. package/dist/get-D6A27Q4E.js.map +0 -1
  788. package/dist/google-NAA4BASO.js +0 -3267
  789. package/dist/google-ads-OIYUNDXQ.js +0 -196
  790. package/dist/google-ads-OIYUNDXQ.js.map +0 -1
  791. package/dist/history-5MRLNTCI.js +0 -67
  792. package/dist/history-5MRLNTCI.js.map +0 -1
  793. package/dist/history-IDYNIB6R.js +0 -134
  794. package/dist/history-IDYNIB6R.js.map +0 -1
  795. package/dist/history-IOUKN3WD.js +0 -100
  796. package/dist/history-IOUKN3WD.js.map +0 -1
  797. package/dist/hubspot-HL6WGC4G.js +0 -780
  798. package/dist/hubspot-HL6WGC4G.js.map +0 -1
  799. package/dist/ideas-NK3KQHAK.js +0 -43
  800. package/dist/images-2XS3JT7E.js +0 -92
  801. package/dist/ingest-DHXWZZX4.js +0 -24
  802. package/dist/ingest-FGTJRCWK.js +0 -108
  803. package/dist/ingest-FGTJRCWK.js.map +0 -1
  804. package/dist/insights-M3CYB22P.js +0 -437
  805. package/dist/insights-M3CYB22P.js.map +0 -1
  806. package/dist/insights-XCT3ONC7.js +0 -130
  807. package/dist/insights-XCT3ONC7.js.map +0 -1
  808. package/dist/inspect-53GGYRC4.js +0 -190
  809. package/dist/inspect-53GGYRC4.js.map +0 -1
  810. package/dist/instant-experiences-HT3HB4QZ.js +0 -258
  811. package/dist/instant-experiences-HT3HB4QZ.js.map +0 -1
  812. package/dist/intent-NSHW7EJT.js +0 -95
  813. package/dist/keyword-gap-ITTWKBWZ.js +0 -130
  814. package/dist/keyword-metrics-LWPE3HHW.js +0 -198
  815. package/dist/keyword-metrics-LWPE3HHW.js.map +0 -1
  816. package/dist/keywords-for-site-5K25VJ35.js +0 -129
  817. package/dist/keywords-for-site-5K25VJ35.js.map +0 -1
  818. package/dist/landing-QONUUP3C.js +0 -28
  819. package/dist/languages-MEFQQBJ2.js +0 -40
  820. package/dist/leads-FSSISJGL.js +0 -113
  821. package/dist/leads-FSSISJGL.js.map +0 -1
  822. package/dist/leads-SZOGCQFK.js +0 -538
  823. package/dist/leads-SZOGCQFK.js.map +0 -1
  824. package/dist/learn-FWWJWBDN.js +0 -205
  825. package/dist/learn-FWWJWBDN.js.map +0 -1
  826. package/dist/line-item-writes-A3UQ44NG.js +0 -209
  827. package/dist/line-item-writes-A3UQ44NG.js.map +0 -1
  828. package/dist/line-items-OH426JGT.js +0 -107
  829. package/dist/link-67E4NVEX.js +0 -65
  830. package/dist/link-67E4NVEX.js.map +0 -1
  831. package/dist/linkedin-CT2OSQ2I.js +0 -1314
  832. package/dist/linkedin-CT2OSQ2I.js.map +0 -1
  833. package/dist/linkedin-person-OSNLPLJJ.js +0 -137
  834. package/dist/linkedin-person-OSNLPLJJ.js.map +0 -1
  835. package/dist/list-J4OUXAKN.js +0 -65
  836. package/dist/list-J4OUXAKN.js.map +0 -1
  837. package/dist/list-L2OQK4W3.js +0 -304
  838. package/dist/list-L2OQK4W3.js.map +0 -1
  839. package/dist/list-LHMDAA2D.js +0 -152
  840. package/dist/list-LHMDAA2D.js.map +0 -1
  841. package/dist/locations-RLWAS6AC.js +0 -40
  842. package/dist/locations-UKBOT6SB.js +0 -67
  843. package/dist/locations-UKBOT6SB.js.map +0 -1
  844. package/dist/log-4EIV54V4.js +0 -93
  845. package/dist/log-4EIV54V4.js.map +0 -1
  846. package/dist/lookup-ZJIP2M4X.js +0 -22
  847. package/dist/make-MFU3CSN7.js +0 -1368
  848. package/dist/make-MFU3CSN7.js.map +0 -1
  849. package/dist/map-VWWWMQLK.js +0 -434
  850. package/dist/map-VWWWMQLK.js.map +0 -1
  851. package/dist/mcp-EKLO2VD7.js +0 -715
  852. package/dist/mcp-EKLO2VD7.js.map +0 -1
  853. package/dist/media-ZWN7E777.js +0 -18
  854. package/dist/media-sources-7L622UTF.js +0 -35
  855. package/dist/members-QK5M5NCJ.js +0 -45
  856. package/dist/members-QK5M5NCJ.js.map +0 -1
  857. package/dist/meta-EHKXH257.js +0 -122
  858. package/dist/metrics-K6FDCMK7.js +0 -152
  859. package/dist/models-JQEPSPNQ.js +0 -155
  860. package/dist/normalize-WI4OGKH5.js +0 -142
  861. package/dist/normalize-WI4OGKH5.js.map +0 -1
  862. package/dist/options-FKJ2QXI6.js +0 -123
  863. package/dist/options-FKJ2QXI6.js.map +0 -1
  864. package/dist/organization-7A7MPUDG.js +0 -947
  865. package/dist/organization-7A7MPUDG.js.map +0 -1
  866. package/dist/page-photos-HWKQOSCU.js +0 -116
  867. package/dist/page-photos-HWKQOSCU.js.map +0 -1
  868. package/dist/performance-K4VB6L6Z.js +0 -25
  869. package/dist/performance-LHAL53YO.js +0 -5539
  870. package/dist/performance-LHAL53YO.js.map +0 -1
  871. package/dist/pixels-Z7ZGXAGB.js +0 -60
  872. package/dist/pixels-Z7ZGXAGB.js.map +0 -1
  873. package/dist/plan-TVQSEKYL.js +0 -207
  874. package/dist/plan-TVQSEKYL.js.map +0 -1
  875. package/dist/preview-CWRGDFCP.js +0 -216
  876. package/dist/preview-CWRGDFCP.js.map +0 -1
  877. package/dist/promoted-tweet-writes-V4ZVJOJU.js +0 -181
  878. package/dist/promoted-tweet-writes-V4ZVJOJU.js.map +0 -1
  879. package/dist/promoted-tweets-KPG4IUVD.js +0 -119
  880. package/dist/publish-Y465CVUD.js +0 -342
  881. package/dist/publish-Y465CVUD.js.map +0 -1
  882. package/dist/query-QM7MBQD7.js +0 -62
  883. package/dist/questionnaire-LEZJLMAV.js +0 -93
  884. package/dist/questionnaire-LEZJLMAV.js.map +0 -1
  885. package/dist/reddit-Z7DOVIGR.js +0 -27
  886. package/dist/refresh-A6TW2Z2F.js +0 -95
  887. package/dist/refresh-A6TW2Z2F.js.map +0 -1
  888. package/dist/release-UFESJ4TM.js +0 -61
  889. package/dist/release-UFESJ4TM.js.map +0 -1
  890. package/dist/relevant-pages-VOICMQ7U.js +0 -99
  891. package/dist/remove-YONNYA4G.js +0 -51
  892. package/dist/remove-YONNYA4G.js.map +0 -1
  893. package/dist/reopen-FYJU2IPO.js +0 -64
  894. package/dist/reopen-FYJU2IPO.js.map +0 -1
  895. package/dist/rerun-B5SBG6ZE.js +0 -93
  896. package/dist/rerun-B5SBG6ZE.js.map +0 -1
  897. package/dist/research-HW4EVOZU.js +0 -72
  898. package/dist/research-OV53DIBX.js +0 -263
  899. package/dist/research-OV53DIBX.js.map +0 -1
  900. package/dist/reset-R4SIQXFH.js +0 -55
  901. package/dist/reset-R4SIQXFH.js.map +0 -1
  902. package/dist/reset-X6ODAKYH.js +0 -55
  903. package/dist/reset-X6ODAKYH.js.map +0 -1
  904. package/dist/resolve-DNRJCLCR.js +0 -122
  905. package/dist/resolve-DNRJCLCR.js.map +0 -1
  906. package/dist/retry-D5MKBHUB.js +0 -63
  907. package/dist/retry-D5MKBHUB.js.map +0 -1
  908. package/dist/retry-DVFLE7JY.js +0 -61
  909. package/dist/retry-DVFLE7JY.js.map +0 -1
  910. package/dist/revenue-QGI6XWSK.js +0 -89
  911. package/dist/revenue-QGI6XWSK.js.map +0 -1
  912. package/dist/rule-writes-S3RN47OG.js +0 -523
  913. package/dist/rule-writes-S3RN47OG.js.map +0 -1
  914. package/dist/rules-KTJ2ZZ62.js +0 -217
  915. package/dist/rules-TR6BAC23.js +0 -97
  916. package/dist/rules-TR6BAC23.js.map +0 -1
  917. package/dist/rules-add-T5ZO5RLR.js +0 -463
  918. package/dist/rules-add-T5ZO5RLR.js.map +0 -1
  919. package/dist/run-WZ5IXWA4.js +0 -67
  920. package/dist/run-WZ5IXWA4.js.map +0 -1
  921. package/dist/run-YRR3KOUU.js +0 -68
  922. package/dist/scaffold-ad-DNUCGCIH.js +0 -1514
  923. package/dist/scaffold-ad-DNUCGCIH.js.map +0 -1
  924. package/dist/scaffold-static-ad-VR65EZAG.js +0 -1013
  925. package/dist/scaffold-static-ad-VR65EZAG.js.map +0 -1
  926. package/dist/scaffold-video-JLMKCCWE.js +0 -886
  927. package/dist/scaffold-video-JLMKCCWE.js.map +0 -1
  928. package/dist/schedule-VRHCVBZA.js +0 -62
  929. package/dist/schedule-VRHCVBZA.js.map +0 -1
  930. package/dist/scheduled-agents-DG7FTCUZ.js +0 -55
  931. package/dist/schema-6Y3IXFDC.js +0 -69
  932. package/dist/schema-WZKDWF5N.js +0 -133
  933. package/dist/schema-WZKDWF5N.js.map +0 -1
  934. package/dist/search-MN66QIKJ.js +0 -175
  935. package/dist/search-MN66QIKJ.js.map +0 -1
  936. package/dist/select-IPSM2BF2.js +0 -104
  937. package/dist/select-IPSM2BF2.js.map +0 -1
  938. package/dist/sends-6FI7WELX.js +0 -348
  939. package/dist/sends-6FI7WELX.js.map +0 -1
  940. package/dist/set-prompt-N6BD3DME.js +0 -196
  941. package/dist/set-prompt-N6BD3DME.js.map +0 -1
  942. package/dist/setup-links-GTA2AROS.js +0 -142
  943. package/dist/setup-links-GTA2AROS.js.map +0 -1
  944. package/dist/shopify-S4TG6WJH.js +0 -3956
  945. package/dist/shopify-S4TG6WJH.js.map +0 -1
  946. package/dist/site-NY622E3H.js +0 -178
  947. package/dist/site-NY622E3H.js.map +0 -1
  948. package/dist/sources-4F2XO7Z6.js +0 -455
  949. package/dist/sources-4F2XO7Z6.js.map +0 -1
  950. package/dist/sources-562ITR77.js +0 -30
  951. package/dist/stale-JKM6MXJF.js +0 -74
  952. package/dist/stale-JKM6MXJF.js.map +0 -1
  953. package/dist/status-AUWMUDA4.js +0 -63
  954. package/dist/status-AUWMUDA4.js.map +0 -1
  955. package/dist/studies-ZOEUY6YP.js +0 -250
  956. package/dist/studio-T5L7UEX6.js +0 -49
  957. package/dist/study-writes-DTGMCNFP.js +0 -468
  958. package/dist/study-writes-DTGMCNFP.js.map +0 -1
  959. package/dist/sync-76MCGHX4.js +0 -55
  960. package/dist/sync-76MCGHX4.js.map +0 -1
  961. package/dist/sync-definition-NJPT6ABG.js +0 -67
  962. package/dist/tags-5KBOJJ5R.js +0 -26
  963. package/dist/tags-CSMLTHTU.js +0 -21
  964. package/dist/tags-CSMLTHTU.js.map +0 -1
  965. package/dist/tags-IFRZYM3G.js +0 -21
  966. package/dist/tags-IFRZYM3G.js.map +0 -1
  967. package/dist/tags-S44ADJ75.js +0 -21
  968. package/dist/tags-S44ADJ75.js.map +0 -1
  969. package/dist/tags-WR7IY3OT.js +0 -225
  970. package/dist/tags-WR7IY3OT.js.map +0 -1
  971. package/dist/targeting-VBQY3HUN.js +0 -760
  972. package/dist/targeting-VBQY3HUN.js.map +0 -1
  973. package/dist/targeting-criteria-FJWNK53T.js +0 -113
  974. package/dist/targets-2EHMMXD4.js +0 -104
  975. package/dist/targets-2EHMMXD4.js.map +0 -1
  976. package/dist/testimonials-WAPFIGFJ.js +0 -32
  977. package/dist/themes-B4LCQUXB.js +0 -95
  978. package/dist/top-companies-DJ2XQKMW.js +0 -109
  979. package/dist/top-companies-DJ2XQKMW.js.map +0 -1
  980. package/dist/transcript-J3LGOHCM.js +0 -163
  981. package/dist/transcript-J3LGOHCM.js.map +0 -1
  982. package/dist/translate-6RXO4C6Z.js +0 -607
  983. package/dist/translate-6RXO4C6Z.js.map +0 -1
  984. package/dist/triggers-CYXPNHQB.js +0 -142
  985. package/dist/triggers-CYXPNHQB.js.map +0 -1
  986. package/dist/unlink-5FJI7XZB.js +0 -68
  987. package/dist/unlink-5FJI7XZB.js.map +0 -1
  988. package/dist/unstage-54ZE2SZK.js +0 -86
  989. package/dist/unstage-54ZE2SZK.js.map +0 -1
  990. package/dist/unstage-MDSSPUKV.js +0 -95
  991. package/dist/unstage-MDSSPUKV.js.map +0 -1
  992. package/dist/update-BVBFNFMO.js +0 -99
  993. package/dist/update-BVBFNFMO.js.map +0 -1
  994. package/dist/update-GV3T7ZRC.js +0 -190
  995. package/dist/update-GV3T7ZRC.js.map +0 -1
  996. package/dist/update-PUQWUGPJ.js +0 -64
  997. package/dist/update-PUQWUGPJ.js.map +0 -1
  998. package/dist/update-YQBK6C3L.js +0 -153
  999. package/dist/update-YQBK6C3L.js.map +0 -1
  1000. package/dist/upload-PXT5JAEV.js +0 -127
  1001. package/dist/upload-PXT5JAEV.js.map +0 -1
  1002. package/dist/url-options-IHL4OU4C.js +0 -130
  1003. package/dist/url-options-IHL4OU4C.js.map +0 -1
  1004. package/dist/url-params-IYUI6SFJ.js +0 -99
  1005. package/dist/url-params-IYUI6SFJ.js.map +0 -1
  1006. package/dist/validate-AD7F7LQ5.js +0 -120
  1007. package/dist/validate-AD7F7LQ5.js.map +0 -1
  1008. package/dist/videos-ZJCTODEB.js +0 -41
  1009. package/dist/viewer-check-GWZNGWCO.js +0 -81
  1010. package/dist/web-76CWAZNW.js +0 -141
  1011. package/dist/web-76CWAZNW.js.map +0 -1
  1012. package/dist/winning-ads-W7GTXTX7.js +0 -86
  1013. package/dist/write-commands-K6M3RTVK.js +0 -1170
  1014. package/dist/write-commands-K6M3RTVK.js.map +0 -1
  1015. package/dist/write-commands-VPU53DLB.js +0 -1498
  1016. package/dist/write-commands-VPU53DLB.js.map +0 -1
  1017. package/dist/x-V4NNNWRU.js +0 -47
  1018. /package/dist/{account-assets-O7IA37RE.js.map → account-assets-J5Z4URLQ.js.map} +0 -0
  1019. /package/dist/{account-reads-SNOWDHHF.js.map → account-reads-FOEVPWDP.js.map} +0 -0
  1020. /package/dist/{actions-4JYHXRFH.js.map → actions-QZDSLFFK.js.map} +0 -0
  1021. /package/dist/{ads-LXWXOQHX.js.map → ads-AYJAYLFR.js.map} +0 -0
  1022. /package/dist/{ads-KBE5JXCH.js.map → ads-MAOI7S6V.js.map} +0 -0
  1023. /package/dist/{adsets-YWBJFPAZ.js.map → adsets-QRKICEFD.js.map} +0 -0
  1024. /package/dist/{animate-2BMHZ4FM.js.map → animate-HRWFVE2N.js.map} +0 -0
  1025. /package/dist/{asset-writes-72DEVXGO.js.map → asset-writes-JLVUAVUZ.js.map} +0 -0
  1026. /package/dist/{audiences-QAH42HIM.js.map → audiences-CDDI5HR5.js.map} +0 -0
  1027. /package/dist/{avatars-N6W6HUPP.js.map → avatars-4HCGWBOL.js.map} +0 -0
  1028. /package/dist/{brand-ITWQVZD2.js.map → brand-C6OB6Q4U.js.map} +0 -0
  1029. /package/dist/{campaigns-XZOQ2VTK.js.map → campaigns-HES5MDUG.js.map} +0 -0
  1030. /package/dist/{campaigns-5BIDXYSR.js.map → campaigns-ZYU4BXDP.js.map} +0 -0
  1031. /package/dist/{canvas-SL3RMOY5.js.map → canvas-AI34UBGU.js.map} +0 -0
  1032. /package/dist/{catalog-TZLU5NWI.js.map → catalog-ZY3MFT55.js.map} +0 -0
  1033. /package/dist/{changes-36C754R4.js.map → changes-OOUVQDBY.js.map} +0 -0
  1034. /package/dist/{chatgpt-3WFOPURY.js.map → chatgpt-NAXIFWXV.js.map} +0 -0
  1035. /package/dist/{chunk-TTLD66NI.js.map → chunk-3CHYJYSS.js.map} +0 -0
  1036. /package/dist/{chunk-XE6N4SZI.js.map → chunk-3G3GC5N4.js.map} +0 -0
  1037. /package/dist/{chunk-5XTGG4PV.js.map → chunk-3M45PYU7.js.map} +0 -0
  1038. /package/dist/{chunk-MI4HXE7M.js.map → chunk-3QHXF3QI.js.map} +0 -0
  1039. /package/dist/{chunk-Y7XSDJEA.js.map → chunk-3XPHUMLJ.js.map} +0 -0
  1040. /package/dist/{chunk-MGYC2IRC.js.map → chunk-45EERHDB.js.map} +0 -0
  1041. /package/dist/{chunk-W4D7C74B.js.map → chunk-4FGTANFK.js.map} +0 -0
  1042. /package/dist/{chunk-PX3PUDK7.js.map → chunk-4IHWT7PH.js.map} +0 -0
  1043. /package/dist/{chunk-PLBITHV6.js.map → chunk-4LF4AYPT.js.map} +0 -0
  1044. /package/dist/{chunk-XGPU2VDU.js.map → chunk-4UQRXKYJ.js.map} +0 -0
  1045. /package/dist/{chunk-Y67LUJBE.js.map → chunk-5JJD33Y2.js.map} +0 -0
  1046. /package/dist/{chunk-Q6JMMBSQ.js.map → chunk-5K4QYYOJ.js.map} +0 -0
  1047. /package/dist/{chunk-SA22KXWT.js.map → chunk-5LJ6E4YU.js.map} +0 -0
  1048. /package/dist/{chunk-WQPUX3BA.js.map → chunk-5T73MMBL.js.map} +0 -0
  1049. /package/dist/{chunk-DQ54POZN.js.map → chunk-64MAHLTK.js.map} +0 -0
  1050. /package/dist/{chunk-JAC6JVCI.js.map → chunk-6OIKNJ7G.js.map} +0 -0
  1051. /package/dist/{chunk-3YJNSUNF.js.map → chunk-6ZFSDYWV.js.map} +0 -0
  1052. /package/dist/{chunk-TVAIOC77.js.map → chunk-7BUIOP36.js.map} +0 -0
  1053. /package/dist/{chunk-K4FLWDEX.js.map → chunk-AN4OEQXE.js.map} +0 -0
  1054. /package/dist/{chunk-TX7CQTD4.js.map → chunk-AULSX5ZA.js.map} +0 -0
  1055. /package/dist/{chunk-MVD7QIXI.js.map → chunk-AVYUFJQQ.js.map} +0 -0
  1056. /package/dist/{chunk-LAC6YHHX.js.map → chunk-B4YF7VQF.js.map} +0 -0
  1057. /package/dist/{chunk-UKSSNYLU.js.map → chunk-BDOYNGUL.js.map} +0 -0
  1058. /package/dist/{chunk-PFTYKINE.js.map → chunk-BJOK7QD4.js.map} +0 -0
  1059. /package/dist/{chunk-IQHO2ABF.js.map → chunk-CMCGFSUS.js.map} +0 -0
  1060. /package/dist/{chunk-KBRJSPIM.js.map → chunk-DMJUIUAL.js.map} +0 -0
  1061. /package/dist/{chunk-HML3VQIW.js.map → chunk-DUCUOZLS.js.map} +0 -0
  1062. /package/dist/{chunk-7HZSORAB.js.map → chunk-FJZYOVSW.js.map} +0 -0
  1063. /package/dist/{chunk-JI77AKT6.js.map → chunk-FKP4ECJY.js.map} +0 -0
  1064. /package/dist/{chunk-DL2UJNJ7.js.map → chunk-GNMEOU46.js.map} +0 -0
  1065. /package/dist/{chunk-WR3FR3K3.js.map → chunk-GYKYXWUQ.js.map} +0 -0
  1066. /package/dist/{chunk-BL6RTOK3.js.map → chunk-GYPLRU4Y.js.map} +0 -0
  1067. /package/dist/{chunk-YNYAT2TZ.js.map → chunk-I43ZEWJQ.js.map} +0 -0
  1068. /package/dist/{chunk-4GAEB6NK.js.map → chunk-IZABTTW5.js.map} +0 -0
  1069. /package/dist/{chunk-GACSA5A6.js.map → chunk-K7IE6UYV.js.map} +0 -0
  1070. /package/dist/{chunk-V5NHJU3M.js.map → chunk-KH5YHHJV.js.map} +0 -0
  1071. /package/dist/{chunk-FKQK22IX.js.map → chunk-KMY7AD3N.js.map} +0 -0
  1072. /package/dist/{chunk-6KWEF6HF.js.map → chunk-KPCHWDJM.js.map} +0 -0
  1073. /package/dist/{chunk-SWN6OHXG.js.map → chunk-KTZCLJ2D.js.map} +0 -0
  1074. /package/dist/{chunk-A3IQAONL.js.map → chunk-MKUA54QE.js.map} +0 -0
  1075. /package/dist/{chunk-FFFJBNHA.js.map → chunk-MTV2RSGY.js.map} +0 -0
  1076. /package/dist/{chunk-INUU3752.js.map → chunk-N2QX57K3.js.map} +0 -0
  1077. /package/dist/{chunk-OJGYYH6K.js.map → chunk-NB2FU6EZ.js.map} +0 -0
  1078. /package/dist/{chunk-ALMYGH5U.js.map → chunk-NEYWS2DQ.js.map} +0 -0
  1079. /package/dist/{chunk-TVTSA4EN.js.map → chunk-NWF2LRKO.js.map} +0 -0
  1080. /package/dist/{chunk-JDR3HUEL.js.map → chunk-OTC6UMJ2.js.map} +0 -0
  1081. /package/dist/{chunk-OLBLXJNI.js.map → chunk-OUY2IAWL.js.map} +0 -0
  1082. /package/dist/{chunk-4D46PS6J.js.map → chunk-PJXNCRMR.js.map} +0 -0
  1083. /package/dist/{chunk-XDNJC62G.js.map → chunk-PYQ3GF7R.js.map} +0 -0
  1084. /package/dist/{chunk-WF25CCLD.js.map → chunk-Q3EIVZAR.js.map} +0 -0
  1085. /package/dist/{chunk-OBJCNGZL.js.map → chunk-QDQZ62FL.js.map} +0 -0
  1086. /package/dist/{chunk-LRV6M2WB.js.map → chunk-QHZE62GP.js.map} +0 -0
  1087. /package/dist/{chunk-AQKRSEBQ.js.map → chunk-RGR6TSTJ.js.map} +0 -0
  1088. /package/dist/{chunk-C6CBBZBO.js.map → chunk-SAAXU7QR.js.map} +0 -0
  1089. /package/dist/{chunk-SIXU5PDF.js.map → chunk-SHTKLRI6.js.map} +0 -0
  1090. /package/dist/{chunk-MZPS46OR.js.map → chunk-SIKCVWM3.js.map} +0 -0
  1091. /package/dist/{chunk-CKQTJ2LV.js.map → chunk-SSXG53CZ.js.map} +0 -0
  1092. /package/dist/{chunk-J3UWMBOP.js.map → chunk-TBWAM577.js.map} +0 -0
  1093. /package/dist/{chunk-RAQHUMKS.js.map → chunk-TGPGQTZA.js.map} +0 -0
  1094. /package/dist/{chunk-F4YQ5PVR.js.map → chunk-UMIX2BMM.js.map} +0 -0
  1095. /package/dist/{chunk-ZNRGH4NS.js.map → chunk-URMAEVZO.js.map} +0 -0
  1096. /package/dist/{chunk-HJKYTNAZ.js.map → chunk-VBO3ZVUU.js.map} +0 -0
  1097. /package/dist/{chunk-JSNMKTFM.js.map → chunk-VFLYMHTO.js.map} +0 -0
  1098. /package/dist/{chunk-6JCX3YLM.js.map → chunk-VGYIVXIZ.js.map} +0 -0
  1099. /package/dist/{chunk-XUJZO7MZ.js.map → chunk-VIB7R533.js.map} +0 -0
  1100. /package/dist/{chunk-D3KLDIPQ.js.map → chunk-WLESMH4J.js.map} +0 -0
  1101. /package/dist/{chunk-MJ7RNDD4.js.map → chunk-WVWLPXBO.js.map} +0 -0
  1102. /package/dist/{chunk-SXMK5AEJ.js.map → chunk-XEH5XAP6.js.map} +0 -0
  1103. /package/dist/{chunk-FLK6QHOY.js.map → chunk-XEOKVL4E.js.map} +0 -0
  1104. /package/dist/{chunk-FFG2OYVV.js.map → chunk-XOGQJYXH.js.map} +0 -0
  1105. /package/dist/{chunk-JNURZHZJ.js.map → chunk-XUXRA7IB.js.map} +0 -0
  1106. /package/dist/{connect-HPQ32KGV.js.map → connect-IAXSZPGA.js.map} +0 -0
  1107. /package/dist/{conversion-upload-command-KTYAY7IG.js.map → conversion-upload-command-IHFKVX2M.js.map} +0 -0
  1108. /package/dist/{creatives-JPKA2RHU.js.map → creatives-BB6S2OF6.js.map} +0 -0
  1109. /package/dist/{creatives-RNOL4F4E.js.map → creatives-BZEVJ6ER.js.map} +0 -0
  1110. /package/dist/{currency-R4ORE2U3.js.map → currency-CGKO5GKH.js.map} +0 -0
  1111. /package/dist/{custom-conversions-5HJBB5XL.js.map → custom-conversions-HAGG72LF.js.map} +0 -0
  1112. /package/dist/{customers-OFZTEXST.js.map → customers-NKKU6S7G.js.map} +0 -0
  1113. /package/dist/{discover-GSJRZUOC.js.map → discover-VM3O7CQM.js.map} +0 -0
  1114. /package/dist/{draft-WYDMLNYA.js.map → draft-CRDBU6LF.js.map} +0 -0
  1115. /package/dist/{fit-53DGYRFD.js.map → fit-Q5GRVF2O.js.map} +0 -0
  1116. /package/dist/{fonts-LFMBUT4R.js.map → fonts-GD4YRXQU.js.map} +0 -0
  1117. /package/dist/{forecast-4AG5F7YC.js.map → forecast-ONVS2QAI.js.map} +0 -0
  1118. /package/dist/{generate-NWHPM2GQ.js.map → generate-VBEY3N3L.js.map} +0 -0
  1119. /package/dist/{google-NAA4BASO.js.map → google-7EZP7I6J.js.map} +0 -0
  1120. /package/dist/{ideas-NK3KQHAK.js.map → ideas-WX7EBPSF.js.map} +0 -0
  1121. /package/dist/{images-2XS3JT7E.js.map → images-4AXF4LAC.js.map} +0 -0
  1122. /package/dist/{ingest-DHXWZZX4.js.map → ingest-C3M4GUO6.js.map} +0 -0
  1123. /package/dist/{intent-NSHW7EJT.js.map → intent-ZMYMFGB4.js.map} +0 -0
  1124. /package/dist/{keyword-gap-ITTWKBWZ.js.map → keyword-gap-XSJO2R77.js.map} +0 -0
  1125. /package/dist/{landing-QONUUP3C.js.map → landing-MUNYZQNA.js.map} +0 -0
  1126. /package/dist/{languages-MEFQQBJ2.js.map → languages-DIQ3OG3E.js.map} +0 -0
  1127. /package/dist/{line-items-OH426JGT.js.map → line-items-JR25T2C5.js.map} +0 -0
  1128. /package/dist/{locations-RLWAS6AC.js.map → locations-HTVYJSDJ.js.map} +0 -0
  1129. /package/dist/{lookup-ZJIP2M4X.js.map → lookup-S5VG7AWH.js.map} +0 -0
  1130. /package/dist/{media-ZWN7E777.js.map → media-P4T4ZBNS.js.map} +0 -0
  1131. /package/dist/{media-sources-7L622UTF.js.map → media-sources-P246GM7W.js.map} +0 -0
  1132. /package/dist/{meta-EHKXH257.js.map → meta-IPLWNYC7.js.map} +0 -0
  1133. /package/dist/{metrics-K6FDCMK7.js.map → metrics-WYWUX6Y5.js.map} +0 -0
  1134. /package/dist/{models-JQEPSPNQ.js.map → models-HJ7Y55AH.js.map} +0 -0
  1135. /package/dist/{performance-K4VB6L6Z.js.map → performance-J3DLNI2W.js.map} +0 -0
  1136. /package/dist/{promoted-tweets-KPG4IUVD.js.map → promoted-tweets-W42FNWS7.js.map} +0 -0
  1137. /package/dist/{query-QM7MBQD7.js.map → query-IQICLABN.js.map} +0 -0
  1138. /package/dist/{reddit-Z7DOVIGR.js.map → reddit-X4CERXYF.js.map} +0 -0
  1139. /package/dist/{relevant-pages-VOICMQ7U.js.map → relevant-pages-UDDQOYLD.js.map} +0 -0
  1140. /package/dist/{research-HW4EVOZU.js.map → research-D5UUJF74.js.map} +0 -0
  1141. /package/dist/{rules-KTJ2ZZ62.js.map → rules-ZVS2MWED.js.map} +0 -0
  1142. /package/dist/{run-YRR3KOUU.js.map → run-T7XAH2W5.js.map} +0 -0
  1143. /package/dist/{scheduled-agents-DG7FTCUZ.js.map → scheduled-agents-ZGCUZ6SB.js.map} +0 -0
  1144. /package/dist/{schema-6Y3IXFDC.js.map → schema-D6BMZAPB.js.map} +0 -0
  1145. /package/dist/{sources-562ITR77.js.map → sources-DVMJEXEX.js.map} +0 -0
  1146. /package/dist/{studies-ZOEUY6YP.js.map → studies-EPO2AM4M.js.map} +0 -0
  1147. /package/dist/{studio-T5L7UEX6.js.map → studio-5Z4NMA4K.js.map} +0 -0
  1148. /package/dist/{sync-definition-NJPT6ABG.js.map → sync-definition-F3CXG6KG.js.map} +0 -0
  1149. /package/dist/{tags-5KBOJJ5R.js.map → tags-SEZ2CQJM.js.map} +0 -0
  1150. /package/dist/{targeting-criteria-FJWNK53T.js.map → targeting-criteria-AU5CSMAU.js.map} +0 -0
  1151. /package/dist/{testimonials-WAPFIGFJ.js.map → testimonials-Y6PUV6AL.js.map} +0 -0
  1152. /package/dist/{themes-B4LCQUXB.js.map → themes-PGPIAKAO.js.map} +0 -0
  1153. /package/dist/{videos-ZJCTODEB.js.map → videos-SVZV5YYC.js.map} +0 -0
  1154. /package/dist/{viewer-check-GWZNGWCO.js.map → viewer-check-LUAEGV6H.js.map} +0 -0
  1155. /package/dist/{winning-ads-W7GTXTX7.js.map → winning-ads-KNLJHHCO.js.map} +0 -0
  1156. /package/dist/{x-V4NNNWRU.js.map → x-ZQNHYIDU.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../api/src/ads-meta/customConversions.ts","../../api/src/ads-meta/leadAds.ts","../../api/src/ads-meta/placements.ts","../../api/src/ads-meta/brandSafety.ts","../../api/src/ads-meta/catalogs.ts","../../api/src/ads-meta/customerList.ts","../../api/src/ads-meta/ops.ts","../../api/src/ads-meta/adRules.ts","../../api/src/ads-meta/adSetCompliance.ts","../../api/src/ads-meta/copies.ts","../../api/src/ads-meta/instantExperiences.ts","../../api/src/ads-meta/leadForms.ts","../../api/src/ads-meta/mediaSpecs.ts","../../api/src/ads-meta/messaging.ts","../../api/src/ads-meta/pagePhotos.ts","../../api/src/ads-meta/reachFrequency.ts"],"sourcesContent":["/**\n * Meta Custom Conversions — the measurement object an account defines once and\n * then optimizes ad sets toward.\n *\n * Baker could not see one until now, which is not a gap the agent could work\n * around: a chat that asked for \"optimize toward my custom conversion\" got an\n * ad set pointed at the raw pixel event instead, silently measuring something\n * wider than what the marketer set up. The two halves live here because both\n * the CLI (which prints the listing) and the backend stage (which fills an ad\n * set's `promoted_object` from the conversion) need exactly the same reading of\n * a Meta node.\n */\n\n/** The Custom Conversion node, as Meta returns it. Every field but `id` is optional on the wire. */\nexport interface MetaCustomConversionNode {\n id: string;\n account_id?: string;\n name?: string;\n description?: string;\n custom_event_type?: string;\n /** The event source the conversion counts from — a pixel for every web conversion. */\n pixel?: { id?: string; name?: string };\n event_source_type?: string;\n /** Meta's own JSON filter language. Opaque on the wire, read by `describeCustomConversionRule`. */\n rule?: string;\n default_conversion_value?: number;\n retention_days?: number;\n is_archived?: boolean;\n is_unavailable?: boolean;\n creation_time?: string;\n first_fired_time?: string;\n last_fired_time?: string;\n}\n\n/**\n * What an ad set has to carry to optimize toward a custom conversion.\n *\n * Read off ad sets Ads Manager itself created: Meta stores the conversion id\n * **and** the pixel, event and rule it was defined from, all four together. An\n * ad set given only `custom_conversion_id` is not what Meta's own tooling\n * sends, so Baker sends the same four.\n */\nexport interface CustomConversionPromotedObject {\n custom_conversion_id: string;\n pixel_id: string;\n custom_event_type: string;\n pixel_rule?: string;\n}\n\n/** Either the four fields an ad set needs, or why this conversion cannot be optimized toward. */\nexport type CustomConversionPromotedObjectResult =\n | { ok: true; promotedObject: CustomConversionPromotedObject }\n | { ok: false; reason: string };\n\n/**\n * Turn a custom conversion into the `promoted_object` an ad set optimizing\n * toward it must carry — or say why it cannot be used.\n *\n * The refusals are all states a listing shows and a payload does not: a\n * conversion somebody archived, one Meta flagged unavailable, and one defined\n * on an event source that is not a pixel (an offline or app conversion, which\n * a website ad set cannot optimize toward). Each is a `BAD_REQUEST` at stage\n * time rather than a rejection at publish, which is the whole point of reading\n * the node before staging.\n */\nexport function customConversionPromotedObject(\n node: MetaCustomConversionNode,\n knownEventTypes?: readonly string[],\n): CustomConversionPromotedObjectResult {\n const label = node.name ? `\"${node.name}\" (${node.id})` : node.id;\n if (node.is_archived) {\n return {\n ok: false,\n reason: `custom conversion ${label} is archived in Meta, so an ad set cannot optimize toward it — unarchive it in Events Manager or name another one`,\n };\n }\n if (node.is_unavailable) {\n return {\n ok: false,\n reason: `Meta reports custom conversion ${label} as unavailable, so an ad set cannot optimize toward it — check it in Events Manager or name another one`,\n };\n }\n const pixelId = node.pixel?.id;\n if (!pixelId) {\n return {\n ok: false,\n reason: `custom conversion ${label} is not defined on a pixel${\n node.event_source_type ? ` (its event source is ${node.event_source_type})` : \"\"\n }, so a website ad set cannot optimize toward it — name a conversion built on the site's pixel`,\n };\n }\n const eventType = node.custom_event_type;\n if (!eventType) {\n return {\n ok: false,\n reason: `custom conversion ${label} names no event category, which Meta requires on the ad set — set its category in Events Manager, or pass --pixel-id and --custom-event-type instead`,\n };\n }\n if (knownEventTypes && !knownEventTypes.includes(eventType)) {\n return {\n ok: false,\n reason: `custom conversion ${label} has event category ${eventType}, which Baker does not know — pass --pixel-id and --custom-event-type explicitly, and report the category so it can be added`,\n };\n }\n return {\n ok: true,\n promotedObject: {\n custom_conversion_id: node.id,\n pixel_id: pixelId,\n custom_event_type: eventType,\n ...(node.rule ? { pixel_rule: node.rule } : {}),\n },\n };\n}\n\nconst RULE_OPERATORS: Record<string, string> = {\n eq: \"is\",\n neq: \"is not\",\n contains: \"contains\",\n i_contains: \"contains\",\n not_contains: \"does not contain\",\n i_not_contains: \"does not contain\",\n starts_with: \"starts with\",\n i_starts_with: \"starts with\",\n ends_with: \"ends with\",\n i_ends_with: \"ends with\",\n gt: \"is more than\",\n gte: \"is at least\",\n lt: \"is less than\",\n lte: \"is at most\",\n regex_match: \"matches\",\n exists: \"exists\",\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction describeLeaf(node: Record<string, unknown>): string | undefined {\n const entry = Object.entries(node);\n const leaf = entry.length === 1 ? entry[0] : undefined;\n if (!leaf) {\n return undefined;\n }\n const [field, condition] = leaf;\n if (!isRecord(condition)) {\n return undefined;\n }\n const conditionEntries = Object.entries(condition);\n const test = conditionEntries.length === 1 ? conditionEntries[0] : undefined;\n if (!test) {\n return undefined;\n }\n const [operator, value] = test;\n const phrase = RULE_OPERATORS[operator];\n return phrase ? `${field} ${phrase} ${JSON.stringify(value)}` : undefined;\n}\n\nfunction describeBranch(node: Record<string, unknown>, joiner: \"and\" | \"or\"): string | undefined {\n const branch = node[joiner];\n if (!Array.isArray(branch)) {\n return undefined;\n }\n const parts = branch.map(describeNode).filter((part): part is string => Boolean(part));\n if (parts.length === 0) {\n return undefined;\n }\n return parts.length === 1 ? parts[0] : `(${parts.join(` ${joiner} `)})`;\n}\n\nfunction describeNode(node: unknown): string | undefined {\n if (!isRecord(node)) {\n return undefined;\n }\n return describeBranch(node, \"and\") ?? describeBranch(node, \"or\") ?? describeLeaf(node);\n}\n\n/**\n * Meta's rule JSON as a sentence a marketer can check.\n *\n * The raw string is `{\"and\":[{\"event\":{\"eq\":\"PageView\"}},{\"or\":[{\"URL\":{\"i_contains\":\"thank-you\"}}]}]}`,\n * which is the one thing that distinguishes two conversions with similar names —\n * and the thing somebody has to read to know whether the right one is being\n * optimized toward. Anything this cannot parse falls back to the raw string\n * rather than to silence: an unreadable rule is still evidence.\n */\nexport function describeCustomConversionRule(rule: string | undefined): string | undefined {\n if (!rule) {\n return undefined;\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(rule);\n } catch {\n return rule;\n }\n const described = describeNode(parsed);\n if (!described) {\n return rule;\n }\n return described.startsWith(\"(\") && described.endsWith(\")\") ? described.slice(1, -1) : described;\n}\n\n/** The pixel event a URL rule narrows. `PageView` is the one every Meta pixel fires on every page. */\nexport const DEFAULT_CUSTOM_CONVERSION_EVENT = \"PageView\";\n\n/**\n * The rule for the conversion marketers actually create: \"this event, on a URL\n * containing this\".\n *\n * Every custom conversion read off real accounts has this exact shape —\n * `and(event eq X, URL i_contains Y)` — because it is what Events Manager\n * writes. Producing it here rather than asking the agent for Meta's filter JSON\n * removes the whole class of rule that parses, stages, creates, and then counts\n * nothing: a `contains` where Meta wants `i_contains`, a `url` where Meta wants\n * `URL`. Anything more elaborate goes in as raw JSON instead.\n */\nexport function buildCustomConversionRule(input: { event?: string; urlContains: string }): Record<string, unknown> {\n return {\n and: [\n { event: { eq: input.event ?? DEFAULT_CUSTOM_CONVERSION_EVENT } },\n { URL: { i_contains: input.urlContains } },\n ],\n };\n}\n\n/**\n * Why Meta will not count anything with this rule, or undefined.\n *\n * Meta accepts a rule it cannot match and answers `{\"success\":true}`: the\n * conversion is created, it counts zero forever, and nothing anywhere says why.\n * Since a custom conversion cannot be deleted — only archived — that mistake is\n * permanent and spends one of the account's hundred slots. So the grammar is\n * checked here, before the op is staged, where it costs nothing.\n *\n * It checks shape, not meaning: a field name can be any event parameter the\n * pixel sends (`value`, `content_category`, `plan_tier`), so there is no list\n * to check against. What is checkable is that every leaf is `{field: {operator:\n * value}}` with an operator Meta has, and that no branch is empty — an empty\n * `and` matches every event, which is the widest possible mistake wearing the\n * name of a narrow conversion.\n */\nexport function customConversionRuleRefusal(rule: Record<string, unknown>): string | undefined {\n const refusal = ruleNodeRefusal(rule, \"rule\");\n if (refusal) {\n return refusal;\n }\n // Meta does not count the event as a rule: a rule with nothing but event\n // tests stages fine and is refused at publish (\"A conversion rule is required\n // at creation time\", subcode 1760020), for standard and custom events alike.\n if (!ruleFields(rule).some((field) => field !== \"event\")) {\n return 'rule only names the event, and Meta refuses a custom conversion with no condition beyond it — narrow it with a URL, referrer or event parameter the event carries, e.g. {\"and\":[{\"event\":{\"eq\":\"Lead\"}},{\"URL\":{\"i_contains\":\"/gracias\"}}]}';\n }\n return undefined;\n}\n\n/** Every field a rule tests, through any depth of `and` / `or`. Assumes a rule `ruleNodeRefusal` accepted. */\nfunction ruleFields(node: unknown): string[] {\n if (!isRecord(node)) {\n return [];\n }\n return Object.entries(node).flatMap(([key, value]) =>\n (key === \"and\" || key === \"or\") && Array.isArray(value) ? value.flatMap(ruleFields) : [key],\n );\n}\n\nfunction branchRefusal(key: \"and\" | \"or\", value: unknown, path: string): string | undefined {\n if (!Array.isArray(value) || value.length === 0) {\n return `${path}.${key} must be a non-empty array of conditions — an empty one counts every event the pixel sends`;\n }\n for (const [index, child] of value.entries()) {\n const refusal = ruleNodeRefusal(child, `${path}.${key}[${index}]`);\n if (refusal) {\n return refusal;\n }\n }\n return undefined;\n}\n\nfunction conditionRefusal(key: string, value: unknown, path: string): string | undefined {\n return key === \"and\" || key === \"or\" ? branchRefusal(key, value, path) : leafRefusal(key, value, path);\n}\n\nfunction ruleNodeRefusal(node: unknown, path: string): string | undefined {\n if (!isRecord(node)) {\n return `${path} must be an object like {\"URL\":{\"i_contains\":\"/thank-you\"}}`;\n }\n const entries = Object.entries(node);\n if (entries.length === 0) {\n return `${path} is empty — a rule with no condition counts every event the pixel sends`;\n }\n // Meta has no implicit and: every node is exactly one branch or one field\n // test. Two keys side by side is what a model writes when it means `and`, and\n // it is worse than unmatchable — `describeCustomConversionRule` reads the\n // first key it recognizes and drops the rest, so the review of a conversion\n // nobody can delete shows less than the rule it is about to create.\n if (entries.length > 1) {\n return `${path} names ${entries.length} conditions side by side (${entries\n .map(([key]) => key)\n .join(\", \")}) — Meta reads one branch or one field test per object, so combine them with {\"and\":[…]}`;\n }\n for (const [key, value] of entries) {\n const refusal = conditionRefusal(key, value, path);\n if (refusal) {\n return refusal;\n }\n }\n return undefined;\n}\n\nfunction leafRefusal(field: string, condition: unknown, path: string): string | undefined {\n if (!isRecord(condition)) {\n return `${path}.${field} must be a test like {\"i_contains\":\"/thank-you\"}, not a bare value`;\n }\n const tests = Object.entries(condition);\n if (tests.length === 0) {\n return `${path}.${field} names no test — use one of ${Object.keys(RULE_OPERATORS).join(\", \")}`;\n }\n // One operator per field, for the same reason: two is read as neither.\n if (tests.length > 1) {\n return `${path}.${field} names ${tests.length} operators at once (${tests\n .map(([operator]) => operator)\n .join(\", \")}) — test a field once per condition and combine them with {\"and\":[…]}`;\n }\n for (const [operator] of tests) {\n if (!RULE_OPERATORS[operator]) {\n return `${path}.${field} uses \"${operator}\", which is not a Meta rule operator — use one of ${Object.keys(RULE_OPERATORS).join(\", \")} (URL matching is i_contains, not contains or includes)`;\n }\n }\n return undefined;\n}\n","/**\n * The two refusals Baker itself produces for lead-ads work, shared verbatim by\n * the backend that throws them and the CLI that has to explain them.\n *\n * They live here rather than in the backend because of what the CLI does with a\n * `FORBIDDEN` from Meta. `metaForbiddenFix` answers the ambiguous case — Meta\n * returns the same code whether a token is short a scope (reconnect) or the user\n * holds no role on one Business asset (reconnecting cannot help), and the only\n * way to tell them apart is testing whether other reads fail too. That advice is\n * right for Meta's own 403s and wrong for ours: these two already name the cause\n * and the remedy, and appending \"try reconnecting\" to *\"this needs switching on\n * by the Baker team\"* sends a client on a reconnect that provably cannot work.\n *\n * So the CLI needs to recognise a refusal Baker wrote. Matching on a shared\n * constant keeps that honest — a reworded message updates both sides at once,\n * where a substring guess in the CLI would silently start missing.\n */\n\nexport const META_LEAD_ADS_NOT_ENABLED_MESSAGE =\n \"Using Meta instant forms and their leads is not switched on for this company. Everything else on Meta keeps \" +\n \"working. Tell the user this needs switching on by the Baker team, and carry on with the rest of the job.\";\n\nexport const META_LEAD_ADS_RECONNECT_MESSAGE =\n \"This Meta connection was made before lead ads were switched on for this company, so it cannot work with instant \" +\n \"forms or read their leads. Ask the user to reconnect Meta in the dashboard — that grants the extra permissions — \" +\n \"then ask for this again. Everything else on Meta keeps working meanwhile.\";\n\n/**\n * Whether a `FORBIDDEN` message is one Baker wrote, and therefore already\n * conclusive. Anything else is Meta's own ambiguous 403 and still needs the\n * blast-radius test.\n */\nexport function isMetaLeadAdsRefusal(message: string): boolean {\n return message === META_LEAD_ADS_NOT_ENABLED_MESSAGE || message === META_LEAD_ADS_RECONNECT_MESSAGE;\n}\n","/**\n * What Meta actually publishes about its placements — and, just as load-bearing,\n * what it does NOT publish.\n *\n * This module exists because of a real incident. Asked why a video ad appeared\n * as a still image, an agent produced a list of \"image-only placements\" (right\n * column, Marketplace, Facebook search, Instagram Explore home) and an\n * explanation (\"Meta serves the video's cover frame as a static image there\"),\n * then staged a placement edit on four live ad sets. Checked against Meta's own\n * docs, the placement list was wrong and the mechanism is documented nowhere.\n *\n * So every fact here carries its source URL, and anything Meta contradicts\n * itself on is marked `contested` instead of being resolved by us. Two rules\n * follow from that incident and are enforced by the callers of this module:\n *\n * 1. Never assert a delivery mechanism Meta does not document. What Meta DOES\n * document for a video creative in a video-incompatible placement is an\n * eligibility error at creation, not a silent fallback to the thumbnail.\n * 2. A placement's format support is checked, never recalled — with\n * `baker ads meta preview --placement <position>` (what Meta renders) and\n * the play-rate breakdown (what the account actually delivered).\n *\n * Verified 2026-08-14 against the pages cited below. Meta adds, renames, and\n * retires surfaces continuously — re-verify before relying on an absence.\n */\n\n/**\n * Meta names the same surface twice, and the two names are not interchangeable.\n *\n * Ad-set **targeting** takes `facebook_positions` / `instagram_positions`\n * (`story`, `profile_feed` on both; `reels`, `explore_home` on Instagram only —\n * the Facebook Reels surface is `facebook_reels`). An **insights** breakdown\n * reports `platform_position` (`facebook_stories`, `instagram_reels`,\n * `instagram_explore_grid_home`, `facebook_profile_feed`). Only `feed`,\n * `facebook_reels`, `facebook_reels_overlay`, `instream_video`, `marketplace`\n * and `right_hand_column` spell the same in both.\n *\n * That matters here because the two halves of this feature sit on opposite\n * sides of it: staging validates targeting, and `--placement` takes a value the\n * agent pasted out of a breakdown. Keying both off one map silently breaks the\n * chain the docs tell the agent to follow, so each is labelled below.\n *\n * Insights spellings verified 2026-08-14 against a live account's\n * `publisher_platform,platform_position` breakdown.\n */\n\n/** Ad-set targeting positions — the `facebook_positions` / `instagram_positions` vocabulary. */\nexport interface PositionScopedTargeting {\n publisher_platforms?: string[];\n facebook_positions?: string[];\n instagram_positions?: string[];\n audience_network_positions?: string[];\n messenger_positions?: string[];\n threads_positions?: string[];\n device_platforms?: string[];\n}\n\n/**\n * Facebook positions Meta rejects unless `feed` is selected alongside them.\n *\n * Source: Marketing API › Placement Targeting — \"If you select `marketplace`,\n * `search`, `profile_feed`, or `notification`, you must use `feed`.\"\n * https://developers.facebook.com/docs/marketing-api/audiences/reference/placement-targeting/\n */\nexport const FACEBOOK_POSITIONS_REQUIRING_FEED = [\"marketplace\", \"search\", \"profile_feed\", \"notification\"] as const;\n\nexport const PLACEMENT_TARGETING_DOC =\n \"https://developers.facebook.com/docs/marketing-api/audiences/reference/placement-targeting/\";\n\n/**\n * The placement vocabulary Meta publishes for ad-set targeting, one closed enum\n * per field.\n *\n * These are write values, and they are the third of three spellings Meta keeps\n * for the same surfaces — targeting takes `reels`, an insights breakdown reports\n * `instagram_reels`, and the `effective_*` read fields report `REELS`. Only the\n * first is accepted here.\n *\n * Kept as a list rather than left to Meta because the refusal costs a publish:\n * the ops apply one at a time, so an ad set rejected for a bad position takes\n * every ad that depends on it with it. One real chat staged `reels` in\n * `facebook_positions` (where the Facebook surface is `facebook_reels`, already\n * in the same list) and lost four ad sets and the 27 ads under them.\n *\n * Source: Marketing API › Placement Targeting, verified 2026-09-18.\n */\nexport const PUBLISHER_PLATFORMS = [\"facebook\", \"instagram\", \"threads\", \"messenger\", \"audience_network\"] as const;\n\nexport const FACEBOOK_POSITIONS = [\n \"feed\",\n \"right_hand_column\",\n \"marketplace\",\n \"story\",\n \"search\",\n \"instream_video\",\n \"facebook_reels\",\n \"facebook_reels_overlay\",\n \"profile_feed\",\n \"notification\",\n] as const;\n\nexport const INSTAGRAM_POSITIONS = [\n \"stream\",\n \"story\",\n \"explore_home\",\n \"reels\",\n \"profile_feed\",\n \"ig_search\",\n \"profile_reels\",\n] as const;\n\nexport const AUDIENCE_NETWORK_POSITIONS = [\"classic\", \"rewarded_video\"] as const;\n\nexport const MESSENGER_POSITIONS = [\"sponsored_messages\"] as const;\n\n/** Threads ships one placement, and it cannot be selected without Instagram `stream`. */\nexport const THREADS_POSITIONS = [\"threads_stream\"] as const;\n\n/**\n * `connected_tv` is absent from the Placement Targeting page and present in\n * Meta's own generated enum spec. Accepted, because refusing a value Meta takes\n * costs a campaign shape and accepting one it refuses costs one publish error.\n */\nexport const DEVICE_PLATFORMS = [\"mobile\", \"desktop\", \"connected_tv\"] as const;\n\n/** Every placement field, with the vocabulary Meta accepts in it. */\nexport const PLACEMENT_VOCABULARIES = {\n publisher_platforms: PUBLISHER_PLATFORMS,\n facebook_positions: FACEBOOK_POSITIONS,\n instagram_positions: INSTAGRAM_POSITIONS,\n audience_network_positions: AUDIENCE_NETWORK_POSITIONS,\n messenger_positions: MESSENGER_POSITIONS,\n threads_positions: THREADS_POSITIONS,\n device_platforms: DEVICE_PLATFORMS,\n} as const satisfies Record<string, readonly string[]>;\n\nexport type PlacementField = keyof typeof PLACEMENT_VOCABULARIES;\n\n/**\n * The same surface under the other platform's name.\n *\n * This is the correction that matters, because it is the mistake that happens:\n * a placement list is written for one platform and pasted into the other's\n * field. Saying only \"not a valid value\" leaves the agent to guess which of\n * eleven values meant Reels.\n */\nconst SAME_SURFACE_ON_THIS_PLATFORM: Partial<Record<PlacementField, Readonly<Record<string, string>>>> = {\n facebook_positions: { reels: \"facebook_reels\", stream: \"feed\", stories: \"story\", ig_search: \"search\" },\n instagram_positions: {\n feed: \"stream\",\n facebook_reels: \"reels\",\n stories: \"story\",\n search: \"ig_search\",\n },\n};\n\n/**\n * Placements Meta still serves and no longer lets an ad set select.\n *\n * A retired placement is the one case the two kinds below cannot express: the\n * value is real, it is spelled right, it is in the correct field, live ad sets\n * created before the retirement still carry it — and a create or an update\n * naming it is refused outright. Meta does not remove it from the Placement\n * Targeting page, so nothing about reading the docs reveals this; only the\n * write does.\n *\n * First verified 2026-09-18 against `act_1342210013621203` on v25.0, by a\n * `validate_only` ad-set create per position. `facebook_positions: [\"feed\",\n * \"video_feeds\"]` is refused with subcode 2490562, \"Facebook video feeds\n * placement is deprecated for this API version and cannot be selected, please\n * remove it from your targeting\"; the same request with `instream_video`\n * instead succeeds. Every other position in every field validated clean.\n *\n * Kept as its own map rather than by deleting the value silently, because the\n * refusal has to name the replacement: dropped from the vocabulary alone,\n * `video_feeds` reads as an unrecognised typo and only earns a warning, which\n * is how it reaches the publish that loses the ad set and every ad under it.\n *\n * Re-run the validate-only sweep when `META_GRAPH_VERSION` is bumped — a\n * retirement is per API version, and the next version can add one.\n */\nexport const RETIRED_PLACEMENTS: Partial<Record<PlacementField, Readonly<Record<string, string>>>> = {\n facebook_positions: {\n video_feeds:\n 'Meta retired Facebook video feeds — use \"instream_video\" for in-stream video, or \"facebook_reels\", and drop \"video_feeds\"',\n },\n // v26.0, re-swept 2026-10-15: `explore` is refused (subcode 2490589, \"IG\n // Explore placement is deprecated for this API version\"); `explore_home`\n // validates on its own.\n instagram_positions: {\n explore: 'Meta retired Instagram Explore — drop \"explore\"; \"explore_home\" (Explore home) still runs on its own',\n },\n // v26.0 takes Messenger `story` and silently drops it from the ad set (every\n // version from 2026-10-27), so what was staged would never be what runs.\n messenger_positions: {\n story:\n 'Meta retired Messenger Stories — drop \"story\" from messenger_positions; Facebook and Instagram \"story\" still run',\n },\n};\n\n/** A placement value Meta does not accept in the field it was written into. */\nexport interface PlacementValueIssue {\n field: PlacementField;\n value: string;\n /**\n * `wrong-field` — Meta publishes this value, in a different placement field.\n * That is the cross-platform paste this whole check exists for, and it is a\n * certain rejection at publish, so it is refused.\n *\n * `retired` — Meta published this value for this field and now refuses it on\n * write (see RETIRED_PLACEMENTS). Also a certain rejection, so also refused.\n *\n * `unknown` — no placement field Meta publishes takes it. Usually a typo, but\n * not always: Meta ships placements before it documents them (`connected_tv`\n * is in its generated enum spec and absent from the Placement Targeting page\n * these lists come from), so this cannot be treated as proof of a rejection.\n */\n kind: \"wrong-field\" | \"retired\" | \"unknown\";\n /** What to do instead, in the agent's own vocabulary. */\n fix: string;\n}\n\nfunction placementFieldsAccepting(value: string, except: PlacementField): PlacementField[] {\n return (Object.keys(PLACEMENT_VOCABULARIES) as PlacementField[]).filter(\n (field) => field !== except && (PLACEMENT_VOCABULARIES[field] as readonly string[]).includes(value),\n );\n}\n\n/**\n * Every placement value Meta's vocabulary does not contain, with the correction\n * that applies: the same surface's name on this platform where there is one,\n * the field the value does belong to where it is simply in the wrong slot, and\n * the allowed list otherwise.\n */\nfunction placementValueIssue(field: PlacementField, value: string): PlacementValueIssue {\n const retired = RETIRED_PLACEMENTS[field]?.[value];\n if (retired) {\n return { field, value, kind: \"retired\", fix: retired };\n }\n const renamed = SAME_SURFACE_ON_THIS_PLATFORM[field]?.[value];\n if (renamed) {\n return {\n field,\n value,\n kind: \"wrong-field\",\n fix: `Meta calls that surface \"${renamed}\" in ${field} — use \"${renamed}\"`,\n };\n }\n const elsewhere = placementFieldsAccepting(value, field);\n if (elsewhere.length > 0) {\n return {\n field,\n value,\n kind: \"wrong-field\",\n fix: `\"${value}\" belongs to ${elsewhere.join(\" / \")}, not ${field} — move it there or drop it`,\n };\n }\n return {\n field,\n value,\n kind: \"unknown\",\n fix: `\"${value}\" is not a placement Baker knows; ${field} accepts ${PLACEMENT_VOCABULARIES[field].join(\", \")}`,\n };\n}\n\nexport function invalidPlacementValues(targeting: PositionScopedTargeting | undefined): PlacementValueIssue[] {\n const issues: PlacementValueIssue[] = [];\n for (const field of Object.keys(PLACEMENT_VOCABULARIES) as PlacementField[]) {\n const allowed = PLACEMENT_VOCABULARIES[field] as readonly string[];\n const selected = targeting?.[field] ?? [];\n for (const value of selected) {\n if (!allowed.includes(value)) {\n issues.push(placementValueIssue(field, value));\n }\n }\n }\n return issues;\n}\n\n/**\n * Co-requirements beyond the `feed` rule, each a deterministic refusal at\n * create time.\n *\n * Facebook `story` needs somewhere to fall back to (Facebook feed or Instagram\n * story) and only runs on mobile; Threads' single placement cannot be selected\n * without Instagram `stream`. The device rule only fires on an explicit\n * `device_platforms` that omits mobile — leaving it unset means every device,\n * which satisfies it.\n *\n * v25.0 refused Instagram `explore_home` without `explore`; v26.0 retired\n * `explore` and takes `explore_home` alone (validate-only sweep, 2026-10-15).\n */\nexport function placementCoRequirementIssues(targeting: PositionScopedTargeting | undefined): string[] {\n const facebook = targeting?.facebook_positions ?? [];\n const instagram = targeting?.instagram_positions ?? [];\n const threads = (targeting as { threads_positions?: string[] } | undefined)?.threads_positions ?? [];\n const devices = (targeting as { device_platforms?: string[] } | undefined)?.device_platforms;\n const issues: string[] = [];\n if (facebook.includes(\"story\")) {\n if (!facebook.includes(\"feed\") && !instagram.includes(\"story\")) {\n issues.push(\n 'Meta refuses Facebook \"story\" on its own — select \"feed\" in facebook_positions or \"story\" in instagram_positions alongside it',\n );\n }\n if (devices && !devices.includes(\"mobile\")) {\n issues.push(\n 'Facebook \"story\" only runs on mobile — add \"mobile\" to device_platforms or drop the story placement',\n );\n }\n }\n if (threads.includes(\"threads_stream\") && !instagram.includes(\"stream\")) {\n issues.push('Threads \"threads_stream\" cannot be selected alone — add \"stream\" to instagram_positions');\n }\n return issues;\n}\n\n/**\n * A placement whose published creative specs constrain what can render there.\n * `contested` means Meta's own surfaces disagree — surface it as something to\n * check, never as a fact to act on.\n */\nexport interface PlacementFormatNote {\n /** Targeting vocabulary — matched against `facebook_positions` / `instagram_positions`. */\n position: string;\n /** Insights vocabulary — the `platform_position` a breakdown reports for the same surface. */\n reportedAs: string;\n platform: \"facebook\" | \"instagram\";\n /**\n * `constraint` — a published spec that limits what renders here, so selecting\n * the placement earns a warning. `correction` — a placement widely believed to\n * be constrained that is not; carried so the false version stays refuted, but\n * never warned about.\n */\n kind: \"constraint\" | \"correction\";\n /** What Meta publishes, in one line the agent can repeat to a marketer. */\n note: string;\n /** True when another Meta surface says otherwise. Verify against the account, don't pick a side. */\n contested: boolean;\n source: string;\n}\n\n/**\n * Placements where Meta's published specs mean a stock 9:16 video creative\n * cannot render the way it does in feed, stories, or reels.\n *\n * This list is deliberately short: it holds only placements with a specific\n * published constraint. A placement's absence here means \"no documented\n * constraint\", NOT \"renders anything\" — and a placement Meta never documents\n * (Facebook notifications, Facebook profile feed, Instagram search) means\n * \"undocumented\", which is not evidence of anything at all.\n */\nexport const CONSTRAINED_PLACEMENTS: readonly PlacementFormatNote[] = [\n {\n position: \"facebook_reels_overlay\",\n reportedAs: \"facebook_reels_overlay\",\n platform: \"facebook\",\n kind: \"constraint\",\n note: \"Ads on Facebook Reels take two shapes and a stock 9:16 video fits neither: overlay ads are 'a single, static image ad' (JPG/PNG, 1:1, 0% ratio tolerance, headline capped at 10 characters), and post-loop ads are 1:1 video of 4-15 seconds. Expect a long-headline 9:16 creative to look wrong here.\",\n contested: false,\n source: \"https://www.facebook.com/business/ads-guide/update/image/facebook-facebook-reels-overlay\",\n },\n {\n position: \"explore_home\",\n reportedAs: \"instagram_explore_grid_home\",\n platform: \"instagram\",\n kind: \"constraint\",\n note: \"Marketing API placement asset customization states 'The explore_home placement only supports the SINGLE_IMAGE format', but Meta's own Ads Guide lists Instagram Explore home under video specs. Check the account's play rate for this position before treating it as image-only.\",\n contested: true,\n source: \"https://developers.facebook.com/docs/marketing-api/dynamic-creative/placement-asset-customization/\",\n },\n {\n position: \"right_hand_column\",\n reportedAs: \"right_hand_column\",\n platform: \"facebook\",\n kind: \"correction\",\n note: \"Facebook right column publishes full video specs (MP4/MOV/GIF, 1:1 at 1440x1440 or mobile-only 4:5 at 1440x1800, 1 second to 241 minutes) — it is NOT image-only. Its real constraint is that it cannot be the only placement for a video, collection, or canvas ad.\",\n contested: false,\n source: \"https://www.facebook.com/business/ads-guide/update/video/facebook-right-hand-column\",\n },\n];\n\n/**\n * Preview `ad_format` for an insights `platform_position`, so \"does this\n * placement render my video as a still?\" is one command instead of a guess.\n *\n * Keyed by the **insights** spelling, because that is what `--placement` is\n * documented to take: the agent reads a breakdown and pastes the position\n * straight across. Keying these by the targeting spelling instead made every\n * position a live account reports fail to resolve except the handful that spell\n * the same both ways.\n *\n * Only mappings we can name are listed. A position missing here returns\n * undefined and the caller says so: v25.0's generatepreviews reference lists\n * the `ad_format` enum, but not which breakdown position each value renders,\n * and a guessed pairing previews the wrong surface with no error.\n */\nexport const FACEBOOK_PREVIEW_FORMATS: Readonly<Record<string, string>> = {\n feed: \"MOBILE_FEED_STANDARD\",\n right_hand_column: \"RIGHT_COLUMN_STANDARD\",\n marketplace: \"MARKETPLACE_MOBILE\",\n facebook_stories: \"FACEBOOK_STORY_MOBILE\",\n facebook_reels: \"FACEBOOK_REELS_MOBILE\",\n facebook_reels_overlay: \"FACEBOOK_REELS_BANNER\",\n instream_video: \"INSTREAM_VIDEO_MOBILE\",\n // In the v25.0 ad_format enum and rendered live (2026-10-14).\n facebook_profile_feed: \"FACEBOOK_PROFILE_FEED_MOBILE\",\n // Retired for targeting (RETIRED_PLACEMENTS) and still reported by a breakdown\n // over any window that predates the retirement — an ad set created before it\n // keeps delivering there. Previewing what a historic row measured has to keep\n // working, so this stays.\n video_feeds: \"INSTREAM_VIDEO_MOBILE\",\n};\n\nexport const INSTAGRAM_PREVIEW_FORMATS: Readonly<Record<string, string>> = {\n feed: \"INSTAGRAM_STANDARD\",\n instagram_stories: \"INSTAGRAM_STORY\",\n instagram_reels: \"INSTAGRAM_REELS\",\n instagram_explore: \"INSTAGRAM_EXPLORE_CONTEXTUAL\",\n instagram_explore_grid_home: \"INSTAGRAM_EXPLORE_GRID_HOME\",\n instagram_search: \"INSTAGRAM_SEARCH_CHAIN\",\n instagram_profile_feed: \"INSTAGRAM_PROFILE_FEED\",\n};\n\n/**\n * `feed` is the one position both platforms report under the same name, and it\n * is also the largest — it carried 51% of delivery on the account this was\n * verified against, split across the two platforms. Listed by name rather than\n * derived from the two maps, because a both-maps test breaks precisely where a\n * platform's format is unpublished: Facebook profile feed has no preview format,\n * so such a test would read `facebook_profile_feed` as unambiguously Instagram.\n */\nexport const PLATFORM_SCOPED_POSITIONS: ReadonlySet<string> = new Set([\"feed\"]);\n\n/**\n * `feed` names both a Facebook and an Instagram surface, so the platform\n * decides. Insights rows carry it as `publisher_platform`; without one, a\n * position meaning different things on each platform stays unresolved rather\n * than silently previewing the wrong surface.\n */\nexport function previewFormatForPosition(position: string, platform?: string): string | undefined {\n if (platform === \"facebook\") return FACEBOOK_PREVIEW_FORMATS[position];\n if (platform === \"instagram\") return INSTAGRAM_PREVIEW_FORMATS[position];\n if (PLATFORM_SCOPED_POSITIONS.has(position)) return undefined;\n return FACEBOOK_PREVIEW_FORMATS[position] ?? INSTAGRAM_PREVIEW_FORMATS[position];\n}\n\n/**\n * The documented constraint for a position an insights breakdown reported.\n * Matches on `reportedAs`, not `position`: the caller is holding a\n * `platform_position`, and `explore_home` never appears in one.\n */\nexport function placementFormatNote(reportedPosition: string): PlacementFormatNote | undefined {\n return CONSTRAINED_PLACEMENTS.find((p) => p.reportedAs === reportedPosition);\n}\n\n/**\n * Positions selected without the `feed` Meta requires alongside them — a\n * documented rejection, so callers treat it as a stage-time error rather than\n * letting publish fail.\n */\nexport function positionsMissingRequiredFeed(targeting: PositionScopedTargeting | undefined): string[] {\n const positions = targeting?.facebook_positions;\n if (!positions?.length || positions.includes(\"feed\")) {\n return [];\n }\n return FACEBOOK_POSITIONS_REQUIRING_FEED.filter((required) => positions.includes(required));\n}\n\n/**\n * True when a video creative would have no placement at all to fall back on.\n *\n * Meta's rule is about the ad set's placements, not Facebook's slice of them:\n * right column \"can't be the only placement\" for a video, collection, or canvas\n * ad. So an Instagram position, or a platform list Meta expands on our behalf,\n * both mean the ad set has somewhere else to render and there is nothing to\n * warn about. Both defaults widen — `publisher_platforms` left unset means every\n * platform, so an unset list is not evidence that Facebook is alone.\n */\nexport function rightColumnIsSolePlacement(targeting: PositionScopedTargeting | undefined): boolean {\n const positions = targeting?.facebook_positions;\n if (positions?.length !== 1 || positions[0] !== \"right_hand_column\") return false;\n if (targeting?.instagram_positions?.length) return false;\n const platforms = targeting?.publisher_platforms;\n return platforms?.length === 1 && platforms[0] === \"facebook\";\n}\n\n/** Documented constraints covering the placements this targeting actually selects. */\nexport function constrainedPlacementsIn(targeting: PositionScopedTargeting | undefined): PlacementFormatNote[] {\n const selected = new Set([...(targeting?.facebook_positions ?? []), ...(targeting?.instagram_positions ?? [])]);\n return CONSTRAINED_PLACEMENTS.filter((p) => p.kind === \"constraint\" && selected.has(p.position));\n}\n\n/** True when a payload pins placements explicitly (rather than leaving Advantage+ to choose). */\nexport function setsExplicitPlacements(targeting: PositionScopedTargeting | undefined): boolean {\n return Boolean(\n targeting?.publisher_platforms?.length ||\n targeting?.facebook_positions?.length ||\n targeting?.instagram_positions?.length,\n );\n}\n","/**\n * Brand safety on Meta: where an ad may NOT appear.\n *\n * - A publisher block list is a list of websites and apps (Audience Network and\n * in-stream) the ad account keeps its ads off. It belongs to the ad account\n * and is applied per ad set through `targeting.excluded_publisher_list_ids`.\n * - `targeting.brand_safety_content_filter_levels` picks how strict Meta's\n * content filter is next to the ad, per family of placements.\n * - `targeting.excluded_publisher_categories` keeps the ad off whole kinds of\n * publishers (dating, gambling, …).\n *\n * Live on v26.0 (2026-10-15) on act_1342210013621203:\n * - `POST /act_<id>/publisher_block_lists` with `name` IGNORES `validate_only`\n * (a dry run made a real list), so it is never dry-run;\n * - `POST /{list}/append_publisher_urls` with `publisher_urls` adds sites\n * (`example.org` read back as `www.example.org`), answering\n * `success_url_count`;\n * - `DELETE /{list}` removes it, and it then reads as gone (subcode 33);\n * - renaming is refused — `POST /{list}` wants an undocumented `spec`\n * (\"Param <update_type> is invalid\" for every value tried) — and there is no\n * edge that takes a site off a list (`delete_web_publishers`: \"Unknown path\n * components\"). A list is changed by adding to it, or replaced by a new one.\n * - Business-level lists (`/{business}/block_list_drafts`, file upload) and\n * content block lists (`/{business}/content_block_lists`) need Meta\n * capability grants this app does not hold (\"Application does not have the\n * capability to make this API call\", code 3).\n */\nimport { z } from \"zod\";\nimport { TEMP_REF_REGEX } from \"./limits\";\n\n/** One site or app on a block list: a domain (`example.com`) or an app store address. */\nconst publisherSchema = z\n .string()\n .trim()\n .min(3)\n .max(2048)\n .refine((value) => !/\\s/.test(value), \"a site or app address has no spaces\");\n\n/** Meta keeps up to 10,000 sites and apps on one list. */\nexport const PUBLISHER_BLOCK_LIST_MAX_URLS = 10_000;\n\nexport const publisherBlockListCreateSchema = z.strictObject({\n name: z.string().trim().min(1).max(100),\n /** The sites and apps to keep ads off. */\n urls: z.array(publisherSchema).min(1).max(PUBLISHER_BLOCK_LIST_MAX_URLS),\n});\nexport type PublisherBlockListCreate = z.infer<typeof publisherBlockListCreateSchema>;\n\nexport const publisherBlockListUpdateSchema = z\n .strictObject({\n /** More sites and apps to keep ads off. Meta takes none off a list. */\n addUrls: z.array(publisherSchema).min(1).max(PUBLISHER_BLOCK_LIST_MAX_URLS).optional(),\n status: z.literal(\"DELETED\").optional(),\n })\n .refine((p) => (p.addUrls === undefined) !== (p.status === undefined), \"add urls OR delete the list\");\nexport type PublisherBlockListUpdate = z.infer<typeof publisherBlockListUpdateSchema>;\n\n/**\n * Meta's content filter next to an ad, three families × three levels:\n * RELAXED (Expanded inventory), STANDARD (Moderate), STRICT (Limited).\n * FACEBOOK_* is in-content (Facebook in-stream and Reels), AN_* Audience\n * Network, FEED_* Facebook and Instagram feeds.\n */\nexport const CONTENT_FILTER_LEVELS = [\n \"FACEBOOK_RELAXED\",\n \"FACEBOOK_STANDARD\",\n \"FACEBOOK_STRICT\",\n \"AN_RELAXED\",\n \"AN_STANDARD\",\n \"AN_STRICT\",\n \"FEED_RELAXED\",\n \"FEED_STANDARD\",\n \"FEED_STRICT\",\n] as const;\n\n/** Kinds of publishers an ad set can stay off. The last three apply to Audience Network and in-stream only. */\nexport const EXCLUDED_PUBLISHER_CATEGORIES = [\n \"dating\",\n \"gambling\",\n \"debated_social_issues\",\n \"mature_audiences\",\n \"tragedy_and_conflict\",\n] as const;\n\n/** A block list id, or the meta_temp_* ref of one this chat creates. */\nconst blockListRefSchema = z.union([z.string().regex(/^\\d+$/), z.string().regex(TEMP_REF_REGEX)]);\n\n/** The brand-safety fields of an ad set's targeting (`ops.ts` `metaTargetingSchema`). */\nexport const brandSafetyTargetingFields = {\n excluded_publisher_list_ids: z.array(blockListRefSchema).min(1).optional(),\n brand_safety_content_filter_levels: z\n .array(z.enum(CONTENT_FILTER_LEVELS))\n .min(1)\n .refine(\n (levels) => new Set(levels.map((level) => level.split(\"_\")[0])).size === levels.length,\n \"one content filter level per family (FACEBOOK, AN, FEED)\",\n )\n .optional(),\n excluded_publisher_categories: z.array(z.enum(EXCLUDED_PUBLISHER_CATEGORIES)).min(1).optional(),\n};\n\nconst BRAND_SAFETY_KEYS: ReadonlySet<string> = new Set(Object.keys(brandSafetyTargetingFields));\n\n/**\n * An ad set update that names only brand-safety targeting keeps the rest of\n * the live targeting: Meta replaces an ad set's whole targeting on update, so\n * `adsets update --block-list <id>` would otherwise drop its locations and\n * audiences. Targeting that names anything else is the caller's whole spec.\n */\nexport function mergeBrandSafetyTargeting(\n staged: Record<string, unknown>,\n live: Record<string, unknown> | undefined,\n): Record<string, unknown> {\n const keys = Object.keys(staged);\n if (!live || keys.length === 0 || !keys.every((key) => BRAND_SAFETY_KEYS.has(key))) return staged;\n return { ...live, ...staged };\n}\n","/**\n * Product catalogs, their products, product sets and feeds — what an\n * Advantage+ catalog ad (and a collection ad) shows. A catalog belongs to a\n * Business, not an ad account; Baker changes only catalogs the selected ad\n * account's own Business owns.\n *\n * What Meta does, live on v26.0 (2026-10-15) on Baker's own Business:\n * - every write here IGNORES `validate_only`: a catalog create\n * (`/{business_id}/owned_product_catalogs`), a product create\n * (`/{catalog_id}/products`), a product set create, a feed create, a product\n * rename and a set rename were each made or applied for real. None is ever\n * dry-run; staging checks what reads can.\n * - a product, a product set and a feed are deleted with `DELETE /{id}` and then\n * read as gone (subcode 33 for a product or a set; a feed answers\n * \"Unsupported request - method type: get\").\n * - `DELETE /{catalog_id}` answered a bare \"An unknown error occurred\" (code 1,\n * subcode 99) and had deleted the catalog with everything in it — the\n * publish reads a catalog delete back before believing the error.\n * - a product's price is sent in the currency's minor units (1999 for €19.99)\n * and reads back formatted (\"€19.99\").\n * - a feed reads back with no catalog field at all, so the catalog it lives in\n * is found through the catalog's own `product_feeds` list.\n */\nimport { z } from \"zod\";\nimport { NUMERIC_ID_REGEX, TEMP_REF_REGEX } from \"./limits\";\n\nconst tempRefSchema = z.string().regex(TEMP_REF_REGEX, \"expected a meta_temp_* reference\");\n/** A catalog: a real id, or the meta_temp_* ref of one this chat creates. */\nconst catalogRefSchema = z.union([z.string().regex(NUMERIC_ID_REGEX, \"expected a numeric id\"), tempRefSchema]);\nconst httpsUrlSchema = z\n .string()\n .url()\n .refine((value) => value.startsWith(\"https://\"), \"must be an https URL\");\n\nexport const CATALOG_LIMITS = {\n nameMax: 100,\n productNameMax: 200,\n descriptionMax: 9999,\n retailerIdMax: 100,\n brandMax: 100,\n additionalImagesMax: 20,\n filterValuesMax: 500,\n};\n\n// --- Catalog ---\n\n/** Pixels (or apps) a catalog's ads count on — Meta's `external_event_sources`. */\nconst eventSourcesSchema = z.array(z.string().regex(NUMERIC_ID_REGEX)).min(1).max(10);\n\nexport const productCatalogCreateSchema = z.strictObject({\n name: z.string().trim().min(1).max(CATALOG_LIMITS.nameMax),\n /** The Business it is made on — filled at staging from the ad account's own Business; any other is refused. */\n business_id: z.string().regex(NUMERIC_ID_REGEX).optional(),\n /**\n * Pixels to connect once it exists. Advantage+ catalog ads need one: live on\n * v26.0 a catalog ad set on a catalog without one was refused — \"An event\n * source (Facebook Pixel or App) is required to run Dynamic Ads\" (1885059).\n */\n event_sources: eventSourcesSchema.optional(),\n});\nexport type ProductCatalogCreate = z.infer<typeof productCatalogCreateSchema>;\n\n/** Rename a catalog, connect or disconnect pixels, or delete it with everything in it. */\nexport const productCatalogUpdateSchema = z\n .strictObject({\n name: z.string().trim().min(1).max(CATALOG_LIMITS.nameMax).optional(),\n event_sources: eventSourcesSchema.optional(),\n unlink_event_sources: eventSourcesSchema.optional(),\n status: z.literal(\"DELETED\").optional(),\n })\n .superRefine((p, ctx) => {\n const changes = [p.name, p.event_sources, p.unlink_event_sources].filter((value) => value !== undefined).length;\n if (p.status === \"DELETED\" && changes > 0) {\n ctx.addIssue({ code: \"custom\", message: \"a catalog delete changes nothing else\" });\n }\n if (p.status === undefined && changes === 0) {\n ctx.addIssue({ code: \"custom\", message: \"rename the catalog, connect or disconnect a pixel, or delete it\" });\n }\n const both = (p.event_sources ?? []).filter((id) => p.unlink_event_sources?.includes(id));\n if (both.length > 0) {\n ctx.addIssue({ code: \"custom\", message: `pixel ${both.join(\", \")} is both connected and disconnected` });\n }\n });\nexport type ProductCatalogUpdate = z.infer<typeof productCatalogUpdateSchema>;\n\n// --- Product ---\n\nexport const PRODUCT_AVAILABILITIES = [\n \"in stock\",\n \"out of stock\",\n \"preorder\",\n \"available for order\",\n \"discontinued\",\n] as const;\nexport const PRODUCT_CONDITIONS = [\"new\", \"refurbished\", \"used\"] as const;\n\n/** A price in major units, as a shopper reads it: \"19.99\". */\nconst priceSchema = z.string().regex(/^\\d{1,9}(\\.\\d{1,2})?$/, 'a price in major units, e.g. \"19.99\"');\nconst currencySchema = z.string().regex(/^[A-Z]{3}$/, \"a three-letter currency code, e.g. EUR\");\n\nconst productFields = {\n name: z.string().trim().min(1).max(CATALOG_LIMITS.productNameMax),\n description: z.string().trim().min(1).max(CATALOG_LIMITS.descriptionMax),\n price: priceSchema,\n sale_price: priceSchema,\n currency: currencySchema,\n availability: z.enum(PRODUCT_AVAILABILITIES),\n condition: z.enum(PRODUCT_CONDITIONS),\n /** The product's own page — where its ad sends people. */\n url: httpsUrlSchema,\n /** A picture Meta fetches: a public https address (a library image's address works). */\n image_url: httpsUrlSchema,\n additional_image_urls: z.array(httpsUrlSchema).min(1).max(CATALOG_LIMITS.additionalImagesMax),\n brand: z.string().trim().min(1).max(CATALOG_LIMITS.brandMax),\n};\n\nexport const productCreateSchema = z.strictObject({\n catalog_id: catalogRefSchema,\n /** The advertiser's own id for the product (Meta's `retailer_id`, the SKU) — what a product set filters on. */\n retailer_id: z.string().trim().min(1).max(CATALOG_LIMITS.retailerIdMax),\n name: productFields.name,\n description: productFields.description,\n price: productFields.price,\n sale_price: productFields.sale_price.optional(),\n currency: productFields.currency,\n availability: productFields.availability.default(\"in stock\"),\n condition: productFields.condition.default(\"new\"),\n url: productFields.url,\n image_url: productFields.image_url,\n additional_image_urls: productFields.additional_image_urls.optional(),\n brand: productFields.brand.optional(),\n});\nexport type ProductCreate = z.infer<typeof productCreateSchema>;\n\n/** Change a product's fields, or delete it. A price names its currency. */\nexport const productUpdateSchema = z\n .strictObject({\n name: productFields.name.optional(),\n description: productFields.description.optional(),\n price: productFields.price.optional(),\n sale_price: productFields.sale_price.optional(),\n currency: productFields.currency.optional(),\n availability: productFields.availability.optional(),\n condition: productFields.condition.optional(),\n url: productFields.url.optional(),\n image_url: productFields.image_url.optional(),\n additional_image_urls: productFields.additional_image_urls.optional(),\n brand: productFields.brand.optional(),\n status: z.literal(\"DELETED\").optional(),\n })\n .superRefine((p, ctx) => {\n const changes = Object.keys(p).filter((key) => key !== \"status\");\n if (p.status === \"DELETED\" && changes.length > 0) {\n ctx.addIssue({ code: \"custom\", message: \"a product delete changes nothing else\" });\n }\n if (p.status === undefined && changes.length === 0) {\n ctx.addIssue({ code: \"custom\", message: \"change at least one field, or delete the product\" });\n }\n if ((p.price !== undefined || p.sale_price !== undefined) && p.currency === undefined) {\n ctx.addIssue({ code: \"custom\", path: [\"currency\"], message: \"a price names its currency\" });\n }\n });\nexport type ProductUpdate = z.infer<typeof productUpdateSchema>;\n\n// --- Product set ---\n\n/**\n * Meta's product set rule operators (`filter`): a field maps to one operator\n * and its value, and `and` / `or` combine rules. `is_any` / `is_not_any` take a\n * list; the comparisons take a number (a price is in minor units there, as Meta\n * stores it); the rest take text.\n */\nconst LIST_OPERATORS = [\"is_any\", \"is_not_any\"] as const;\nconst NUMBER_OPERATORS = [\"lt\", \"lte\", \"gt\", \"gte\"] as const;\nconst TEXT_OPERATORS = [\n \"eq\",\n \"neq\",\n \"contains\",\n \"not_contains\",\n \"i_contains\",\n \"i_not_contains\",\n \"starts_with\",\n] as const;\n/** The operator names a rule may use, for the agent's error messages and docs. */\nexport const PRODUCT_SET_OPERATORS = [...LIST_OPERATORS, ...NUMBER_OPERATORS, ...TEXT_OPERATORS];\n\nconst conditionSchema = z.union([\n ...LIST_OPERATORS.map((operator) =>\n z.strictObject({ [operator]: z.array(z.string().min(1)).min(1).max(CATALOG_LIMITS.filterValuesMax) }),\n ),\n ...NUMBER_OPERATORS.map((operator) => z.strictObject({ [operator]: z.number() })),\n ...TEXT_OPERATORS.map((operator) => z.strictObject({ [operator]: z.string().min(1) })),\n]);\n\nexport type ProductSetFilter = { and: ProductSetFilter[] } | { or: ProductSetFilter[] } | Record<string, unknown>;\n\nconst FIELD_NAME_REGEX = /^[a-z][a-z0-9_.]*$/;\n\n/** What is wrong with a rule, depth first, or `undefined` when Meta can take it. */\nexport function productSetFilterIssue(rule: unknown): string | undefined {\n if (!rule || typeof rule !== \"object\" || Array.isArray(rule)) return \"a rule is an object\";\n const entries = Object.entries(rule as Record<string, unknown>);\n if (entries.length !== 1) return \"one field per rule — combine several with and / or\";\n const [key, value] = entries[0] as [string, unknown];\n if (key === \"and\" || key === \"or\") {\n if (!Array.isArray(value) || value.length === 0) return `${key} takes a list of rules`;\n for (const inner of value) {\n const issue = productSetFilterIssue(inner);\n if (issue) return issue;\n }\n return undefined;\n }\n if (!FIELD_NAME_REGEX.test(key)) {\n return \"a rule names a product field, e.g. retailer_id, brand, product_type, price, custom_label_0\";\n }\n return conditionSchema.safeParse(value).success\n ? undefined\n : `${key}: one operator of ${PRODUCT_SET_OPERATORS.join(\", \")} with its value — a list for is_any / is_not_any, a number for lt / lte / gt / gte, text for the rest`;\n}\n\n/**\n * A product set rule (Meta's `filter`), checked whole by `productSetFilterIssue`\n * — one opaque value to the review, which reads it as words.\n */\nexport const productSetFilterSchema = z\n .record(z.string(), z.unknown())\n .superRefine((rule, ctx) => {\n const issue = productSetFilterIssue(rule);\n if (issue) ctx.addIssue({ code: \"custom\", message: issue });\n })\n .transform((rule) => rule as ProductSetFilter);\n\nexport const productSetCreateSchema = z.strictObject({\n catalog_id: catalogRefSchema,\n name: z.string().trim().min(1).max(CATALOG_LIMITS.nameMax),\n /** Which products are in it. Without one the set holds the whole catalog. */\n filter: productSetFilterSchema.optional(),\n});\nexport type ProductSetCreate = z.infer<typeof productSetCreateSchema>;\n\n/** Rename a set, change its rule (the whole rule is replaced), or delete it. */\nexport const productSetUpdateSchema = z\n .strictObject({\n name: z.string().trim().min(1).max(CATALOG_LIMITS.nameMax).optional(),\n filter: productSetFilterSchema.optional(),\n status: z.literal(\"DELETED\").optional(),\n })\n .superRefine((p, ctx) => {\n const changes = p.name !== undefined || p.filter !== undefined;\n if (p.status === \"DELETED\" && changes) {\n ctx.addIssue({ code: \"custom\", message: \"a product set delete changes nothing else\" });\n }\n if (p.status === undefined && !changes) {\n ctx.addIssue({ code: \"custom\", message: \"rename the set, change its filter, or delete it\" });\n }\n });\nexport type ProductSetUpdate = z.infer<typeof productSetUpdateSchema>;\n\n/** The common case as a rule: exactly these products, by the advertiser's own ids. */\nexport function retailerIdFilter(retailerIds: readonly string[]): ProductSetFilter {\n return { retailer_id: { is_any: [...retailerIds] } };\n}\n\n// --- Feed ---\n\nexport const FEED_INTERVALS = [\"HOURLY\", \"DAILY\", \"WEEKLY\"] as const;\nexport const FEED_DAYS = [\"MONDAY\", \"TUESDAY\", \"WEDNESDAY\", \"THURSDAY\", \"FRIDAY\", \"SATURDAY\", \"SUNDAY\"] as const;\n\n/** Meta fetches the file at `url` on this schedule and replaces the catalog's products from it. */\nexport const feedScheduleSchema = z\n .strictObject({\n url: httpsUrlSchema,\n interval: z.enum(FEED_INTERVALS),\n /** Hour of day, 0–23, in Meta's feed time zone. */\n hour: z.number().int().min(0).max(23).optional(),\n day_of_week: z.enum(FEED_DAYS).optional(),\n })\n .superRefine((s, ctx) => {\n if (s.interval === \"WEEKLY\" && s.day_of_week === undefined) {\n ctx.addIssue({ code: \"custom\", path: [\"day_of_week\"], message: \"a weekly schedule names its day\" });\n }\n if (s.interval !== \"WEEKLY\" && s.day_of_week !== undefined) {\n ctx.addIssue({ code: \"custom\", path: [\"day_of_week\"], message: \"only a weekly schedule names a day\" });\n }\n });\nexport type FeedSchedule = z.infer<typeof feedScheduleSchema>;\n\nexport const productFeedCreateSchema = z.strictObject({\n catalog_id: catalogRefSchema,\n name: z.string().trim().min(1).max(CATALOG_LIMITS.nameMax),\n /** Without one the feed waits for files uploaded to it. */\n schedule: feedScheduleSchema.optional(),\n});\nexport type ProductFeedCreate = z.infer<typeof productFeedCreateSchema>;\n\n/** Rename a feed, replace its schedule, or delete it (its products stay in the catalog). */\nexport const productFeedUpdateSchema = z\n .strictObject({\n name: z.string().trim().min(1).max(CATALOG_LIMITS.nameMax).optional(),\n schedule: feedScheduleSchema.optional(),\n status: z.literal(\"DELETED\").optional(),\n })\n .superRefine((p, ctx) => {\n const changes = p.name !== undefined || p.schedule !== undefined;\n if (p.status === \"DELETED\" && changes) {\n ctx.addIssue({ code: \"custom\", message: \"a feed delete changes nothing else\" });\n }\n if (p.status === undefined && !changes) {\n ctx.addIssue({ code: \"custom\", message: \"rename the feed, change its schedule, or delete it\" });\n }\n });\nexport type ProductFeedUpdate = z.infer<typeof productFeedUpdateSchema>;\n\n/** A product set rule in plain words, for the review and the summary. */\nexport function describeProductSetFilter(filter: ProductSetFilter | undefined): string {\n if (!filter) return \"every product in the catalog\";\n if (\"and\" in filter && Array.isArray(filter.and)) {\n return filter.and.map((rule) => describeProductSetFilter(rule as ProductSetFilter)).join(\" and \");\n }\n if (\"or\" in filter && Array.isArray(filter.or)) {\n return `(${filter.or.map((rule) => describeProductSetFilter(rule as ProductSetFilter)).join(\" or \")})`;\n }\n const [field, condition] = Object.entries(filter)[0] ?? [];\n const [operator, value] = Object.entries((condition ?? {}) as Record<string, unknown>)[0] ?? [];\n // A price is compared in minor units, and the rule names no currency to turn it back into one.\n const minor = /(^|_)price$/.test(String(field)) && (NUMBER_OPERATORS as readonly string[]).includes(operator ?? \"\");\n const shown = Array.isArray(value) ? value.join(\", \") : minor ? `${String(value)} cents` : String(value);\n const words: Record<string, string> = {\n is_any: \"is one of\",\n is_not_any: \"is none of\",\n eq: \"is\",\n neq: \"is not\",\n contains: \"contains\",\n not_contains: \"does not contain\",\n i_contains: \"contains\",\n i_not_contains: \"does not contain\",\n starts_with: \"starts with\",\n lt: \"is under\",\n lte: \"is at most\",\n gt: \"is over\",\n gte: \"is at least\",\n };\n return `${String(field).replace(/_/g, \" \")} ${words[operator ?? \"\"] ?? operator} ${shown}`;\n}\n","/**\n * The people in a Meta customer list — the contract between the CLI that\n * hashes them, the backend that holds them until Publish, and Meta's\n * `/{audience_id}/users` edges that receive them.\n *\n * Every identifying value is normalized and SHA-256 hashed in the CLI, on the\n * agent's machine (`packages/cli/src/commands/ads/meta/customer-list.ts`), so\n * no raw email, phone or name ever reaches Baker or Meta. Meta's own rules\n * (Custom Audiences guide, \"Hashing and normalization\"): EMAIL, PHONE, FN, LN,\n * FI, CT, ST, ZIP, COUNTRY, DOBY, DOBM, DOBD and GEN are hashed; MADID and\n * EXTERN_ID are sent as they are; LOOKALIKE_VALUE — a person's value on a\n * value-based list — is a number, never hashed.\n *\n * The hashed rows are too large to keep in the draft (one Convex document for\n * the whole chat), so they travel in batches of at most 10,000 rows — Meta's\n * own per-request ceiling — each stored as a file the staged op names. The\n * op itself carries only the columns, the files and how many people each holds,\n * which is all the review ever shows.\n */\nimport { z } from \"zod\";\nimport { NUMERIC_ID_REGEX, TEMP_REF_REGEX } from \"./limits\";\n\n/** Meta's multi-key schema columns, plus the value column of a value-based list. */\nexport const CUSTOMER_LIST_KEYS = [\n \"EMAIL\",\n \"PHONE\",\n \"FN\",\n \"LN\",\n \"FI\",\n \"CT\",\n \"ST\",\n \"ZIP\",\n \"COUNTRY\",\n \"DOBY\",\n \"DOBM\",\n \"DOBD\",\n \"GEN\",\n \"MADID\",\n \"EXTERN_ID\",\n \"LOOKALIKE_VALUE\",\n] as const;\nexport type CustomerListKey = (typeof CUSTOMER_LIST_KEYS)[number];\n\n/** The columns Meta matches people on without hashing. */\nexport const UNHASHED_CUSTOMER_LIST_KEYS: ReadonlySet<CustomerListKey> = new Set([\n \"MADID\",\n \"EXTERN_ID\",\n \"LOOKALIKE_VALUE\",\n]);\n\n/** Columns that identify a person on their own — a list needs at least one. */\nexport const IDENTIFYING_CUSTOMER_LIST_KEYS: readonly CustomerListKey[] = [\"EMAIL\", \"PHONE\", \"MADID\", \"EXTERN_ID\"];\n\n/** Meta's ceiling per `/users` request. */\nexport const CUSTOMER_LIST_BATCH_ROWS = 10_000;\n/**\n * Batches one staged change may carry. Each is one request at Publish (a full\n * batch is ~3 MB of hashes and can take Meta several seconds, plus the rate\n * limiter's waits), and the whole change runs in one step of the publish, which\n * an action's 10-minute ceiling ends — so the cap keeps the worst case under\n * half of it: 200,000 people. A longer list is split across changes (`add`\n * twice), except a replace, which Meta runs as one session.\n */\nexport const CUSTOMER_LIST_MAX_BATCHES = 20;\n\nconst SHA256_HEX = /^[0-9a-f]{64}$/;\n/** A mobile advertiser id: Apple IDFA or Google AAID, lowercase with hyphens, as Meta asks. */\nconst MADID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;\n\n/** Why one cell cannot be sent for its column, or undefined. An empty cell is a key the person has no value for. */\nexport function customerListCellIssue(key: CustomerListKey, value: string): string | undefined {\n if (value === \"\") {\n return key === \"LOOKALIKE_VALUE\"\n ? \"a value-based list carries a value for every person — give the row a value or leave it out\"\n : undefined;\n }\n if (key === \"LOOKALIKE_VALUE\") {\n return /^\\d+(\\.\\d+)?$/.test(value) ? undefined : \"a value-based list carries a number of 0 or more per person\";\n }\n if (key === \"MADID\") {\n return MADID.test(value) ? undefined : \"a mobile advertiser id is a lowercase IDFA/AAID with hyphens\";\n }\n if (key === \"EXTERN_ID\") {\n return value.length <= 256 ? undefined : \"an external id is at most 256 characters\";\n }\n return SHA256_HEX.test(value)\n ? undefined\n : `${key} must be the lowercase SHA-256 digest the CLI makes from the normalized value, never the value itself`;\n}\n\nconst schemaColumnsSchema = z\n .array(z.enum(CUSTOMER_LIST_KEYS))\n .min(1)\n .refine((keys) => new Set(keys).size === keys.length, \"each column appears once\")\n .refine(\n (keys) => keys.some((key) => IDENTIFYING_CUSTOMER_LIST_KEYS.includes(key)),\n `a customer list matches people on at least one of ${IDENTIFYING_CUSTOMER_LIST_KEYS.join(\", \")}`,\n );\n\n/** One batch of hashed rows, as the CLI sends it to be held until Publish. */\nexport const customerListBatchSchema = z\n .strictObject({\n schema: schemaColumnsSchema,\n rows: z.array(z.array(z.string())).min(1).max(CUSTOMER_LIST_BATCH_ROWS),\n })\n .superRefine((batch, ctx) => {\n for (const [index, row] of batch.rows.entries()) {\n if (row.length !== batch.schema.length) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"rows\", index],\n message: `each row has one value per column (${batch.schema.length})`,\n });\n return;\n }\n for (const [column, key] of batch.schema.entries()) {\n const issue = customerListCellIssue(key, row[column] ?? \"\");\n if (issue) {\n // The offending value is never echoed: it may be a raw email.\n ctx.addIssue({ code: \"custom\", path: [\"rows\", index, column], message: issue });\n return;\n }\n }\n }\n });\nexport type CustomerListBatch = z.infer<typeof customerListBatchSchema>;\n\n/** What the backend answers for a stored batch: the file the op names, and its row count. */\nexport const customerListBatchResponseSchema = z.object({ fileId: z.string(), rows: z.number().int() });\nexport type CustomerListBatchResponse = z.infer<typeof customerListBatchResponseSchema>;\n\nexport const CUSTOMER_LIST_ACTIONS = [\"add\", \"remove\", \"replace\"] as const;\nexport type CustomerListAction = (typeof CUSTOMER_LIST_ACTIONS)[number];\n\n/**\n * A change to who is in a customer list: add people, remove them, or replace\n * the whole list (Meta's `usersreplace` — everyone not in the new list leaves).\n * The audience is a real id or the ref of a customer list this chat creates.\n */\nexport const customAudienceMembersSchema = z\n .strictObject({\n audience_id: z.union([z.string().regex(NUMERIC_ID_REGEX), z.string().regex(TEMP_REF_REGEX)]),\n action: z.enum(CUSTOMER_LIST_ACTIONS),\n schema: schemaColumnsSchema,\n batches: z\n .array(z.strictObject({ fileId: z.string().min(1), rows: z.number().int().min(1).max(CUSTOMER_LIST_BATCH_ROWS) }))\n .min(1)\n .max(CUSTOMER_LIST_MAX_BATCHES),\n })\n .superRefine((p, ctx) => {\n if (new Set(p.batches.map((batch) => batch.fileId)).size !== p.batches.length) {\n ctx.addIssue({ code: \"custom\", path: [\"batches\"], message: \"each batch is sent once\" });\n }\n });\nexport type CustomAudienceMembers = z.infer<typeof customAudienceMembersSchema>;\n\n/** How many people a staged change names, summed over its batches. */\nexport function customerListRowCount(p: Pick<CustomAudienceMembers, \"batches\">): number {\n return p.batches.reduce((sum, batch) => sum + batch.rows, 0);\n}\n","/**\n * Staged Meta Ads write operations — the wire + storage payload contract.\n *\n * Ops are staged per chat and applied only when the chat publishes. Every\n * payload here is validated at stage time (lengths, enums, budget rules, ref\n * shapes, cross-field constraints); referential checks (account scope, parent\n * existence, page/Instagram identity ownership, media readiness) happen in the\n * backend stage action on top of these schemas.\n *\n * Object graph: Campaign → Ad Set → Ad Creative → Ad, plus Custom Audiences,\n * Custom Conversions, automated rules (`adRules.ts`), A/B tests (`adStudies.ts`) and media uploads. Unlike LinkedIn (where the creative *is* the ad), Meta\n * keeps the creative a separate object that an ad references by id.\n */\nimport { z } from \"zod\";\nimport { adRuleCreateSchema, adRuleTempRefs, adRuleUpdateSchema } from \"./adRules\";\nimport {\n placementSoftOptOutSchema,\n regionalRegulationFields,\n softOptOutPlacementIssue,\n validateRegionalRegulation,\n} from \"./adSetCompliance\";\nimport { adStudyCreateSchema, adStudyTempRefs, adStudyUpdateSchema, adStudyWarnings } from \"./adStudies\";\nimport {\n brandSafetyTargetingFields,\n publisherBlockListCreateSchema,\n publisherBlockListUpdateSchema,\n} from \"./brandSafety\";\nimport {\n productCatalogCreateSchema,\n productCatalogUpdateSchema,\n productCreateSchema,\n productFeedCreateSchema,\n productFeedUpdateSchema,\n productSetCreateSchema,\n productSetUpdateSchema,\n productUpdateSchema,\n} from \"./catalogs\";\nimport { adCopySchema, adSetCopySchema, campaignCopySchema, copyWarnings } from \"./copies\";\nimport { customConversionRuleRefusal } from \"./customConversions\";\nimport { customAudienceMembersSchema } from \"./customerList\";\nimport { type CanvasCreate, canvasCreateSchema, canvasUpdateSchema } from \"./instantExperiences\";\nimport { leadFormCreateSchema, leadFormUpdateSchema } from \"./leadForms\";\nimport {\n AD_FORMATS,\n ADVANTAGE_AUDIENCE_MAX_HARD_AGE_MIN,\n ADVANTAGE_AUDIENCE_OPEN_AGE_MAX,\n ASSET_FEED_CTA_TYPES,\n ATTRIBUTION_EVENT_TYPES,\n ATTRIBUTION_MAX_WINDOW_DAYS,\n BID_STRATEGIES,\n BID_STRATEGIES_FORBIDDING_AMOUNT,\n BID_STRATEGIES_REQUIRING_AMOUNT,\n BILLING_EVENTS,\n BUYING_TYPES,\n CREATIVE_UPDATE_STATUSES,\n CTA_TYPES,\n CURRENCY_MINIMUMS,\n CUSTOM_AUDIENCE_SUBTYPES,\n CUSTOM_EVENT_TYPES,\n CUSTOMER_FILE_SOURCES,\n DEFAULT_CURRENCY_MINIMUM,\n DESTINATION_TYPES,\n ENROLL_STATUSES,\n EU_DSA_COUNTRIES,\n FREQUENCY_CAP_EVENTS,\n FREQUENCY_CAP_TYPES,\n IMAGE_HASH_REGEX,\n LEAD_FORM_CTA_TYPES,\n MEDIA_KINDS,\n META_LIMITS,\n type MetaBidStrategy,\n type MetaMediaKind,\n NUMERIC_ID_REGEX,\n OBJECTIVES,\n OPTIMIZATION_GOALS,\n OPTIMIZATION_GOALS_REQUIRING_APP,\n OPTIMIZATION_GOALS_REQUIRING_CONVERSION_SOURCE,\n OPTIMIZATION_GOALS_REQUIRING_PAGE,\n OPTIMIZATION_GOALS_REQUIRING_PIXEL,\n OPTIMIZATION_GOALS_WITH_FREQUENCY_CAP,\n PACING_TYPES,\n ROAS_FLOOR_SCALE,\n SCHEDULE_TIMEZONE_TYPES,\n SPECIAL_AD_CATEGORIES,\n SPECIAL_CATEGORIES_REQUIRING_COUNTRY,\n STAGEABLE_CREATE_STATUSES,\n TEMP_REF_REGEX,\n UPDATE_STATUSES,\n visualEnhancementsOn,\n} from \"./limits\";\nimport { PLACEMENT_SLOTS } from \"./mediaSpecs\";\nimport {\n APP_DESTINATIONS,\n MESSAGING_CTA_DESTINATION,\n MESSAGING_DESTINATION_TYPES,\n welcomeMessageSchema,\n} from \"./messaging\";\nimport { pagePhotoCreateSchema, pagePhotoUpdateSchema } from \"./pagePhotos\";\nimport {\n constrainedPlacementsIn,\n invalidPlacementValues,\n PLACEMENT_TARGETING_DOC,\n placementCoRequirementIssues,\n positionsMissingRequiredFeed,\n rightColumnIsSolePlacement,\n setsExplicitPlacements,\n} from \"./placements\";\nimport { reachFrequencyReservationCreateSchema, reachFrequencyReservationUpdateSchema } from \"./reachFrequency\";\n\n// --- Shared primitives ---\n\nexport const tempRefSchema = z.string().regex(TEMP_REF_REGEX, \"expected a meta_temp_* reference\");\n\n/** A parent reference: a real bare-numeric Meta id, or a meta_temp_* ref staged earlier in the same draft. */\nexport const parentRefSchema = z.union([z.string().regex(NUMERIC_ID_REGEX, \"expected a numeric id\"), tempRefSchema]);\n\n/**\n * Money in major units — the backend fills currencyCode from the account and converts to Meta minor units.\n * Up to two decimals: Meta counts every account currency in hundredths or whole units (`ads/meta/currency.ts`).\n */\nexport const moneySchema = z.strictObject({\n amount: z\n .string()\n .regex(/^\\d+(\\.\\d{1,2})?$/, \"expected a decimal amount like 50 or 50.00\")\n .refine((val) => Number(val) > 0, \"amount must be greater than zero\"),\n currencyCode: z.string().length(3).optional(),\n});\nexport type MetaMoney = z.infer<typeof moneySchema>;\n\n// Money only exists at these top-level budget-bearing fields — walking deeper\n// would mistake look-alikes for money and silently mutate user data.\nexport const MONEY_FIELDS = [\n \"dailyBudget\",\n \"lifetimeBudget\",\n \"bidAmount\",\n \"spendCap\",\n \"dailyMinSpendTarget\",\n \"dailySpendCap\",\n \"lifetimeMinSpendTarget\",\n \"lifetimeSpendCap\",\n \"testDailyBudget\",\n] as const;\nexport type MoneyField = (typeof MONEY_FIELDS)[number];\n\nfunction isMoneyMissingCurrency(value: unknown): value is Record<string, unknown> {\n return (\n value !== null &&\n typeof value === \"object\" &&\n !Array.isArray(value) &&\n typeof (value as Record<string, unknown>).amount === \"string\" &&\n (value as Record<string, unknown>).currencyCode === undefined\n );\n}\n\n/** A budget schedule's `increase`, the one money that sits below the top level. */\nfunction scheduleIncreases(payload: Record<string, unknown>): unknown[] {\n const schedules = payload.budgetSchedules;\n return Array.isArray(schedules)\n ? schedules.map((period) => (period as Record<string, unknown> | null)?.increase)\n : [];\n}\n\n/** True when a money field in the payload still needs its currencyCode. */\nexport function hasMoneyMissingCurrency(payload: unknown): boolean {\n if (payload === null || typeof payload !== \"object\" || Array.isArray(payload)) {\n return false;\n }\n const record = payload as Record<string, unknown>;\n return (\n MONEY_FIELDS.some((field) => isMoneyMissingCurrency(record[field])) ||\n scheduleIncreases(record).some(isMoneyMissingCurrency)\n );\n}\n\nfunction withCurrency(value: unknown, currencyCode: string): unknown {\n return isMoneyMissingCurrency(value) ? { ...value, currencyCode } : value;\n}\n\n/** Fills currency-less money fields with the ad account's currency. */\nexport function fillMissingCurrencyCodes(payload: unknown, currencyCode: string): { value: unknown; filled: boolean } {\n if (!hasMoneyMissingCurrency(payload)) {\n return { value: payload, filled: false };\n }\n const out = { ...(payload as Record<string, unknown>) };\n for (const field of MONEY_FIELDS) {\n if (out[field] !== undefined) {\n out[field] = withCurrency(out[field], currencyCode);\n }\n }\n if (Array.isArray(out.budgetSchedules)) {\n out.budgetSchedules = out.budgetSchedules.map((period: Record<string, unknown>) =>\n period.increase === undefined ? period : { ...period, increase: withCurrency(period.increase, currencyCode) },\n );\n }\n return { value: out, filled: true };\n}\n\nconst httpsUrlSchema = z\n .string()\n .url()\n .refine((u) => u.startsWith(\"https://\"), \"destination URLs must be https\");\n\n/** Baker library reference (images/videos table id) — uploaded to Meta by a `media.upload` op. */\nconst bakerMediaIdSchema = z.string().min(1);\n\nconst stageableStatusSchema = z.enum(STAGEABLE_CREATE_STATUSES);\nconst updateStatusSchema = z.enum(UPDATE_STATUSES);\n\n/**\n * The labels an object carries. `adlabels` is the whole set Meta is sent —\n * `POST /{id}` with `adlabels` replaces the object's labels (live on v25.0,\n * 2026-10-14: a set of one label dropped the label it had, and an empty set\n * cleared them). `addLabels` / `removeLabels` are how a caller asks for a\n * change; staging resolves them against the labels the object has now into\n * `adlabels`, so the review shows the set that will be applied.\n */\nconst labelFields = {\n adlabels: z.array(parentRefSchema).max(META_LIMITS.adLabel.perObjectMax).optional(),\n addLabels: z.array(parentRefSchema).min(1).optional(),\n removeLabels: z.array(parentRefSchema).min(1).optional(),\n};\nconst createLabelFields = { adlabels: labelFields.adlabels };\n\n/** The label ids a payload names, wherever it names them. */\nexport function payloadLabelIds(payload: unknown): string[] {\n const record = (payload ?? {}) as { adlabels?: unknown; addLabels?: unknown; removeLabels?: unknown };\n return [record.adlabels, record.addLabels, record.removeLabels].flatMap((list) =>\n Array.isArray(list) ? list.filter((id): id is string => typeof id === \"string\") : [],\n );\n}\n\n/**\n * The label set after a requested change: the current set with `addLabels`\n * added and `removeLabels` taken away, in that order, without duplicates.\n * Returns the payload with `adlabels` holding the whole set and the two\n * requests gone — the shape the request builder sends.\n */\nexport function resolveLabelChanges(\n payload: Record<string, unknown>,\n current: readonly string[],\n): Record<string, unknown> {\n const { addLabels, removeLabels, ...rest } = payload as {\n addLabels?: string[];\n removeLabels?: string[];\n } & Record<string, unknown>;\n if (addLabels === undefined && removeLabels === undefined) {\n return payload;\n }\n const base = Array.isArray(rest.adlabels) ? (rest.adlabels as string[]) : [...current];\n const removed = new Set(removeLabels ?? []);\n const next = [...new Set([...base, ...(addLabels ?? [])])].filter((id) => !removed.has(id));\n return { ...rest, adlabels: next };\n}\n\nfunction currencyMinimums(currencyCode: string): { dailyBudgetMin: number } {\n return CURRENCY_MINIMUMS[currencyCode] ?? DEFAULT_CURRENCY_MINIMUM;\n}\n\nfunction validateDailyBudgetFloor(money: MetaMoney | undefined, ctx: z.RefinementCtx, path: (string | number)[]): void {\n // Currency-less money is filled from the account at stage time and re-validated there.\n if (money?.currencyCode) {\n const min = currencyMinimums(money.currencyCode).dailyBudgetMin;\n if (Number(money.amount) < min) {\n ctx.addIssue({ code: \"custom\", path, message: `below the ${min} ${money.currencyCode} daily minimum` });\n }\n }\n}\n\n// --- Targeting spec (the big one) ---\n\nconst geoLocationsSchema = z\n .object({\n countries: z.array(z.string().length(2)).optional(),\n regions: z.array(z.object({ key: z.string() })).optional(),\n cities: z\n .array(z.object({ key: z.string(), radius: z.number().optional(), distance_unit: z.string().optional() }))\n .optional(),\n zips: z.array(z.object({ key: z.string() })).optional(),\n location_types: z.array(z.string()).optional(),\n })\n .catchall(z.unknown());\n\nconst idNameSchema = z.object({ id: z.string(), name: z.string().optional() });\n\n/**\n * One event window of a product audience: people who did `rule`'s event on a\n * product of the set within `retention_seconds`. Meta: \"Each rule must include\n * an `event` with the `eq` operator\" (Advantage+ catalog ads guide).\n */\nconst productAudienceEventSchema = z.strictObject({\n retention_seconds: z\n .number()\n .int()\n .min(3600)\n .max(180 * 86_400),\n rule: z.record(z.string(), z.unknown()).refine((rule) => JSON.stringify(rule).includes('\"event\"'), {\n message: 'a product audience rule names the event it counts, e.g. {\"event\":{\"eq\":\"ViewContent\"}}',\n }),\n});\n\n/**\n * Dynamic retargeting: people who interacted with products of a set (viewed,\n * added to cart) and, optionally, not with others (purchased) — Meta's\n * `product_audience_specs` / `excluded_product_audience_specs`.\n */\nconst productAudienceSpecSchema = z.strictObject({\n /** A product set's id, or the meta_temp_* ref of one this chat creates. */\n product_set_id: parentRefSchema,\n inclusions: z.array(productAudienceEventSchema).min(1),\n exclusions: z.array(productAudienceEventSchema).min(1).optional(),\n});\n\n/**\n * Ad-set targeting. Known fields are typed; unknown facets Meta may add pass\n * through untouched. Custom-audience ids may be meta_temp_* refs to audiences\n * staged earlier in the same draft.\n */\nexport const metaTargetingSchema = z\n .object({\n geo_locations: geoLocationsSchema.optional(),\n excluded_geo_locations: geoLocationsSchema.optional(),\n age_min: z.number().int().min(13).max(65).optional(),\n age_max: z.number().int().min(13).max(65).optional(),\n genders: z.array(z.union([z.literal(1), z.literal(2)])).optional(),\n locales: z.array(z.number().int()).optional(),\n interests: z.array(idNameSchema).optional(),\n behaviors: z.array(idNameSchema).optional(),\n custom_audiences: z.array(z.object({ id: parentRefSchema })).optional(),\n excluded_custom_audiences: z.array(z.object({ id: parentRefSchema })).optional(),\n flexible_spec: z.array(z.record(z.string(), z.unknown())).optional(),\n product_audience_specs: z.array(productAudienceSpecSchema).min(1).optional(),\n excluded_product_audience_specs: z.array(productAudienceSpecSchema).min(1).optional(),\n /**\n * Retired by Meta: live on v25.0 (2026-10-14) a create excluding one\n * interest was refused — \"Detailed targeting exclusions are no longer\n * available for ad sets\" (subcode 3858492). Excluding people goes through\n * `excluded_custom_audiences`.\n */\n exclusions: z\n .record(z.string(), z.unknown())\n .refine((value) => Object.keys(value).length === 0, {\n message:\n \"Meta no longer lets an ad set exclude detailed targeting (interests, behaviors, demographics) — take targeting.exclusions out; to keep people out, exclude a custom audience (excluded_custom_audiences)\",\n })\n .optional(),\n publisher_platforms: z.array(z.string()).optional(),\n facebook_positions: z.array(z.string()).optional(),\n instagram_positions: z.array(z.string()).optional(),\n audience_network_positions: z.array(z.string()).optional(),\n messenger_positions: z.array(z.string()).optional(),\n threads_positions: z.array(z.string()).optional(),\n device_platforms: z.array(z.string()).optional(),\n targeting_automation: z\n .object({ advantage_audience: z.union([z.literal(0), z.literal(1)]) })\n .partial()\n .optional(),\n ...brandSafetyTargetingFields,\n })\n .catchall(z.unknown());\nexport type MetaTargeting = z.infer<typeof metaTargetingSchema>;\n\n/**\n * geo_locations inclusion keys that count as a real location (location_types is\n * a modifier, not a place) — every place type Meta's targeting search returns\n * (`discovery.ts` `GEO_KEY_LISTS`) and the rest of Meta's geo_locations keys.\n */\nconst GEO_INCLUSION_KEYS = [\n \"countries\",\n \"country_groups\",\n \"regions\",\n \"cities\",\n \"zips\",\n \"geo_markets\",\n \"places\",\n \"custom_locations\",\n \"electoral_districts\",\n \"subcities\",\n \"neighborhoods\",\n \"subneighborhoods\",\n \"metro_areas\",\n \"large_geo_areas\",\n \"medium_geo_areas\",\n \"small_geo_areas\",\n] as const;\n\n/** True when targeting names a real place via any geo_locations inclusion key. */\nfunction targetingHasGeo(t: MetaTargeting | undefined): boolean {\n const geo = t?.geo_locations as Record<string, unknown> | undefined;\n return Boolean(\n geo && GEO_INCLUSION_KEYS.some((key) => Array.isArray(geo[key]) && (geo[key] as unknown[]).length > 0),\n );\n}\n\n/**\n * Meta rejects an ad set whose targeting has no location — geo_locations (a\n * country/region/city/…) is required unless the ad set is bounded by a custom\n * audience instead. Checks the typed and catch-all geo keys so a facet Meta\n * later adds still counts.\n */\nexport function targetingHasGeoOrAudience(t: MetaTargeting | undefined): boolean {\n if (!t) {\n return false;\n }\n return targetingHasGeo(t) || Boolean(t.custom_audiences?.length);\n}\n\nfunction advantageAudienceSetting(t: MetaTargeting): 0 | 1 | undefined {\n const value = t.targeting_automation?.advantage_audience;\n return value === 0 || value === 1 ? value : undefined;\n}\n\n/**\n * True when the ad set includes any EU country and therefore needs DSA\n * beneficiary/payor.\n *\n * Known limitation: only `geo_locations.countries` is inspected. Meta identifies\n * regions/cities/zips by opaque `key` with no country attached, so an ad set\n * targeting an EU region/city *without* a top-level country entry isn't detected\n * here and won't get DSA fields auto-filled — mapping those keys back to a\n * country needs a lookup table we don't carry. Such an ad set can still hit the\n * DSA rejection at publish; the caller can pass dsa_beneficiary/dsa_payor to\n * cover it.\n */\nexport function targetingTargetsEu(t: MetaTargeting | undefined): boolean {\n return (t?.geo_locations?.countries ?? []).some((c) => EU_DSA_COUNTRIES.has(c.toUpperCase()));\n}\n\n/**\n * True when the targeting hard-limits demographics in a way Advantage+ Audience\n * treats as only a suggestion (and rejects with subcode 1870189): a narrowed\n * `age_max`, an `age_min` above 25, or a single-gender restriction. `genders`\n * of `[1, 2]` (both) is not a narrowing.\n */\nexport function targetingHardLimitsDemographics(t: MetaTargeting | undefined): boolean {\n if (!t) {\n return false;\n }\n const narrowsAgeMax = typeof t.age_max === \"number\" && t.age_max < ADVANTAGE_AUDIENCE_OPEN_AGE_MAX;\n const narrowsAgeMin = typeof t.age_min === \"number\" && t.age_min > ADVANTAGE_AUDIENCE_MAX_HARD_AGE_MIN;\n const narrowsGender = Array.isArray(t.genders) && t.genders.length === 1;\n return narrowsAgeMax || narrowsAgeMin || narrowsGender;\n}\n\n/** Housing, Employment and Financial products (`CREDIT` is its old name, sent as the new one). */\nconst HEC_F_CATEGORIES = new Set([\"HOUSING\", \"EMPLOYMENT\", \"FINANCIAL_PRODUCTS_SERVICES\", \"CREDIT\"]);\n\n/** Targeting Advantage+ Audience may widen past — anything narrower than places alone. */\nfunction targetingHasRelaxableOptions(t: MetaTargeting): boolean {\n return Boolean(t.custom_audiences?.length || t.flexible_spec?.length || t.interests?.length);\n}\n\n/**\n * From v26.0 a Housing, Employment or Financial products ad set whose audience\n * Advantage+ Audience could widen must say whether it may (`advantage_audience`\n * 1 or 0); left out, Meta refuses the create with\n * ADS_TARGETING__REQUIRE_EXPLICIT_ADVANTAGE_AUDIENCE_FLAG (v26.0 changelog,\n * \"Require explicit advantage_audience for HEC-F campaigns\"). Baker does not\n * pick for the agent: the two values reach different people.\n */\nexport function specialCategoryAdvantageAudienceRefusal(\n categories: readonly string[],\n t: MetaTargeting | undefined,\n): string | undefined {\n if (!t || !categories.some((c) => HEC_F_CATEGORIES.has(c))) return undefined;\n if (advantageAudienceSetting(t) !== undefined || !targetingHasRelaxableOptions(t)) return undefined;\n return \"this campaign is a Housing, Employment or Financial products campaign and the ad set narrows its audience, so Meta needs to be told whether Advantage+ Audience may reach beyond it — set targeting.targeting_automation.advantage_audience to 1 (let Meta widen it) or 0 (keep to this audience)\";\n}\n\n/**\n * A hard age/gender limit is honored only with `advantage_audience: 0`. When the\n * caller left it unset, Meta v23+ defaults it to 1 and rejects the limit — so\n * force it off. Explicit 0/1 is left untouched (an explicit 1 conflict is caught\n * by schema validation, not silently overridden).\n */\nexport function normalizeTargetingAdvantageAudience(t: MetaTargeting): {\n targeting: MetaTargeting;\n autoDisabledAdvantageAudience: boolean;\n} {\n if (!targetingHardLimitsDemographics(t) || t.targeting_automation?.advantage_audience !== undefined) {\n return { targeting: t, autoDisabledAdvantageAudience: false };\n }\n return {\n targeting: { ...t, targeting_automation: { ...t.targeting_automation, advantage_audience: 0 } },\n autoDisabledAdvantageAudience: true,\n };\n}\n\n// --- Budget schedules (campaign and ad set) ---\n\nconst QUARTER_HOUR_MS = 15 * 60_000;\nconst MIN_HIGH_DEMAND_PERIOD_MS = 3 * 3_600_000;\n\n/**\n * A high-demand period: between `time_start` and `time_end` (epoch ms) the daily\n * budget rises by `increase` (an amount, in the account currency) or by\n * `increasePercent` (Meta's MULTIPLIER, a percentage: 50 raises a 100 budget to\n * 150). Sent as Meta's `budget_schedule_specs`, one-time periods only — the\n * High Demand Period reference: \"Currently we only support non-recurring high\n * demand periods\". Meta's refusals, live on v25.0 (2026-10-14): shorter than 3\n * hours (subcode 3858094), off a 15-minute mark (3858205), a percentage above\n * 800 (3858092 — an amount has its own ceiling, which Meta names).\n */\nconst budgetScheduleSchema = z\n .strictObject({\n time_start: z.number().int().positive(),\n time_end: z.number().int().positive(),\n increase: moneySchema.optional(),\n increasePercent: z.number().int().min(1).max(800).optional(),\n })\n .superRefine((period, ctx) => {\n if ((period.increase === undefined) === (period.increasePercent === undefined)) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"increase\"],\n message:\n \"a budget schedule raises the budget by an amount (increase) or a percentage (increasePercent) — one of them\",\n });\n }\n if (period.time_end - period.time_start < MIN_HIGH_DEMAND_PERIOD_MS) {\n ctx.addIssue({ code: \"custom\", path: [\"time_end\"], message: \"a high-demand period lasts at least 3 hours\" });\n }\n if (period.time_start % QUARTER_HOUR_MS !== 0 || period.time_end % QUARTER_HOUR_MS !== 0) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"time_start\"],\n message: \"Meta starts and ends a high-demand period on a quarter hour (:00, :15, :30 or :45)\",\n });\n }\n });\n\nexport type MetaBudgetSchedule = z.infer<typeof budgetScheduleSchema>;\n\n/**\n * One kind of raise per schedule: Meta refuses amounts and percentages mixed —\n * \"You can scale your budget by using a value amount or percentage, but not\n * both\" (live on v25.0, 2026-10-14).\n */\nconst budgetSchedulesSchema = z\n .array(budgetScheduleSchema)\n .min(1)\n .max(META_LIMITS.adSet.budgetSchedulesMax)\n .refine(\n (periods) => new Set(periods.map((period) => period.increase === undefined)).size <= 1,\n \"Meta raises a budget by amounts or by percentages, not both — use one kind for every period\",\n );\n\n/**\n * Meta raises only a daily budget (\"Budget scheduling can only be used for\n * campaigns with a daily budget\"), and it reads that budget from the request\n * itself: an update to a campaign whose daily budget is already live is still\n * refused \"Campaign must have daily budget to support budget schedule\"\n * (subcode 3858199) unless it restates it — live on v25.0, 2026-10-14.\n */\nfunction validateBudgetSchedules(\n p: { budgetSchedules?: unknown[]; dailyBudget?: MetaMoney },\n ctx: z.RefinementCtx,\n): void {\n if (p.budgetSchedules && !p.dailyBudget) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"budgetSchedules\"],\n message:\n \"a budget schedule raises a daily budget, and Meta needs that daily budget in the same change — pass dailyBudget (the current one, on an update)\",\n });\n }\n}\n\n/**\n * One live boost moved to another window. Meta has no update for a boost —\n * `POST /{boost}` answers \"Accesssing Deprecated Platform API Endpoint -\n * GraphHighDemandPeriodPost\" (code 100, subcode 33; live on v26.0, 2026-10-15)\n * — so a move is the same raise added on the new window through the\n * `budget_schedules` edge, then the old boost deleted. Staging fills the raise\n * (`increase` / `increasePercent`) from the live boost; the caller names only\n * the id and the new window.\n */\nconst boostMoveSchema = z\n .strictObject({\n id: z.string().regex(NUMERIC_ID_REGEX, \"a boost is named by its id from `baker ads meta high-demand-periods`\"),\n time_start: z.number().int().positive(),\n time_end: z.number().int().positive(),\n increase: moneySchema.optional(),\n increasePercent: z.number().int().min(1).max(800).optional(),\n })\n .superRefine((move, ctx) => {\n if (move.increase !== undefined && move.increasePercent !== undefined) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"increase\"],\n message:\n \"a boost raises the budget by an amount or by a percentage, not both — a move keeps the live boost's own\",\n });\n }\n if (move.time_end - move.time_start < MIN_HIGH_DEMAND_PERIOD_MS) {\n ctx.addIssue({ code: \"custom\", path: [\"time_end\"], message: \"a high-demand period lasts at least 3 hours\" });\n }\n if (move.time_start % QUARTER_HOUR_MS !== 0 || move.time_end % QUARTER_HOUR_MS !== 0) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"time_start\"],\n message: \"Meta starts and ends a high-demand period on a quarter hour (:00, :15, :30 or :45)\",\n });\n }\n });\nexport type MetaBoostMove = z.infer<typeof boostMoveSchema>;\n\n/**\n * Individual boost edits on a live campaign or ad set: `removeBoosts` deletes\n * the named boosts (`DELETE /{boost}`, live on v26.0), `moveBoosts` re-times\n * them. Neither is dry-run: the edge ignores `validate_only`.\n */\nconst boostEditFields = {\n removeBoosts: z\n .array(z.string().regex(NUMERIC_ID_REGEX, \"a boost is named by its id from `baker ads meta high-demand-periods`\"))\n .min(1)\n .max(META_LIMITS.adSet.budgetSchedulesMax)\n .optional(),\n moveBoosts: z.array(boostMoveSchema).min(1).max(META_LIMITS.adSet.budgetSchedulesMax).optional(),\n};\n\n/** A boost both moved and removed, or edited beside a clear of every boost, says two things at once. */\nfunction validateBoostEdits(\n p: { removeBoosts?: readonly string[]; moveBoosts?: readonly MetaBoostMove[]; clear?: readonly string[] },\n ctx: z.RefinementCtx,\n): void {\n const removed = new Set(p.removeBoosts ?? []);\n for (const move of p.moveBoosts ?? []) {\n if (removed.has(move.id)) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"moveBoosts\"],\n message: `boost ${move.id} is both moved and removed — pick one`,\n });\n }\n }\n if (p.clear?.includes(\"budgetSchedules\") && (p.removeBoosts || p.moveBoosts)) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"clear\"],\n message: \"clearing every boost already removes the ones named — drop removeBoosts/moveBoosts or the clear\",\n });\n }\n}\n\n// --- Campaign ---\n\nconst specialAdCategoriesSchema = z.array(z.enum(SPECIAL_AD_CATEGORIES)).default([\"NONE\"]);\n\nexport const campaignCreateSchema = z\n .strictObject({\n name: z.string().min(1).max(META_LIMITS.campaign.nameMax),\n objective: z.enum(OBJECTIVES),\n status: stageableStatusSchema.default(\"PAUSED\"),\n special_ad_categories: specialAdCategoriesSchema,\n special_ad_category_country: z.array(z.string().length(2)).optional(),\n buying_type: z.enum(BUYING_TYPES).default(\"AUCTION\"),\n bid_strategy: z.enum(BID_STRATEGIES).optional(),\n /** Campaign Budget Optimization (Advantage campaign budget) — mutually exclusive with ad-set budgets. */\n dailyBudget: moneySchema.optional(),\n lifetimeBudget: moneySchema.optional(),\n spendCap: moneySchema.optional(),\n /**\n * Ad-set budget sharing: lets ad sets lend up to 20% of their budget to each\n * other. Meta requires an explicit true/false on any campaign that carries no\n * campaign budget (subcode 4834011); Baker sends false unless asked, because\n * turning it on moves real spend between ad sets nobody asked to move.\n */\n adSetBudgetSharing: z.boolean().optional(),\n budgetSchedules: budgetSchedulesSchema.optional(),\n start_time: z.number().int().positive().optional(),\n stop_time: z.number().int().positive().optional(),\n /**\n * Advantage+ catalog ads: the catalog the campaign sells from. Meta fixes it\n * at creation; each ad set then names one of its product sets.\n */\n promoted_object: z.strictObject({ product_catalog_id: parentRefSchema }).optional(),\n ...createLabelFields,\n })\n .superRefine((p, ctx) => {\n if (p.dailyBudget && p.lifetimeBudget) {\n ctx.addIssue({ code: \"custom\", path: [\"dailyBudget\"], message: \"set only one of dailyBudget or lifetimeBudget\" });\n }\n validateDailyBudgetFloor(p.dailyBudget, ctx, [\"dailyBudget\", \"amount\"]);\n validateBudgetSchedules(p, ctx);\n if (p.stop_time && p.start_time && p.stop_time <= p.start_time) {\n ctx.addIssue({ code: \"custom\", path: [\"stop_time\"], message: \"stop_time must be after start_time\" });\n }\n // ISSUES_ELECTIONS_POLITICS ads must declare the country they run in.\n const needsCountry = p.special_ad_categories.some((c) => SPECIAL_CATEGORIES_REQUIRING_COUNTRY.includes(c));\n if (needsCountry && !p.special_ad_category_country?.length) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"special_ad_category_country\"],\n message:\n \"ISSUES_ELECTIONS_POLITICS campaigns need special_ad_category_country — pass the 2-letter country code(s) the ads run in\",\n });\n }\n // Meta stopped political ads in the EU on 2025-10-06 (TTPA, special-ad-category reference).\n const euCountries = (p.special_ad_category_country ?? []).filter((c) => EU_DSA_COUNTRIES.has(c.toUpperCase()));\n if (needsCountry && euCountries.length > 0) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"special_ad_category_country\"],\n message: `Meta no longer runs ads about social issues, elections or politics in the EU (since 6 October 2025), so it refuses this campaign for ${euCountries.join(\", \")} — drop the EU countries, or run these ads outside Meta`,\n });\n }\n });\nexport type CampaignCreate = z.infer<typeof campaignCreateSchema>;\n\n/**\n * Delivery controls an update can take away, each by the value Meta reads as\n * \"none\" (live on v25.0, 2026-10-14, read back on a harness ad set): a spend\n * minimum by 0, a spend cap by Meta's no-cap sentinel, an ad schedule by an\n * empty schedule with standard pacing, budget boosts by deleting each period\n * the campaign or ad set had when the change was staged.\n *\n * Two are not here, on purpose: a ROAS floor goes by switching the bid\n * strategy (the floor is dropped with it), and a frequency cap cannot be taken\n * off a reach ad set at all — Meta answers an empty list with success and keeps\n * the cap.\n */\nexport const AD_SET_CLEARABLE_CONTROLS = [\n \"dailyMinSpendTarget\",\n \"dailySpendCap\",\n \"lifetimeMinSpendTarget\",\n \"lifetimeSpendCap\",\n \"adset_schedule\",\n \"budgetSchedules\",\n] as const;\nexport const CAMPAIGN_CLEARABLE_CONTROLS = [\"budgetSchedules\"] as const;\n\n/** A control both set and cleared in one change says two things at once. */\nfunction validateClear(p: { clear?: readonly string[] } & Record<string, unknown>, ctx: z.RefinementCtx): void {\n for (const field of p.clear ?? []) {\n if (p[field] !== undefined) {\n ctx.addIssue({ code: \"custom\", path: [\"clear\"], message: `${field} is both set and cleared — pick one` });\n }\n }\n}\n\nexport const campaignUpdateSchema = z\n .strictObject({\n name: z.string().min(1).max(META_LIMITS.campaign.nameMax).optional(),\n status: updateStatusSchema.optional(),\n bid_strategy: z.enum(BID_STRATEGIES).optional(),\n dailyBudget: moneySchema.optional(),\n lifetimeBudget: moneySchema.optional(),\n spendCap: moneySchema.optional(),\n budgetSchedules: budgetSchedulesSchema.optional(),\n start_time: z.number().int().positive().optional(),\n stop_time: z.number().int().positive().optional(),\n /** Budget boosts to take away — every one the campaign had when this was staged. */\n clear: z.array(z.enum(CAMPAIGN_CLEARABLE_CONTROLS)).min(1).optional(),\n ...boostEditFields,\n ...labelFields,\n })\n .superRefine((p, ctx) => {\n if (!Object.values(p).some((val) => val !== undefined)) {\n ctx.addIssue({ code: \"custom\", message: \"update needs at least one field\" });\n }\n if (p.dailyBudget && p.lifetimeBudget) {\n ctx.addIssue({ code: \"custom\", path: [\"dailyBudget\"], message: \"set only one of dailyBudget or lifetimeBudget\" });\n }\n validateDailyBudgetFloor(p.dailyBudget, ctx, [\"dailyBudget\", \"amount\"]);\n validateBudgetSchedules(p, ctx);\n validateClear(p, ctx);\n validateBoostEdits(p, ctx);\n });\nexport type CampaignUpdate = z.infer<typeof campaignUpdateSchema>;\n\n// --- Ad set ---\n\nconst promotedObjectFields = {\n page_id: parentRefSchema.optional(),\n pixel_id: z.string().regex(NUMERIC_ID_REGEX).optional(),\n custom_event_type: z.enum(CUSTOM_EVENT_TYPES).optional(),\n /**\n * A Custom Conversion to optimize toward, instead of a raw pixel event.\n * Named alone by the caller: the stage reads the conversion off Meta and\n * fills `pixel_id`, `custom_event_type` and `pixel_rule` from it, so the\n * staged payload matches what Ads Manager stores and the review shows the\n * event the ad set will actually chase.\n */\n custom_conversion_id: z.union([z.string().regex(NUMERIC_ID_REGEX), tempRefSchema]).optional(),\n /** The custom conversion's own filter, filled by the stage. Never written by hand. */\n pixel_rule: z.string().optional(),\n application_id: z.string().regex(NUMERIC_ID_REGEX).optional(),\n object_store_url: z.string().url().optional(),\n product_catalog_id: parentRefSchema.optional(),\n /** A product set's id, or the meta_temp_* ref of one this chat creates. */\n product_set_id: parentRefSchema.optional(),\n whatsapp_phone_number: z.string().optional(),\n offline_conversion_data_set_id: z.string().regex(NUMERIC_ID_REGEX).optional(),\n};\n\n/**\n * Strict, and says what it does take: a key Baker does not carry used to be\n * dropped while the stage reported success, so an ad set staged without the\n * event it was meant to optimize toward. Nested, so `baker capabilities` does\n * not list these keys — the refusal has to.\n */\nconst promotedObjectSchema = z.strictObject(promotedObjectFields, {\n error: (issue) =>\n issue.code === \"unrecognized_keys\"\n ? `promoted_object does not take ${issue.keys.map((key) => `\"${key}\"`).join(\", \")} — it takes ${Object.keys(promotedObjectFields).join(\", \")}`\n : undefined,\n});\n\nconst attributionSpecSchema = z.array(\n z\n .strictObject({\n event_type: z.enum(ATTRIBUTION_EVENT_TYPES),\n window_days: z.union([z.literal(1), z.literal(7)]),\n })\n .refine((w) => w.window_days <= ATTRIBUTION_MAX_WINDOW_DAYS[w.event_type], {\n error: \"Meta counts a view or an engaged video view for 1 day only — window_days 1\",\n path: [\"window_days\"],\n }),\n);\n\n/**\n * The return a LOWEST_COST_WITH_MIN_ROAS ad set must average, as a multiple of\n * spend: 2 means 200% (every euro spent brings back two). Sent to Meta as\n * `bid_constraints.roas_average_floor`, scaled by `ROAS_FLOOR_SCALE`.\n */\nconst minRoasSchema = z\n .number()\n .min(META_LIMITS.adSet.minRoasMin, `minRoas must be at least ${META_LIMITS.adSet.minRoasMin} (Meta's floor)`)\n .max(META_LIMITS.adSet.minRoasMax, `minRoas must be at most ${META_LIMITS.adSet.minRoasMax} (Meta's ceiling)`)\n .refine(\n (roas) => Math.round(roas * ROAS_FLOOR_SCALE) / ROAS_FLOOR_SCALE === roas,\n \"Meta keeps a minimum ROAS to 4 decimals (2.3333, not 2.33333)\",\n );\n\n/**\n * How often one person may see the ads: at most `max_frequency` times every\n * `interval_days` days. Meta's own shape, sent as `frequency_control_specs`.\n */\nconst frequencyCapSchema = z.strictObject({\n event: z.enum(FREQUENCY_CAP_EVENTS).default(\"IMPRESSIONS\"),\n interval_days: z.number().int().min(1).max(META_LIMITS.adSet.frequencyIntervalDaysMax),\n max_frequency: z.number().int().min(1).max(META_LIMITS.adSet.frequencyMaxImpressionsMax),\n type: z.enum(FREQUENCY_CAP_TYPES).optional(),\n});\n\n/**\n * An ad set's share of its campaign's budget (Ads Manager's \"ad set spend\n * limits\"): spend at least the minimum, at most the cap, best effort. Only\n * under a campaign budget, and of the campaign budget's own kind.\n */\nconst spendLimitFields = {\n dailyMinSpendTarget: moneySchema.optional(),\n dailySpendCap: moneySchema.optional(),\n lifetimeMinSpendTarget: moneySchema.optional(),\n lifetimeSpendCap: moneySchema.optional(),\n};\n\ninterface SpendLimits {\n dailyBudget?: MetaMoney;\n lifetimeBudget?: MetaMoney;\n dailyMinSpendTarget?: MetaMoney;\n dailySpendCap?: MetaMoney;\n lifetimeMinSpendTarget?: MetaMoney;\n lifetimeSpendCap?: MetaMoney;\n}\n\nfunction minAboveCap(min: MetaMoney | undefined, cap: MetaMoney | undefined): boolean {\n return min !== undefined && cap !== undefined && Number(min.amount) > Number(cap.amount);\n}\n\n/**\n * Meta's spend-limit rules, each refused live on v25.0 (2026-10-14): a limit\n * beside the ad set's own budget (subcode 1885624), daily and lifetime limits\n * mixed — they must match the campaign budget's kind (1885652) — and a minimum\n * above the cap (2016091). Whether the campaign's budget is daily or lifetime is\n * the campaign's to say; Meta's own check names it at stage time.\n */\nfunction validateSpendLimits(p: SpendLimits, ctx: z.RefinementCtx): void {\n const daily = p.dailyMinSpendTarget !== undefined || p.dailySpendCap !== undefined;\n const lifetime = p.lifetimeMinSpendTarget !== undefined || p.lifetimeSpendCap !== undefined;\n if ((daily || lifetime) && (p.dailyBudget || p.lifetimeBudget)) {\n ctx.addIssue({\n code: \"custom\",\n path: [daily ? \"dailySpendCap\" : \"lifetimeSpendCap\"],\n message:\n \"spend limits share out a campaign budget — an ad set with its own budget takes none; drop the budget or the limits\",\n });\n }\n if (daily && lifetime) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"lifetimeSpendCap\"],\n message: \"use daily limits under a daily campaign budget and lifetime limits under a lifetime one, never both\",\n });\n }\n if (\n minAboveCap(p.dailyMinSpendTarget, p.dailySpendCap) ||\n minAboveCap(p.lifetimeMinSpendTarget, p.lifetimeSpendCap)\n ) {\n ctx.addIssue({\n code: \"custom\",\n path: [daily ? \"dailyMinSpendTarget\" : \"lifetimeMinSpendTarget\"],\n message: \"the minimum spend can't be higher than the spend cap\",\n });\n }\n}\n\nconst MINUTES_PER_DAY = 24 * 60;\n\n/**\n * One block of an ad schedule: the hours (as minutes of the day) on the given\n * days (0 = Sunday … 6 = Saturday) the ads may run. Meta's own shape, sent as\n * `adset_schedule`. Meta refuses a block that does not start and end on the hour\n * or is shorter than an hour (subcode 2490260), and a day outside 0–6\n * (subcode 1487097) — both live on v25.0, 2026-10-14.\n */\nconst scheduleBlockSchema = z\n .strictObject({\n start_minute: z.number().int().min(0).max(MINUTES_PER_DAY),\n end_minute: z.number().int().min(0).max(MINUTES_PER_DAY),\n days: z.array(z.number().int().min(0).max(6)).min(1),\n timezone_type: z.enum(SCHEDULE_TIMEZONE_TYPES).optional(),\n })\n .superRefine((block, ctx) => {\n if (block.start_minute % 60 !== 0 || block.end_minute % 60 !== 0) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"start_minute\"],\n message: \"Meta schedules whole hours — start_minute and end_minute must be multiples of 60 (540 = 9:00)\",\n });\n }\n if (block.end_minute - block.start_minute < 60) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"end_minute\"],\n message: \"a schedule block must end at least one hour after it starts\",\n });\n }\n });\n\nconst adSetFields = {\n name: z.string().min(1).max(META_LIMITS.adSet.nameMax),\n campaign_id: parentRefSchema,\n status: stageableStatusSchema.default(\"PAUSED\"),\n dailyBudget: moneySchema.optional(),\n lifetimeBudget: moneySchema.optional(),\n bidAmount: moneySchema.optional(),\n bid_strategy: z.enum(BID_STRATEGIES).optional(),\n minRoas: minRoasSchema.optional(),\n frequency_control_specs: z.array(frequencyCapSchema).min(1).optional(),\n adset_schedule: z.array(scheduleBlockSchema).min(1).optional(),\n pacing: z.enum(PACING_TYPES).optional(),\n ...spendLimitFields,\n /**\n * Create-only on an ad set. Meta refuses `budget_schedule_specs` on an ad set\n * update even beside its daily budget (\"Ad set must have daily budget to\n * support budget schedule\", subcode 3858199 — live on v25.0, 2026-10-14);\n * only the `/budget_schedules` edge adds one later, and that edge ignores\n * `validate_only` (a dry run created a real period), so Baker does not use it.\n */\n budgetSchedules: budgetSchedulesSchema.optional(),\n /**\n * A Dynamic Creative ad set: its one ad mixes the images, videos and texts of\n * an asset-feed (`dynamic`) creative. Create-only — Meta fixes it for the ad\n * set's life — and such an ad set holds exactly one ad (subcode 1885553).\n */\n is_dynamic_creative: z.boolean().optional(),\n /**\n * Reach and frequency: the reservation this ad set is bought on (its id, or\n * the meta_temp_* ref of a `reachFrequencyReservation.create` in this chat).\n * Its campaign is `buying_type: RESERVED` (`reachFrequency.ts`).\n */\n rf_prediction_id: parentRefSchema.optional(),\n billing_event: z.enum(BILLING_EVENTS),\n optimization_goal: z.enum(OPTIMIZATION_GOALS),\n destination_type: z.enum(DESTINATION_TYPES).optional(),\n promoted_object: promotedObjectSchema.optional(),\n attribution_spec: attributionSpecSchema.optional(),\n start_time: z.number().int().positive().optional(),\n end_time: z.number().int().positive().optional(),\n targeting: metaTargetingSchema,\n /**\n * The live ad set this one was copied from, verbatim, by `duplicate`. Baker\n * only — `adSetCommonBody` never sends it to Meta. Set exclusively when the\n * targeting IS the source's targeting, because that is what it licenses:\n * placement validation is skipped for it (see `validateAdSetPlacements`).\n */\n clonedFrom: z.string().regex(NUMERIC_ID_REGEX).optional(),\n /** EU Digital Services Act: who benefits from / pays for the ad. Auto-filled from the account for EU geo when omitted. */\n dsa_beneficiary: z.string().min(1).max(100).optional(),\n dsa_payor: z.string().min(1).max(100).optional(),\n /** Advantage+ placements with limited spend — Sales and Leads campaigns only (`adSetCompliance.ts`). */\n placement_soft_opt_out: placementSoftOptOutSchema.optional(),\n ...regionalRegulationFields,\n ...createLabelFields,\n};\n\nconst MIN_ROAS: MetaBidStrategy = \"LOWEST_COST_WITH_MIN_ROAS\";\n\n/**\n * A minimum ROAS belongs to the min-ROAS strategy and to nothing else. Meta\n * refuses the floor beside any other strategy (\"The ROAS average floor bid\n * constraint is incompatible with is_autobid\", subcode 1815890) and refuses the\n * strategy without a floor (\"For ROAS goal, you must provide roas average floor\n * in bid constraints\", subcode 2490487) — both live on v25.0, 2026-10-14.\n *\n * `requireFloor` is off for an update, which may be switching a live ad set\n * that already carries its floor; the stage checks that against the snapshot.\n */\nfunction validateMinRoas(\n p: { bid_strategy?: MetaBidStrategy; minRoas?: number },\n ctx: z.RefinementCtx,\n requireFloor: boolean,\n): void {\n if (p.minRoas !== undefined && p.bid_strategy !== undefined && p.bid_strategy !== MIN_ROAS) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"minRoas\"],\n message: `minRoas only works with bid_strategy ${MIN_ROAS} — Meta refuses a ROAS floor beside ${p.bid_strategy}`,\n });\n }\n if (requireFloor && p.bid_strategy === MIN_ROAS && p.minRoas === undefined) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"minRoas\"],\n message: `${MIN_ROAS} needs minRoas — the return every euro spent must average, e.g. 2.5 for 250% (--min-roas 2.5)`,\n });\n }\n}\n\n/**\n * The goals Meta attributes nothing but a 1-day click on. Live on v25.0\n * (2026-10-14), dry-run against every window combination: LINK_CLICKS,\n * LANDING_PAGE_VIEWS and REACH took `1d_click` alone (\"For the selected\n * objective and performance goal, use one of these supported windows: 1 days\",\n * \"…combinations: (1, 0)\"); OFFSITE_CONVERSIONS and VALUE took every one. Goals\n * not measured here are left to Meta's own dry run.\n */\nconst ONE_DAY_CLICK_GOALS: ReadonlySet<string> = new Set([\"LINK_CLICKS\", \"LANDING_PAGE_VIEWS\", \"REACH\"]);\n\nfunction validateAttribution(\n p: { optimization_goal?: string; attribution_spec?: readonly { event_type: string; window_days: number }[] },\n ctx: z.RefinementCtx,\n): void {\n const goal = p.optimization_goal;\n if (!p.attribution_spec || !goal || !ONE_DAY_CLICK_GOALS.has(goal)) return;\n const oneDayClick = p.attribution_spec.every((w) => w.event_type === \"CLICK_THROUGH\" && w.window_days === 1);\n if (!oneDayClick) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"attribution_spec\"],\n message: `Meta attributes a ${goal} ad set on a 1-day click only — use --attribution 1d_click, or leave it out`,\n });\n }\n}\n\n/**\n * A frequency cap on a goal Meta does not cap, or counting video views Meta\n * does not count on that goal — checked whenever the op names the goal. Live\n * on v25.0 (2026-10-14): a plain `VIDEO_VIEWS` cap is answered with \"An unknown\n * error has occurred\" on REACH and THRUPLAY alike (a real create failed with\n * it), and `VIDEO_VIEWS_6S` is refused on anything but REACH. A TARGET\n * frequency is a reach-and-frequency ad set's, so it passes beside a prediction.\n */\nfunction validateFrequencyCap(\n p: {\n optimization_goal?: (typeof OPTIMIZATION_GOALS)[number];\n frequency_control_specs?: unknown[];\n rf_prediction_id?: string;\n },\n ctx: z.RefinementCtx,\n): void {\n const goal = p.optimization_goal;\n if (p.frequency_control_specs && goal && !OPTIMIZATION_GOALS_WITH_FREQUENCY_CAP.includes(goal)) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"frequency_control_specs\"],\n message: `Meta caps frequency only on ${OPTIMIZATION_GOALS_WITH_FREQUENCY_CAP.join(\" or \")} ad sets, not ${goal}`,\n });\n }\n if (\n !p.rf_prediction_id &&\n (p.frequency_control_specs ?? []).some((cap) => (cap as { type?: string }).type === \"TARGET\")\n ) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"frequency_control_specs\"],\n message:\n \"Meta takes a TARGET frequency only on a reach-and-frequency ad set with a prediction attached (subcode 3858652) — use a CAP (leave type out)\",\n });\n }\n const events = (p.frequency_control_specs ?? []).map((cap) => (cap as { event?: string }).event);\n if (events.includes(\"VIDEO_VIEWS\")) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"frequency_control_specs\"],\n message:\n \"Meta fails a VIDEO_VIEWS frequency cap with an unknown error — count VIDEO_VIEWS_2S or VIDEO_VIEWS_15S, or IMPRESSIONS\",\n });\n }\n if (events.includes(\"VIDEO_VIEWS_6S\") && goal && goal !== \"REACH\") {\n ctx.addIssue({\n code: \"custom\",\n path: [\"frequency_control_specs\"],\n message: `Meta counts VIDEO_VIEWS_6S caps on REACH ad sets only, not ${goal} — use VIDEO_VIEWS_2S or VIDEO_VIEWS_15S`,\n });\n }\n}\n\n/**\n * Pacing and the ad schedule, checked together because Meta checks them\n * together (all live on v25.0, 2026-10-14): a schedule needs day-parting pacing\n * (subcode 1487675) — which the wire fills when pacing is left unset — and\n * cannot run on a daily budget (1487682); day-parting pacing needs a schedule;\n * accelerated delivery (`no_pacing`) needs a bid cap (1885018 on auto-bid,\n * 2446193 on cost cap).\n */\nfunction validatePacing(\n p: {\n adset_schedule?: unknown[];\n pacing?: (typeof PACING_TYPES)[number];\n dailyBudget?: MetaMoney;\n bid_strategy?: MetaBidStrategy;\n },\n ctx: z.RefinementCtx,\n): void {\n if (p.adset_schedule && p.pacing !== undefined && p.pacing !== \"day_parting\") {\n ctx.addIssue({\n code: \"custom\",\n path: [\"pacing\"],\n message: `an ad schedule runs only with day_parting pacing, not ${p.pacing} — drop pacing and Baker sends day_parting`,\n });\n }\n if (p.adset_schedule && p.dailyBudget) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"adset_schedule\"],\n message: \"Meta runs an ad schedule only on a lifetime budget — use lifetimeBudget with an end_time\",\n });\n }\n if (p.pacing === \"day_parting\" && !p.adset_schedule) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"pacing\"],\n message: \"day_parting pacing needs adset_schedule — the hours the ads may run\",\n });\n }\n if (p.pacing === \"no_pacing\" && p.bid_strategy !== undefined && p.bid_strategy !== \"LOWEST_COST_WITH_BID_CAP\") {\n ctx.addIssue({\n code: \"custom\",\n path: [\"pacing\"],\n message: `accelerated delivery (no_pacing) works only with LOWEST_COST_WITH_BID_CAP, not ${p.bid_strategy}`,\n });\n }\n}\n\nfunction validateBidStrategy(\n p: {\n bidAmount?: MetaMoney;\n bid_strategy?: (typeof BID_STRATEGIES)[number];\n optimization_goal?: (typeof OPTIMIZATION_GOALS)[number];\n billing_event?: (typeof BILLING_EVENTS)[number];\n },\n ctx: z.RefinementCtx,\n): void {\n const strategy = p.bid_strategy;\n if (!strategy) {\n return;\n }\n if (BID_STRATEGIES_REQUIRING_AMOUNT.includes(strategy) && !p.bidAmount) {\n ctx.addIssue({ code: \"custom\", path: [\"bidAmount\"], message: `${strategy} requires a bidAmount` });\n }\n if (BID_STRATEGIES_FORBIDDING_AMOUNT.includes(strategy) && p.bidAmount) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"bidAmount\"],\n message: `${strategy} must not set a bidAmount — Meta rejects one (it bids automatically)`,\n });\n }\n // COST_CAP is impression-billed and standard-paced; Meta rejects other billing.\n if (strategy === \"COST_CAP\" && p.billing_event && p.billing_event !== \"IMPRESSIONS\") {\n ctx.addIssue({\n code: \"custom\",\n path: [\"billing_event\"],\n message: \"COST_CAP requires billing_event IMPRESSIONS\",\n });\n }\n // Min-ROAS bidding only optimizes value-based delivery.\n if (strategy === \"LOWEST_COST_WITH_MIN_ROAS\" && p.optimization_goal && p.optimization_goal !== \"VALUE\") {\n ctx.addIssue({\n code: \"custom\",\n path: [\"bid_strategy\"],\n message: \"LOWEST_COST_WITH_MIN_ROAS requires optimization_goal VALUE\",\n });\n }\n}\n\nfunction validateAdSetBudgetAndBid(\n p: {\n dailyBudget?: MetaMoney;\n lifetimeBudget?: MetaMoney;\n bidAmount?: MetaMoney;\n bid_strategy?: (typeof BID_STRATEGIES)[number];\n optimization_goal?: (typeof OPTIMIZATION_GOALS)[number];\n billing_event?: (typeof BILLING_EVENTS)[number];\n end_time?: number;\n start_time?: number;\n },\n ctx: z.RefinementCtx,\n): void {\n if (p.dailyBudget && p.lifetimeBudget) {\n ctx.addIssue({ code: \"custom\", path: [\"dailyBudget\"], message: \"set only one of dailyBudget or lifetimeBudget\" });\n }\n validateDailyBudgetFloor(p.dailyBudget, ctx, [\"dailyBudget\", \"amount\"]);\n if (p.lifetimeBudget && !p.end_time) {\n ctx.addIssue({ code: \"custom\", path: [\"end_time\"], message: \"lifetimeBudget ad sets need an end_time\" });\n }\n validateBidStrategy(p, ctx);\n if (p.end_time && p.start_time && p.end_time <= p.start_time) {\n ctx.addIssue({ code: \"custom\", path: [\"end_time\"], message: \"end_time must be after start_time\" });\n }\n}\n\n/**\n * Optimization goals Meta rejects without the right `promoted_object`:\n * - page-like/lead goals need `page_id` (subcode 1815430)\n * - OFFSITE_CONVERSIONS needs `pixel_id` + `custom_event_type`\n * - VALUE needs `custom_event_type` + a source: `pixel_id` (web) OR `application_id` (app)\n * - app goals need `application_id`\n * Caught at stage time so the ad set never fails at publish.\n *\n * `custom_conversion_id` satisfies the pixel and event requirements on its own:\n * a custom conversion IS a pixel and an event, and the stage fills both from it\n * before anything reaches Meta. Demanding them alongside would make the agent\n * restate what the conversion already says — and get it wrong.\n */\nfunction validateAdSetPromotedObject(\n p: {\n optimization_goal?: (typeof OPTIMIZATION_GOALS)[number];\n promoted_object?: {\n page_id?: string;\n pixel_id?: string;\n custom_event_type?: string;\n custom_conversion_id?: string;\n application_id?: string;\n product_set_id?: string;\n };\n },\n ctx: z.RefinementCtx,\n): void {\n const goal = p.optimization_goal;\n if (!goal) {\n return;\n }\n const po = p.promoted_object;\n // A custom conversion stands in for both: the stage resolves it into the\n // pixel and the event before the payload leaves Baker.\n const namesConversion = Boolean(po?.custom_conversion_id);\n // A catalog ad set's events come from the event sources linked to its\n // catalog (Meta's Advantage+ catalog ads guide: `promoted_object` is\n // `{product_set_id, custom_event_type}`), so the product set stands in for the pixel.\n const hasPixel = Boolean(po?.pixel_id) || namesConversion || Boolean(po?.product_set_id);\n const hasEventType = Boolean(po?.custom_event_type) || namesConversion;\n if (OPTIMIZATION_GOALS_REQUIRING_PAGE.includes(goal) && !po?.page_id) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"promoted_object\", \"page_id\"],\n message: `optimization_goal ${goal} needs promoted_object.page_id — pass --page-id with the Facebook Page the leads/likes belong to`,\n });\n }\n if (OPTIMIZATION_GOALS_REQUIRING_PIXEL.includes(goal) && !hasPixel) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"promoted_object\", \"pixel_id\"],\n message: `optimization_goal ${goal} needs promoted_object.pixel_id — pass --pixel-id with the conversion pixel, or --custom-conversion-id to optimize toward a custom conversion`,\n });\n }\n // VALUE optimizes toward a conversion the pixel (web) or app (app value optimization) reports.\n if (OPTIMIZATION_GOALS_REQUIRING_CONVERSION_SOURCE.includes(goal) && !hasPixel && !po?.application_id) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"promoted_object\", \"pixel_id\"],\n message: `optimization_goal ${goal} needs a conversion source — pass promoted_object.pixel_id (web value optimization) or promoted_object.application_id (app value optimization)`,\n });\n }\n // OFFSITE_CONVERSIONS and VALUE both need the event the source reports.\n if (\n (OPTIMIZATION_GOALS_REQUIRING_PIXEL.includes(goal) ||\n OPTIMIZATION_GOALS_REQUIRING_CONVERSION_SOURCE.includes(goal)) &&\n !hasEventType\n ) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"promoted_object\", \"custom_event_type\"],\n message: `optimization_goal ${goal} needs promoted_object.custom_event_type — pass --custom-event-type (e.g. PURCHASE, LEAD), or --custom-conversion-id to optimize toward a custom conversion`,\n });\n }\n if (OPTIMIZATION_GOALS_REQUIRING_APP.includes(goal) && !po?.application_id) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"promoted_object\", \"application_id\"],\n message: `optimization_goal ${goal} needs promoted_object.application_id`,\n });\n }\n}\n\n/**\n * A click-to-message ad set promotes the Page the conversation is with\n * (Meta's click-to-messenger/whatsapp/instagram guides: \"promoted_object – set\n * to the ID for your business' Facebook Page\"), and the CONVERSATIONS goal\n * means nothing unless a click opens a conversation.\n */\nfunction validateMessagingAdSet(\n p: { optimization_goal?: string; destination_type?: string; promoted_object?: { page_id?: string } },\n ctx: z.RefinementCtx,\n): void {\n const opensConversation = MESSAGING_DESTINATION_TYPES.some((type) => type === p.destination_type);\n if (opensConversation && !p.promoted_object?.page_id) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"promoted_object\", \"page_id\"],\n message: `destination_type ${p.destination_type} opens a conversation with a Page — pass promoted_object.page_id (--page-id) with that Page`,\n });\n }\n if (p.optimization_goal === \"CONVERSATIONS\" && p.destination_type !== undefined && !opensConversation) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"destination_type\"],\n message: `optimization_goal CONVERSATIONS needs destination_type MESSENGER, WHATSAPP, INSTAGRAM_DIRECT or a MESSAGING_* mix — ${p.destination_type} opens no conversation`,\n });\n }\n if (p.optimization_goal === \"CONVERSATIONS\" && p.destination_type === undefined) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"destination_type\"],\n message:\n \"optimization_goal CONVERSATIONS needs destination_type MESSENGER, WHATSAPP, INSTAGRAM_DIRECT or a MESSAGING_* mix — where the conversation opens\",\n });\n }\n}\n\n/**\n * A hard age/gender limit and Advantage+ Audience (`advantage_audience: 1`) are\n * contradictory — Meta treats the limit as a suggestion and rejects it (subcode\n * 1870189). When it's left unset the wire layer forces it off; an explicit 1 is\n * a caller mistake we surface here.\n */\nfunction validateAdvantageAudience(p: { targeting?: MetaTargeting }, ctx: z.RefinementCtx): void {\n const t = p.targeting;\n if (t && targetingHardLimitsDemographics(t) && advantageAudienceSetting(t) === 1) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"targeting\", \"targeting_automation\", \"advantage_audience\"],\n message:\n \"Advantage+ Audience (advantage_audience: 1) treats age and gender as suggestions, so a hard age/gender limit is rejected — set advantage_audience: 0 to enforce the limit, or drop the age_max/age_min/gender restriction\",\n });\n }\n}\n\n/**\n * Meta refuses `marketplace`, `search`, `profile_feed`, and `notification`\n * unless `feed` is selected alongside them, so a placement list built by\n * filtering an existing one can go out live-invalid. Catching it at stage time\n * keeps it out of the sequential publish, where a rejection strands the ops\n * after it.\n */\nfunction validateAdSetPlacements(p: { targeting?: MetaTargeting; clonedFrom?: string }, ctx: z.RefinementCtx): void {\n // A duplicate carries the source ad set's own targeting, read back off Meta.\n // Meta produced every value in it and already enforced every co-requirement\n // on it, so there is nothing here to discover and a refusal could only be\n // wrong — it would block copying an ad set that is serving right now, on a\n // vocabulary that lags Meta's by definition. `placementWarnings` still names\n // anything Baker cannot place.\n //\n // A retired placement is the exception, and duplicating is where it actually\n // happens: the source ad set predates the retirement, is serving on the\n // placement today, and hands it straight back to a create Meta refuses. That\n // one is proven against Meta rather than inferred from the vocabulary, so it\n // is named here instead of costing the publish.\n if (p.clonedFrom) {\n for (const issue of invalidPlacementValues(p.targeting)) {\n if (issue.kind === \"retired\") {\n ctx.addIssue({\n code: \"custom\",\n path: [\"targeting\", issue.field],\n message: `${issue.field} no longer accepts \"${issue.value}\". ${issue.fix} (${PLACEMENT_TARGETING_DOC})`,\n });\n }\n }\n return;\n }\n const missingFeed = positionsMissingRequiredFeed(p.targeting);\n if (missingFeed.length > 0) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"targeting\", \"facebook_positions\"],\n message: `Meta requires \"feed\" alongside ${missingFeed.join(\", \")} — add \"feed\" to facebook_positions or drop those positions (${PLACEMENT_TARGETING_DOC})`,\n });\n }\n for (const issue of invalidPlacementValues(p.targeting)) {\n // `unknown` is not evidence of a rejection — Meta ships placements before\n // it documents them — so it warns rather than refuses. See PlacementValueIssue.\n if (issue.kind === \"unknown\") {\n continue;\n }\n ctx.addIssue({\n code: \"custom\",\n path: [\"targeting\", issue.field],\n message:\n issue.kind === \"retired\"\n ? `${issue.field} no longer accepts \"${issue.value}\". ${issue.fix} (${PLACEMENT_TARGETING_DOC})`\n : `${issue.field} does not accept \"${issue.value}\". ${issue.fix} (${PLACEMENT_TARGETING_DOC})`,\n });\n }\n for (const message of placementCoRequirementIssues(p.targeting)) {\n ctx.addIssue({ code: \"custom\", path: [\"targeting\"], message: `${message} (${PLACEMENT_TARGETING_DOC})` });\n }\n}\n\nfunction validateSoftOptOut(\n p: { placement_soft_opt_out?: Record<string, readonly string[] | undefined>; targeting?: unknown },\n ctx: z.RefinementCtx,\n isCreate: boolean,\n): void {\n const issue = softOptOutPlacementIssue(\n p.placement_soft_opt_out,\n p.targeting as Record<string, unknown> | undefined,\n isCreate,\n );\n if (issue) ctx.addIssue({ code: \"custom\", path: [\"placement_soft_opt_out\"], message: issue });\n}\n\nexport const adSetCreateSchema = z.strictObject(adSetFields).superRefine((p, ctx) => {\n validateAdSetBudgetAndBid(p, ctx);\n validateMinRoas(p, ctx, true);\n validateFrequencyCap(p, ctx);\n validateAttribution(p, ctx);\n validatePacing(p, ctx);\n validateSpendLimits(p, ctx);\n validateBudgetSchedules(p, ctx);\n validateAdSetPromotedObject(p, ctx);\n validateMessagingAdSet(p, ctx);\n validateAdvantageAudience(p, ctx);\n validateAdSetPlacements(p, ctx);\n validateRegionalRegulation(p, ctx);\n validateSoftOptOut(p, ctx, true);\n if (!targetingHasGeoOrAudience(p.targeting)) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"targeting\", \"geo_locations\"],\n message:\n 'targeting needs a location — set targeting.geo_locations (e.g. countries: [\"US\"]) or include a custom audience; Meta rejects an ad set with no geo',\n });\n }\n});\nexport type AdSetCreate = z.infer<typeof adSetCreateSchema>;\n\nexport const adSetUpdateSchema = z\n .strictObject({\n name: adSetFields.name.optional(),\n status: updateStatusSchema.optional(),\n dailyBudget: moneySchema.optional(),\n lifetimeBudget: moneySchema.optional(),\n bidAmount: moneySchema.optional(),\n bid_strategy: z.enum(BID_STRATEGIES).optional(),\n minRoas: minRoasSchema.optional(),\n frequency_control_specs: z.array(frequencyCapSchema).min(1).optional(),\n adset_schedule: z.array(scheduleBlockSchema).min(1).optional(),\n pacing: z.enum(PACING_TYPES).optional(),\n ...spendLimitFields,\n optimization_goal: z.enum(OPTIMIZATION_GOALS).optional(),\n destination_type: z.enum(DESTINATION_TYPES).optional(),\n promoted_object: promotedObjectSchema.optional(),\n attribution_spec: attributionSpecSchema.optional(),\n start_time: z.number().int().positive().optional(),\n end_time: z.number().int().positive().optional(),\n targeting: metaTargetingSchema.optional(),\n dsa_beneficiary: z.string().min(1).max(100).optional(),\n dsa_payor: z.string().min(1).max(100).optional(),\n placement_soft_opt_out: placementSoftOptOutSchema.optional(),\n ...regionalRegulationFields,\n /**\n * Boosts ADDED to a live ad set. Meta refuses `budget_schedule_specs` in an\n * ad set update (subcode 3858199) but takes each period on the\n * `/{adset}/budget_schedules` edge without the budget restated (live on\n * v26.0, 2026-10-15), so the executor sends them there.\n */\n budgetSchedules: budgetSchedulesSchema.optional(),\n /** Delivery controls to take away (`AD_SET_CLEARABLE_CONTROLS`). */\n clear: z.array(z.enum(AD_SET_CLEARABLE_CONTROLS)).min(1).optional(),\n ...boostEditFields,\n ...labelFields,\n })\n .superRefine((p, ctx) => {\n if (!Object.values(p).some((val) => val !== undefined)) {\n ctx.addIssue({ code: \"custom\", message: \"update needs at least one field\" });\n }\n validateClear(p, ctx);\n validateBoostEdits(p, ctx);\n validateAdSetBudgetAndBid(p, ctx);\n validateMinRoas(p, ctx, false);\n validateFrequencyCap(p, ctx);\n validateAttribution(p, ctx);\n validatePacing(p, ctx);\n validateSpendLimits(p, ctx);\n // Only enforce when this update sets the optimization goal — a partial\n // update that touches other fields can't know the ad set's existing\n // promoted_object, so requiring page_id there would false-positive.\n if (p.optimization_goal) {\n validateAdSetPromotedObject(p, ctx);\n }\n // Likewise only a change of where clicks go is checked whole.\n if (p.destination_type) {\n validateMessagingAdSet(p, ctx);\n }\n validateAdvantageAudience(p, ctx);\n validateAdSetPlacements(p, ctx);\n validateRegionalRegulation(p, ctx);\n validateSoftOptOut(p, ctx, false);\n });\nexport type AdSetUpdate = z.infer<typeof adSetUpdateSchema>;\n\n// --- Ad creative (discriminated on our `creativeType`) ---\n\nconst messageSchema = z.string().min(1).max(META_LIMITS.creative.messageHardMax);\nconst headlineSchema = z.string().min(1).max(META_LIMITS.creative.headlineMax);\nconst descriptionSchema = z.string().min(1).max(META_LIMITS.creative.descriptionMax);\n\nconst callToActionSchema = z\n .strictObject({\n type: z.enum(CTA_TYPES),\n /** Overrides the base link for the CTA button; defaults to the ad's link. */\n link: httpsUrlSchema.optional(),\n /**\n * The instant form the button opens — Meta's `call_to_action.value.lead_gen_form_id`.\n * This is the ONLY place an instant form is named: the ad set says leads open\n * on the ad (`destination_type: ON_AD`), and the creative says which form.\n * Without it Meta refuses every ad in that ad set with subcode 3390001,\n * \"Choose or create an instant form for your leads campaign\".\n */\n lead_gen_form_id: parentRefSchema.optional(),\n /** The app a click-to-message button opens a conversation in — `value.app_destination`. */\n app_destination: z.enum(APP_DESTINATIONS).optional(),\n /**\n * App ads: the deep link the button opens in an installed app (`value.app_link`,\n * e.g. `myapp://product/12`). Meta refuses one without an app-store `link`\n * beside it (subcode 1885949, live on v25.0, 2026-10-15).\n */\n app_link: z.string().min(3).max(1000).optional(),\n /**\n * App ads: the Meta app the button installs or opens (`value.application`).\n * Meta refuses one whose store does not match the button's link (subcode\n * 1885270, live on v25.0, 2026-10-15).\n */\n application: z.string().regex(NUMERIC_ID_REGEX).optional(),\n })\n .superRefine((p, ctx) => {\n validateMessagingButton(p, ctx);\n // Meta only lets six of its buttons open an instant form, and refuses the\n // rest at creation. Catch it here, where the agent can still change the\n // button — at publish the creative is rejected and the ad that depends on\n // it is skipped, so the ad set ends up half filled.\n if (p.lead_gen_form_id && !LEAD_FORM_CTA_TYPES.some((allowed) => allowed === p.type)) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"type\"],\n message:\n `${p.type} cannot open an instant form — Meta refuses it (subcode 1856030). ` +\n `Use one of ${LEAD_FORM_CTA_TYPES.join(\", \")}, or drop lead_gen_form_id if this ad should go to the website.`,\n });\n }\n });\nexport type MetaCallToAction = z.infer<typeof callToActionSchema>;\n\n/**\n * A messaging button opens the app it names: MESSAGE_PAGE Messenger,\n * WHATSAPP_MESSAGE WhatsApp, INSTAGRAM_MESSAGE Instagram Direct. A messaging\n * destination never opens an instant form.\n */\nfunction validateMessagingButton(\n p: { type: string; app_destination?: string; lead_gen_form_id?: string },\n ctx: z.RefinementCtx,\n): void {\n const opens = MESSAGING_CTA_DESTINATION[p.type];\n if (opens && p.app_destination && p.app_destination !== opens) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"app_destination\"],\n message: `${p.type} opens ${opens} — set app_destination ${opens}, or pick the button of ${p.app_destination}`,\n });\n }\n if (p.app_destination && p.lead_gen_form_id) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"app_destination\"],\n message: \"a button opens a conversation or an instant form, not both — drop app_destination or lead_gen_form_id\",\n });\n }\n}\n\n/**\n * Advantage+ Creative enhancements. `standardEnhancements` switches Meta's\n * suggestions to the TEXT (`TEXT_ENHANCEMENT_FEATURES`); it never reaches the\n * media. `features` names individual feature keys, passed through as Meta's\n * own so newly surfaced ones need no schema bump — and is the only way a\n * feature that changes the picture or video (`VISUAL_ENHANCEMENT_FEATURES`)\n * is switched on. Every other visual feature is sent OPT_OUT.\n */\nexport const creativeEnhancementsSchema = z.strictObject({\n standardEnhancements: z.enum(ENROLL_STATUSES).optional(),\n features: z.record(z.string(), z.enum(ENROLL_STATUSES)).optional(),\n});\nexport type MetaCreativeEnhancements = z.infer<typeof creativeEnhancementsSchema>;\n\n/** Fields shared by every creative variant (identity, tracking, enhancements). */\n/**\n * Multi-advertiser ads: after someone engages with the ad, Meta may show it\n * beside other advertisers' ads. A creative made since 2024-08-19 without a\n * choice is opted IN. `opt_out` sends `contextual_multi_ads.enroll_status`\n * OPT_OUT (dry-run accepted live on v26.0, 2026-10-15).\n */\nconst multiAdvertiserSchema = z.enum([\"opt_in\", \"opt_out\"]);\n\n/**\n * A partnership ad: the brand's identity plus a partner's (a creator or\n * another brand), both shown on the ad. The partner is a Facebook Page\n * (`facebook_branded_content.sponsor_page_id`) and/or an Instagram account\n * (`instagram_branded_content.sponsor_id`); `ad_format` is Meta's\n * `branded_content.ad_format` — both identities (1, Meta's default), the first\n * only (2), or Meta's choice (3, Instagram only).\n *\n * Live on v26.0 (2026-10-15), dry run on act_1342210013621203: the ad needs an\n * Instagram identity of its own (3867111 \"Partnership ads require you to\n * select both first and second identities\"), the partner Page needs a linked\n * Instagram account (3867008), and the partner cannot be the ad's own Page\n * (1946011). Meta delivers the ad only once the partner has approved it (or\n * granted the brand permission ahead), so a creative staged without that\n * approval publishes and waits.\n */\nconst partnerSchema = z\n .strictObject({\n facebook_page_id: z.string().regex(NUMERIC_ID_REGEX).optional(),\n instagram_user_id: z.string().regex(NUMERIC_ID_REGEX).optional(),\n ad_format: z.enum([\"both\", \"first_only\", \"auto\"]).optional(),\n })\n .refine(\n (p) => p.facebook_page_id !== undefined || p.instagram_user_id !== undefined,\n \"name the partner's Page or Instagram account\",\n );\nexport type MetaCreativePartner = z.infer<typeof partnerSchema>;\n\nconst creativeSharedFields = {\n name: z.string().max(META_LIMITS.creative.nameMax).optional(),\n /** Facebook Page id backing the ad's identity. */\n page_id: parentRefSchema,\n /** Instagram account id for IG placements (aka instagram_actor_id on read). */\n instagram_user_id: z.string().regex(NUMERIC_ID_REGEX).optional(),\n /** URL tracking parameters appended to the destination, e.g. \"utm_source=fb&utm_campaign=x\". */\n url_tags: z.string().max(1000).optional(),\n enhancements: creativeEnhancementsSchema.optional(),\n /**\n * v26: on an advertiser with a shop, Meta sends eligible new ads to the shop\n * as well as the website (`destination_spec` WEBSITE_AND_SHOP) unless told\n * not to. `website_only` opts out (WEBSITE_AND_SHOP_OPT_OUT); unset leaves\n * Meta's default. Live on v26.0: both values validate, any other is refused.\n */\n shop_destination: z.enum([\"website_and_shop\", \"website_only\"]).optional(),\n multi_advertiser: multiAdvertiserSchema.optional(),\n partner: partnerSchema.optional(),\n};\n\n/**\n * What a click-to-message or app ad adds to a composed creative: the greeting\n * a conversation opens with (`page_welcome_message`), and how an app link\n * opens (`applink_treatment`).\n */\nconst conversationAndAppFields = {\n welcome_message: welcomeMessageSchema.optional(),\n /**\n * How a deep link opens: `deeplink_with_web_fallback` (the app, else the\n * website), `deeplink_with_appstore_fallback` (the app, else its store page),\n * `web_only`, or `automatic` (Meta decides).\n */\n applink_treatment: z\n .enum([\"automatic\", \"deeplink_with_web_fallback\", \"deeplink_with_appstore_fallback\", \"web_only\"])\n .optional(),\n};\n\n/** One image reference: a real Meta hash, or a meta_temp_* ref to a staged media.upload. */\nconst imageMediaFields = {\n imageHash: z.string().regex(IMAGE_HASH_REGEX).optional(),\n imageRef: tempRefSchema.optional(),\n};\nconst videoMediaFields = {\n videoId: z.string().regex(NUMERIC_ID_REGEX).optional(),\n videoRef: tempRefSchema.optional(),\n /** The video's cover: a picture already in the ad account, by hash. */\n thumbnailHash: z.string().regex(IMAGE_HASH_REGEX).optional(),\n /** The video's cover: a library picture staged as a `media upload --kind image` in this chat. */\n thumbnailRef: tempRefSchema.optional(),\n /** The video's cover: a public picture URL Meta fetches. */\n imageUrl: z.string().url().optional(),\n};\n\n/**\n * A deep link opens the app only from an ad whose button leads to the app's\n * store page: Meta refused `app_link` beside a website link (\"A call to action\n * that specifies an app_link value must also contain a link to an app store\n * URL\", subcode 1885949, live on v25.0, 2026-10-15).\n */\nfunction validateDeepLink(\n cta: { app_link?: string; link?: string } | undefined,\n creativeLink: string | undefined,\n ctx: z.RefinementCtx,\n path: (string | number)[],\n): void {\n if (!cta?.app_link) return;\n const link = cta.link ?? creativeLink;\n if (!link || !isAppStoreUrl(link)) {\n ctx.addIssue({\n code: \"custom\",\n path,\n message: `a deep link (app_link) needs the button to lead to the app's store page — Meta refuses it beside ${link ?? \"no link\"} (subcode 1885949); set the link to the App Store or Google Play URL`,\n });\n }\n}\n\n/** The App Store or Google Play page of an app. */\nexport function isAppStoreUrl(url: string): boolean {\n try {\n const host = new URL(url).hostname.toLowerCase();\n return [\"apps.apple.com\", \"itunes.apple.com\", \"play.google.com\"].includes(host);\n } catch {\n return false;\n }\n}\n\n/** A greeting is what a conversation opens with — only a button that opens one shows it. */\nfunction validateWelcomeOpensConversation(\n p: { welcome_message?: unknown; call_to_action?: { app_destination?: string } },\n ctx: z.RefinementCtx,\n): void {\n if (p.welcome_message && !p.call_to_action?.app_destination) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"welcome_message\"],\n message:\n \"a greeting needs a button that opens a conversation — set call_to_action.app_destination (MESSENGER, WHATSAPP or INSTAGRAM_DIRECT)\",\n });\n }\n}\n\nfunction countImageRefs(p: { imageHash?: string; imageRef?: string }): number {\n return [p.imageHash, p.imageRef].filter(Boolean).length;\n}\nfunction countVideoRefs(p: { videoId?: string; videoRef?: string }): number {\n return [p.videoId, p.videoRef].filter(Boolean).length;\n}\n\nconst singleCreativeSchema = z\n .strictObject({\n creativeType: z.literal(\"single\"),\n ...creativeSharedFields,\n /** Primary text. */\n message: messageSchema,\n link: httpsUrlSchema,\n /** Headline. */\n headline: headlineSchema.optional(),\n description: descriptionSchema.optional(),\n /** Display URL / caption shown under the headline. */\n caption: z.string().max(255).optional(),\n call_to_action: callToActionSchema.optional(),\n ...imageMediaFields,\n ...videoMediaFields,\n ...conversationAndAppFields,\n })\n .superRefine((p, ctx) => {\n validateWelcomeOpensConversation(p, ctx);\n validateDeepLink(p.call_to_action, p.link, ctx, [\"call_to_action\", \"app_link\"]);\n const images = countImageRefs(p);\n const videos = countVideoRefs(p);\n if (images + videos === 0) {\n ctx.addIssue({ code: \"custom\", path: [\"imageHash\"], message: \"a single ad needs one image or one video\" });\n }\n if (images > 1) {\n ctx.addIssue({ code: \"custom\", path: [\"imageHash\"], message: \"provide exactly one image reference\" });\n }\n if (videos > 1) {\n ctx.addIssue({ code: \"custom\", path: [\"videoId\"], message: \"provide exactly one video reference\" });\n }\n if (images > 0 && videos > 0) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"videoId\"],\n message: \"a single ad is either an image OR a video, not both\",\n });\n }\n });\n\nconst carouselCardSchema = z\n .strictObject({\n link: httpsUrlSchema,\n headline: z.string().max(META_LIMITS.creative.headlineMax).optional(),\n description: z.string().max(META_LIMITS.creative.descriptionMax).optional(),\n call_to_action: callToActionSchema.optional(),\n ...imageMediaFields,\n ...videoMediaFields,\n })\n .superRefine((p, ctx) => {\n const images = countImageRefs(p);\n const videos = countVideoRefs(p);\n if (images + videos === 0) {\n ctx.addIssue({ code: \"custom\", path: [\"imageHash\"], message: \"each card needs an image or a video\" });\n }\n if (images > 1) {\n ctx.addIssue({ code: \"custom\", path: [\"imageHash\"], message: \"each card needs exactly one image reference\" });\n }\n if (videos > 1) {\n ctx.addIssue({ code: \"custom\", path: [\"videoId\"], message: \"each card needs exactly one video reference\" });\n }\n if (images > 0 && videos > 0) {\n ctx.addIssue({ code: \"custom\", path: [\"videoId\"], message: \"each card is an image OR a video, not both\" });\n }\n });\n\nconst carouselCreativeSchema = z\n .strictObject({\n creativeType: z.literal(\"carousel\"),\n ...creativeSharedFields,\n message: messageSchema,\n /** Optional \"see more\" card destination applied when a card has no own link. */\n link: httpsUrlSchema.optional(),\n call_to_action: callToActionSchema.optional(),\n cards: z\n .array(carouselCardSchema)\n .min(META_LIMITS.creative.carouselCardsMin)\n .max(META_LIMITS.creative.carouselCardsMax),\n /**\n * `multi_share_optimized`. Meta's default (`optimized`) reorders the cards\n * by performance and may show only the top five; `fixed` — Baker's default —\n * shows every card in the order it was built.\n */\n card_order: z.enum([\"fixed\", \"optimized\"]).default(\"fixed\"),\n /** `multi_share_end_card`: Meta adds a card linking to the Page after the last one. Off unless asked. */\n end_card: z.boolean().default(false),\n ...conversationAndAppFields,\n })\n .superRefine((p, ctx) => {\n validateWelcomeOpensConversation(p, ctx);\n validateDeepLink(p.call_to_action, p.link ?? p.cards[0]?.link, ctx, [\"call_to_action\", \"app_link\"]);\n p.cards.forEach((card, index) => {\n validateDeepLink(card.call_to_action, card.link, ctx, [\"cards\", index, \"call_to_action\", \"app_link\"]);\n });\n // Meta's lead-ads guide, on the carousel form: \"You can only specify the\n // same <FORM_ID> for all child attachments.\" A carousel naming two forms is\n // refused at creation, so catch it where the agent can still fix it.\n const forms = new Set(\n [p.call_to_action?.lead_gen_form_id, ...p.cards.map((card) => card.call_to_action?.lead_gen_form_id)].filter(\n Boolean,\n ),\n );\n if (forms.size > 1) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"cards\"],\n message: `every card of a carousel must open the SAME instant form — this one names ${[...forms].join(\" and \")}`,\n });\n }\n });\n\nconst dynamicImageSchema = z\n .strictObject({ ...imageMediaFields })\n .refine((p) => countImageRefs(p) === 1, \"each dynamic image needs exactly one reference\");\nconst dynamicVideoSchema = z\n .strictObject({\n videoId: videoMediaFields.videoId,\n videoRef: videoMediaFields.videoRef,\n thumbnailHash: videoMediaFields.thumbnailHash,\n thumbnailRef: videoMediaFields.thumbnailRef,\n })\n .refine((p) => countVideoRefs(p) === 1, \"each dynamic video needs exactly one reference\");\n\nconst DYN = META_LIMITS.creative;\n\n/** How Meta counts an asset feed against its 30: every entry of every list, and the format as one. */\nfunction assetFeedCount(p: {\n bodies: unknown[];\n titles: unknown[];\n descriptions?: unknown[];\n images?: unknown[];\n videos?: unknown[];\n link_urls: unknown[];\n call_to_action_types?: unknown[];\n}): number {\n return (\n p.bodies.length +\n p.titles.length +\n (p.descriptions?.length ?? 0) +\n (p.images?.length ?? 0) +\n (p.videos?.length ?? 0) +\n p.link_urls.length +\n (p.call_to_action_types?.length ?? 0) +\n 1\n );\n}\nconst dynamicCreativeSchema = z\n .strictObject({\n creativeType: z.literal(\"dynamic\"),\n ...creativeSharedFields,\n bodies: z\n .array(z.strictObject({ text: z.string().min(1).max(DYN.assetFeedBodyMax) }))\n .min(DYN.dynamicTextsMin)\n .max(DYN.dynamicTextsMax),\n titles: z\n .array(z.strictObject({ text: z.string().min(1).max(DYN.assetFeedTitleMax) }))\n .min(DYN.dynamicTextsMin)\n .max(DYN.dynamicTextsMax),\n descriptions: z\n .array(z.strictObject({ text: z.string().min(1).max(DYN.assetFeedTitleMax) }))\n .max(DYN.dynamicTextsMax)\n .optional(),\n images: z.array(dynamicImageSchema).max(DYN.assetFeedImagesMax).optional(),\n videos: z.array(dynamicVideoSchema).max(DYN.assetFeedVideosMax).optional(),\n /**\n * Exactly one format (\"Only one ad_format is allowed per asset feed\").\n * Meta's doc calls it required; when it is left out the builder fills it\n * from the media (`AUTOMATIC_FORMAT` for pictures and videos together) —\n * except on a flexible (`DEGREES_OF_FREEDOM`) creative, every one of which\n * read back off a live account omits it.\n */\n ad_formats: z.array(z.enum(AD_FORMATS)).length(1).optional(),\n call_to_action_types: z.array(z.string()).max(DYN.dynamicTextsMax).optional(),\n /**\n * The button on the creative's own `link_data` — a flexible ad carries both\n * envelopes, and this is the one that takes `SEE_DETAILS`. Kept separate\n * from `call_to_action_types` because Meta validates the two against\n * different enums.\n */\n call_to_action: callToActionSchema.optional(),\n link_urls: z\n .array(z.strictObject({ website_url: httpsUrlSchema, display_url: z.string().optional() }))\n .min(1)\n .max(DYN.dynamicTextsMax),\n /**\n * `asset_feed_spec.optimization_type` — passed through as a free string on\n * purpose. Meta's own 400 enumerates ten values and then accepts\n * `DEGREES_OF_FREEDOM`, which is not among them and is what every\n * Advantage+ flexible creative on a live account reports. An enum here\n * would refuse the value Meta itself hands back.\n */\n optimization_type: z.string().optional(),\n /** Multi-language / placement customization — structural passthrough for v1. */\n asset_customization_rules: z.array(z.record(z.string(), z.unknown())).optional(),\n })\n .superRefine((p, ctx) => {\n if (!(p.images?.length || p.videos?.length)) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"images\"],\n message: \"a dynamic creative needs at least one image or video\",\n });\n }\n const assets = assetFeedCount(p);\n if (assets > DYN.assetFeedAssetsMax) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"images\"],\n message: `a dynamic creative carries at most ${DYN.assetFeedAssetsMax} assets in all (pictures, videos, texts, links, buttons and the format each count) — this has ${assets}`,\n });\n }\n p.call_to_action_types?.forEach((type, index) => {\n if (ASSET_FEED_CTA_TYPES.some((allowed) => allowed === type)) {\n return;\n }\n // The two CTA slots have different vocabularies, and the overlap is large\n // enough that the difference reads as a bug in Baker. Say which slot the\n // value belongs to rather than listing 104 alternatives.\n const isLinkButton = CTA_TYPES.some((allowed) => allowed === type);\n ctx.addIssue({\n code: \"custom\",\n path: [\"call_to_action_types\", index],\n message: isLinkButton\n ? `${type} is not one of the buttons Meta accepts in asset_feed_spec.call_to_action_types — it is a link_data button. Pass it as call_to_action: { type: \"${type}\" } instead.`\n : `${type} is not a Meta call-to-action button.`,\n });\n });\n });\n\n/**\n * One ad that shows a different picture or video per placement — Meta's\n * placement asset customization. Each asset names the placements it is for;\n * exactly one is the `default`, shown wherever no other asset is named. The\n * builder labels every asset and writes one `asset_customization_rules` entry\n * per asset, with `optimization_type: PLACEMENT` and a single `ad_formats`.\n *\n * Meta refuses it inside a Dynamic Creative ad set (\"For Dynamic Creative,\n * asset_feed_spec should not have customization rules\"), which ad staging checks.\n */\nconst placementAssetSchema = z\n .strictObject({\n ...imageMediaFields,\n ...videoMediaFields,\n placements: z.array(z.enum(PLACEMENT_SLOTS)).min(1),\n })\n .superRefine((p, ctx) => {\n const images = countImageRefs(p);\n const videos = countVideoRefs(p);\n if (images + videos !== 1) {\n ctx.addIssue({ code: \"custom\", path: [\"imageRef\"], message: \"each asset is exactly one picture or one video\" });\n }\n if (p.placements.includes(\"default\") && p.placements.length > 1) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"placements\"],\n message: '\"default\" already means every placement no other asset names — give it alone',\n });\n }\n });\n\nconst placementCreativeSchema = z\n .strictObject({\n creativeType: z.literal(\"placement\"),\n ...creativeSharedFields,\n message: z.string().min(1).max(META_LIMITS.creative.assetFeedBodyMax),\n link: httpsUrlSchema,\n headline: z.string().min(1).max(META_LIMITS.creative.assetFeedTitleMax).optional(),\n description: z.string().min(1).max(META_LIMITS.creative.assetFeedTitleMax).optional(),\n call_to_action: callToActionSchema.optional(),\n assets: z.array(placementAssetSchema).min(2).max(META_LIMITS.creative.assetFeedImagesMax),\n })\n .superRefine((p, ctx) => {\n // Meta reads a placement creative's button from `asset_feed_spec.call_to_action_types`,\n // which holds a type and nothing else: a form, a link or an app the button names\n // would be dropped, and a lead ad refused at publish (subcode 3390001).\n const carried = ([\"lead_gen_form_id\", \"link\", \"app_destination\", \"app_link\", \"application\"] as const).filter(\n (key) => p.call_to_action?.[key] !== undefined,\n );\n if (carried.length > 0) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"call_to_action\"],\n message: `a placement creative's button is its type only — Meta keeps no ${carried.join(\", \")} on it. For an Instant Form, a different button link or a messaging app, use a single or carousel creative`,\n });\n }\n const defaults = p.assets.filter((asset) => asset.placements.includes(\"default\")).length;\n if (defaults !== 1) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"assets\"],\n message: `exactly one asset must be \"default\" — the one every other placement shows (this has ${defaults})`,\n });\n }\n const claimed = new Map<string, number>();\n p.assets.forEach((asset, index) => {\n for (const slot of asset.placements) {\n if (slot !== \"default\" && claimed.has(slot)) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"assets\", index, \"placements\"],\n message: `${slot} is already given to asset ${claimed.get(slot)} — one asset per placement`,\n });\n }\n claimed.set(slot, index);\n }\n });\n const kinds = new Set(p.assets.map((asset) => (countVideoRefs(asset) > 0 ? \"video\" : \"image\")));\n if (kinds.size > 1) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"assets\"],\n message:\n \"every asset of a placement creative is a picture, or every one is a video — Meta takes one format per ad\",\n });\n }\n });\n\n/**\n * Boost a post that already exists: a Facebook Page post (`object_story_id`),\n * an Instagram post (`source_instagram_media_id`, run as the brand's Page and\n * Instagram account), or a creator's post through the partnership ad code they\n * shared (`instagram_ad_code`, Meta's `branded_content.instagram_boost_post_access_token`).\n * The post keeps its likes, comments and shares.\n */\nconst existingPostCreativeSchema = z\n .strictObject({\n creativeType: z.literal(\"existing_post\"),\n name: creativeSharedFields.name,\n /** \"<page_id>_<post_id>\" object story id of the Facebook post to promote. */\n object_story_id: z\n .string()\n .regex(/^\\d+_\\d+$/, 'expected \"<page_id>_<post_id>\"')\n .optional(),\n /** An Instagram post's media id — from `baker ads meta instagram-media`. */\n source_instagram_media_id: z.string().regex(NUMERIC_ID_REGEX).optional(),\n /** A creator's partnership ad code for their Instagram post. */\n instagram_ad_code: z.string().trim().min(8).max(500).optional(),\n /** The brand's Page the ad runs as — needed with an Instagram post or an ad code. */\n page_id: z.string().regex(NUMERIC_ID_REGEX).optional(),\n instagram_user_id: creativeSharedFields.instagram_user_id,\n url_tags: creativeSharedFields.url_tags,\n enhancements: creativeSharedFields.enhancements,\n multi_advertiser: creativeSharedFields.multi_advertiser,\n partner: creativeSharedFields.partner,\n })\n .superRefine((p, ctx) => {\n const sources = [p.object_story_id, p.source_instagram_media_id, p.instagram_ad_code].filter(Boolean).length;\n if (sources !== 1) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"object_story_id\"],\n message:\n \"boost ONE post: object_story_id (Facebook), source_instagram_media_id (Instagram) or instagram_ad_code\",\n });\n }\n if ((p.source_instagram_media_id || p.instagram_ad_code) && !p.page_id) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"page_id\"],\n message: \"an Instagram post runs as the brand's Facebook Page — add page_id\",\n });\n }\n });\n\n/**\n * A creative given in Meta's own vocabulary, verbatim.\n *\n * The four shapes above cover what an agent composes from scratch. This one\n * covers what already exists: a creative read back off a live ad and re-posted\n * with one field changed. Meta's creative surface is wider than any union we\n * keep in step with it — a flexible ad carries `link_data` AND `asset_feed_spec`\n * together, catalogue and collection ads carry fields we model nowhere — so\n * \"reproduce this ad exactly\" cannot be expressed by re-deriving it. It is\n * expressed by passing Meta's own bytes back.\n *\n * This is what `ads retag` stages, and it is why retagging a live ad no longer\n * depends on Baker being able to describe the ad it is retagging.\n */\nconst specCreativeSchema = z\n .strictObject({\n creativeType: z.literal(\"spec\"),\n name: creativeSharedFields.name,\n url_tags: creativeSharedFields.url_tags,\n /** Promote the existing post — keeps the ad's likes, comments and shares. */\n object_story_id: z\n .string()\n .regex(/^\\d+_\\d+$/, 'expected \"<page_id>_<post_id>\"')\n .optional(),\n object_story_spec: z.record(z.string(), z.unknown()).optional(),\n asset_feed_spec: z.record(z.string(), z.unknown()).optional(),\n degrees_of_freedom_spec: z.record(z.string(), z.unknown()).optional(),\n instagram_user_id: creativeSharedFields.instagram_user_id,\n /** The creative this spec was cloned from, for the review diff. */\n clonedFrom: z.string().regex(NUMERIC_ID_REGEX).optional(),\n })\n .superRefine((p, ctx) => {\n if (!(p.object_story_id || p.object_story_spec || p.asset_feed_spec)) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"object_story_spec\"],\n message: \"a spec creative needs object_story_id, object_story_spec or asset_feed_spec\",\n });\n }\n });\n\n/**\n * The namespaces a catalog template token reads from — one per catalog type\n * Meta's Advantage+ catalog ads serve (products, categories, hotels, flights,\n * destinations, home listings, vehicles).\n */\nconst CATALOG_TOKEN_NAMESPACES = [\n \"product\",\n \"category\",\n \"hotel\",\n \"flight\",\n \"destination\",\n \"home_listing\",\n \"vehicle\",\n \"vehicle_offer\",\n \"trip\",\n] as const;\n\n/** Every `{{…}}` in a template that reads no catalog field — `{{price}}` instead of `{{product.price}}`. */\nexport function unknownCatalogTokens(text: string | undefined): string[] {\n return [...(text ?? \"\").matchAll(/\\{\\{\\s*([^}|\\s]+)[^}]*\\}\\}/g)]\n .filter((match) => !CATALOG_TOKEN_NAMESPACES.some((ns) => match[1]?.startsWith(`${ns}.`)))\n .map((match) => match[0]);\n}\n\nconst templateText = (max: number) => z.string().trim().min(1).max(max);\n\n/**\n * An Advantage+ catalog ad: one template Meta fills per product of a set\n * (`object_story_spec.template_data` + `product_set_id`). Text may carry tokens\n * such as `{{product.name}}`, `{{product.price}}`, `{{product.description}}`.\n * The button carries only its type — Meta's guide: \"The `value` field should be\n * omitted\" — and every product links to its own catalog URL; `link` is the\n * carousel's end-card / caption destination.\n */\nconst catalogCreativeSchema = z\n .strictObject({\n creativeType: z.literal(\"catalog\"),\n name: creativeSharedFields.name,\n page_id: creativeSharedFields.page_id,\n instagram_user_id: creativeSharedFields.instagram_user_id,\n url_tags: creativeSharedFields.url_tags,\n /** A product set's id, or the meta_temp_* ref of one this chat creates. */\n product_set_id: parentRefSchema,\n message: templateText(META_LIMITS.creative.messageHardMax),\n link: httpsUrlSchema,\n headline: templateText(255).optional(),\n description: templateText(255).optional(),\n call_to_action: z.strictObject({ type: z.enum(CTA_TYPES) }).optional(),\n /**\n * `carousel` (Meta picks the products, one card each — the default),\n * `single` (one product per ad: `force_single_link`), or `slideshow` (each\n * card cycles a product's pictures: `format_option: carousel_slideshows`).\n */\n format: z.enum([\"carousel\", \"single\", \"slideshow\"]).default(\"carousel\"),\n /** `multi_share_end_card`: a last card linking to the Page. Off unless asked. */\n end_card: z.boolean().default(false),\n })\n .superRefine((p, ctx) => {\n for (const key of [\"message\", \"headline\", \"description\"] as const) {\n const unknown = unknownCatalogTokens(p[key]);\n if (unknown.length > 0) {\n ctx.addIssue({\n code: \"custom\",\n path: [key],\n message: `${unknown.join(\", \")} reads no catalog field — a token names its catalog type, e.g. {{product.name}}, {{product.price}}`,\n });\n }\n }\n });\n\n/**\n * An ad that opens an Instant Experience full screen\n * (`link` = `https://fb.com/canvas_doc/<id>`, Meta's guide). `collection` is the\n * collection format: the experience's products or photos show under the ad\n * (`object_type` SHARE for a picture, VIDEO for a video) — Meta builds it only\n * from an experience with a product set shown in feed, or four photos.\n */\nconst instantExperienceCreativeSchema = z\n .strictObject({\n creativeType: z.literal(\"instant_experience\"),\n name: creativeSharedFields.name,\n page_id: creativeSharedFields.page_id,\n instagram_user_id: creativeSharedFields.instagram_user_id,\n url_tags: creativeSharedFields.url_tags,\n /** The experience: its id, or the meta_temp_* ref of one this chat creates. */\n canvas_id: parentRefSchema,\n message: messageSchema,\n headline: headlineSchema.optional(),\n description: descriptionSchema.optional(),\n call_to_action: z.strictObject({ type: z.enum(CTA_TYPES) }).optional(),\n format: z.enum([\"standard\", \"collection\"]).default(\"standard\"),\n /**\n * A collection over a photo experience (more than header → product set →\n * footer) shows four pictures under its hero, named by the experience's\n * elements: a photo element, or one product of a product-set element\n * (`element_child_index`). Meta refuses such a collection without four\n * (2131023). Only a live experience has element ids — read them with\n * `instant-experiences --page-id`.\n */\n collection_thumbnails: z\n .array(\n z.strictObject({\n element_id: z.string().regex(NUMERIC_ID_REGEX),\n element_child_index: z.number().int().min(0).optional(),\n /**\n * The square of a photo element shown, in the photo's pixels:\n * `{\"100x100\": [[left, top], [right, bottom]]}` — Meta's only key.\n * Required on a photo element (live); staging fills a centered\n * square from the photo when it is left out.\n */\n element_crops: z\n .strictObject({\n \"100x100\": z.tuple([\n z.tuple([z.number().int().min(0), z.number().int().min(0)]),\n z.tuple([z.number().int().positive(), z.number().int().positive()]),\n ]),\n })\n .optional(),\n }),\n )\n .length(4, \"a collection shows exactly four pictures under its hero\")\n .optional(),\n ...imageMediaFields,\n ...videoMediaFields,\n })\n .superRefine((p, ctx) => {\n if (p.collection_thumbnails && (p.format !== \"collection\" || !NUMERIC_ID_REGEX.test(p.canvas_id))) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"collection_thumbnails\"],\n message:\n \"collection thumbnails go on a --format collection ad over a live Instant Experience (its elements have ids only once it exists)\",\n });\n }\n const images = countImageRefs(p);\n const videos = countVideoRefs(p);\n if (images + videos !== 1) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"imageHash\"],\n message: \"the ad shows one picture or one video before it opens the experience\",\n });\n }\n });\n\nexport const creativeContentSchema = z.discriminatedUnion(\"creativeType\", [\n singleCreativeSchema,\n carouselCreativeSchema,\n dynamicCreativeSchema,\n placementCreativeSchema,\n existingPostCreativeSchema,\n specCreativeSchema,\n catalogCreativeSchema,\n instantExperienceCreativeSchema,\n]);\nexport type MetaCreativeContent = z.infer<typeof creativeContentSchema>;\nexport type MetaCreativeType = MetaCreativeContent[\"creativeType\"];\n\nexport const adCreativeCreateSchema = creativeContentSchema;\nexport type AdCreativeCreate = z.infer<typeof adCreativeCreateSchema>;\n\n/**\n * Meta ad creatives are largely immutable once live. On a real target only\n * name/status may change; content edits must stage a NEW creative and repoint\n * the ad. Amending a staged (meta_temp_*) creative merges into the create.\n */\nexport const adCreativeUpdateSchema = z\n .strictObject({\n name: z.string().max(META_LIMITS.creative.nameMax).optional(),\n status: z.enum(CREATIVE_UPDATE_STATUSES).optional(),\n /** Content patch — only honored when the target is a staged meta_temp_* creative. */\n content: z.record(z.string(), z.unknown()).optional(),\n ...labelFields,\n })\n .refine((p) => Object.values(p).some((val) => val !== undefined), \"update needs at least one field\");\nexport type AdCreativeUpdate = z.infer<typeof adCreativeUpdateSchema>;\n\n// --- Ad ---\n\nexport const adCreateSchema = z.strictObject({\n name: z.string().min(1).max(META_LIMITS.ad.nameMax),\n adset_id: parentRefSchema,\n status: stageableStatusSchema.default(\"PAUSED\"),\n creative: z.strictObject({ creative_id: parentRefSchema }),\n /** Conversion pixel / offline event set / view tags — structural passthrough. */\n tracking_specs: z.array(z.record(z.string(), z.unknown())).optional(),\n /**\n * The website domain the ad's conversions are counted on — the registrable\n * domain only (`example.com`, never `www.example.com` or a URL). Meta fills\n * it from the destination when left out; set it when the site and the\n * pixel's domain differ. Create-only on Meta's ad reference.\n */\n conversion_domain: z\n .string()\n .trim()\n .toLowerCase()\n .regex(/^(?!www\\.)[a-z0-9-]+(\\.[a-z0-9-]+)+$/, \"the domain alone, e.g. example.com (no www., no https://)\")\n .optional(),\n ...createLabelFields,\n});\nexport type AdCreate = z.infer<typeof adCreateSchema>;\n\nexport const adUpdateSchema = z\n .strictObject({\n name: z.string().min(1).max(META_LIMITS.ad.nameMax).optional(),\n status: updateStatusSchema.optional(),\n /** Swapping the creative is the Meta way to \"edit\" an ad's creative. */\n creative: z.strictObject({ creative_id: parentRefSchema }).optional(),\n tracking_specs: z.array(z.record(z.string(), z.unknown())).optional(),\n ...labelFields,\n })\n .refine((p) => Object.values(p).some((val) => val !== undefined), \"update needs at least one field\");\nexport type AdUpdate = z.infer<typeof adUpdateSchema>;\n\n// --- Custom audiences ---\n\n/** Meta sizes a lookalike in whole percent steps: 0.01 is the 1% most similar people. */\nconst lookalikeRatioSchema = z\n .number()\n .min(0.01)\n .max(0.2)\n .refine(\n (ratio) => Math.abs(Math.round(ratio * 100) - ratio * 100) < 1e-9,\n \"Meta sizes a lookalike in 1% steps (0.01–0.20)\",\n );\n\n/**\n * A lookalike of one seed audience. Meta takes a single `origin_audience_id`\n * for an audience seed — live on v26.0 (2026-10-15) a second seed in\n * `lookalike_spec.origin` was accepted and silently dropped (the audience read\n * back one origin), and `origin_ids` of audiences was refused — so `origin`\n * holds exactly one.\n *\n * `conversions_of` seeds it instead from the people who converted in live\n * campaigns or ad sets (`origin_ids` + `conversion_type: campaign_conversions`;\n * Meta wants 100 of them — live, a harness campaign with none was refused\n * 1713008). Meta warns (1713242) that `country` and `location_spec` leave\n * `lookalike_spec` in v27, where a lookalike follows its ad sets' locations.\n *\n * `starting_ratio` with `ratio` takes a band of similarity rather than the top\n * of it (0.01 to 0.03 is the 1%–3% band), which is how Ads Manager builds\n * several non-overlapping lookalikes from one seed. `countries` sends Meta's\n * `location_spec`, for a lookalike spread over several countries; `country`\n * stays for one.\n */\nconst lookalikeSpecSchema = z\n .strictObject({\n origin: z\n .array(\n z.strictObject({\n // An audience this chat creates holds nobody until it publishes and Meta\n // matches it, and Meta refuses a lookalike of an empty seed (1713008).\n id: z\n .string()\n .regex(\n NUMERIC_ID_REGEX,\n \"a lookalike's seed must already hold people — an audience this chat creates is empty until it publishes and Meta matches it (up to a day); make the lookalike in a later chat\",\n ),\n }),\n )\n .min(1)\n .max(1, \"Meta builds a lookalike from one seed audience — make one lookalike per seed\")\n .optional(),\n conversions_of: z\n .array(z.string().regex(NUMERIC_ID_REGEX, \"a live campaign or ad set id\"))\n .min(1)\n .max(10)\n .optional(),\n ratio: lookalikeRatioSchema,\n starting_ratio: z\n .number()\n .min(0)\n .max(0.19)\n .refine(\n (ratio) => Math.abs(Math.round(ratio * 100) - ratio * 100) < 1e-9,\n \"a band starts on a whole percent (0.00, 0.01, … 0.19)\",\n )\n .optional(),\n country: z.string().length(2).optional(),\n countries: z.array(z.string().length(2)).min(1).max(50).optional(),\n allow_international_seeds: z.boolean().optional(),\n })\n .superRefine((spec, ctx) => {\n if ((spec.origin === undefined) === (spec.conversions_of === undefined)) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"origin\"],\n message:\n \"a lookalike has one seed: an audience (origin) or the people who converted in live campaigns or ad sets (conversions_of)\",\n });\n }\n if (!spec.country && !spec.countries) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"country\"],\n message: \"a lookalike is found in a country — name one (country) or several (countries)\",\n });\n }\n if (spec.country && spec.countries) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"countries\"],\n message: \"name one country or a list of countries, not both\",\n });\n }\n if (spec.starting_ratio !== undefined && (spec.ratio === undefined || spec.starting_ratio >= spec.ratio)) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"starting_ratio\"],\n message:\n \"starting_ratio begins a band that ends at ratio, so it needs a larger ratio (0.01 to 0.03 is the 1%–3% band)\",\n });\n }\n });\n\n/**\n * A rule is a structural passthrough, so both readers below walk the whole tree\n * for a key instead of assuming a shape. The shapes Meta accepts are not one:\n * `inclusions`/`exclusions` each wrap a `rules` array, and Meta's own website\n * example passes `event_sources` at the top level with no section wrapper at\n * all — a reader that only looked at `<section>.rules[]` silently saw nothing\n * in the second shape.\n */\nfunction valuesOfKey(node: unknown, key: string): unknown[] {\n if (Array.isArray(node)) return node.flatMap((entry) => valuesOfKey(entry, key));\n if (!node || typeof node !== \"object\") return [];\n const record = node as Record<string, unknown>;\n return [\n ...(key in record ? [record[key]] : []),\n ...Object.values(record).flatMap((value) => valuesOfKey(value, key)),\n ];\n}\n\n/**\n * Meta refuses an audience whose event sources span two kinds (\"Only one type of\n * event source is allowed\", subcode 1870028) — a Page and an Instagram profile\n * are two audiences, not one. The subcode is undocumented, but the guides bear\n * it out: every engagement example keeps to a single source type, and each type\n * carries its own event vocabulary and its own retention ceiling, so there is\n * no window the mixed rule could even mean.\n *\n * The error names the audience, not the rule set, so the types are collected\n * across the whole rule: `inclusions` and `exclusions` are one audience between\n * them, and checking each section alone waved through a Page inclusion with an\n * Instagram exclusion. Excluding the same source type you include stays legal.\n *\n * Caught here rather than at publish because the refusal is deterministic, and\n * at publish it arrives after the ad sets that target the audience have already\n * been skipped for depending on it.\n */\nfunction mixedEventSourceTypes(rule: Record<string, unknown> | undefined): string[] {\n const types = valuesOfKey(rule, \"event_sources\")\n .flatMap((sources) => (Array.isArray(sources) ? sources : []))\n .map((source) => (source as { type?: unknown })?.type)\n .filter((type): type is string => typeof type === \"string\");\n const distinct = [...new Set(types)].sort();\n return distinct.length > 1 ? distinct : [];\n}\n\n/**\n * The retention windows a rule carries, in days, distinct and ascending.\n *\n * A rule-based audience's window lives in the rule's own `retention_seconds`\n * and `retention_days` is refused next to a rule, so every surface that shows a\n * staged audience's retention reads it from here — otherwise the review shows a\n * number the request never sends.\n */\nexport function ruleRetentionDays(rule: Record<string, unknown> | undefined): number[] {\n const seconds = valuesOfKey(rule, \"retention_seconds\").filter(\n (value): value is number => typeof value === \"number\" && value > 0,\n );\n return [...new Set(seconds.map((value) => Math.round(value / 86_400)))].sort((a, b) => a - b);\n}\n\n/**\n * One person on a customer list, as typed or as already hashed. The backend replaces every value by\n * its SHA-256 at stage time (`convex/ads/meta/writes/customerList.ts`), so a draft never holds an\n * address; a 64-hex value passes through as a digest. A country alone matches nobody.\n */\nexport const customAudienceMemberSchema = z\n .strictObject({\n email: z.string().min(1).optional(),\n phone: z.string().min(1).optional(),\n /** Two-letter ISO country (US, GB) — Meta reads a phone without its country code against it. */\n country: z.string().min(1).optional(),\n })\n .refine((m) => m.email !== undefined || m.phone !== undefined, \"each person needs an email or a phone\");\nexport type CustomAudienceMember = z.infer<typeof customAudienceMemberSchema>;\n\nexport const customAudienceCreateSchema = z\n .strictObject({\n name: z.string().min(1).max(META_LIMITS.audience.nameMax),\n subtype: z.enum(CUSTOM_AUDIENCE_SUBTYPES),\n description: z.string().max(500).optional(),\n customer_file_source: z.enum(CUSTOMER_FILE_SOURCES).optional(),\n retention_days: z.number().int().min(1).max(META_LIMITS.audience.retentionDaysMax).optional(),\n lookalike_spec: lookalikeSpecSchema.optional(),\n /** Website/engagement rule — structural passthrough validated by Meta. */\n rule: z.record(z.string(), z.unknown()).optional(),\n /** The people of a customer list (subtype CUSTOM), uploaded right after the audience is created at publish. */\n members: z.array(customAudienceMemberSchema).min(1).max(META_LIMITS.audience.membersMax).optional(),\n /**\n * A value-based customer list: each person carries what they are worth\n * (the LOOKALIKE_VALUE column), and a lookalike of it finds people like\n * the most valuable ones. Fixed at creation.\n */\n is_value_based: z.boolean().optional(),\n })\n .superRefine((p, ctx) => {\n if (p.members && p.subtype !== \"CUSTOM\") {\n ctx.addIssue({\n code: \"custom\",\n path: [\"members\"],\n message:\n \"only a customer list (subtype CUSTOM) is made of people you upload — drop members or use subtype CUSTOM\",\n });\n }\n if (p.members && p.is_value_based) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"members\"],\n message:\n \"a value-based list needs a value for each person — create it without members, then use audiences members add with a LOOKALIKE_VALUE column\",\n });\n }\n if (p.is_value_based && (p.subtype !== \"CUSTOM\" || !p.customer_file_source)) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"is_value_based\"],\n message: \"a value-based audience is a customer list — subtype CUSTOM with customer_file_source\",\n });\n }\n if (p.subtype === \"LOOKALIKE\" && !p.lookalike_spec) {\n ctx.addIssue({ code: \"custom\", path: [\"lookalike_spec\"], message: \"LOOKALIKE audiences need a lookalike_spec\" });\n }\n if ((p.subtype === \"WEBSITE\" || p.subtype === \"ENGAGEMENT\") && !p.rule) {\n ctx.addIssue({ code: \"custom\", path: [\"rule\"], message: `${p.subtype} audiences need a rule (use --file)` });\n }\n if (p.rule && p.retention_days !== undefined) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"retention_days\"],\n message:\n \"a rule carries its own window in retention_seconds, so drop retention_days — Meta takes it only on a customer-file audience, and sending both leaves the review showing a window the audience will not have\",\n });\n }\n const mixed = mixedEventSourceTypes(p.rule);\n if (mixed.length > 0) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"rule\"],\n message: `one audience covers one kind of source, but this rule mixes ${mixed.join(\" and \")} — split it into one audience per source`,\n });\n }\n });\nexport type CustomAudienceCreate = z.infer<typeof customAudienceCreateSchema>;\n\n/**\n * What Meta changes on a live audience (live on v25.0, 2026-10-14): its name,\n * description, where a customer list came from, the opt-out link, and a website\n * or engagement audience's rule. A customer list's retention is fixed (\"You can\n * not update retention_days for an existing DFCA cluster\"), and a lookalike's\n * seed and size are fixed — a different lookalike is a new audience.\n *\n * Deleting is `status: DELETED`, sent as `DELETE /{audience_id}`: Meta removes\n * the audience outright, and the ads that target it stop for good.\n */\nexport const customAudienceUpdateSchema = z\n .strictObject({\n name: z.string().min(1).max(META_LIMITS.audience.nameMax).optional(),\n description: z.string().max(500).optional(),\n customer_file_source: z.enum(CUSTOMER_FILE_SOURCES).optional(),\n opt_out_link: httpsUrlSchema.optional(),\n rule: z.record(z.string(), z.unknown()).optional(),\n status: z.literal(\"DELETED\").optional(),\n })\n .superRefine((p, ctx) => {\n if (!Object.values(p).some((val) => val !== undefined)) {\n ctx.addIssue({ code: \"custom\", message: \"update needs at least one field\" });\n }\n if (p.status === \"DELETED\" && Object.values(p).filter((val) => val !== undefined).length > 1) {\n ctx.addIssue({ code: \"custom\", path: [\"status\"], message: \"a deleted audience takes no other change\" });\n }\n const mixed = mixedEventSourceTypes(p.rule);\n if (mixed.length > 0) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"rule\"],\n message: `one audience covers one kind of source, but this rule mixes ${mixed.join(\" and \")} — split it into one audience per source`,\n });\n }\n });\nexport type CustomAudienceUpdate = z.infer<typeof customAudienceUpdateSchema>;\n\n// --- Custom conversion ---\n\n/**\n * A new Custom Conversion.\n *\n * Create-only on purpose. Meta's own `/act_x/customconversions` edge supports\n * neither update nor delete, and the node's delete archives rather than\n * removes — so there is no staged op that could take this back, and the\n * Session-staging promise (\"discard reverses it\") holds only up to Publish.\n * That is also why the cap is worth guarding: a slot spent is spent.\n */\nexport const customConversionCreateSchema = z\n .strictObject({\n name: z.string().min(1).max(META_LIMITS.customConversion.nameMax),\n description: z.string().max(META_LIMITS.customConversion.descriptionMax).optional(),\n /** The pixel the conversion counts from — `event_source_id` on the wire. Baker never creates pixels, so this is always a real id. */\n pixel_id: z.string().regex(NUMERIC_ID_REGEX),\n custom_event_type: z.enum(CUSTOM_EVENT_TYPES),\n /** Meta's filter JSON. Built by `buildCustomConversionRule` for the URL case. */\n rule: z.record(z.string(), z.unknown()),\n /** What one conversion is worth, when the site cannot send a value with the event. */\n default_conversion_value: z.number().min(0).optional(),\n })\n .superRefine((p, ctx) => {\n const refusal = customConversionRuleRefusal(p.rule);\n if (refusal) {\n ctx.addIssue({ code: \"custom\", path: [\"rule\"], message: refusal });\n }\n });\nexport type CustomConversionCreate = z.infer<typeof customConversionCreateSchema>;\n\n/**\n * What Meta changes on a live Custom Conversion (live on v25.0, 2026-10-14):\n * name, description and the default value. Meta answers `success` to a new\n * `rule` or `custom_event_type` and keeps the old one, so neither is offered —\n * a conversion that counts something else is a new conversion.\n *\n * Deleting is `status: DELETED`, sent as `DELETE /{conversion_id}`. Meta\n * archives rather than removes it: it stops counting and leaves the listing's\n * active conversions, and still counts against the account's cap.\n */\nexport const customConversionUpdateSchema = z\n .strictObject({\n name: z.string().min(1).max(META_LIMITS.customConversion.nameMax).optional(),\n description: z.string().max(META_LIMITS.customConversion.descriptionMax).optional(),\n default_conversion_value: z.number().min(0).optional(),\n status: z.literal(\"DELETED\").optional(),\n })\n .superRefine((p, ctx) => {\n const set = Object.values(p).filter((val) => val !== undefined);\n if (set.length === 0) {\n ctx.addIssue({ code: \"custom\", message: \"update needs at least one field\" });\n }\n if (p.status === \"DELETED\" && set.length > 1) {\n ctx.addIssue({ code: \"custom\", path: [\"status\"], message: \"a deleted conversion takes no other change\" });\n }\n });\nexport type CustomConversionUpdate = z.infer<typeof customConversionUpdateSchema>;\n\n// --- Ad labels ---\n\n/** An ad label: a name an account files campaigns, ad sets, ads and creatives under. */\nexport const adLabelCreateSchema = z.strictObject({\n name: z.string().trim().min(1).max(META_LIMITS.adLabel.nameMax),\n});\nexport type AdLabelCreate = z.infer<typeof adLabelCreateSchema>;\n\n/** Rename a label, or delete it (`DELETE /{label_id}`) — the objects it was on keep running, unlabelled. */\nexport const adLabelUpdateSchema = z\n .strictObject({\n name: z.string().trim().min(1).max(META_LIMITS.adLabel.nameMax).optional(),\n status: z.literal(\"DELETED\").optional(),\n })\n .refine((p) => (p.name === undefined) !== (p.status === undefined), \"rename the label or delete it — one of them\");\nexport type AdLabelUpdate = z.infer<typeof adLabelUpdateSchema>;\n\n// --- Media delete ---\n\n/**\n * Take an image out of the ad account's image library (`DELETE\n * /act_<id>/adimages?hash=`). Meta refuses an image a creative still uses. Live\n * on v25.0 (2026-10-14) the image left the library listing while a read by its\n * hash still answered — a hash names the picture's bytes, not the library entry.\n */\nexport const mediaDeleteSchema = z\n .strictObject({\n imageHash: z.string().regex(IMAGE_HASH_REGEX).optional(),\n /**\n * Or a video, taken out of the ad account's video library\n * (`DELETE /act_<id>/advideos?video_id=`). Live on v26.0, `DELETE /{video_id}`\n * was refused with the user token and the Page token alike (1363055 \"You\n * might not have permission to delete this video\"), with `pages_manage_posts`\n * granted; the library delete took it off the account.\n */\n videoId: z.string().regex(NUMERIC_ID_REGEX).optional(),\n })\n .refine((p) => (p.imageHash === undefined) !== (p.videoId === undefined), \"name imageHash OR videoId\");\nexport type MediaDelete = z.infer<typeof mediaDeleteSchema>;\n\n// --- Media upload ---\n\nexport const mediaUploadSchema = z\n .strictObject({\n kind: z.enum(MEDIA_KINDS),\n bakerImageId: bakerMediaIdSchema.optional(),\n bakerVideoId: bakerMediaIdSchema.optional(),\n /** Optional display name / filename hint. */\n name: z.string().max(255).optional(),\n })\n .superRefine((p, ctx) => {\n if (p.kind === \"image\" && !p.bakerImageId) {\n ctx.addIssue({ code: \"custom\", path: [\"bakerImageId\"], message: \"image uploads need a bakerImageId\" });\n }\n if (p.kind === \"video\" && !p.bakerVideoId) {\n ctx.addIssue({ code: \"custom\", path: [\"bakerVideoId\"], message: \"video uploads need a bakerVideoId\" });\n }\n });\nexport type MediaUpload = z.infer<typeof mediaUploadSchema>;\n\n// --- Ad account settings ---\n\n/**\n * The ad account's own settings: its name and its account spending limit.\n * Only the account the op names (the target IS the account). Live on v26.0\n * (2026-10-15) on act_1342210013621203:\n * - `POST /act_<id>` IGNORES `validate_only` — a dry run set a real €5,000 cap\n * — so it is never dry-run;\n * - `spend_cap` is written in MAJOR units (\"10\" set €10.00) while the account\n * reads it back in minor units (\"1000\");\n * - setting a limit starts the count again: `amount_spent` (spent toward the\n * limit) read 0 right after, where it had read €1,304.26 with no limit;\n * - `spend_cap_action: delete` removes the limit (reads back \"0\"); `reset`\n * starts the count again from 0, keeping the limit.\n */\nexport const adAccountUpdateSchema = z\n .strictObject({\n name: z.string().trim().min(1).max(100).optional(),\n /** The account spending limit — spending stops when the account has spent this since it was set. */\n spendCap: moneySchema.optional(),\n /** `remove`: no limit at all. `reset`: start counting toward the limit again from zero. */\n spendCapAction: z.enum([\"remove\", \"reset\"]).optional(),\n /**\n * The EU (DSA) advertiser and payer every new ad set on the account starts\n * with (`default_dsa_beneficiary` / `default_dsa_payor`). Meta keeps both or\n * neither, and clears them with two empty strings (`clearDefaultDsa`).\n * Written on the account node, which ignores `validate_only`.\n */\n defaultDsaBeneficiary: z.string().trim().min(1).max(512).optional(),\n defaultDsaPayor: z.string().trim().min(1).max(512).optional(),\n clearDefaultDsa: z.literal(true).optional(),\n })\n .superRefine((p, ctx) => {\n const dsa = [p.defaultDsaBeneficiary, p.defaultDsaPayor].filter((value) => value !== undefined).length;\n if (\n p.name === undefined &&\n p.spendCap === undefined &&\n p.spendCapAction === undefined &&\n dsa === 0 &&\n !p.clearDefaultDsa\n ) {\n ctx.addIssue({\n code: \"custom\",\n message: \"name, spendCap, spendCapAction, the default EU advertiser and payer, or clearDefaultDsa is required\",\n });\n }\n if (dsa === 1) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"defaultDsaPayor\"],\n message:\n \"Meta keeps the default EU advertiser and payer together — pass both (the same name when one business does both)\",\n });\n }\n if (dsa > 0 && p.clearDefaultDsa) {\n ctx.addIssue({ code: \"custom\", path: [\"clearDefaultDsa\"], message: \"set the defaults OR clear them, not both\" });\n }\n if (p.spendCap !== undefined && p.spendCapAction === \"remove\") {\n ctx.addIssue({\n code: \"custom\",\n path: [\"spendCapAction\"],\n message: \"set a spending limit OR remove it, not both\",\n });\n }\n });\nexport type AdAccountUpdate = z.infer<typeof adAccountUpdateSchema>;\n\n/** A Page-owned Instant Form (`leadForms.ts`). The form itself is created only when the Session publishes. */\nexport { type LeadFormCreate, type LeadFormUpdate, leadFormCreateSchema, leadFormUpdateSchema } from \"./leadForms\";\n\n// --- The op union ---\n\nexport const META_DRAFT_OP_KINDS = [\n \"campaign.create\",\n \"campaign.update\",\n \"adSet.create\",\n \"adSet.update\",\n \"adCreative.create\",\n \"adCreative.update\",\n \"ad.create\",\n \"ad.update\",\n \"customAudience.create\",\n \"customAudience.update\",\n \"customAudience.members\",\n \"customConversion.create\",\n \"customConversion.update\",\n \"leadForm.create\",\n \"leadForm.update\",\n \"media.upload\",\n \"media.delete\",\n \"adLabel.create\",\n \"adLabel.update\",\n \"adRule.create\",\n \"adRule.update\",\n \"adStudy.create\",\n \"adStudy.update\",\n \"campaign.copy\",\n \"adSet.copy\",\n \"ad.copy\",\n \"canvas.create\",\n \"canvas.update\",\n \"productCatalog.create\",\n \"productCatalog.update\",\n \"product.create\",\n \"product.update\",\n \"productSet.create\",\n \"productSet.update\",\n \"productFeed.create\",\n \"productFeed.update\",\n \"pagePhoto.create\",\n \"pagePhoto.update\",\n \"adAccount.update\",\n \"publisherBlockList.create\",\n \"publisherBlockList.update\",\n \"reachFrequencyReservation.create\",\n \"reachFrequencyReservation.update\",\n] as const;\nexport const metaDraftOpKindSchema = z.enum(META_DRAFT_OP_KINDS);\nexport type MetaDraftOpKind = z.infer<typeof metaDraftOpKindSchema>;\n\nconst accountIdSchema = z.string().regex(NUMERIC_ID_REGEX, \"accountId must be the bare numeric ad account id\");\n/**\n * Update targets: a real bare-numeric id, or a meta_temp_* ref — targeting a\n * temp ref AMENDS the create staged earlier in the same draft (merge +\n * re-validate) instead of staging a Meta update.\n */\nconst updateTargetSchema = z.union([z.string().regex(NUMERIC_ID_REGEX), tempRefSchema]);\n\nfunction createOp<K extends MetaDraftOpKind, P extends z.ZodTypeAny>(kind: K, payload: P) {\n return z.object({ kind: z.literal(kind), accountId: accountIdSchema, payload });\n}\nfunction updateOp<K extends MetaDraftOpKind, P extends z.ZodTypeAny>(kind: K, payload: P) {\n return z.object({ kind: z.literal(kind), accountId: accountIdSchema, target: updateTargetSchema, payload });\n}\n/** `confirmBudgetIncrease` is accepted and ignored: only the person's answer approves a large raise (`convex/ads/budgetJump.ts`). */\nfunction budgetUpdateOp<K extends MetaDraftOpKind, P extends z.ZodTypeAny>(kind: K, payload: P) {\n return updateOp(kind, payload).extend({ confirmBudgetIncrease: z.boolean().optional() });\n}\n\nexport const metaDraftOpInputSchema = z.discriminatedUnion(\"kind\", [\n createOp(\"campaign.create\", campaignCreateSchema),\n budgetUpdateOp(\"campaign.update\", campaignUpdateSchema),\n createOp(\"adSet.create\", adSetCreateSchema),\n budgetUpdateOp(\"adSet.update\", adSetUpdateSchema),\n createOp(\"adCreative.create\", adCreativeCreateSchema),\n updateOp(\"adCreative.update\", adCreativeUpdateSchema),\n createOp(\"ad.create\", adCreateSchema),\n updateOp(\"ad.update\", adUpdateSchema),\n createOp(\"customAudience.create\", customAudienceCreateSchema),\n updateOp(\"customAudience.update\", customAudienceUpdateSchema),\n createOp(\"customAudience.members\", customAudienceMembersSchema),\n createOp(\"customConversion.create\", customConversionCreateSchema),\n updateOp(\"customConversion.update\", customConversionUpdateSchema),\n createOp(\"leadForm.create\", leadFormCreateSchema),\n updateOp(\"leadForm.update\", leadFormUpdateSchema),\n createOp(\"media.upload\", mediaUploadSchema),\n createOp(\"media.delete\", mediaDeleteSchema),\n createOp(\"adLabel.create\", adLabelCreateSchema),\n updateOp(\"adLabel.update\", adLabelUpdateSchema),\n createOp(\"adRule.create\", adRuleCreateSchema),\n updateOp(\"adRule.update\", adRuleUpdateSchema),\n createOp(\"adStudy.create\", adStudyCreateSchema),\n updateOp(\"adStudy.update\", adStudyUpdateSchema),\n createOp(\"campaign.copy\", campaignCopySchema),\n createOp(\"adSet.copy\", adSetCopySchema),\n createOp(\"ad.copy\", adCopySchema),\n createOp(\"canvas.create\", canvasCreateSchema),\n updateOp(\"canvas.update\", canvasUpdateSchema),\n createOp(\"productCatalog.create\", productCatalogCreateSchema),\n updateOp(\"productCatalog.update\", productCatalogUpdateSchema),\n createOp(\"product.create\", productCreateSchema),\n updateOp(\"product.update\", productUpdateSchema),\n createOp(\"productSet.create\", productSetCreateSchema),\n updateOp(\"productSet.update\", productSetUpdateSchema),\n createOp(\"productFeed.create\", productFeedCreateSchema),\n updateOp(\"productFeed.update\", productFeedUpdateSchema),\n createOp(\"pagePhoto.create\", pagePhotoCreateSchema),\n updateOp(\"pagePhoto.update\", pagePhotoUpdateSchema),\n updateOp(\"adAccount.update\", adAccountUpdateSchema),\n createOp(\"publisherBlockList.create\", publisherBlockListCreateSchema),\n updateOp(\"publisherBlockList.update\", publisherBlockListUpdateSchema),\n createOp(\"reachFrequencyReservation.create\", reachFrequencyReservationCreateSchema),\n updateOp(\"reachFrequencyReservation.update\", reachFrequencyReservationUpdateSchema),\n]);\nexport type MetaDraftOpInput = z.infer<typeof metaDraftOpInputSchema>;\n\nexport function isCreateKind(kind: MetaDraftOpKind): boolean {\n return kind.endsWith(\".create\") || kind === \"media.upload\";\n}\n\n/**\n * A copy through Meta's `copies` edge: it makes a new node, like a create, but\n * its payload is the copy's options rather than the node's fields — so it is\n * never amended, and a change to the copy stages as an update of its ref.\n */\nexport function isCopyKind(kind: MetaDraftOpKind): kind is \"campaign.copy\" | \"adSet.copy\" | \"ad.copy\" {\n return kind.endsWith(\".copy\");\n}\n\nexport type MetaDraftEntity =\n | \"campaign\"\n | \"adSet\"\n | \"adCreative\"\n | \"ad\"\n | \"customAudience\"\n | \"customConversion\"\n | \"leadForm\"\n | \"media\"\n | \"adRule\"\n | \"adStudy\"\n | \"adLabel\"\n | \"canvas\"\n | \"productCatalog\"\n | \"product\"\n | \"productSet\"\n | \"productFeed\"\n | \"pagePhoto\"\n | \"adAccount\"\n | \"publisherBlockList\"\n | \"reachFrequencyReservation\";\n\nexport function entityOfKind(kind: MetaDraftOpKind): MetaDraftEntity {\n return kind.split(\".\")[0] as MetaDraftEntity;\n}\n\n/** A `meta_temp_*` ref an op consumes. A media ref also says whether it must be a picture or a video upload. */\ntype TempRefDep = { ref: string; entity: MetaDraftEntity; mediaKind?: MetaMediaKind };\ntype AddDep = (value: string | undefined, entity: MetaDraftEntity, mediaKind?: MetaMediaKind) => void;\n\nfunction collectCreativeMediaRefs(payload: MetaCreativeContent, add: AddDep): void {\n const addImageVideo = (m: { imageRef?: string; videoRef?: string; thumbnailRef?: string }): void => {\n add(m.imageRef, \"media\", \"image\");\n add(m.videoRef, \"media\", \"video\");\n add(m.thumbnailRef, \"media\", \"image\");\n };\n switch (payload.creativeType) {\n case \"single\":\n addImageVideo(payload);\n break;\n case \"carousel\":\n for (const card of payload.cards) {\n addImageVideo(card);\n }\n break;\n case \"placement\":\n for (const asset of payload.assets) {\n addImageVideo(asset);\n }\n break;\n case \"instant_experience\":\n addImageVideo(payload);\n break;\n case \"dynamic\":\n for (const img of payload.images ?? []) {\n add(img.imageRef, \"media\", \"image\");\n }\n for (const vid of payload.videos ?? []) {\n add(vid.videoRef, \"media\", \"video\");\n add(vid.thumbnailRef, \"media\", \"image\");\n }\n break;\n default:\n break;\n }\n}\n\nexport function creativeFormIds(payload: MetaCreativeContent): string[] {\n if (\n payload.creativeType === \"existing_post\" ||\n payload.creativeType === \"spec\" ||\n payload.creativeType === \"catalog\" ||\n payload.creativeType === \"instant_experience\"\n ) {\n return [];\n }\n const ids = [payload.call_to_action?.lead_gen_form_id];\n if (payload.creativeType === \"carousel\") {\n ids.push(...payload.cards.map((card) => card.call_to_action?.lead_gen_form_id));\n }\n return ids.filter((id): id is string => id !== undefined);\n}\n\nfunction collectCreativeFormRefs(payload: MetaCreativeContent, add: AddDep): void {\n for (const id of creativeFormIds(payload)) add(id, \"leadForm\");\n}\n\nfunction collectTargetingAudienceRefs(targeting: MetaTargeting | undefined, add: AddDep): void {\n if (!targeting) {\n return;\n }\n for (const a of targeting.custom_audiences ?? []) {\n add(a.id, \"customAudience\");\n }\n for (const a of targeting.excluded_custom_audiences ?? []) {\n add(a.id, \"customAudience\");\n }\n for (const list of targeting.excluded_publisher_list_ids ?? []) {\n add(list, \"publisherBlockList\");\n }\n}\n\n/** The Instant Experience an ad opens — one this chat creates is made first. */\nfunction collectCreativeCanvasRef(payload: MetaCreativeContent, add: AddDep): void {\n if (payload.creativeType === \"instant_experience\") {\n add(payload.canvas_id, \"canvas\");\n }\n}\n\n/** An experience's video can be a library video this chat uploads, its photos and product sets ones it creates. */\nfunction collectCanvasMediaRefs(payload: CanvasCreate, add: AddDep): void {\n for (const element of payload.elements) {\n if (element.type === \"video\") add(element.videoRef, \"media\", \"video\");\n if (element.type === \"photo\") add(element.photo_id, \"pagePhoto\");\n if (element.type === \"product_set\") add(element.product_set_id, \"productSet\");\n }\n}\n\n/** The product sets an ad set retargets on and promotes — ones this chat creates are made first. */\nfunction collectAdSetCatalogRefs(payload: AdSetCreate | AdSetUpdate, add: AddDep): void {\n add(payload.promoted_object?.product_set_id, \"productSet\");\n add(payload.promoted_object?.product_catalog_id, \"productCatalog\");\n const targeting = payload.targeting;\n for (const spec of [\n ...(targeting?.product_audience_specs ?? []),\n ...(targeting?.excluded_product_audience_specs ?? []),\n ]) {\n add(spec.product_set_id, \"productSet\");\n }\n}\n\n/** Temp refs an op consumes, keyed by the entity kind each ref must resolve to. */\nexport function collectTempRefDeps(op: MetaDraftOpInput): TempRefDep[] {\n const deps: TempRefDep[] = [];\n const add: AddDep = (value, entity, mediaKind) => {\n if (value && TEMP_REF_REGEX.test(value)) {\n deps.push(mediaKind ? { ref: value, entity, mediaKind } : { ref: value, entity });\n }\n };\n for (const id of payloadLabelIds(op.payload)) {\n add(id, \"adLabel\");\n }\n switch (op.kind) {\n case \"campaign.create\":\n add(op.payload.promoted_object?.product_catalog_id, \"productCatalog\");\n break;\n case \"adSet.create\":\n add(op.payload.campaign_id, \"campaign\");\n add(op.payload.rf_prediction_id, \"reachFrequencyReservation\");\n add(op.payload.promoted_object?.custom_conversion_id, \"customConversion\");\n collectTargetingAudienceRefs(op.payload.targeting, add);\n collectAdSetCatalogRefs(op.payload, add);\n break;\n case \"adSet.update\":\n add(op.payload.promoted_object?.custom_conversion_id, \"customConversion\");\n collectTargetingAudienceRefs(op.payload.targeting, add);\n collectAdSetCatalogRefs(op.payload, add);\n break;\n case \"adCreative.create\":\n collectCreativeMediaRefs(op.payload, add);\n collectCreativeFormRefs(op.payload, add);\n collectCreativeCanvasRef(op.payload, add);\n if (op.payload.creativeType === \"catalog\") add(op.payload.product_set_id, \"productSet\");\n break;\n // A product, set or feed goes into a catalog this chat creates once it exists.\n case \"product.create\":\n case \"productSet.create\":\n case \"productFeed.create\":\n add(op.payload.catalog_id, \"productCatalog\");\n break;\n case \"canvas.create\":\n collectCanvasMediaRefs(op.payload, add);\n break;\n case \"ad.create\":\n add(op.payload.adset_id, \"adSet\");\n add(op.payload.creative.creative_id, \"adCreative\");\n break;\n // Swapping the creative is how an ad's content is edited at all — the\n // creative is staged first and the ad repointed at its ref. Without the\n // dependency the two publish in staging order rather than in the order they\n // need, and a creative that fails does not take its repoint with it.\n case \"ad.update\":\n add(op.payload.creative?.creative_id, \"adCreative\");\n break;\n case \"customAudience.create\":\n for (const o of op.payload.lookalike_spec?.origin ?? []) {\n add(o.id, \"customAudience\");\n }\n break;\n // People join a list this chat creates once it exists.\n case \"customAudience.members\":\n add(op.payload.audience_id, \"customAudience\");\n break;\n // A rule watching an ad this draft creates must be created after it, and\n // skipped if the ad never lands — Meta refuses a rule naming an unknown id.\n case \"adRule.create\":\n case \"adRule.update\":\n for (const dep of adRuleTempRefs(op.payload.evaluation_spec)) {\n add(dep.ref, dep.entity);\n }\n break;\n // A test over ad sets this draft creates is created after them, and skipped\n // if one never lands — Meta refuses a version naming an unknown id.\n case \"adStudy.create\":\n for (const dep of adStudyTempRefs(op.payload.cells)) {\n add(dep.ref, dep.entity);\n }\n break;\n // A copy into a campaign or ad set this draft creates (or copies) waits for it.\n case \"adSet.copy\":\n add(op.payload.campaign_id, \"campaign\");\n break;\n case \"ad.copy\":\n add(op.payload.adset_id, \"adSet\");\n break;\n default:\n break;\n }\n return deps;\n}\n\n// --- Stage-time warnings (non-blocking; shared by CLI preflight and backend) ---\n\nfunction campaignCreateWarnings(p: CampaignCreate): string[] {\n const warnings: string[] = [];\n if (!p.special_ad_categories.includes(\"NONE\") && p.special_ad_categories.length > 0) {\n warnings.push(\n `special ad category ${p.special_ad_categories.join(\", \")} — Meta restricts age, gender, ZIP, and some interest targeting on these ads`,\n );\n }\n if (p.start_time && p.start_time < Date.now()) {\n warnings.push(\"start_time is in the past — Meta will start delivery immediately on publish\");\n }\n // Asked for, and not applied: sharing is a property of ad-set budgets, so a\n // campaign that holds the budget takes no answer for it. Silence here would\n // leave the agent believing it had set a spend behaviour it had not.\n if (p.adSetBudgetSharing !== undefined && (p.dailyBudget || p.lifetimeBudget)) {\n warnings.push(\n \"adSetBudgetSharing is ignored on a campaign that carries its own budget (CBO) — move the budget to the ad sets for it to apply\",\n );\n }\n return warnings;\n}\n\n/**\n * What Meta publishes about the placements this ad set pins. Every line is a\n * documented spec, never an inferred delivery mechanism: Meta does not document\n * what it renders for a creative a placement cannot take, so the agent is sent\n * to `preview` and the account's own play rate instead of being handed a story.\n */\nfunction placementWarnings(t: MetaTargeting | undefined): string[] {\n const warnings: string[] = constrainedPlacementsIn(t).map((placement) => `${placement.position}: ${placement.note}`);\n for (const issue of invalidPlacementValues(t)) {\n if (issue.kind === \"unknown\") {\n warnings.push(\n `Baker does not recognise \"${issue.value}\" in ${issue.field} — it is not on Meta's published placement list, so it was left as written; Meta refuses it at publish if it is a typo`,\n );\n }\n }\n if (rightColumnIsSolePlacement(t)) {\n warnings.push(\n \"right_hand_column is this ad set's only placement — Meta refuses it alone for video, collection, and canvas ads, so pair it with feed if this ad set runs anything but a single image\",\n );\n }\n return warnings;\n}\n\nfunction adSetCreateWarnings(p: AdSetCreate): string[] {\n const warnings: string[] = placementWarnings(p.targeting);\n const t = p.targeting;\n // A geo-less ad set is a hard error unless it has a custom audience; here it\n // passed validation via an audience, so it's valid but unbounded by place.\n // Shares targetingHasGeo with the hard-error check so the two can't drift.\n if (!targetingHasGeo(t) && t.custom_audiences?.length) {\n warnings.push(\n \"no geo targeting — delivery is bounded only by your custom audience; add geo_locations to control where ads run\",\n );\n }\n if (targetingHardLimitsDemographics(t) && advantageAudienceSetting(t) === undefined) {\n warnings.push(\n \"age or gender is a hard limit, so Advantage+ Audience was turned off to honor it — set targeting.targeting_automation.advantage_audience to 1 if you'd rather let Meta expand beyond your age/gender selection\",\n );\n }\n return warnings;\n}\n\n/**\n * An ad-set update reaches a LIVE ad set, so a placement edit here is not the\n * same act as choosing placements at create time. Meta's published list of\n * significant edits — the ones that re-enter the learning phase — names \"any\n * change to targeting\", and placements live inside the targeting spec, so\n * expect a reset. Meta does not name placements explicitly, so this says\n * \"expect\", not \"will\".\n *\n * The second half is the one that was actually missing: the incident that\n * prompted this warning removed placements carrying 0.3% of delivery from four\n * ad sets that had finished learning, on a mechanism nobody had checked. Cheap\n * to state the share first; expensive to restart learning for nothing.\n */\nfunction adSetUpdateWarnings(p: AdSetUpdate): string[] {\n const warnings: string[] = placementWarnings(p.targeting);\n if (setsExplicitPlacements(p.targeting)) {\n warnings.push(\n \"this edits placements on a live ad set — placements sit inside targeting, and Meta counts a targeting change as a significant edit, so expect the ad set to re-enter the learning phase. Before publishing, state the share of delivery the placements you are removing actually carry (`insights --breakdowns publisher_platform,platform_position`) and verify any 'this placement can't show my video' claim with `preview --placement <position>` — do not remove a placement on a remembered rule\",\n );\n }\n return warnings;\n}\n\nfunction messageWarnings(message: string): string[] {\n const warnings: string[] = [];\n if (message.length > META_LIMITS.creative.messageSoftMax) {\n warnings.push(\n `primary text is ${message.length} chars — the feed truncates after ${META_LIMITS.creative.messageSoftMax} with \"… See more\"; front-load the hook`,\n );\n }\n if (message.trim().length < META_LIMITS.creative.messageGoodMin) {\n warnings.push(\n `primary text is only ${message.trim().length} chars — a stronger ad opens with a hook, the value, and a reason to act`,\n );\n }\n return warnings;\n}\n\n/**\n * A single picture or video runs everywhere; Meta cuts it to each placement\n * (live crops: `mediaSpecs.ts`). The fix is Meta's placement asset\n * customization — `creativeType: placement` — not a dynamic creative.\n */\nexport const SINGLE_ASSET_PLACEMENT_NOTE =\n \"one picture or video serves every placement and Meta cuts it to fit each — to give Stories & Reels a 9:16 and feeds a 4:5 in one ad, use creativeType placement with an asset per placement\";\n\n/**\n * Where Meta cuts text off (Ads Guide, 2026-10-14). Refusals are Meta's hard\n * limits in the schema; these are the points where text stops being read.\n */\nconst TEXT_VISIBLE = {\n single: { headline: 27, headlineWhere: \"the Facebook feed shows about 27\", description: 27 },\n carousel: { headline: 32, headlineWhere: \"a carousel card shows about 32\", description: 18 },\n} as const;\n\nfunction textLengthWarnings(\n text: { headline?: string; description?: string },\n shape: keyof typeof TEXT_VISIBLE,\n where = \"\",\n): string[] {\n const limits = TEXT_VISIBLE[shape];\n const warnings: string[] = [];\n if (text.headline && text.headline.length > limits.headline) {\n warnings.push(\n `${where}headline is ${text.headline.length} characters — ${limits.headlineWhere} before cutting it off (Instagram and Stories about 40); put the point first`,\n );\n }\n if (text.description && text.description.length > limits.description) {\n warnings.push(\n `${where}description is ${text.description.length} characters — about ${limits.description} show before it is cut off`,\n );\n }\n return warnings;\n}\n\nfunction singleCreativeWarnings(p: Extract<AdCreativeCreate, { creativeType: \"single\" }>): string[] {\n const warnings: string[] = [];\n if (!p.headline) {\n warnings.push(\"no headline — the bold line under the media is the ad's second-strongest read; add one\");\n }\n if (!p.description) {\n warnings.push(\"no link description — the grey line under the headline reinforces the offer; add one\");\n }\n if (!p.call_to_action) {\n warnings.push(\"no call-to-action button — pick a CTA (e.g. SIGN_UP, SHOP_NOW) so people know the next step\");\n }\n warnings.push(...textLengthWarnings({ headline: p.headline, description: p.description }, \"single\"));\n warnings.push(SINGLE_ASSET_PLACEMENT_NOTE);\n return warnings;\n}\n\nfunction carouselCreativeWarnings(p: Extract<AdCreativeCreate, { creativeType: \"carousel\" }>): string[] {\n const warnings: string[] = [];\n if (p.cards.length < META_LIMITS.creative.carouselCardsGoodMin) {\n warnings.push(\n `only ${p.cards.length} carousel cards — ${META_LIMITS.creative.carouselCardsGoodMin}+ gives Meta more to optimize and tells a fuller story`,\n );\n }\n if (p.cards.some((card) => !card.headline)) {\n warnings.push(\"some carousel cards have no headline — each card reads best with its own headline\");\n }\n if (!p.call_to_action && p.cards.some((card) => !card.call_to_action)) {\n warnings.push(\"cards without a call-to-action fall back to none — set a card CTA or a creative-level CTA\");\n }\n p.cards.forEach((card, index) => {\n warnings.push(...textLengthWarnings(card, \"carousel\", `card ${index + 1} `));\n });\n if (p.card_order === \"optimized\") {\n warnings.push(\n \"card_order optimized: Meta reorders the cards by performance and may show only the top 5 — keep fixed for a story told in order\",\n );\n }\n return warnings;\n}\n\nfunction dynamicCreativeWarnings(p: Extract<AdCreativeCreate, { creativeType: \"dynamic\" }>): string[] {\n const warnings: string[] = [];\n const assets = (p.images?.length ?? 0) + (p.videos?.length ?? 0);\n if (assets < META_LIMITS.creative.dynamicAssetsGoodMin) {\n warnings.push(\n `only ${assets} media asset(s) — dynamic ads work best with ${META_LIMITS.creative.dynamicAssetsGoodMin}+ so Meta can mix and match`,\n );\n }\n if (!p.call_to_action_types?.length) {\n warnings.push(\"no call_to_action_types — dynamic ads should offer at least one CTA\");\n }\n p.bodies.forEach((body, index) => {\n if (body.text.length > META_LIMITS.creative.messageSoftMax) {\n warnings.push(\n `body ${index + 1} is ${body.text.length} characters — the feed cuts it after ${META_LIMITS.creative.messageSoftMax} with \"… See more\"; front-load the hook`,\n );\n }\n });\n p.titles.forEach((title, index) => {\n warnings.push(...textLengthWarnings({ headline: title.text }, \"single\", `title ${index + 1} `));\n });\n // Meta mixes a dynamic creative's assets freely — a 9:16 can land in Feed,\n // cut down — and refuses customization rules in a Dynamic Creative ad set.\n warnings.push(\n p.asset_customization_rules?.length\n ? \"asset_customization_rules on a dynamic creative: Meta refuses them in a Dynamic Creative ad set — for a different picture per placement use creativeType placement\"\n : \"Meta mixes these assets across every placement, so a 9:16 can run cut down in Feed — to give Stories & Reels their own 9:16 and Feed its 4:5, use creativeType placement\",\n );\n return warnings;\n}\n\n/**\n * Best-practice nudges that make a *valid* creative a *good* one. These are\n * advisory (non-blocking) — a strong feed ad carries primary text, a headline,\n * a link description, a clear CTA, and an Instagram identity so it runs on IG.\n */\nfunction creativeCreateWarnings(p: AdCreativeCreate): string[] {\n // A `spec` creative is a live creative copied verbatim. Every nudge below\n // asks \"did you compose this well?\", and the answer was settled when the ad\n // was built — telling the agent its clone has no Instagram identity when the\n // original does not either is noise on a change that adds nothing but tags.\n if (p.creativeType === \"spec\") {\n return [];\n }\n const warnings: string[] = [];\n if (\n p.creativeType === \"single\" ||\n p.creativeType === \"carousel\" ||\n p.creativeType === \"placement\" ||\n p.creativeType === \"instant_experience\"\n ) {\n warnings.push(...messageWarnings(p.message));\n }\n if (p.creativeType === \"instant_experience\" && p.format === \"collection\") {\n warnings.push(\n \"a collection ad shows the experience's products or photos under the ad — Meta builds it only from an experience with a product set shown in feed, or four photos\",\n );\n }\n if (p.creativeType === \"placement\") {\n warnings.push(...textLengthWarnings({ headline: p.headline, description: p.description }, \"single\"));\n }\n if (p.creativeType === \"single\") {\n warnings.push(...singleCreativeWarnings(p));\n }\n if (p.creativeType === \"carousel\") {\n warnings.push(...carouselCreativeWarnings(p));\n }\n if (p.creativeType === \"dynamic\") {\n warnings.push(...dynamicCreativeWarnings(p));\n }\n if (p.creativeType !== \"existing_post\" && !p.instagram_user_id) {\n warnings.push(\n \"no Instagram identity — without instagram_user_id the ad can't run on Instagram feeds, Reels, or Stories\",\n );\n }\n const visual = visualEnhancementsOn(\"enhancements\" in p ? p.enhancements : undefined);\n if (visual.length > 0) {\n warnings.push(\n `Meta may change the media itself: ${visual.join(\", \")} — switch these on only because the user asked for them by name`,\n );\n }\n return warnings;\n}\n\nexport function collectOpWarnings(op: MetaDraftOpInput): string[] {\n switch (op.kind) {\n case \"campaign.create\":\n return campaignCreateWarnings(op.payload);\n case \"adSet.create\":\n return adSetCreateWarnings(op.payload);\n case \"adSet.update\":\n return adSetUpdateWarnings(op.payload);\n case \"adCreative.create\":\n return creativeCreateWarnings(op.payload);\n case \"customAudience.create\":\n return customerListWarnings(op.payload);\n case \"adStudy.create\":\n return adStudyWarnings(op.payload, Math.floor(Date.now() / 1000));\n case \"campaign.copy\":\n case \"adSet.copy\":\n case \"ad.copy\":\n return copyWarnings(op.payload);\n case \"customAudience.update\":\n return op.payload.status === \"DELETED\"\n ? [\n \"deleting an audience is permanent — every ad that targets it stops and cannot be restarted, and Meta refuses it while a lookalike is built from it (delete the lookalike first)\",\n ]\n : [];\n case \"customAudience.members\":\n return op.payload.action === \"replace\"\n ? [\n \"replace swaps the whole list: everyone not in this file leaves the audience. Meta refuses it while the list is still updating from an earlier change, and it takes up to 24 hours to show\",\n ]\n : [\"Meta takes up to 24 hours to match the people and update the audience's size\"];\n default:\n return [];\n }\n}\n\n/**\n * A customer list publishes whatever its size, but Meta matches only part of it and marks a small\n * audience \"too small\" to deliver to (`delivery_status` 300); a lookalike needs 100 people in one\n * country. Said at stage time, while there is still time to add people.\n */\nfunction customerListWarnings(p: CustomAudienceCreate): string[] {\n const people = p.members?.length ?? 0;\n if (people === 0 || people >= META_LIMITS.audience.minLookalikeSourceRows) {\n return [];\n }\n return [\n `this customer list has ${people} ${people === 1 ? \"person\" : \"people\"} — Meta matches only some of them and will not deliver to an audience that small, nor build a lookalike from fewer than ${META_LIMITS.audience.minLookalikeSourceRows}; it still publishes`,\n ];\n}\n","/**\n * Meta automated rules (`/act_<id>/adrules_library`) — the staged contract.\n *\n * A rule is Meta's own automation: Meta evaluates it on its schedule (or the\n * moment a metric changes) and acts on live ads with no Baker involvement. So a\n * rule is staged like every other Meta write and created only at Publish.\n *\n * The payload keeps Meta's own shape — `evaluation_spec`, `execution_spec`,\n * `schedule_spec` with `{field, operator, value}` filters — so a rule read with\n * `baker ads meta rules` can be edited and staged back as it reads. The one\n * difference is money: Meta compares cost and budget values in the account's\n * minor units (1000 = $10.00); the payload carries major units beside a\n * `currencyCode`, like every other Baker money field, and the backend converts\n * on the way out.\n *\n * Every refusal below is Meta's documented rule\n * (developers.facebook.com/documentation/ads-commerce/marketing-api/ad-rules)\n * or one Meta answered live on v25.0 (marked \"live\").\n */\nimport { z } from \"zod\";\n\n// --- Vocabularies ---\n\nexport const AD_RULE_EVALUATION_TYPES = [\"SCHEDULE\", \"TRIGGER\"] as const;\nexport type AdRuleEvaluationType = (typeof AD_RULE_EVALUATION_TYPES)[number];\n\nexport const AD_RULE_OPERATORS = [\n \"GREATER_THAN\",\n \"LESS_THAN\",\n \"EQUAL\",\n \"NOT_EQUAL\",\n \"IN_RANGE\",\n \"NOT_IN_RANGE\",\n \"IN\",\n \"NOT_IN\",\n \"CONTAIN\",\n \"NOT_CONTAIN\",\n \"ANY\",\n \"ALL\",\n \"NONE\",\n] as const;\nexport type AdRuleOperator = (typeof AD_RULE_OPERATORS)[number];\n\nexport const AD_RULE_TRIGGER_TYPES = [\n \"METADATA_CREATION\",\n \"METADATA_UPDATE\",\n \"STATS_MILESTONE\",\n \"STATS_CHANGE\",\n \"DELIVERY_INSIGHTS_CHANGE\",\n] as const;\n\n/**\n * What a rule can do. Meta's reference enum lists more (DCO,\n * ADD_INTEREST_RELAXATION, AUDIENCE_CONSOLIDATION, …) that no guide documents\n * a spec for; they are left out rather than staged blind. `PING_ENDPOINT` is\n * left out on purpose: it calls the webhook of the Meta app that made the rule —\n * Baker's — which nothing listens to, so the rule would fire into nothing.\n */\nexport const AD_RULE_EXECUTION_TYPES = [\n \"PAUSE\",\n \"UNPAUSE\",\n \"NOTIFICATION\",\n \"CHANGE_BUDGET\",\n \"CHANGE_CAMPAIGN_BUDGET\",\n \"CHANGE_BID\",\n \"ROTATE\",\n \"REBALANCE_BUDGET\",\n] as const;\nexport type AdRuleExecutionType = (typeof AD_RULE_EXECUTION_TYPES)[number];\n\n/** Live (subcode 1815577): \"For the evaluation_type TRIGGER, the execution_type must be … PAUSE or UNPAUSE or NOTIFICATION.\" */\nconst TRIGGER_EXECUTION_TYPES: ReadonlySet<string> = new Set([\"PAUSE\", \"UNPAUSE\", \"NOTIFICATION\"]);\n\nexport const AD_RULE_SCHEDULE_TYPES = [\"DAILY\", \"HOURLY\", \"SEMI_HOURLY\", \"CUSTOM\"] as const;\nexport const AD_RULE_CREATE_STATUSES = [\"ENABLED\", \"DISABLED\"] as const;\nexport const AD_RULE_UPDATE_STATUSES = [\"ENABLED\", \"DISABLED\", \"DELETED\"] as const;\nexport const AD_RULE_ENTITY_TYPES = [\"AD\", \"ADSET\", \"CAMPAIGN\"] as const;\nexport type AdRuleEntityType = (typeof AD_RULE_ENTITY_TYPES)[number];\n\n/** Presets that include today — the only ones a trigger rule takes, since it evaluates in real time. */\nconst TIME_PRESETS_WITH_TODAY = [\n \"LIFETIME\",\n \"TODAY\",\n \"LAST_2_DAYS\",\n \"LAST_3_DAYS\",\n \"LAST_7_DAYS\",\n \"LAST_14_DAYS\",\n \"LAST_28_DAYS\",\n \"LAST_30_DAYS\",\n \"THIS_MONTH\",\n \"THIS_WEEK_MON_TODAY\",\n \"THIS_WEEK_SUN_TODAY\",\n] as const;\n\nexport const AD_RULE_TIME_PRESETS = [\n ...TIME_PRESETS_WITH_TODAY,\n \"YESTERDAY\",\n \"LAST_2D\",\n \"LAST_3D\",\n \"LAST_7D\",\n \"LAST_14D\",\n \"LAST_28D\",\n \"LAST_30D\",\n \"LAST_ND_14_8\",\n \"LAST_ND_30_8\",\n \"LAST_ND_60_8\",\n \"LAST_ND_120_8\",\n \"LAST_ND_180_8\",\n \"LAST_ND_LIFETIME_8\",\n \"LAST_ND_60_29\",\n \"LAST_ND_120_29\",\n \"LAST_ND_180_29\",\n \"LAST_ND_LIFETIME_29\",\n] as const;\nexport type AdRuleTimePreset = (typeof AD_RULE_TIME_PRESETS)[number];\n\n// --- Fields ---\n\n/** Fields that shape the evaluation rather than describe an object. */\nconst SPECIAL_FIELDS = [\"entity_type\", \"time_preset\", \"attribution_window\", \"aggregation_id\"] as const;\n\n/** Metadata filters both rule kinds take. */\nconst METADATA_FIELDS = [\n \"id\",\n \"name\",\n \"adlabel_ids\",\n \"objective\",\n \"start_time\",\n \"stop_time\",\n \"buying_type\",\n \"billing_event\",\n \"optimization_goal\",\n \"is_autobid\",\n \"daily_budget\",\n \"lifetime_budget\",\n \"spend_cap\",\n \"bid_amount\",\n \"created_time\",\n \"updated_time\",\n] as const;\n\n/** Metadata filters only a schedule rule takes. */\nconst SCHEDULE_ONLY_METADATA_FIELDS = [\n \"effective_status\",\n \"placement.page_types\",\n \"budget_reset_period\",\n \"hours_since_creation\",\n \"estimated_budget_spending_percentage\",\n \"audience_reached_percentage\",\n \"active_time\",\n \"current_time\",\n] as const;\n\nconst APP_EVENTS = [\n \"achievement_unlocked\",\n \"activate_app\",\n \"add_payment_info\",\n \"add_to_cart\",\n \"add_to_wishlist\",\n \"complete_registration\",\n \"content_view\",\n \"initiated_checkout\",\n \"level_achieved\",\n \"purchase\",\n \"rate\",\n \"search\",\n \"spent_credits\",\n \"tutorial_completion\",\n] as const;\nconst OFFLINE_EVENTS = [\n \"add_payment_info\",\n \"add_to_cart\",\n \"add_to_wishlist\",\n \"complete_registration\",\n \"initiate_checkout\",\n \"lead\",\n \"other\",\n \"purchase\",\n \"search\",\n \"view_content\",\n] as const;\nconst PIXEL_EVENTS = [\n \"add_payment_info\",\n \"add_to_cart\",\n \"add_to_wishlist\",\n \"complete_registration\",\n \"initiate_checkout\",\n \"lead\",\n \"purchase\",\n \"search\",\n \"view_content\",\n \"other\",\n] as const;\nconst PIXEL_COST_EVENTS = [\n \"add_payment_info\",\n \"add_to_cart\",\n \"add_to_wishlist\",\n \"complete_registration\",\n \"initiate_checkout\",\n \"lead\",\n \"purchase\",\n \"search\",\n \"view_content\",\n] as const;\n\n/** Insights filters a trigger rule refuses (the evaluation-spec table's \"No\" rows). */\nconst SCHEDULE_ONLY_INSIGHTS_FIELDS = [\n \"mobile_app_purchase_roas\",\n \"website_purchase_roas\",\n \"offline_conversion\",\n ...OFFLINE_EVENTS.map((event) => `offline_conversion.${event}`),\n \"cost_per_offline_conversion\",\n \"cost_per_offline_other\",\n \"cost_per_post_engagement\",\n \"lifetime_impressions\",\n \"lifetime_spent\",\n \"today_spent\",\n \"yesterday_spent\",\n // The same page lists both as \"Yes\" higher up and \"No\" in its last rows; the\n // stricter reading is kept, since a refused real-time rule fails at publish.\n \"unique_clicks\",\n \"reach\",\n];\n\n/** Every Insights filter Meta documents for rules. */\nconst INSIGHTS_FIELDS: ReadonlySet<string> = new Set([\n ...SCHEDULE_ONLY_INSIGHTS_FIELDS,\n \"impressions\",\n \"unique_impressions\",\n \"clicks\",\n \"unique_clicks\",\n \"spent\",\n \"results\",\n \"cost_per\",\n \"cpc\",\n \"cpm\",\n \"ctr\",\n \"cpa\",\n \"cpp\",\n \"reach\",\n \"frequency\",\n \"leadgen\",\n \"link_ctr\",\n \"cost_per_unique_click\",\n \"result_rate\",\n \"mobile_app_install\",\n \"cost_per_mobile_app_install\",\n \"app_custom_event\",\n ...APP_EVENTS.map((event) => `app_custom_event.fb_mobile_${event}`),\n \"app_custom_event.other\",\n ...APP_EVENTS.map((event) => `cost_per_mobile_${event}`),\n \"offsite_conversion\",\n ...PIXEL_EVENTS.map((event) => `offsite_conversion.fb_pixel_${event}`),\n ...PIXEL_COST_EVENTS.map((event) => `cost_per_${event}_fb`),\n \"link_click\",\n \"cost_per_link_click\",\n \"like\",\n \"offsite_engagement\",\n \"post\",\n \"post_comment\",\n \"post_engagement\",\n \"post_like\",\n \"post_reaction\",\n \"view_content\",\n \"video_play\",\n \"video_view\",\n \"vote\",\n]);\n\n/** Advanced aliases — schedule rules only. */\nconst ADVANCED_FIELDS: ReadonlySet<string> = new Set([\"daily_ratio_spent\", \"lifetime_ratio_spent\"]);\n\nconst OBJECT_PREFIXES = [\"ad\", \"adset\", \"campaign\"] as const;\n\n/** Attribution-window prefixes (`7d_click:spent`), and the values of the `attribution_window` filter they mirror. */\nconst ATTRIBUTION_PREFIXES = [\n \"account_default\",\n \"default\",\n \"inline\",\n \"1d_view\",\n \"7d_view\",\n \"28d_view\",\n \"1d_click\",\n \"7d_click\",\n \"28d_click\",\n \"1d_view_1d_click\",\n \"7d_view_1d_click\",\n \"28d_view_1d_click\",\n \"1d_view_7d_click\",\n \"7d_view_7d_click\",\n \"28d_view_7d_click\",\n \"7d_view_28d_click\",\n \"28d_view_28d_click\",\n] as const;\n/**\n * The one attribution window Meta still takes in a rule. Live on v25.0\n * (2026-10-14) every other one was refused at create with \"(#11) This\n * attribution window has been deprecated\" — as an `attribution_window` filter\n * (7D_CLICK, 28D_CLICK, 1D_VIEW, 1D_VIEW_7D_CLICK, DEFAULT, INLINE) and as a\n * field prefix (`7d_click:`, `default:`). The rest stay in\n * `ATTRIBUTION_PREFIXES` so a rule read back carrying one still parses.\n */\nconst LIVE_ATTRIBUTION_PREFIX = \"account_default\";\nexport const AD_RULE_ATTRIBUTION_WINDOWS = [LIVE_ATTRIBUTION_PREFIX.toUpperCase()];\n\nconst RETIRED_ATTRIBUTION =\n 'Meta retired every attribution window in rules but the account\\'s own (#11 \"This attribution window has been deprecated\") — leave the window out, or use ACCOUNT_DEFAULT (account_default:)';\n\n/** A field prefixed with an attribution window Meta has retired (`7d_click:cost_per`). */\nfunction retiredAttributionPrefix(field: string): boolean {\n const colon = field.indexOf(\":\");\n const prefix = colon > 0 ? field.slice(0, colon) : undefined;\n return (\n prefix !== undefined &&\n prefix !== LIVE_ATTRIBUTION_PREFIX &&\n (ATTRIBUTION_PREFIXES as readonly string[]).includes(prefix)\n );\n}\n\n/** Time-preset prefixes (`yesterday_spent`), longest first so `last_7d_` never reads as `last_7_days_`'s cousin. */\nconst TIME_PREFIXES = AD_RULE_TIME_PRESETS.map((preset) => `${preset.toLowerCase()}_`).sort(\n (a, b) => b.length - a.length,\n);\n\nconst KNOWN_PLAIN_FIELDS: ReadonlySet<string> = new Set([\n ...SPECIAL_FIELDS,\n ...METADATA_FIELDS,\n ...SCHEDULE_ONLY_METADATA_FIELDS,\n ...INSIGHTS_FIELDS,\n ...ADVANCED_FIELDS,\n]);\n\nexport type AdRuleFieldKind = \"special\" | \"metadata\" | \"insights\" | \"advanced\" | \"aggregate\" | \"formula\";\n\nexport interface ParsedAdRuleField {\n kind: AdRuleFieldKind;\n /** The field with every prefix taken off — `spent` for `adset.7d_click:yesterday_spent`. */\n base: string;\n /** `ad` / `adset` / `campaign` when the filter reads a parent's value. */\n object?: (typeof OBJECT_PREFIXES)[number];\n}\n\nfunction plainKind(field: string): AdRuleFieldKind | undefined {\n if ((SPECIAL_FIELDS as readonly string[]).includes(field)) return \"special\";\n if (INSIGHTS_FIELDS.has(field)) return \"insights\";\n if (ADVANCED_FIELDS.has(field)) return \"advanced\";\n if (KNOWN_PLAIN_FIELDS.has(field)) return \"metadata\";\n return undefined;\n}\n\n/** An Insights field behind attribution and time prefixes (`7d_click:last_7d_spent`). */\nfunction insightsBase(field: string): string | undefined {\n let rest = field;\n const colon = rest.indexOf(\":\");\n if (colon > 0) {\n if (!(ATTRIBUTION_PREFIXES as readonly string[]).includes(rest.slice(0, colon))) return undefined;\n rest = rest.slice(colon + 1);\n }\n if (INSIGHTS_FIELDS.has(rest)) return rest;\n const prefix = TIME_PREFIXES.find((candidate) => rest.startsWith(candidate));\n const base = prefix ? rest.slice(prefix.length) : undefined;\n return base && INSIGHTS_FIELDS.has(base) ? base : undefined;\n}\n\nfunction singleField(field: string): ParsedAdRuleField | undefined {\n const kind = plainKind(field);\n if (kind) return { kind, base: field };\n const aggregate = /^aggregate\\((.+)\\)$/.exec(field);\n if (aggregate?.[1]) {\n const base = insightsBase(aggregate[1]);\n return base ? { kind: \"aggregate\", base } : undefined;\n }\n const dot = field.indexOf(\".\");\n const object = dot > 0 ? OBJECT_PREFIXES.find((prefix) => prefix === field.slice(0, dot)) : undefined;\n const rest = object ? field.slice(dot + 1) : field;\n const restKind = object ? plainKind(rest) : undefined;\n if (object && restKind && restKind !== \"special\") return { kind: restKind, base: rest, object };\n const base = insightsBase(rest);\n return base ? { kind: \"insights\", base, ...(object ? { object } : {}) } : undefined;\n}\n\nconst FORMULA_OPERATORS = new Set([\"+\", \"-\", \"*\", \"/\"]);\nconst MAX_FORMULA_FIELDS = 6;\n\n/** The fields of a formula (`today_spent / adset.daily_budget`), or the reason it is not one Meta takes. */\nfunction formulaTerms(field: string): { fields: string[] } | { refusal: string } {\n const tokens = field.trim().split(/\\s+/);\n const fields: string[] = [];\n for (const [index, token] of tokens.entries()) {\n const isOperator = FORMULA_OPERATORS.has(token);\n if (index % 2 === 1 ? !isOperator : isOperator) {\n return { refusal: `formula \"${field}\" must alternate terms and + - * / operators, each separated by a space` };\n }\n if (!isOperator && !/^-?\\d+(\\.\\d+)?$/.test(token)) fields.push(token);\n }\n if (tokens.length % 2 === 0) return { refusal: `formula \"${field}\" ends with an operator` };\n if (fields.length > MAX_FORMULA_FIELDS) {\n return { refusal: `formula \"${field}\" uses ${fields.length} fields; Meta allows at most ${MAX_FORMULA_FIELDS}` };\n }\n return { fields };\n}\n\nconst FIELD_HELP =\n \"see the field list in `baker schema ads.meta.rules.create` (Insights metrics like cost_per, spent, results, cpm, ctr, frequency, website_purchase_roas; metadata like name, daily_budget, hours_since_creation), optionally prefixed by ad./adset./campaign., the account's attribution window (account_default:) or a time range (yesterday_)\";\n\n/** What a filter field is, or why Meta would answer \"Unrecognized filter field\". */\nexport function parseAdRuleField(field: string): ParsedAdRuleField | { refusal: string } {\n const retired = field\n .split(/[\\s()]+/)\n .map((term) => term.replace(/^(ad|adset|campaign)\\./, \"\"))\n .find(retiredAttributionPrefix);\n if (retired) return { refusal: `\"${field}\": ${RETIRED_ATTRIBUTION}` };\n if (!/\\s/.test(field.trim())) {\n return singleField(field) ?? { refusal: `Meta does not recognise the filter field \"${field}\" — ${FIELD_HELP}` };\n }\n const terms = formulaTerms(field);\n if (\"refusal\" in terms) return terms;\n const unknown = terms.fields.find((term) => {\n const parsed = singleField(term);\n return !parsed || parsed.kind === \"special\";\n });\n if (unknown) {\n return { refusal: `formula \"${field}\": Meta does not recognise the field \"${unknown}\" — ${FIELD_HELP}` };\n }\n return formulaAmountRefusal(field, terms.fields) ?? { kind: \"formula\", base: field };\n}\n\n/**\n * A formula that comes out as an amount (\"spent / results\") is compared in the\n * account's minor units, which Baker converts for a plain field but cannot\n * inside a formula — so only a ratio of two amounts, which has no unit, is\n * taken.\n */\nfunction formulaAmountRefusal(field: string, fields: readonly string[]): { refusal: string } | undefined {\n const amounts = fields.filter((term) => isAdRuleMoneyField(term));\n if (amounts.length === 0) return undefined;\n const ratioOfAmounts = fields.length === 2 && amounts.length === 2 && field.trim().split(/\\s+/)[1] === \"/\";\n return ratioOfAmounts\n ? undefined\n : {\n refusal: `formula \"${field}\" works out to an amount, which Meta compares in the account's minor units and Baker cannot convert inside a formula — use a plain cost field (cost_per, cpa, cpc) or a ratio of two amounts`,\n };\n}\n\nconst COST_BASES = new Set([\"cpa\", \"cpc\", \"cpm\", \"cpp\", \"cost_per\"]);\n\n/** Whether a lower value of this Insights field is the better one: a cost (cpa, cpc, cpm, cost_per_*). */\nexport function isCostField(field: string): boolean {\n const parsed = parseAdRuleField(field);\n return (\n \"kind\" in parsed && parsed.kind !== \"formula\" && (COST_BASES.has(parsed.base) || parsed.base.startsWith(\"cost_per\"))\n );\n}\n\nfunction isInsightsField(field: string): boolean {\n const parsed = parseAdRuleField(field);\n return \"kind\" in parsed && parsed.kind !== \"special\" && parsed.kind !== \"metadata\";\n}\n\n// --- Schemas ---\n\nconst scalarSchema = z.union([z.number(), z.string(), z.boolean()]);\n\nexport const adRuleFilterSchema = z.strictObject({\n field: z.string().min(1),\n operator: z.enum(AD_RULE_OPERATORS),\n value: z.union([scalarSchema, z.array(scalarSchema)]),\n});\nexport type AdRuleFilter = z.infer<typeof adRuleFilterSchema>;\n\nconst triggerSchema = z.strictObject({\n type: z.enum(AD_RULE_TRIGGER_TYPES),\n field: z.string().min(1).optional(),\n operator: z.enum(AD_RULE_OPERATORS).optional(),\n value: z.union([scalarSchema, z.array(scalarSchema)]).optional(),\n});\nexport type AdRuleTrigger = z.infer<typeof triggerSchema>;\n\nexport const adRuleEvaluationSpecSchema = z.strictObject({\n evaluation_type: z.enum(AD_RULE_EVALUATION_TYPES),\n filters: z.array(adRuleFilterSchema).min(1),\n trigger: triggerSchema.optional(),\n});\nexport type AdRuleEvaluationSpec = z.infer<typeof adRuleEvaluationSpecSchema>;\n\nconst executionOptionSchema = z.strictObject({\n field: z.string().min(1),\n operator: z.enum([\"EQUAL\", \"IN\"]).default(\"EQUAL\"),\n value: z.unknown(),\n});\nexport type AdRuleExecutionOption = z.infer<typeof executionOptionSchema>;\n\nexport const adRuleExecutionSpecSchema = z.strictObject({\n execution_type: z.enum(AD_RULE_EXECUTION_TYPES),\n execution_options: z.array(executionOptionSchema).optional(),\n});\nexport type AdRuleExecutionSpec = z.infer<typeof adRuleExecutionSpecSchema>;\n\nconst scheduleItemSchema = z.strictObject({\n start_minute: z.number().int().optional(),\n end_minute: z.number().int().optional(),\n days: z.array(z.number().int()).optional(),\n});\n\nexport const adRuleScheduleSpecSchema = z.strictObject({\n schedule_type: z.enum(AD_RULE_SCHEDULE_TYPES),\n schedule: z.array(scheduleItemSchema).optional(),\n});\nexport type AdRuleScheduleSpec = z.infer<typeof adRuleScheduleSpecSchema>;\n\n/** The parts of a rule a check can read; an update carries any subset. */\nexport interface AdRuleShape {\n evaluation_spec?: AdRuleEvaluationSpec;\n execution_spec?: AdRuleExecutionSpec;\n schedule_spec?: AdRuleScheduleSpec;\n}\n\n// --- Checks ---\n\ntype Issue = { path: (string | number)[]; message: string };\n\nconst COMPARE = [\"GREATER_THAN\", \"LESS_THAN\", \"EQUAL\", \"IN_RANGE\", \"NOT_IN_RANGE\"] as const;\nconst BOUNDED = [\"GREATER_THAN\", \"LESS_THAN\", \"IN_RANGE\", \"NOT_IN_RANGE\"] as const;\nconst LISTED = [\"IN\", \"NOT_IN\"] as const;\nconst TAGGED = [\"ANY\", \"ALL\", \"NONE\"] as const;\n\n/** The operators each metadata filter takes (evaluation spec, \"Metadata filters\"). */\nconst METADATA_OPERATORS: Readonly<Record<string, readonly AdRuleOperator[]>> = {\n id: [\"EQUAL\", \"IN\", \"NOT_IN\"],\n name: [\"EQUAL\", \"CONTAIN\", \"NOT_CONTAIN\"],\n adlabel_ids: TAGGED,\n objective: LISTED,\n buying_type: LISTED,\n billing_event: LISTED,\n optimization_goal: LISTED,\n is_autobid: LISTED,\n effective_status: LISTED,\n budget_reset_period: LISTED,\n \"placement.page_types\": TAGGED,\n stop_time: [\"GREATER_THAN\", \"LESS_THAN\"],\n};\n\nconst SPECIAL_OPERATORS: Readonly<Record<string, readonly AdRuleOperator[]>> = {\n entity_type: [\"EQUAL\"],\n time_preset: [\"EQUAL\"],\n attribution_window: [\"EQUAL\"],\n aggregation_id: [\"IN\"],\n};\n\nfunction operatorsFor(parsed: ParsedAdRuleField): readonly AdRuleOperator[] {\n if (parsed.kind === \"special\") return SPECIAL_OPERATORS[parsed.base] ?? [\"EQUAL\"];\n if (parsed.kind === \"metadata\") return METADATA_OPERATORS[parsed.base] ?? BOUNDED;\n return COMPARE;\n}\n\nfunction isAscendingPair(value: unknown): boolean {\n return (\n Array.isArray(value) &&\n value.length === 2 &&\n value.every((bound) => typeof bound === \"number\") &&\n (value[0] as number) < (value[1] as number)\n );\n}\n\nconst isNonEmptyList = (value: unknown): boolean => Array.isArray(value) && value.length > 0;\nconst isText = (value: unknown): boolean => typeof value === \"string\" && value.length > 0;\n\n/** Each non-scalar operator's value shape, and the words for it. */\nconst VALUE_SHAPES: Partial<Record<AdRuleOperator, { fits: (value: unknown) => boolean; words: string }>> = {\n IN_RANGE: { fits: isAscendingPair, words: \"a [low, high] pair of numbers, low first\" },\n NOT_IN_RANGE: { fits: isAscendingPair, words: \"a [low, high] pair of numbers, low first\" },\n IN: { fits: isNonEmptyList, words: \"a non-empty list\" },\n NOT_IN: { fits: isNonEmptyList, words: \"a non-empty list\" },\n ANY: { fits: isNonEmptyList, words: \"a non-empty list\" },\n ALL: { fits: isNonEmptyList, words: \"a non-empty list\" },\n NONE: { fits: isNonEmptyList, words: \"a non-empty list\" },\n CONTAIN: { fits: isText, words: \"text\" },\n NOT_CONTAIN: { fits: isText, words: \"text\" },\n};\n\n/** The value one operator compares against, in words, or undefined when `value` fits. */\nfunction valueShapeIssue(operator: AdRuleOperator, value: unknown, textual: boolean): string | undefined {\n const shape = VALUE_SHAPES[operator] ?? {\n fits: (candidate: unknown) => typeof candidate === \"number\" || (textual && typeof candidate === \"string\"),\n words: textual ? \"text\" : \"a number\",\n };\n return shape.fits(value) ? undefined : `${operator} takes ${shape.words}`;\n}\n\n/** Filters compared as text or as an id rather than as a number. */\nconst TEXTUAL_FIELDS = new Set([\"name\", \"id\", \"entity_type\", \"time_preset\", \"attribution_window\"]);\n\nconst ENUM_VALUES: Readonly<Record<string, readonly string[]>> = {\n entity_type: AD_RULE_ENTITY_TYPES,\n time_preset: AD_RULE_TIME_PRESETS,\n attribution_window: AD_RULE_ATTRIBUTION_WINDOWS,\n};\n\nfunction enumIssue(parsed: ParsedAdRuleField, value: unknown): string | undefined {\n const allowed = parsed.kind === \"special\" ? ENUM_VALUES[parsed.base] : undefined;\n if (!allowed || (typeof value === \"string\" && allowed.includes(value))) return undefined;\n return `${parsed.base} must be one of ${allowed.join(\", \")}`;\n}\n\nfunction oneFilterIssue(filter: AdRuleFilter): string | undefined {\n const parsed = parseAdRuleField(filter.field);\n if (\"refusal\" in parsed) return parsed.refusal;\n const operators = operatorsFor(parsed);\n if (!operators.includes(filter.operator)) {\n return `${filter.field} takes ${operators.join(\", \")} — not ${filter.operator}`;\n }\n return (\n valueShapeIssue(filter.operator, filter.value, TEXTUAL_FIELDS.has(parsed.base)) ?? enumIssue(parsed, filter.value)\n );\n}\n\nfunction filtersNamed(spec: AdRuleEvaluationSpec, field: string): AdRuleFilter[] {\n return spec.filters.filter((filter) => filter.field === field);\n}\n\n/** Meta: \"For every rule … you must specify either an entity_type or id filter.\" */\nfunction scopeIssues(spec: AdRuleEvaluationSpec): Issue[] {\n if (filtersNamed(spec, \"entity_type\").length > 0 || filtersNamed(spec, \"id\").length > 0) return [];\n return [\n {\n path: [\"evaluation_spec\", \"filters\"],\n message:\n \"say what the rule applies to — add an entity_type filter (EQUAL AD, ADSET or CAMPAIGN) or an id filter (IN [ids])\",\n },\n ];\n}\n\nfunction onceOnly(spec: AdRuleEvaluationSpec, field: string): Issue[] {\n return filtersNamed(spec, field).length > 1\n ? [{ path: [\"evaluation_spec\", \"filters\"], message: `Meta takes one ${field} filter per rule` }]\n : [];\n}\n\nfunction measuresPerformance(spec: AdRuleEvaluationSpec): boolean {\n return (\n spec.filters.some((filter) => isInsightsField(filter.field)) || spec.trigger?.type.startsWith(\"STATS\") === true\n );\n}\n\n/** Live (code 100): \"time_preset is a required filter field\" once any performance condition is present. */\nfunction timePresetIssues(spec: AdRuleEvaluationSpec): Issue[] {\n if (!measuresPerformance(spec) || filtersNamed(spec, \"time_preset\").length > 0) return [];\n return [\n {\n path: [\"evaluation_spec\", \"filters\"],\n message:\n \"a performance condition needs a time range — add a time_preset filter (EQUAL, e.g. LAST_7D); Meta refuses the rule without one\",\n },\n ];\n}\n\nfunction aggregateIssues(spec: AdRuleEvaluationSpec): Issue[] {\n const aggregates = spec.filters.some((filter) => filter.field.startsWith(\"aggregate(\"));\n if (!aggregates || filtersNamed(spec, \"aggregation_id\").length > 0) return [];\n return [\n {\n path: [\"evaluation_spec\", \"filters\"],\n message: \"an aggregate(...) filter needs an aggregation_id filter (IN [ids]) naming what to add up\",\n },\n ];\n}\n\n// --- Object references ---\n\nconst TEMP_REF = /^meta_temp_[A-Za-z0-9_-]{4,}$/;\nconst NUMERIC_ID = /^\\d+$/;\n\nexport type AdRuleRefEntity = \"ad\" | \"adSet\" | \"campaign\" | \"adLabel\";\n\nconst ENTITY_OF_LEVEL: Record<AdRuleEntityType, \"ad\" | \"adSet\" | \"campaign\"> = {\n AD: \"ad\",\n ADSET: \"adSet\",\n CAMPAIGN: \"campaign\",\n};\nconst ENTITY_OF_PREFIX: Record<string, AdRuleRefEntity> = {\n \"ad.id\": \"ad\",\n \"adset.id\": \"adSet\",\n \"campaign.id\": \"campaign\",\n};\n\n/** Filters that name objects by id: what they name, or `undefined` for the level the rule's entity_type sets. */\nfunction idFilterEntity(field: string): AdRuleRefEntity | \"level\" | undefined {\n if (field === \"id\") return \"level\";\n if (/(^|\\.)adlabel_ids$/.test(field)) return \"adLabel\";\n return ENTITY_OF_PREFIX[field];\n}\n\n/** What a bare `id` filter names: objects at the rule's own level (entity_type). */\nexport function adRuleIdEntity(spec: AdRuleEvaluationSpec | undefined): \"ad\" | \"adSet\" | \"campaign\" | undefined {\n const level = adRuleLevel(spec);\n return level ? ENTITY_OF_LEVEL[level] : undefined;\n}\n\nfunction idValues(value: AdRuleFilter[\"value\"]): string[] {\n return (Array.isArray(value) ? value : [value]).map(String);\n}\n\n/**\n * The `meta_temp_*` refs a rule names, keyed by what each must be — so a rule\n * staged against an ad this same draft creates publishes after it, and is\n * skipped if the ad never lands.\n */\nexport function adRuleTempRefs(spec: AdRuleEvaluationSpec | undefined): { ref: string; entity: AdRuleRefEntity }[] {\n if (!spec) return [];\n const idEntity = adRuleIdEntity(spec);\n return spec.filters.flatMap((filter) => {\n const named = idFilterEntity(filter.field);\n const entity = named === \"level\" ? idEntity : named;\n if (!entity) return [];\n return idValues(filter.value)\n .filter((id) => TEMP_REF.test(id))\n .map((ref) => ({ ref, entity }));\n });\n}\n\nfunction idFilterIssue(filter: AdRuleFilter, level: AdRuleEntityType | undefined): string | undefined {\n const named = idFilterEntity(filter.field);\n const ids = filter.field === \"aggregation_id\" || named ? idValues(filter.value) : [];\n const bad = ids.find((id) => !NUMERIC_ID.test(id) && !TEMP_REF.test(id));\n if (bad) return `${filter.field} takes bare numeric ids or meta_temp_* refs — not \"${bad}\"`;\n const temp = ids.some((id) => TEMP_REF.test(id));\n if (temp && filter.field === \"aggregation_id\")\n return \"aggregation_id takes ids already on Meta, not meta_temp_* refs\";\n if (temp && named === \"level\" && !level) {\n return \"an id filter naming meta_temp_* refs needs an entity_type filter too, so the rule waits for the right objects\";\n }\n return undefined;\n}\n\nfunction filterIssues(spec: AdRuleEvaluationSpec): Issue[] {\n const issues: Issue[] = [];\n const level = adRuleLevel(spec);\n for (const [index, filter] of spec.filters.entries()) {\n const message = oneFilterIssue(filter) ?? idFilterIssue(filter, level);\n if (message) issues.push({ path: [\"evaluation_spec\", \"filters\", index], message });\n }\n return [\n ...issues,\n ...scopeIssues(spec),\n ...onceOnly(spec, \"time_preset\"),\n ...onceOnly(spec, \"attribution_window\"),\n ...timePresetIssues(spec),\n ...aggregateIssues(spec),\n ];\n}\n\nconst SCHEDULE_ONLY_FIELDS: ReadonlySet<string> = new Set([\n ...SCHEDULE_ONLY_METADATA_FIELDS,\n ...SCHEDULE_ONLY_INSIGHTS_FIELDS,\n \"attribution_window\",\n]);\n\n/** A filter a trigger rule refuses — schedule-only metadata and metrics, and every advanced form. */\nfunction scheduleOnlyFilter(filter: AdRuleFilter): boolean {\n const parsed = parseAdRuleField(filter.field);\n if (\"refusal\" in parsed) return false;\n if (parsed.kind === \"advanced\" || parsed.kind === \"aggregate\" || parsed.kind === \"formula\") return true;\n if (parsed.kind === \"insights\" && parsed.base !== filter.field) return true;\n return SCHEDULE_ONLY_FIELDS.has(parsed.base);\n}\n\nconst STATS_CHANGE_OPERATORS: readonly AdRuleOperator[] = [\"GREATER_THAN\", \"LESS_THAN\", \"IN_RANGE\", \"NOT_IN_RANGE\"];\n\n/**\n * The metrics Meta counts milestones of, with the smallest step it takes\n * (trigger-based rules guide). Spelled as that list spells them — the events\n * with underscores (`offsite_conversion_fb_pixel_purchase`), not the dotted\n * action types a filter takes — so a milestone field is checked here, never\n * against the filter fields (`triggerShapeIssue`). `spent` is in the account's minor units there\n * (1000 cents), so it is held to its minimum once converted — `milestoneMinimumIssue`.\n */\nconst MILESTONE_MINIMUMS: Readonly<Record<string, number>> = {\n impressions: 1000,\n unique_impressions: 1000,\n reach: 1000,\n clicks: 10,\n unique_clicks: 10,\n spent: 1000,\n results: 5,\n ...Object.fromEntries(\n [\n ...APP_EVENTS.map((event) => `app_custom_event_fb_mobile_${event}`),\n \"app_custom_event\",\n \"app_custom_event_other\",\n \"leadgen\",\n \"like\",\n \"link_click\",\n \"mobile_app_install\",\n \"offsite_conversion\",\n \"offsite_conversion_add_to_cart\",\n \"offsite_conversion_checkout\",\n ...PIXEL_EVENTS.map((event) => `offsite_conversion_fb_pixel_${event}`),\n \"offsite_engagement\",\n \"post\",\n \"post_comment\",\n \"post_engagement\",\n \"post_like\",\n \"post_reaction\",\n \"view_content\",\n \"video_play\",\n \"video_view\",\n \"vote\",\n ].map((field) => [field, 1]),\n ),\n};\n\n/** A milestone's step below Meta's minimum, read on the wire (money in minor units). */\nexport function milestoneMinimumIssue(trigger: AdRuleTrigger): string | undefined {\n if (trigger.type !== \"STATS_MILESTONE\" || !trigger.field) return undefined;\n const minimum = MILESTONE_MINIMUMS[trigger.field];\n return minimum !== undefined && typeof trigger.value === \"number\" && trigger.value < minimum\n ? `a ${trigger.field} milestone steps by at least ${minimum}${trigger.field === \"spent\" ? \" in the account's minor units (10.00 in a two-decimal currency)\" : \"\"}`\n : undefined;\n}\n\nfunction milestoneIssue(trigger: AdRuleTrigger, spec: AdRuleEvaluationSpec): string | undefined {\n if (trigger.operator !== \"EQUAL\") {\n return \"a STATS_MILESTONE trigger takes operator EQUAL (it fires at every multiple of the value)\";\n }\n const preset = filtersNamed(spec, \"time_preset\")[0]?.value;\n if (preset !== undefined && preset !== \"LIFETIME\") return \"a STATS_MILESTONE trigger needs time_preset LIFETIME\";\n if (!trigger.field || MILESTONE_MINIMUMS[trigger.field] === undefined) {\n return `Meta counts milestones only of ${Object.keys(MILESTONE_MINIMUMS).slice(0, 7).join(\", \")} and the conversion events — not ${trigger.field}; use a STATS_CHANGE trigger for it`;\n }\n if (!(typeof trigger.value === \"number\" && trigger.value > 0))\n return \"a STATS_MILESTONE trigger takes a positive number\";\n // Money is held to its minimum on the wire, where the account's units are known.\n return trigger.field === \"spent\" ? undefined : milestoneMinimumIssue(trigger);\n}\n\nfunction statsTriggerIssue(trigger: AdRuleTrigger, spec: AdRuleEvaluationSpec): string | undefined {\n if (trigger.type === \"STATS_MILESTONE\") return milestoneIssue(trigger, spec);\n if (trigger.type === \"STATS_CHANGE\" && !(trigger.operator && STATS_CHANGE_OPERATORS.includes(trigger.operator))) {\n return `a STATS_CHANGE trigger takes ${STATS_CHANGE_OPERATORS.join(\", \")}`;\n }\n return trigger.operator ? valueShapeIssue(trigger.operator, trigger.value, false) : \"the trigger needs an operator\";\n}\n\nfunction triggerShapeIssue(trigger: AdRuleTrigger, spec: AdRuleEvaluationSpec): string | undefined {\n if (trigger.type === \"METADATA_CREATION\") return undefined;\n if (!trigger.field) return `a ${trigger.type} trigger needs a field`;\n if (trigger.type === \"STATS_MILESTONE\") return milestoneIssue(trigger, spec);\n const parsed = parseAdRuleField(trigger.field);\n if (\"refusal\" in parsed) return parsed.refusal;\n const isMetadata = parsed.kind === \"metadata\";\n if (trigger.type === \"METADATA_UPDATE\") {\n return isMetadata ? undefined : `a METADATA_UPDATE trigger watches a metadata field, not ${trigger.field}`;\n }\n if (isMetadata || parsed.kind === \"special\") {\n return `a ${trigger.type} trigger watches a metric, not ${trigger.field}`;\n }\n return statsTriggerIssue(trigger, spec);\n}\n\nfunction triggerIssues(spec: AdRuleEvaluationSpec): Issue[] {\n const at = (message: string, path: (string | number)[] = []): Issue => ({\n path: [\"evaluation_spec\", ...path],\n message,\n });\n if (spec.evaluation_type === \"SCHEDULE\") {\n return spec.trigger\n ? [at(\"a SCHEDULE rule has no trigger — use evaluation_type TRIGGER, or drop the trigger\", [\"trigger\"])]\n : [];\n }\n const issues: Issue[] = [];\n if (!spec.trigger) {\n issues.push(\n at(\"a TRIGGER rule needs a trigger ({type, field, operator, value}) saying what change it reacts to\", [\n \"trigger\",\n ]),\n );\n } else {\n const shape = triggerShapeIssue(spec.trigger, spec);\n if (shape) issues.push(at(shape, [\"trigger\"]));\n }\n for (const [index, filter] of spec.filters.entries()) {\n if (scheduleOnlyFilter(filter)) {\n issues.push(\n at(`${filter.field} works only on a schedule — use evaluation_type SCHEDULE, or drop it`, [\"filters\", index]),\n );\n }\n }\n const preset = filtersNamed(spec, \"time_preset\")[0]?.value;\n if (typeof preset === \"string\" && !(TIME_PRESETS_WITH_TODAY as readonly string[]).includes(preset)) {\n issues.push(\n at(\n `a TRIGGER rule evaluates in real time, so its time_preset must include today (${TIME_PRESETS_WITH_TODAY.join(\", \")}) — not ${preset}`,\n [\"filters\"],\n ),\n );\n }\n return issues;\n}\n\nfunction evaluationIssues(spec: AdRuleEvaluationSpec): Issue[] {\n return [...filterIssues(spec), ...triggerIssues(spec)];\n}\n\n/** The pairing of how a rule is checked with what it does and when it runs. */\nfunction pairingIssues(rule: AdRuleShape, partial: boolean): Issue[] {\n const evaluationType = rule.evaluation_spec?.evaluation_type;\n if (!evaluationType) return [];\n const issues: Issue[] = [];\n if (evaluationType === \"TRIGGER\") {\n const executionType = rule.execution_spec?.execution_type;\n if (executionType && !TRIGGER_EXECUTION_TYPES.has(executionType)) {\n issues.push({\n path: [\"execution_spec\", \"execution_type\"],\n message: `a TRIGGER rule can only PAUSE, UNPAUSE or NOTIFICATION — ${executionType} needs evaluation_type SCHEDULE`,\n });\n }\n if (rule.schedule_spec) {\n issues.push({\n path: [\"schedule_spec\"],\n message: \"a TRIGGER rule runs the moment the metric changes, so it takes no schedule_spec — drop it\",\n });\n }\n } else if (!rule.schedule_spec && !partial) {\n issues.push({\n path: [\"schedule_spec\"],\n message: \"a SCHEDULE rule needs a schedule_spec (schedule_type DAILY, HOURLY, SEMI_HOURLY or CUSTOM)\",\n });\n }\n return issues;\n}\n\n// --- Execution ---\n\nexport const AD_RULE_CHANGE_UNITS = [\"ACCOUNT_CURRENCY\", \"PERCENTAGE\"] as const;\nexport const AD_RULE_REBALANCE_TYPES = [\n \"EVEN\",\n \"PROPORTIONAL\",\n \"NO_PAUSE_PROPORTIONAL\",\n \"MATCHED_ONLY_PROPORTIONAL\",\n] as const;\n\nconst CHANGE_TYPES: ReadonlySet<string> = new Set([\"CHANGE_BUDGET\", \"CHANGE_CAMPAIGN_BUDGET\", \"CHANGE_BID\"]);\n\n/** The level an action works on (execution spec): budgets and bids are set on ad sets, unless it is the campaign budget. */\nconst ACTION_LEVEL: Partial<Record<AdRuleExecutionType, { level: AdRuleEntityType; words: string }>> = {\n CHANGE_BUDGET: { level: \"ADSET\", words: \"ad sets (CHANGE_CAMPAIGN_BUDGET changes a campaign's)\" },\n CHANGE_BID: { level: \"ADSET\", words: \"ad sets\" },\n REBALANCE_BUDGET: { level: \"ADSET\", words: \"ad sets\" },\n CHANGE_CAMPAIGN_BUDGET: { level: \"CAMPAIGN\", words: \"campaigns (CHANGE_BUDGET changes an ad set's)\" },\n ROTATE: { level: \"AD\", words: \"ads, rotating within the ad sets an adset.id filter names\" },\n};\n\n/** Which options each action reads — Meta refuses the rest. */\nfunction optionAllowed(field: string, executionType: AdRuleExecutionType): boolean {\n switch (field) {\n case \"user_ids\":\n case \"alert_preferences\":\n return true;\n case \"change_spec\":\n case \"execution_count_limit\":\n case \"action_frequency\":\n return CHANGE_TYPES.has(executionType);\n case \"rebalance_spec\":\n return executionType === \"REBALANCE_BUDGET\";\n default:\n return false;\n }\n}\n\nfunction isPositiveInt(value: unknown): boolean {\n return typeof value === \"number\" && Number.isInteger(value) && value > 0;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isNumberPair(value: unknown): boolean {\n return (\n Array.isArray(value) &&\n value.length === 2 &&\n value.every((bound) => typeof bound === \"number\") &&\n (value[0] as number) <= (value[1] as number)\n );\n}\n\n/** Change spec (ad-rules/overview/change-spec): amount, unit unless target_field, limit a cap — or a range with target_field. */\nfunction changeSpecIssue(value: unknown): string | undefined {\n if (!isRecord(value)) return \"change_spec takes {amount, unit, limit?, target_field?}\";\n if (typeof value.amount !== \"number\" || value.amount === 0) return \"change_spec.amount takes a non-zero number\";\n const target = value.target_field;\n if (target !== undefined) {\n if (typeof target !== \"string\" || !isInsightsField(target)) {\n return \"change_spec.target_field takes an Insights metric (e.g. cost_per, website_purchase_roas)\";\n }\n return value.limit === undefined || isNumberPair(value.limit)\n ? undefined\n : \"with target_field, change_spec.limit takes a [lowest, highest] pair\";\n }\n if (!(AD_RULE_CHANGE_UNITS as readonly unknown[]).includes(value.unit)) {\n return `change_spec.unit takes ${AD_RULE_CHANGE_UNITS.join(\" or \")} (required unless target_field is set)`;\n }\n return value.limit === undefined || (typeof value.limit === \"number\" && value.limit > 0)\n ? undefined\n : \"change_spec.limit takes a positive amount — the most (or least) the budget or bid may reach\";\n}\n\n/** Rebalance spec (ad-rules/guides/rebalance-budget). */\nfunction rebalanceSpecIssue(value: unknown): string | undefined {\n if (!isRecord(value) || !(AD_RULE_REBALANCE_TYPES as readonly unknown[]).includes(value.type)) {\n return `rebalance_spec.type takes ${AD_RULE_REBALANCE_TYPES.join(\", \")}`;\n }\n const needsTarget = value.type !== \"EVEN\" || value.target_count !== undefined;\n if (needsTarget && (typeof value.target_field !== \"string\" || !isInsightsField(value.target_field))) {\n return \"rebalance_spec needs a target_field (an Insights metric to rank by) unless type is EVEN with no target_count\";\n }\n if (value.target_count !== undefined && !isPositiveInt(value.target_count)) {\n return \"rebalance_spec.target_count takes a positive whole number\";\n }\n // Meta ranks by the value itself, highest first: by a cost, that hands the most budget to the most expensive.\n if (typeof value.target_field === \"string\" && isCostField(value.target_field) && value.is_inverse !== true) {\n return `rebalance_spec ranks by ${value.target_field}, a cost, so Meta would give the most budget to the most expensive ad sets — add is_inverse: true to favour the cheapest`;\n }\n return undefined;\n}\n\nfunction optionValueIssue(option: AdRuleExecutionOption): string | undefined {\n switch (option.field) {\n case \"change_spec\":\n return changeSpecIssue(option.value);\n case \"rebalance_spec\":\n return rebalanceSpecIssue(option.value);\n case \"execution_count_limit\":\n case \"action_frequency\":\n return isPositiveInt(option.value) ? undefined : `${option.field} takes a positive whole number`;\n case \"user_ids\":\n return Array.isArray(option.value) && option.value.length > 0\n ? undefined\n : \"user_ids takes a list of Facebook user ids to notify\";\n default:\n return undefined;\n }\n}\n\nconst REQUIRED_OPTION: Partial<Record<AdRuleExecutionType, string>> = {\n CHANGE_BUDGET: \"change_spec\",\n CHANGE_CAMPAIGN_BUDGET: \"change_spec\",\n CHANGE_BID: \"change_spec\",\n REBALANCE_BUDGET: \"rebalance_spec\",\n};\n\nfunction executionIssues(spec: AdRuleExecutionSpec): Issue[] {\n const issues: Issue[] = [];\n const options = spec.execution_options ?? [];\n const seen = new Set<string>();\n for (const [index, option] of options.entries()) {\n const path = [\"execution_spec\", \"execution_options\", index];\n if (seen.has(option.field)) issues.push({ path, message: `${option.field} is given twice` });\n seen.add(option.field);\n if (!optionAllowed(option.field, spec.execution_type)) {\n issues.push({ path, message: `${spec.execution_type} does not take the ${option.field} option` });\n continue;\n }\n const message = optionValueIssue(option);\n if (message) issues.push({ path, message });\n }\n const required = REQUIRED_OPTION[spec.execution_type];\n if (required && !seen.has(required)) {\n issues.push({\n path: [\"execution_spec\", \"execution_options\"],\n message: `${spec.execution_type} needs a ${required} option saying how much to change`,\n });\n }\n return issues;\n}\n\n/** The level a rule applies to, when its filters say so. */\nexport function adRuleLevel(spec: AdRuleEvaluationSpec | undefined): AdRuleEntityType | undefined {\n const value = spec ? filtersNamed(spec, \"entity_type\")[0]?.value : undefined;\n return (AD_RULE_ENTITY_TYPES as readonly unknown[]).includes(value) ? (value as AdRuleEntityType) : undefined;\n}\n\n/**\n * Meta's execution-spec reference says ROTATE \"requires an id filter of ad\n * sets, and an entity_type filter of an ad\", but a bare `id` filter of ad sets\n * beside entity_type AD is refused (live on v25.0, 2026-10-14: \"If both\n * entity_type and id filters are present, they must be the same ad object\n * type\"); the same ad sets named by `adset.id` were taken.\n */\nfunction rotateIssues(rule: AdRuleShape): Issue[] {\n if (rule.execution_spec?.execution_type !== \"ROTATE\" || !rule.evaluation_spec) return [];\n return filtersNamed(rule.evaluation_spec, \"id\").length > 0\n ? [\n {\n path: [\"evaluation_spec\", \"filters\"],\n message:\n \"a ROTATE rule names the ad sets whose ads it rotates with an adset.id filter (entity_type AD) — Meta refuses a bare id filter of ad sets\",\n },\n ]\n : [];\n}\n\nfunction levelIssues(rule: AdRuleShape): Issue[] {\n const executionType = rule.execution_spec?.execution_type;\n const wanted = executionType ? ACTION_LEVEL[executionType] : undefined;\n const level = adRuleLevel(rule.evaluation_spec);\n if (!wanted || !level || level === wanted.level) return [];\n return [\n {\n path: [\"execution_spec\", \"execution_type\"],\n message: `${executionType} acts on ${wanted.words} — set entity_type ${wanted.level}, not ${level}`,\n },\n ];\n}\n\n// --- Schedule ---\n\nconst MINUTES_PER_DAY = 24 * 60;\n\nfunction minuteIssue(name: string, value: number | undefined): string | undefined {\n if (value === undefined) return undefined;\n return value % 30 === 0 && value >= 0 && value <= MINUTES_PER_DAY\n ? undefined\n : `${name} is minutes after midnight, a multiple of 30 between 0 and ${MINUTES_PER_DAY}`;\n}\n\nfunction scheduleItemIssue(item: NonNullable<AdRuleScheduleSpec[\"schedule\"]>[number]): string | undefined {\n if (item.days === undefined && item.start_minute === undefined && item.end_minute === undefined) {\n return \"a custom schedule entry names its days (0–6) and/or start_minute/end_minute — an empty one says nothing about when to run\";\n }\n const minute = minuteIssue(\"start_minute\", item.start_minute) ?? minuteIssue(\"end_minute\", item.end_minute);\n if (minute) return minute;\n if (item.start_minute !== undefined && item.end_minute !== undefined && item.end_minute < item.start_minute) {\n return \"end_minute must be at or after start_minute\";\n }\n const days = item.days ?? [];\n if (days.some((day) => day < 0 || day > 6) || new Set(days).size !== days.length) {\n return \"days are distinct numbers from 0 (Sunday) to 6 (Saturday)\";\n }\n return undefined;\n}\n\nfunction scheduleIssues(spec: AdRuleScheduleSpec, executionType: AdRuleExecutionType | undefined): Issue[] {\n const issues: Issue[] = [];\n const items = spec.schedule ?? [];\n if (spec.schedule_type === \"CUSTOM\" && items.length === 0) {\n issues.push({\n path: [\"schedule_spec\", \"schedule\"],\n message: \"a CUSTOM schedule needs at least one {start_minute, end_minute, days} entry\",\n });\n }\n if (spec.schedule_type !== \"CUSTOM\" && items.length > 0) {\n issues.push({\n path: [\"schedule_spec\", \"schedule\"],\n message: `schedule entries need schedule_type CUSTOM, not ${spec.schedule_type}`,\n });\n }\n for (const [index, item] of items.entries()) {\n const message = scheduleItemIssue(item);\n if (message) issues.push({ path: [\"schedule_spec\", \"schedule\", index], message });\n }\n if (executionType === \"REBALANCE_BUDGET\" && spec.schedule_type !== \"DAILY\" && spec.schedule_type !== \"CUSTOM\") {\n issues.push({\n path: [\"schedule_spec\", \"schedule_type\"],\n message: \"a REBALANCE_BUDGET rule runs DAILY or on a CUSTOM schedule\",\n });\n }\n return issues;\n}\n\n/**\n * Everything Meta would refuse about the parts of a rule that are present.\n * `partial` is an update's view: a part it does not restate stays as it is on\n * Meta, so its absence is no refusal.\n */\nexport function adRuleIssues(rule: AdRuleShape, { partial = false }: { partial?: boolean } = {}): Issue[] {\n return [\n ...(rule.evaluation_spec ? evaluationIssues(rule.evaluation_spec) : []),\n ...(rule.execution_spec ? executionIssues(rule.execution_spec) : []),\n ...(rule.schedule_spec ? scheduleIssues(rule.schedule_spec, rule.execution_spec?.execution_type) : []),\n ...pairingIssues(rule, partial),\n ...levelIssues(rule),\n ...rotateIssues(rule),\n ];\n}\n\nfunction addIssues(rule: AdRuleShape, ctx: z.RefinementCtx, partial = false): void {\n for (const issue of adRuleIssues(rule, { partial })) {\n ctx.addIssue({ code: \"custom\", path: issue.path, message: issue.message });\n }\n}\n\n// --- Payloads ---\n\nconst currencyCodeSchema = z\n .string()\n .regex(/^[A-Z]{3}$/)\n .optional();\n\nexport const adRuleCreateSchema = z\n .strictObject({\n name: z.string().min(1).max(255),\n status: z.enum(AD_RULE_CREATE_STATUSES).default(\"ENABLED\"),\n evaluation_spec: adRuleEvaluationSpecSchema,\n execution_spec: adRuleExecutionSpecSchema,\n schedule_spec: adRuleScheduleSpecSchema.optional(),\n /** The account currency the money values are in — filled by the backend. */\n currencyCode: currencyCodeSchema,\n })\n .superRefine((rule, ctx) => addIssues(rule, ctx));\nexport type AdRuleCreate = z.infer<typeof adRuleCreateSchema>;\n\n// --- Money on the wire ---\n\nconst MONEY_METADATA = new Set([\"daily_budget\", \"lifetime_budget\", \"spend_cap\", \"bid_amount\"]);\nconst MONEY_INSIGHTS = new Set([\n \"spent\",\n \"today_spent\",\n \"yesterday_spent\",\n \"lifetime_spent\",\n \"cpc\",\n \"cpm\",\n \"cpa\",\n \"cpp\",\n]);\n\n/** Whether Meta compares this field in the account's minor units (cost metrics, spend, budgets, bids). */\n/**\n * A field as its units read: a rule made before Meta retired its attribution\n * window still comes back with it (`7d_click:cost_per`), and its money is in\n * minor units like any other — so the retired window reads as the live one.\n */\nfunction unitsField(field: string): string {\n return field\n .split(/(\\s+|[()])/)\n .map((term) => {\n const object = /^(ad|adset|campaign)\\./.exec(term)?.[0] ?? \"\";\n const bare = term.slice(object.length);\n return retiredAttributionPrefix(bare)\n ? `${object}${LIVE_ATTRIBUTION_PREFIX}${bare.slice(bare.indexOf(\":\"))}`\n : term;\n })\n .join(\"\");\n}\n\nexport function isAdRuleMoneyField(field: string): boolean {\n const parsed = parseAdRuleField(unitsField(field));\n if (\"refusal\" in parsed || parsed.kind === \"formula\" || parsed.kind === \"special\") return false;\n if (parsed.kind === \"metadata\") return MONEY_METADATA.has(parsed.base);\n return MONEY_INSIGHTS.has(parsed.base) || parsed.base.startsWith(\"cost_per\");\n}\n\n/** Whether a filter on this field compares numbers (and so reads back from Meta's strings as numbers). */\nfunction isNumericField(field: string): boolean {\n const parsed = parseAdRuleField(unitsField(field));\n if (\"refusal\" in parsed || parsed.kind === \"special\") return false;\n if (parsed.kind !== \"metadata\") return true;\n // A time compared only above or below (`stop_time`) is a number too.\n const operators = METADATA_OPERATORS[parsed.base];\n return !operators || operators.every((operator) => operator === \"GREATER_THAN\" || operator === \"LESS_THAN\");\n}\n\ntype Scale = (value: number) => number;\n\nfunction scaleValue(value: unknown, scale: Scale): unknown {\n if (Array.isArray(value)) return value.map((item) => scaleValue(item, scale));\n const number = typeof value === \"string\" && value.trim() !== \"\" ? Number(value) : value;\n return typeof number === \"number\" && Number.isFinite(number) ? scale(number) : value;\n}\n\nfunction scaleFilter<F extends { field: string; value?: unknown }>(filter: F, scale: Scale): F {\n if (filter.value === undefined || !isNumericField(filter.field)) return filter;\n const money = isAdRuleMoneyField(filter.field);\n return { ...filter, value: scaleValue(filter.value, money ? scale : (n) => n) };\n}\n\nfunction scaleChangeSpec(value: unknown, scale: Scale): unknown {\n if (!isRecord(value)) return value;\n const target = typeof value.target_field === \"string\" ? value.target_field : undefined;\n const amountIsMoney = target ? isAdRuleMoneyField(target) : value.unit === \"ACCOUNT_CURRENCY\";\n return {\n ...value,\n ...(value.amount !== undefined ? { amount: scaleValue(value.amount, amountIsMoney ? scale : (n) => n) } : {}),\n ...(value.limit !== undefined ? { limit: scaleValue(value.limit, scale) } : {}),\n };\n}\n\nfunction scaleRule<R extends Record<string, unknown>>(rule: R, scale: Scale): R {\n const evaluation = isRecord(rule.evaluation_spec) ? rule.evaluation_spec : undefined;\n const execution = isRecord(rule.execution_spec) ? rule.execution_spec : undefined;\n const filters = Array.isArray(evaluation?.filters) ? (evaluation.filters as AdRuleFilter[]) : undefined;\n const trigger = isRecord(evaluation?.trigger) ? (evaluation.trigger as AdRuleTrigger) : undefined;\n const options = Array.isArray(execution?.execution_options)\n ? (execution.execution_options as AdRuleExecutionOption[])\n : undefined;\n return {\n ...rule,\n ...(evaluation\n ? {\n evaluation_spec: {\n ...evaluation,\n ...(filters ? { filters: filters.map((filter) => scaleFilter(filter, scale)) } : {}),\n ...(trigger?.field ? { trigger: scaleFilter({ ...trigger, field: trigger.field }, scale) } : {}),\n },\n }\n : {}),\n ...(execution && options\n ? {\n execution_spec: {\n ...execution,\n execution_options: options.map((option) =>\n option.field === \"change_spec\" ? { ...option, value: scaleChangeSpec(option.value, scale) } : option,\n ),\n },\n }\n : {}),\n };\n}\n\n/** A staged rule as Meta takes it: money values times the account currency's minor-unit multiplier. */\nexport function adRuleToWire<R extends AdRuleShape>(rule: R, multiplier: number): R {\n return scaleRule(rule as R & Record<string, unknown>, (value) => Math.round(value * multiplier));\n}\n\n/** `{\"0\": a, \"1\": b}` — how Meta returns a list it was sent inside a change spec. */\nfunction indexedPair(value: unknown): unknown {\n if (!isRecord(value)) return value;\n const keys = Object.keys(value);\n return keys.length > 0 && keys.every((key, index) => key === String(index)) ? keys.map((key) => value[key]) : value;\n}\n\n/**\n * An option's value in the shape it was sent. Live on v25.0 (2026-10-14) a\n * change toward a target sent with `limit: [500, 4000]` came back as\n * `{\"0\": \"500\", \"1\": \"4000\"}`; every change spec came back with the unused one\n * of `unit` / `target_field` as `null`, and a rebalance spec with\n * `is_cross_campaign`, `is_inverse` and `target_count` as `null`.\n */\nfunction sentOptionValue(value: unknown): unknown {\n if (!isRecord(value)) return value;\n const out = Object.fromEntries(Object.entries(value).filter(([, item]) => item !== null));\n return out.limit === undefined ? out : { ...out, limit: indexedPair(out.limit) };\n}\n\n/** A rule as Meta returns it, with its change and rebalance specs back in the shape they were sent. Units unchanged. */\nexport function adRuleWireAsSent<R extends Record<string, unknown>>(node: R): R {\n const execution = isRecord(node.execution_spec) ? node.execution_spec : undefined;\n if (!execution || !Array.isArray(execution.execution_options)) return node;\n return {\n ...node,\n execution_spec: {\n ...execution,\n execution_options: (execution.execution_options as AdRuleExecutionOption[]).map((option) =>\n option.field === \"change_spec\" || option.field === \"rebalance_spec\"\n ? { ...option, value: sentOptionValue(option.value) }\n : option,\n ),\n },\n };\n}\n\n/** A rule as Meta returns it, in staged vocabulary: numbers instead of Meta's strings, money in major units. */\nexport function adRuleFromWire(\n node: Record<string, unknown>,\n multiplier: number,\n): AdRuleShape & Record<string, unknown> {\n return scaleRule(adRuleWireAsSent(node), (value) => value / multiplier) as AdRuleShape & Record<string, unknown>;\n}\n\nexport const adRuleUpdateSchema = z\n .strictObject({\n name: z.string().min(1).max(255).optional(),\n status: z.enum(AD_RULE_UPDATE_STATUSES).optional(),\n /** Each spec is replaced whole — Meta takes no partial spec on update. */\n evaluation_spec: adRuleEvaluationSpecSchema.optional(),\n execution_spec: adRuleExecutionSpecSchema.optional(),\n schedule_spec: adRuleScheduleSpecSchema.optional(),\n /**\n * Run the rule once, now (`POST /{rule}/execute`), after any change staged\n * beside it — the rule acts on what matches it at that moment, whatever its\n * schedule and even while it is off. Meta ignores `validate_only` there (a\n * validate-only execute ran the rule, its history shows it; live on v26.0,\n * 2026-10-15), so it is never dry-run.\n */\n run_now: z.literal(true).optional(),\n currencyCode: currencyCodeSchema,\n })\n .refine(\n (p) => Object.entries(p).some(([key, value]) => key !== \"currencyCode\" && value !== undefined),\n \"update needs at least one field\",\n )\n .refine((p) => !(p.run_now && p.status === \"DELETED\"), \"a rule being deleted cannot also run now — pick one\")\n .superRefine((rule, ctx) => addIssues(rule, ctx, true));\nexport type AdRuleUpdate = z.infer<typeof adRuleUpdateSchema>;\n\n// --- Reads ---\n\n/** A live rule as `baker ads meta rules` returns it: staged vocabulary, plus Meta's bookkeeping and a sentence. */\nexport interface MetaAdRuleRow extends AdRuleShape {\n id: string;\n name?: string;\n status?: string;\n currencyCode?: string;\n /** The rule in words — \"Pause the ad when cost per result is above €20 …\". */\n description: string;\n created_time?: string;\n updated_time?: string;\n created_by?: { id?: string; name?: string };\n /** Why Meta stopped the rule, when status is HAS_ISSUES. */\n disable_error_code?: number;\n}\n\n/** One run of a rule (`/{rule_id}/history`, `/act_<id>/adrules_history`). */\nexport interface MetaAdRuleHistoryRow {\n rule_id?: string;\n timestamp?: string;\n /** True when someone ran it by hand rather than on its schedule. */\n is_manual?: boolean;\n /** One entry per object the run changed, with each change made. */\n results?: Array<{\n object_id?: string;\n object_type?: string;\n actions?: Array<{ action?: string; field?: string; old_value?: string; new_value?: string }>;\n }>;\n exception_code?: number;\n exception_message?: string;\n}\n\n/** Filters Meta's history endpoints take. */\nexport const metaAdRuleHistoryQuerySchema = z.strictObject({\n accountId: z.string().min(1),\n ruleId: z.string().regex(/^\\d+$/).optional(),\n objectId: z.string().regex(/^\\d+$/).optional(),\n /** Meta's action names, e.g. PAUSED, UNPAUSED, CHANGED_BUDGET, CHANGED_BID, NOTIFICATION. */\n action: z.string().min(1).optional(),\n hideNoChanges: z.boolean().optional(),\n limit: z.number().int().min(1).max(500).optional(),\n});\nexport type MetaAdRuleHistoryQuery = z.infer<typeof metaAdRuleHistoryQuerySchema>;\n","import { z } from \"zod\";\nimport {\n AUDIENCE_NETWORK_POSITIONS,\n FACEBOOK_POSITIONS,\n INSTAGRAM_POSITIONS,\n MESSENGER_POSITIONS,\n THREADS_POSITIONS,\n} from \"./placements\";\n\n/**\n * Advantage+ placements with limited spend (`placement_soft_opt_out`, v24+):\n * positions the ad set does not target that Meta may still spend up to 5% on.\n * Sales and Leads campaigns only. Live on v26.0 (2026-10-15): Meta keeps the\n * positions lists and drops anything else — a `publisher_platforms` key alone\n * is refused \"Invalid Flexible Placement Configuration\" (subcode 4940001), and\n * an ad set read back `{facebook_positions, audience_network_positions}` exactly.\n */\nexport const placementSoftOptOutSchema = z\n .strictObject({\n facebook_positions: z.array(z.enum(FACEBOOK_POSITIONS)).min(1).optional(),\n instagram_positions: z.array(z.enum(INSTAGRAM_POSITIONS)).min(1).optional(),\n audience_network_positions: z.array(z.enum(AUDIENCE_NETWORK_POSITIONS)).min(1).optional(),\n messenger_positions: z.array(z.enum(MESSENGER_POSITIONS)).min(1).optional(),\n threads_positions: z.array(z.enum(THREADS_POSITIONS)).min(1).optional(),\n })\n .refine(\n (spec) => Object.values(spec).some((positions) => positions !== undefined),\n \"name at least one position Meta may spend on (e.g. audience_network_positions: [classic])\",\n );\n\n/**\n * Regional regulated categories: an ad set reaching Singapore, Taiwan,\n * Thailand or Brazil — or financial services in Australia, India or Taiwan —\n * declares the category and the VERIFIED advertiser ids Meta holds for it.\n * Live on v26.0 (2026-10-15): an ad set targeting SG without the category is\n * refused (3858550, \"Regional regulated categories value required\"), and with\n * it but no verified advertiser (3858548, \"Advertiser is missing\"). The ids\n * come from the advertiser verification done in Meta's Business settings; no\n * Marketing API read lists them.\n */\nexport const REGIONAL_REGULATED_CATEGORIES = [\n \"TAIWAN_FINSERV\",\n \"AUSTRALIA_FINSERV\",\n \"INDIA_FINSERV\",\n \"TAIWAN_UNIVERSAL\",\n \"SINGAPORE_UNIVERSAL\",\n \"THAILAND_UNIVERSAL\",\n \"BRAZIL_REGULATION\",\n] as const;\nexport type RegionalRegulatedCategory = (typeof REGIONAL_REGULATED_CATEGORIES)[number];\n\n/** The identity key prefix each category is declared with — Thailand and Brazil share `universal_*`. */\nconst IDENTITY_PREFIX: Record<RegionalRegulatedCategory, string> = {\n TAIWAN_FINSERV: \"taiwan_finserv\",\n AUSTRALIA_FINSERV: \"australia_finserv\",\n INDIA_FINSERV: \"india_finserv\",\n TAIWAN_UNIVERSAL: \"taiwan_universal\",\n SINGAPORE_UNIVERSAL: \"singapore_universal\",\n THAILAND_UNIVERSAL: \"universal\",\n BRAZIL_REGULATION: \"universal\",\n};\n\nconst identityId = z.string().regex(/^\\d+$/, \"a verified advertiser id (digits)\");\nconst IDENTITY_KEYS = [...new Set(Object.values(IDENTITY_PREFIX))].flatMap((prefix) => [\n `${prefix}_beneficiary`,\n `${prefix}_payer`,\n]);\n\nexport const regionalRegulationIdentitiesSchema = z.strictObject(\n Object.fromEntries(IDENTITY_KEYS.map((key) => [key, identityId.optional()])) as Record<\n string,\n z.ZodOptional<typeof identityId>\n >,\n);\n\nexport const regionalRegulationFields = {\n regional_regulated_categories: z.array(z.enum(REGIONAL_REGULATED_CATEGORIES)).min(1).optional(),\n regional_regulation_identities: regionalRegulationIdentitiesSchema.optional(),\n};\n\n/** Each declared category needs both of its ids; Taiwan financial services also declares Taiwan universal. */\nexport function validateRegionalRegulation(\n p: {\n regional_regulated_categories?: readonly RegionalRegulatedCategory[];\n regional_regulation_identities?: Record<string, string | undefined>;\n },\n ctx: z.RefinementCtx,\n): void {\n const categories = p.regional_regulated_categories ?? [];\n const identities = p.regional_regulation_identities ?? {};\n for (const category of categories) {\n const prefix = IDENTITY_PREFIX[category];\n const missing = [`${prefix}_beneficiary`, `${prefix}_payer`].filter((key) => !identities[key]);\n if (missing.length > 0) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"regional_regulation_identities\"],\n message: `${category} needs ${missing.join(\" and \")} in regional_regulation_identities — the verified advertiser ids from Meta's advertiser verification (Meta refuses it without them, 3858548)`,\n });\n }\n }\n if (categories.includes(\"TAIWAN_FINSERV\") && !categories.includes(\"TAIWAN_UNIVERSAL\")) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"regional_regulated_categories\"],\n message: \"a Taiwan financial-services ad set declares TAIWAN_UNIVERSAL beside TAIWAN_FINSERV\",\n });\n }\n}\n\nconst SOFT_PLATFORM: Record<string, string> = {\n facebook_positions: \"facebook\",\n instagram_positions: \"instagram\",\n audience_network_positions: \"audience_network\",\n messenger_positions: \"messenger\",\n threads_positions: \"threads\",\n};\n\n/**\n * Limited spend reaches only positions the ad set leaves out. Live on v26.0\n * (2026-10-15) Meta kept it on an ad set with manual placements and dropped it\n * without a word on one with automatic placements (the read-back drifted), so\n * it needs `publisher_platforms` in the targeting and positions outside it.\n * An update without targeting is left to Meta's dry run and the read-back.\n */\nexport function softOptOutPlacementIssue(\n soft: Record<string, readonly string[] | undefined> | undefined,\n targeting: Record<string, unknown> | undefined,\n isCreate: boolean,\n): string | undefined {\n if (!soft || (!isCreate && targeting === undefined)) return undefined;\n const platforms = Array.isArray(targeting?.publisher_platforms) ? (targeting.publisher_platforms as string[]) : [];\n if (platforms.length === 0) {\n return \"limited spend reaches placements the ad set leaves out, so it needs manual placements (targeting.publisher_platforms and positions) — with automatic placements Meta drops it\";\n }\n for (const [key, positions] of Object.entries(soft)) {\n const platform = SOFT_PLATFORM[key];\n const running = targeting?.[key];\n if (!platform || !positions || !platforms.includes(platform)) continue;\n const runs = Array.isArray(running) ? (running as string[]) : undefined;\n const overlap = positions.filter((position) => runs === undefined || runs.includes(position));\n if (overlap.length > 0) {\n return `the ad set already runs on ${overlap.map((position) => `${platform} ${position}`).join(\", \")} — limited spend names only positions it leaves out`;\n }\n }\n return undefined;\n}\n","/**\n * Copies through Meta's own `copies` edges — `POST /{campaign_id}/copies`,\n * `/{adset_id}/copies` and `/{ad_id}/copies`. Meta builds the copy from what it\n * holds, so a copy keeps every setting, creative and child Baker cannot read\n * back or write (Advantage+ state, placements Baker does not model, the ad's\n * creative as it is). The snapshot-based `duplicate` stays for the other case:\n * a copy whose fields change in the same step.\n *\n * Live on v25.0 (2026-10-14):\n * - every copies edge IGNORES `validate_only`: an ad, an ad set and a campaign\n * were each copied for real by a validate-only call, so no copy is dry-run.\n * - a synchronous deep copy is refused when it holds 3 objects or more, counting\n * the copied object itself (subcode 1885194, \"must be fewer than 3\") — so an\n * ad set with two ads cannot be deep-copied synchronously. Every deep copy\n * therefore runs through Meta's asynchronous batch (`asyncbatch` on the Graph\n * root), which Meta documents up to 51 ads, and the publish waits for it.\n */\nimport { z } from \"zod\";\nimport { NUMERIC_ID_REGEX, TEMP_REF_REGEX } from \"./limits\";\n\nexport const COPY_STATUS_OPTIONS = [\"PAUSED\", \"ACTIVE\", \"INHERITED_FROM_SOURCE\"] as const;\nexport type CopyStatusOption = (typeof COPY_STATUS_OPTIONS)[number];\nexport const COPY_RENAME_STRATEGIES = [\"DEEP_RENAME\", \"ONLY_TOP_LEVEL_RENAME\", \"NO_RENAME\"] as const;\n\n/** Meta's ceiling on the ads one asynchronous deep copy carries. */\nexport const DEEP_COPY_MAX_ADS = 51;\n\nconst sourceIdSchema = z\n .string()\n .regex(\n NUMERIC_ID_REGEX,\n \"the source must be a published Meta id — to repeat something staged in this chat, stage it again\",\n );\nconst destinationSchema = z.union([\n z.string().regex(NUMERIC_ID_REGEX, \"expected a numeric id\"),\n z.string().regex(TEMP_REF_REGEX, \"expected a meta_temp_* reference\"),\n]);\n\n/** What a deep copy takes with it, counted when it is staged — for the review, and Meta's ceiling. */\nexport const copiedTreeSchema = z.strictObject({\n adSets: z.number().int().nonnegative().optional(),\n ads: z.number().int().nonnegative(),\n});\nexport type CopiedTree = z.infer<typeof copiedTreeSchema>;\n\nconst naming = {\n status_option: z.enum(COPY_STATUS_OPTIONS).optional(),\n rename_strategy: z.enum(COPY_RENAME_STRATEGIES).optional(),\n rename_prefix: z.string().min(1).max(100).optional(),\n rename_suffix: z.string().min(1).max(100).optional(),\n};\n\nconst schedule = {\n start_time: z.number().int().positive().optional(),\n end_time: z.number().int().positive().optional(),\n};\n\ninterface CopyShape {\n deep_copy?: boolean;\n rename_strategy?: string;\n rename_prefix?: string;\n rename_suffix?: string;\n start_time?: number;\n end_time?: number;\n sourceTree?: CopiedTree;\n}\n\nfunction copyIssues(p: CopyShape, ctx: z.RefinementCtx): void {\n if (p.rename_strategy === \"NO_RENAME\" && (p.rename_prefix || p.rename_suffix)) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"rename_strategy\"],\n message: \"NO_RENAME keeps every name as it is, so a prefix or suffix would be ignored — drop one of them\",\n });\n }\n if (p.start_time !== undefined && p.end_time !== undefined && p.end_time <= p.start_time) {\n ctx.addIssue({ code: \"custom\", path: [\"end_time\"], message: \"end_time must be after start_time\" });\n }\n if (p.deep_copy && p.sourceTree && p.sourceTree.ads > DEEP_COPY_MAX_ADS) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"deep_copy\"],\n message: `Meta copies at most ${DEEP_COPY_MAX_ADS} ads in one go and this holds ${p.sourceTree.ads} — copy its ad sets one by one (\\`adsets copy <id> --deep --to-campaign <copy>\\`)`,\n });\n }\n}\n\nexport const campaignCopySchema = z\n .strictObject({\n source_id: sourceIdSchema,\n /** Copy the ad sets and ads too. Without it Meta copies the campaign alone. */\n deep_copy: z.boolean().optional(),\n ...naming,\n /** For a deep copy only: when the copied ad sets start and end (else they keep the originals'). */\n ...schedule,\n sourceTree: copiedTreeSchema.optional(),\n })\n .superRefine((p, ctx) => {\n if (!p.deep_copy && (p.start_time !== undefined || p.end_time !== undefined)) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"start_time\"],\n message: \"start and end apply to the copied ad sets, so they need a deep copy (--deep)\",\n });\n }\n copyIssues(p, ctx);\n });\nexport type CampaignCopy = z.infer<typeof campaignCopySchema>;\n\nexport const adSetCopySchema = z\n .strictObject({\n source_id: sourceIdSchema,\n /** The campaign the copy goes into; omitted, it stays beside the original. */\n campaign_id: destinationSchema.optional(),\n /** Copy the ads too. */\n deep_copy: z.boolean().optional(),\n ...naming,\n ...schedule,\n sourceTree: copiedTreeSchema.optional(),\n })\n .superRefine(copyIssues);\nexport type AdSetCopy = z.infer<typeof adSetCopySchema>;\n\nexport const adCopySchema = z\n .strictObject({\n source_id: sourceIdSchema,\n /** The ad set the copy goes into; omitted, it stays beside the original. */\n adset_id: destinationSchema.optional(),\n ...naming,\n })\n .superRefine(copyIssues);\nexport type AdCopy = z.infer<typeof adCopySchema>;\n\nexport type MetaCopyPayload = CampaignCopy | AdSetCopy | AdCopy;\n\n/** What `status_option` means to the person approving it. */\nexport function copyStatusWords(status: CopyStatusOption | undefined): string {\n if (status === \"ACTIVE\") return \"live once published\";\n if (status === \"INHERITED_FROM_SOURCE\") return \"same status as the original\";\n return \"paused\";\n}\n\nfunction plural(count: number, one: string, many: string): string {\n return `${count} ${count === 1 ? one : many}`;\n}\n\n/** \"with its 3 ad sets and 7 ads\", or what a shallow copy leaves behind. */\nexport function copiedTreeWords(\n level: \"campaign\" | \"adSet\",\n deep: boolean | undefined,\n tree: CopiedTree | undefined,\n): string {\n if (!deep) {\n return level === \"campaign\" ? \"without its ad sets\" : \"without its ads\";\n }\n if (!tree) {\n return level === \"campaign\" ? \"with its ad sets and ads\" : \"with its ads\";\n }\n const ads = plural(tree.ads, \"ad\", \"ads\");\n return level === \"campaign\" && tree.adSets !== undefined\n ? `with its ${plural(tree.adSets, \"ad set\", \"ad sets\")} and ${ads}`\n : `with its ${ads}`;\n}\n\n/** Warnings a copy carries whatever it copies. */\nexport function copyWarnings(p: { status_option?: CopyStatusOption; deep_copy?: boolean }): string[] {\n const warnings: string[] = [];\n if (p.status_option === \"ACTIVE\") {\n warnings.push(\"the copy starts delivering — and spending — as soon as this is published\");\n }\n if (p.status_option === \"INHERITED_FROM_SOURCE\") {\n warnings.push(\"the copy takes the original's status, so a running original means a running copy once published\");\n }\n if (p.deep_copy) {\n warnings.push(\n \"Meta copies everything underneath in the background and the publish waits for it; the copied ads run copies of the original creatives (new creative ids, same content)\",\n );\n }\n return warnings;\n}\n","/**\n * Instant Experiences (Meta's API still calls them canvases): the full-screen\n * page an ad opens on the phone, owned by a Facebook Page and built from\n * elements — text, buttons, photos, videos, a product set, a footer.\n *\n * What Meta allows, live on v25.0 (2026-10-15) on Baker's own Page:\n * - elements are created one by one on `/{page_id}/canvas_elements`, then the\n * experience on `/{page_id}/canvases` with their ids (`body_element_ids`);\n * - only an UNPUBLISHED experience can be renamed or published later\n * (`POST /{canvas_id}`); a published one is fixed;\n * - nothing here can be deleted: `DELETE /{canvas_id}` and `DELETE /{element_id}`\n * both answer \"Unsupported delete request\" (subcode 33) — an experience\n * stays in the Page's library once made, so it is only ever made at publish;\n * - a photo element takes a photo already on the Page (`photo_id`) and nothing\n * else (an image URL or an ad image hash is refused); a new one is a staged\n * Page photo (`pagePhotos.ts`), behind the Page posts switch;\n * - a video element takes a video of the ad account (`video_id`);\n * - an ad can only open a PUBLISHED experience (\"Please provide a published\n * Instant Experience\").\n */\nimport { z } from \"zod\";\nimport { NUMERIC_ID_REGEX, TEMP_REF_REGEX } from \"./limits\";\n\nconst tempRefSchema = z.string().regex(TEMP_REF_REGEX, \"expected a meta_temp_* reference\");\nconst httpsUrlSchema = z\n .string()\n .url()\n .refine((value) => value.startsWith(\"https://\"), \"must be an https URL\");\n\nexport const CANVAS_LIMITS = { nameMax: 100, elementsMax: 20, textMax: 1000, buttonTextMax: 30 };\n\nconst textElement = z.strictObject({\n type: z.literal(\"text\"),\n text: z.string().trim().min(1).max(CANVAS_LIMITS.textMax),\n});\n\nconst buttonFields = {\n text: z.string().trim().min(1).max(CANVAS_LIMITS.buttonTextMax),\n url: httpsUrlSchema,\n};\n\nconst buttonElement = z.strictObject({\n type: z.literal(\"button\"),\n ...buttonFields,\n /** Meta's `button_style`: BUTTON_FILLED or BUTTON_OUTLINE (the two it took, live). */\n style: z.enum([\"filled\", \"outline\"]).default(\"filled\"),\n});\n\n/** A real id, or the meta_temp_* ref of something this chat creates first. */\nconst idOrRefSchema = z.union([z.string().regex(NUMERIC_ID_REGEX), tempRefSchema]);\n\nconst photoElement = z.strictObject({\n type: z.literal(\"photo\"),\n /**\n * A photo on the Page — the only picture Meta takes in an experience: its id,\n * or the ref of a Page photo this chat uploads (`pages photos upload`).\n */\n photo_id: idOrRefSchema,\n});\n\nconst videoElement = z\n .strictObject({\n type: z.literal(\"video\"),\n /** A video of the ad account (`baker ads meta media`), by id. */\n video_id: z.string().regex(NUMERIC_ID_REGEX).optional(),\n /** A library video this chat uploads (`media upload --kind video`). */\n videoRef: tempRefSchema.optional(),\n })\n .refine(\n (p) => (p.video_id === undefined) !== (p.videoRef === undefined),\n \"a video element names video_id OR videoRef\",\n );\n\nconst productSetElement = z.strictObject({\n type: z.literal(\"product_set\"),\n /** A product set's id, or the ref of one this chat creates. */\n product_set_id: idOrRefSchema,\n /** Meta's `show_in_feed`: the products also show under the ad itself — what makes a collection ad. */\n show_in_feed: z.boolean().default(true),\n /** Catalog tokens allowed, e.g. \"{{product.name}}\". */\n item_headline: z.string().trim().min(1).max(200).optional(),\n item_description: z.string().trim().min(1).max(200).optional(),\n});\n\n/** A button pinned to the bottom of the screen. */\nconst footerElement = z.strictObject({ type: z.literal(\"footer\"), ...buttonFields });\n\nexport const canvasElementSchema = z.discriminatedUnion(\"type\", [\n textElement,\n buttonElement,\n photoElement,\n videoElement,\n productSetElement,\n footerElement,\n]);\nexport type CanvasElement = z.infer<typeof canvasElementSchema>;\n\nexport const canvasCreateSchema = z\n .strictObject({\n page_id: z.string().regex(NUMERIC_ID_REGEX),\n name: z.string().trim().min(1).max(CANVAS_LIMITS.nameMax),\n /** Six hex digits, no `#` — e.g. FFFFFF. */\n background_color: z\n .string()\n .regex(/^[0-9A-Fa-f]{6}$/, \"a colour is six hex digits, e.g. FFFFFF\")\n .optional(),\n elements: z.array(canvasElementSchema).min(1).max(CANVAS_LIMITS.elementsMax),\n /** Publish it with the Session: an ad can only open a published experience, and a published one is fixed. */\n publish: z.boolean().default(true),\n })\n .superRefine((p, ctx) => {\n const footers = p.elements.flatMap((element, index) => (element.type === \"footer\" ? [index] : []));\n if (footers.length > 1 || (footers.length === 1 && footers[0] !== p.elements.length - 1)) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"elements\"],\n message: \"an experience has at most one footer, and it is the last element\",\n });\n }\n });\nexport type CanvasCreate = z.infer<typeof canvasCreateSchema>;\n\n/** Rename or publish an experience — Meta changes only an unpublished one. */\nexport const canvasUpdateSchema = z\n .strictObject({\n name: z.string().trim().min(1).max(CANVAS_LIMITS.nameMax).optional(),\n publish: z.literal(true).optional(),\n })\n .refine((p) => p.name !== undefined || p.publish !== undefined, \"rename the experience or publish it\");\nexport type CanvasUpdate = z.infer<typeof canvasUpdateSchema>;\n\n/** The address an ad opens an experience at. */\nexport function canvasLink(canvasId: string): string {\n return `https://fb.com/canvas_doc/${canvasId}`;\n}\n\n/** Element names Meta shows in the Page's library: the experience's name, its position and kind. */\nexport function canvasElementName(canvasName: string, index: number, type: string): string {\n return `${canvasName} · ${index + 1} ${type}`.slice(0, CANVAS_LIMITS.nameMax);\n}\n\n/** A button's own fields on the wire, shared by a body button and a footer's. */\nfunction buttonBody(text: string, url: string, style: \"filled\" | \"outline\", name: string): Record<string, unknown> {\n return {\n name,\n button_style: style === \"outline\" ? \"BUTTON_OUTLINE\" : \"BUTTON_FILLED\",\n rich_text: { plain_text: text },\n open_url_action: { url },\n };\n}\n\n/**\n * The `canvas_elements` POST body for one element, by Meta's parameter name.\n * A footer is two: its button first, then the footer holding it\n * (`footerBody`). A video names the video id it resolves to.\n */\nexport function canvasElementBody(element: CanvasElement, name: string): Record<string, unknown> {\n switch (element.type) {\n case \"text\":\n return { canvas_text: { name, rich_text: { plain_text: element.text } } };\n case \"button\":\n return { canvas_button: buttonBody(element.text, element.url, element.style, name) };\n case \"footer\":\n return { canvas_button: buttonBody(element.text, element.url, \"filled\", name) };\n case \"photo\":\n return { canvas_photo: { name, photo_id: element.photo_id } };\n case \"video\":\n return { canvas_video: { name, video_id: element.video_id ?? element.videoRef } };\n case \"product_set\":\n return {\n canvas_product_set: {\n name,\n product_set_id: element.product_set_id,\n show_in_feed: element.show_in_feed,\n ...(element.item_headline ? { item_headline: element.item_headline } : {}),\n ...(element.item_description ? { item_description: element.item_description } : {}),\n },\n };\n default:\n return {};\n }\n}\n\n/** The footer that holds a footer element's button. */\nexport function footerBody(buttonId: string, name: string): Record<string, unknown> {\n return { canvas_footer: { name, child_elements: [buttonId] } };\n}\n\n/** The experience itself, once its elements exist. */\nexport function canvasBody(p: CanvasCreate, elementIds: readonly string[]): Record<string, unknown> {\n return {\n name: p.name,\n body_element_ids: elementIds,\n is_published: p.publish,\n ...(p.background_color ? { background_color: p.background_color.toUpperCase() } : {}),\n };\n}\n\n/** A plain description of an experience's elements, in order, for the review and the summary. */\nexport function describeCanvasElements(elements: readonly CanvasElement[]): string[] {\n return elements.map((element) => {\n switch (element.type) {\n case \"text\":\n return `Text: ${element.text}`;\n case \"button\":\n return `Button \"${element.text}\" → ${element.url}`;\n case \"footer\":\n return `Footer button \"${element.text}\" → ${element.url}`;\n case \"photo\":\n return `Photo ${element.photo_id}`;\n case \"video\":\n return `Video ${element.video_id ?? element.videoRef}`;\n case \"product_set\":\n return `Products from set ${element.product_set_id}${element.show_in_feed ? \", also under the ad\" : \"\"}`;\n default:\n return \"Element\";\n }\n });\n}\n","/**\n * Instant Forms (Meta's API calls them lead gen forms): the form a lead ad\n * opens, owned by a Facebook Page and created on `/{page_id}/leadgen_forms`.\n *\n * What Meta allows, measured live on v25.0 (2026-10-15) on Baker's own Page:\n * - a form is permanent: it cannot be deleted (`status: DELETED` is refused,\n * subcode 1892082), only archived and unarchived (`status: ARCHIVED` /\n * `ACTIVE`, either token). Archived forms leave the Page's form library and\n * no ad can use them;\n * - nothing else on a form changes once it exists. A new name, headline or\n * follow-up link is answered `success: true` and ignored; sent beside a\n * status it is refused (\"Mutation on ACTIVE form is not allowed\", 1892083).\n * A changed form is a new form — `lead-forms duplicate`;\n * - `execution_options: [\"validate_only\"]` is ignored on both the create (it\n * made the form) and the status change (it archived it), so no lead form is\n * ever dry-run: these checks are the stage-time check;\n * - every form name on a Page is unique (1892019);\n * - Meta words its own questions: a label on EMAIL, PHONE… is refused\n * (1892063); CUSTOM, DATE_TIME and SLIDER must carry one (1892068);\n * - at most 15 custom questions (1892067); a multiple-choice question needs at\n * least 2 answers (1892130), each with a key (without keys: unknown error);\n * no two questions share a key (1892070);\n * - a privacy policy is required (1892075), and a follow-up link when there is\n * no thank-you screen (1892085);\n * - an intro in PARAGRAPH_STYLE holds exactly one paragraph, and needs a title.\n */\nimport { z } from \"zod\";\nimport { NUMERIC_ID_REGEX } from \"./limits\";\n\nconst httpsUrlSchema = z\n .string()\n .url()\n .refine((value) => value.startsWith(\"https://\"), \"must be an https URL\");\n\n/** Meta's 32 form languages (the `locale` enum Meta answers with when given anything else). */\nexport const LEAD_FORM_LOCALES = [\n \"AR_AR\",\n \"CS_CZ\",\n \"DA_DK\",\n \"DE_DE\",\n \"EL_GR\",\n \"EN_GB\",\n \"EN_US\",\n \"ES_ES\",\n \"ES_LA\",\n \"FI_FI\",\n \"FR_FR\",\n \"HE_IL\",\n \"HI_IN\",\n \"HU_HU\",\n \"ID_ID\",\n \"IT_IT\",\n \"JA_JP\",\n \"KO_KR\",\n \"NB_NO\",\n \"NL_NL\",\n \"PL_PL\",\n \"PT_BR\",\n \"PT_PT\",\n \"RO_RO\",\n \"RU_RU\",\n \"SV_SE\",\n \"TH_TH\",\n \"TR_TR\",\n \"VI_VN\",\n \"ZH_CN\",\n \"ZH_HK\",\n \"ZH_TW\",\n] as const;\nexport type LeadFormLocale = (typeof LEAD_FORM_LOCALES)[number];\n\n/** Every question `type` Meta documents for `/{page_id}/leadgen_forms` (v26). `MARITIAL_STATUS` is Meta's spelling. */\nexport const LEAD_FORM_QUESTION_TYPES = [\n \"CUSTOM\",\n \"FULL_NAME\",\n \"FIRST_NAME\",\n \"LAST_NAME\",\n \"EMAIL\",\n \"PHONE\",\n \"PHONE_OTP\",\n \"WORK_EMAIL\",\n \"WORK_PHONE_NUMBER\",\n \"WHATSAPP_NUMBER\",\n \"COMPANY_NAME\",\n \"JOB_TITLE\",\n \"WEBSITE\",\n \"STREET_ADDRESS\",\n \"ADDRESS_LINE_TWO\",\n \"CITY\",\n \"STATE\",\n \"PROVINCE\",\n \"COUNTRY\",\n \"ZIP\",\n \"POST_CODE\",\n \"DOB\",\n \"GENDER\",\n \"MARITIAL_STATUS\",\n \"RELATIONSHIP_STATUS\",\n \"MILITARY_STATUS\",\n \"EDUCATION_LEVEL\",\n \"VIN\",\n \"LICENSE_PLATE\",\n \"EMAIL_ALIAS\",\n \"DATE_TIME\",\n \"SLIDER\",\n \"ID_CPF\",\n \"ID_AR_DNI\",\n \"ID_CL_RUT\",\n \"ID_CO_CC\",\n \"ID_EC_CI\",\n \"ID_PE_DNI\",\n \"ID_MX_RFC\",\n \"USER_PROVIDED_PHONE_NUMBER\",\n \"STORE_LOOKUP\",\n \"STORE_LOOKUP_WITH_TYPEAHEAD\",\n \"LOCAL_DEALER\",\n \"JOIN_CODE\",\n \"FACEBOOK_LEAD_ID\",\n \"MESSENGER\",\n \"THREAD_LINK\",\n] as const;\nexport type LeadFormQuestionType = (typeof LEAD_FORM_QUESTION_TYPES)[number];\n\n/** Questions the advertiser words: Meta refuses them without a label and counts them as custom questions. */\nexport const WORDED_QUESTION_TYPES: ReadonlySet<string> = new Set([\"CUSTOM\", \"DATE_TIME\", \"SLIDER\"]);\n\n/** The country each national-ID question validates for. The ad set must target only that country. */\nexport const NATIONAL_ID_COUNTRY: Readonly<Record<string, string>> = {\n ID_AR_DNI: \"AR\",\n ID_CPF: \"BR\",\n ID_CL_RUT: \"CL\",\n ID_CO_CC: \"CO\",\n ID_EC_CI: \"EC\",\n ID_PE_DNI: \"PE\",\n ID_MX_RFC: \"MX\",\n};\n\n/**\n * Types Meta lists but refuses on a form made through the API, measured live\n * (v25.0, 2026-10-15). Refused at staging with the reason, rather than at\n * Publish with Meta's \"An unknown error has occurred\".\n */\nexport const REFUSED_QUESTION_TYPES: Readonly<Record<string, string>> = {\n USER_PROVIDED_PHONE_NUMBER: \"Meta refuses it on a form made through its API — ask for PHONE instead\",\n LOCAL_DEALER: \"Meta refuses it on a form made through its API (it needs a dealer setup in Ads Manager)\",\n JOIN_CODE: \"Meta refuses it on a form made through its API\",\n FACEBOOK_LEAD_ID: \"Meta refuses it on a form made through its API\",\n MESSENGER: \"Meta refuses it on a form made through its API\",\n THREAD_LINK: \"Meta refuses it on a form made through its API\",\n STORE_LOOKUP:\n \"a store locator needs a store-locations setup Meta does not open to Baker (#3, no capability) — build that form in Ads Manager\",\n STORE_LOOKUP_WITH_TYPEAHEAD:\n \"a store locator needs a store-locations setup Meta does not open to Baker (#3, no capability) — build that form in Ads Manager\",\n};\n\nexport const LEAD_FORM_LIMITS = {\n nameMax: 255,\n labelMax: 255,\n questionsMax: 50,\n wordedQuestionsMax: 15,\n optionsMin: 2,\n optionsMax: 100,\n optionMax: 255,\n privacyLinkTextMax: 70,\n textMax: 1000,\n introItemsMax: 5,\n buttonTextMax: 60,\n checkboxesMax: 10,\n trackingParametersMax: 20,\n};\n\nconst keySchema = z\n .string()\n .trim()\n .min(1)\n .max(100)\n .regex(/^[A-Za-z0-9_]+$/, \"a key is letters, digits and underscores\");\n\nconst optionSchema = z.strictObject({\n value: z.string().trim().min(1).max(LEAD_FORM_LIMITS.optionMax),\n /** What the answer is stored as on a lead; Baker numbers them when left out (Meta needs one). */\n key: keySchema.optional(),\n});\n\n/** Legacy spelling an earlier Baker accepted; Meta's type is ZIP. */\nconst questionTypeSchema = z.preprocess(\n (value) => (value === \"ZIP_CODE\" ? \"ZIP\" : value),\n z.enum(LEAD_FORM_QUESTION_TYPES),\n);\n\nexport const leadFormQuestionSchema = z.strictObject({\n type: questionTypeSchema,\n /** The question's wording — CUSTOM, DATE_TIME and SLIDER only; Meta words the rest in the form's language. */\n label: z.string().trim().min(1).max(LEAD_FORM_LIMITS.labelMax).optional(),\n /** The field name the answer is stored under on a lead (Meta picks one when left out). */\n key: keySchema.optional(),\n /** A short note under the question, e.g. \"We'll call to confirm the time.\" */\n inlineContext: z.string().trim().min(1).max(LEAD_FORM_LIMITS.textMax).optional(),\n /** Multiple choice answers (CUSTOM only). */\n options: z.array(optionSchema).max(LEAD_FORM_LIMITS.optionsMax).optional(),\n});\nexport type LeadFormQuestion = z.infer<typeof leadFormQuestionSchema>;\n\n/** Thank-you screen buttons Meta takes on a form made through its API (live, v25.0). */\nexport const THANK_YOU_BUTTON_TYPES = [\n \"VIEW_WEBSITE\",\n \"DOWNLOAD\",\n \"BOOK_ON_WEBSITE\",\n \"CALL_BUSINESS\",\n \"WHATSAPP\",\n \"P2B_MESSENGER\",\n \"PROMO_CODE\",\n \"NONE\",\n \"MESSAGE_BUSINESS\",\n \"SCHEDULE_APPOINTMENT\",\n \"VIEW_ON_FACEBOOK\",\n] as const;\n\n/** What Meta answered when asked for these buttons through the API (live, v25.0, 2026-10-15). */\nexport const REFUSED_THANK_YOU_BUTTONS: Readonly<Record<string, string>> = {\n MESSAGE_BUSINESS: 'Meta answers \"This button type is not yet supported\" — use P2B_MESSENGER to open Messenger',\n SCHEDULE_APPOINTMENT:\n 'Meta answers \"Appointment integration is missing\" — it needs a booking integration set up in Meta Business Suite',\n VIEW_ON_FACEBOOK:\n \"it opens a downloadable file Meta takes only as an upload Baker cannot send — use DOWNLOAD with a link\",\n};\n\n/** Buttons that open a website, and so need one. */\nexport const WEBSITE_BUTTONS: ReadonlySet<string> = new Set([\"VIEW_WEBSITE\", \"DOWNLOAD\", \"BOOK_ON_WEBSITE\"]);\n\nconst thankYouSchema = z.strictObject({\n title: z.string().trim().min(1).max(LEAD_FORM_LIMITS.nameMax),\n body: z.string().trim().min(1).max(LEAD_FORM_LIMITS.textMax).optional(),\n buttonType: z.enum(THANK_YOU_BUTTON_TYPES).default(\"VIEW_WEBSITE\"),\n buttonText: z.string().trim().min(1).max(LEAD_FORM_LIMITS.buttonTextMax).optional(),\n /** Where VIEW_WEBSITE, DOWNLOAD and BOOK_ON_WEBSITE go; defaults to the form's follow-up link. */\n websiteUrl: httpsUrlSchema.optional(),\n /** CALL_BUSINESS: the number, with its country. */\n businessPhoneNumber: z.string().trim().min(5).max(30).optional(),\n countryCode: z\n .string()\n .regex(/^[A-Z]{2}$/, \"a two-letter country code, e.g. US\")\n .optional(),\n /** Also offer to continue the conversation in Messenger. */\n enableMessenger: z.boolean().optional(),\n});\n\nconst introSchema = z.strictObject({\n title: z.string().trim().min(1).max(LEAD_FORM_LIMITS.nameMax),\n /** PARAGRAPH_STYLE: one paragraph. LIST_STYLE: up to five bullet points. */\n style: z.enum([\"PARAGRAPH_STYLE\", \"LIST_STYLE\"]).default(\"PARAGRAPH_STYLE\"),\n content: z.array(z.string().trim().min(1).max(LEAD_FORM_LIMITS.textMax)).min(1).max(LEAD_FORM_LIMITS.introItemsMax),\n buttonText: z.string().trim().min(1).max(LEAD_FORM_LIMITS.buttonTextMax).optional(),\n /** A photo already on the Page, by id — the only cover Meta takes from Baker. */\n coverPhotoId: z.string().regex(NUMERIC_ID_REGEX).optional(),\n});\n\nconst disclaimerSchema = z.strictObject({\n title: z.string().trim().min(1).max(LEAD_FORM_LIMITS.nameMax).optional(),\n body: z.string().trim().min(1).max(LEAD_FORM_LIMITS.textMax),\n /** Words of the body that link somewhere — each `text` must appear in the body. */\n links: z\n .array(z.strictObject({ text: z.string().trim().min(1), url: httpsUrlSchema }))\n .max(5)\n .optional(),\n checkboxes: z\n .array(\n z.strictObject({\n text: z.string().trim().min(1).max(LEAD_FORM_LIMITS.textMax),\n key: keySchema.optional(),\n /** Whether the box must be ticked to submit (Meta's default: required). */\n required: z.boolean().default(true),\n checkedByDefault: z.boolean().default(false),\n }),\n )\n .max(LEAD_FORM_LIMITS.checkboxesMax)\n .optional(),\n});\n\ntype IssueSink = z.RefinementCtx;\n\nfunction refuseQuestion(question: LeadFormQuestion, index: number, ctx: IssueSink): void {\n const path = [\"questions\", index];\n const refused = REFUSED_QUESTION_TYPES[question.type];\n if (refused) {\n ctx.addIssue({ code: \"custom\", path: [...path, \"type\"], message: `${question.type}: ${refused}` });\n }\n const worded = WORDED_QUESTION_TYPES.has(question.type);\n if (worded && !question.label) {\n ctx.addIssue({ code: \"custom\", path: [...path, \"label\"], message: `${question.type} questions need a label` });\n }\n if (!worded && question.label) {\n ctx.addIssue({\n code: \"custom\",\n path: [...path, \"label\"],\n message: `Meta words ${question.type} itself, in the form's language — drop the label, or ask a CUSTOM question`,\n });\n }\n if (question.options && question.type !== \"CUSTOM\") {\n ctx.addIssue({ code: \"custom\", path: [...path, \"options\"], message: \"only a CUSTOM question takes answers\" });\n }\n if (question.options && question.options.length < LEAD_FORM_LIMITS.optionsMin) {\n ctx.addIssue({\n code: \"custom\",\n path: [...path, \"options\"],\n message: \"a multiple-choice question needs at least 2 answers\",\n });\n }\n if (question.inlineContext && !worded) {\n ctx.addIssue({\n code: \"custom\",\n path: [...path, \"inlineContext\"],\n message: \"a note under the question goes on a CUSTOM, DATE_TIME or SLIDER question\",\n });\n }\n}\n\n/** The key a question's answer is stored under on a lead: its own, or Meta's for its type. */\nfunction storedKey(question: LeadFormQuestion): string | undefined {\n return question.key ?? (WORDED_QUESTION_TYPES.has(question.type) ? undefined : question.type.toLowerCase());\n}\n\nfunction refuseQuestions(questions: readonly LeadFormQuestion[], ctx: IssueSink): void {\n questions.forEach((question, index) => {\n refuseQuestion(question, index, ctx);\n });\n const worded = questions.filter((question) => WORDED_QUESTION_TYPES.has(question.type)).length;\n if (worded > LEAD_FORM_LIMITS.wordedQuestionsMax) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"questions\"],\n message: `Meta allows at most ${LEAD_FORM_LIMITS.wordedQuestionsMax} custom questions (CUSTOM, DATE_TIME, SLIDER) on a form`,\n });\n }\n const ids = questions.filter((question) => question.type in NATIONAL_ID_COUNTRY);\n if (ids.length > 1) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"questions\"],\n message: \"a form asks for one national ID at most, and its ads must target only that ID's country\",\n });\n }\n const seen = new Map<string, number>();\n questions.forEach((question, index) => {\n const key = storedKey(question);\n const typeKey = `${question.type}:${question.label ?? \"\"}`;\n for (const id of [key && `key:${key}`, `q:${typeKey}`]) {\n if (!id) continue;\n if (seen.has(id)) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"questions\", index],\n message: id.startsWith(\"key:\") ? `two questions share the key \"${key}\"` : \"duplicate question\",\n });\n }\n seen.set(id, index);\n }\n });\n}\n\ntype ThankYou = z.infer<typeof thankYouSchema>;\n\nfunction refuseThankYou(thankYou: ThankYou, followUpActionUrl: string | undefined, ctx: IssueSink): void {\n const path = [\"thankYou\"];\n const refused = REFUSED_THANK_YOU_BUTTONS[thankYou.buttonType];\n if (refused) {\n ctx.addIssue({ code: \"custom\", path: [...path, \"buttonType\"], message: `${thankYou.buttonType}: ${refused}` });\n }\n if (thankYou.buttonType !== \"NONE\" && thankYou.buttonType !== \"VIEW_WEBSITE\" && !thankYou.buttonText) {\n ctx.addIssue({ code: \"custom\", path: [...path, \"buttonText\"], message: \"the thank-you button needs its text\" });\n }\n if (WEBSITE_BUTTONS.has(thankYou.buttonType) && !thankYou.websiteUrl && !followUpActionUrl) {\n ctx.addIssue({\n code: \"custom\",\n path: [...path, \"websiteUrl\"],\n message: `a ${thankYou.buttonType} button needs the website it opens (websiteUrl or followUpActionUrl)`,\n });\n }\n if (thankYou.buttonType === \"CALL_BUSINESS\" && (!thankYou.businessPhoneNumber || !thankYou.countryCode)) {\n ctx.addIssue({\n code: \"custom\",\n path: [...path, \"businessPhoneNumber\"],\n message: \"a CALL_BUSINESS button needs businessPhoneNumber and its countryCode\",\n });\n }\n}\n\ntype Intro = z.infer<typeof introSchema>;\n\nfunction refuseIntro(intro: Intro, ctx: IssueSink): void {\n if (intro.style === \"PARAGRAPH_STYLE\" && intro.content.length !== 1) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"intro\", \"content\"],\n message: \"a PARAGRAPH_STYLE intro holds exactly one paragraph — use LIST_STYLE for bullet points\",\n });\n }\n}\n\ntype Disclaimer = z.infer<typeof disclaimerSchema>;\n\nfunction refuseDisclaimer(disclaimer: Disclaimer, ctx: IssueSink): void {\n for (const [index, link] of (disclaimer.links ?? []).entries()) {\n if (!disclaimer.body.includes(link.text)) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"disclaimer\", \"links\", index, \"text\"],\n message: `\"${link.text}\" is not in the disclaimer's text — a link is words of the text`,\n });\n }\n }\n}\n\nexport const leadFormCreateSchema = z\n .strictObject({\n page_id: z.string().regex(NUMERIC_ID_REGEX),\n /** Unique among the Page's forms — Meta refuses a name the Page already has. */\n name: z.string().trim().min(1).max(LEAD_FORM_LIMITS.nameMax),\n locale: z.enum(LEAD_FORM_LOCALES).default(\"EN_US\"),\n /** The headline above the questions. */\n questionPageHeadline: z.string().trim().min(1).max(LEAD_FORM_LIMITS.nameMax).optional(),\n questions: z.array(leadFormQuestionSchema).min(1).max(LEAD_FORM_LIMITS.questionsMax),\n privacyPolicyUrl: httpsUrlSchema,\n privacyPolicyLinkText: z.string().trim().min(1).max(LEAD_FORM_LIMITS.privacyLinkTextMax).default(\"Privacy Policy\"),\n /** Where \"View website\" goes after submitting. Required without a thank-you screen. */\n followUpActionUrl: httpsUrlSchema.optional(),\n /** Higher intent: people review and confirm their answers before submitting. Off = more volume. */\n optimizedForQuality: z.boolean().default(false),\n /** The intro screen before the questions (Meta's context card). */\n intro: introSchema.optional(),\n /** Extra terms and consent checkboxes shown with the privacy policy. */\n disclaimer: disclaimerSchema.optional(),\n thankYou: thankYouSchema.optional(),\n /**\n * \"restricted\": only people the ad was shown to can open the form (Meta's\n * default when unset). \"open\": anyone the ad is shared with can.\n */\n sharing: z.enum([\"restricted\", \"open\"]).optional(),\n /** Confirm the phone number with a code sent by text message. Needs a PHONE question. */\n smsVerification: z.boolean().optional(),\n /** Name/value pairs Meta adds to every lead's answers, e.g. { \"campaign\": \"spring\" }. */\n trackingParameters: z\n .record(keySchema, z.string().trim().min(1).max(LEAD_FORM_LIMITS.optionMax))\n .refine(\n (value) => Object.keys(value).length <= LEAD_FORM_LIMITS.trackingParametersMax,\n `at most ${LEAD_FORM_LIMITS.trackingParametersMax} tracking parameters`,\n )\n .optional(),\n })\n .superRefine((form, ctx) => {\n refuseQuestions(form.questions, ctx);\n if (form.thankYou) {\n refuseThankYou(form.thankYou, form.followUpActionUrl, ctx);\n } else if (!form.followUpActionUrl) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"followUpActionUrl\"],\n message: \"a form without a thank-you screen needs followUpActionUrl (Meta's View website button)\",\n });\n }\n if (form.intro) refuseIntro(form.intro, ctx);\n if (form.disclaimer) refuseDisclaimer(form.disclaimer, ctx);\n if (form.smsVerification && !form.questions.some((question) => question.type === \"PHONE\")) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"smsVerification\"],\n message: \"text-message verification needs a PHONE question\",\n });\n }\n });\nexport type LeadFormCreate = z.infer<typeof leadFormCreateSchema>;\n\n/**\n * The one change Meta makes to an existing form: archive it (it leaves the\n * Page's form library and no ad can use it) or bring it back. Anything else is\n * refused here, because Meta answers it `success: true` and changes nothing.\n */\nexport const leadFormUpdateSchema = z\n .looseObject({ status: z.enum([\"ARCHIVED\", \"ACTIVE\"]).optional() })\n .superRefine((p, ctx) => {\n const others = Object.keys(p).filter((key) => key !== \"status\");\n if (others.length > 0) {\n ctx.addIssue({\n code: \"custom\",\n path: [others[0] ?? \"status\"],\n message:\n `Meta keeps an Instant Form's ${others.join(\", \")} as they were once the form exists (it answers success and ` +\n \"changes nothing). Make a changed copy instead: `baker ads meta lead-forms duplicate <formId> --name \" +\n '\"…\" --file changes.json`, point the ads at the copy, then `lead-forms archive <formId>`.',\n });\n }\n if (p.status === undefined && others.length === 0) {\n ctx.addIssue({ code: \"custom\", path: [\"status\"], message: \"archive the form or unarchive it (status)\" });\n }\n });\nexport type LeadFormUpdate = { status?: \"ARCHIVED\" | \"ACTIVE\" };\n\nfunction questionBody(question: LeadFormQuestion): Record<string, unknown> {\n return {\n type: question.type,\n ...(question.key ? { key: question.key } : {}),\n ...(question.label ? { label: question.label } : {}),\n ...(question.inlineContext ? { inline_context: question.inlineContext } : {}),\n // Meta refuses answers without keys (unknown error, live) — number the ones left out.\n ...(question.options\n ? {\n options: question.options.map((option, i) => ({ value: option.value, key: option.key ?? `option_${i + 1}` })),\n }\n : {}),\n };\n}\n\nfunction thankYouBody(thankYou: ThankYou, followUpActionUrl: string | undefined): Record<string, unknown> {\n const website = thankYou.websiteUrl ?? followUpActionUrl;\n return {\n title: thankYou.title,\n ...(thankYou.body ? { body: thankYou.body } : {}),\n button_type: thankYou.buttonType,\n ...(thankYou.buttonType === \"NONE\"\n ? {}\n : { button_text: thankYou.buttonText ?? (thankYou.buttonType === \"VIEW_WEBSITE\" ? \"View website\" : undefined) }),\n ...(WEBSITE_BUTTONS.has(thankYou.buttonType) && website ? { website_url: website } : {}),\n ...(thankYou.businessPhoneNumber ? { business_phone_number: thankYou.businessPhoneNumber } : {}),\n ...(thankYou.countryCode ? { country_code: thankYou.countryCode } : {}),\n ...(thankYou.enableMessenger !== undefined ? { enable_messenger: thankYou.enableMessenger } : {}),\n };\n}\n\nfunction introBody(intro: Intro): Record<string, unknown> {\n return {\n title: intro.title,\n style: intro.style,\n content: intro.content,\n ...(intro.buttonText ? { button_text: intro.buttonText } : {}),\n ...(intro.coverPhotoId ? { cover_photo_id: intro.coverPhotoId } : {}),\n };\n}\n\n/** A linked phrase as Meta's `url_entities`: where in the text it starts, and how long it is. */\nfunction disclaimerBody(disclaimer: Disclaimer): Record<string, unknown> {\n const links = (disclaimer.links ?? []).map((link) => ({\n offset: disclaimer.body.indexOf(link.text),\n length: link.text.length,\n url: link.url,\n }));\n return {\n ...(disclaimer.title ? { title: disclaimer.title } : {}),\n body: { text: disclaimer.body, ...(links.length > 0 ? { url_entities: links } : {}) },\n ...(disclaimer.checkboxes\n ? {\n checkboxes: disclaimer.checkboxes.map((box, i) => ({\n text: box.text,\n key: box.key ?? `consent_${i + 1}`,\n is_required: box.required,\n is_checked_by_default: box.checkedByDefault,\n })),\n }\n : {}),\n };\n}\n\n/** The `/{page_id}/leadgen_forms` POST body, by Meta's parameter names. */\nexport function leadFormBody(p: LeadFormCreate): Record<string, unknown> {\n return {\n name: p.name,\n locale: p.locale,\n questions: p.questions.map(questionBody),\n privacy_policy: { url: p.privacyPolicyUrl, link_text: p.privacyPolicyLinkText },\n ...(p.followUpActionUrl ? { follow_up_action_url: p.followUpActionUrl } : {}),\n is_optimized_for_quality: p.optimizedForQuality,\n ...(p.questionPageHeadline ? { question_page_custom_headline: p.questionPageHeadline } : {}),\n ...(p.intro ? { context_card: introBody(p.intro) } : {}),\n ...(p.disclaimer ? { custom_disclaimer: disclaimerBody(p.disclaimer) } : {}),\n ...(p.thankYou ? { thank_you_page: thankYouBody(p.thankYou, p.followUpActionUrl) } : {}),\n ...(p.sharing ? { block_display_for_non_targeted_viewer: p.sharing === \"restricted\" } : {}),\n ...(p.smsVerification !== undefined ? { is_phone_sms_verify_enabled: p.smsVerification } : {}),\n ...(p.trackingParameters ? { tracking_parameters: p.trackingParameters } : {}),\n };\n}\n\n// --- Duplicate: a stageable form from a live one ---\n\ntype Raw = Record<string, unknown>;\nconst rec = (value: unknown): Raw =>\n value && typeof value === \"object\" && !Array.isArray(value) ? (value as Raw) : {};\nconst list = (value: unknown): Raw[] => (Array.isArray(value) ? value.map(rec) : []);\nconst text = (value: unknown): string | undefined => (typeof value === \"string\" && value !== \"\" ? value : undefined);\nconst flag = (value: unknown): boolean | undefined => (typeof value === \"boolean\" ? value : undefined);\n\n/** Drop the keys whose value is undefined, so the spec reads as what the form holds. */\nfunction defined(record: Raw): Raw {\n return Object.fromEntries(Object.entries(record).filter(([, value]) => value !== undefined));\n}\n\nfunction questionFromLive(q: Raw): { question?: Raw; skipped?: string } {\n const type = text(q.type) ?? \"\";\n const name = text(q.label) ?? type;\n if (q.conditional_questions_group_id || q.dependent_conditional_questions) {\n return { skipped: `question \"${name}\" (conditional answers need a CSV upload only Ads Manager takes)` };\n }\n if (!(LEAD_FORM_QUESTION_TYPES as readonly string[]).includes(type) || REFUSED_QUESTION_TYPES[type]) {\n return { skipped: `question \"${name}\" (${type} cannot be made through Meta's API)` };\n }\n const options = list(q.options).map((o) => defined({ value: text(o.value), key: text(o.key) }));\n return {\n question: defined({\n type,\n key: text(q.key),\n label: WORDED_QUESTION_TYPES.has(type) ? text(q.label) : undefined,\n inlineContext: text(q.inline_context),\n options: options.length > 0 ? options : undefined,\n }),\n };\n}\n\nfunction introFromLive(card: Raw): Raw | undefined {\n if (!text(card.title)) return undefined;\n return defined({\n title: text(card.title),\n style: text(card.style),\n content: Array.isArray(card.content) ? card.content : undefined,\n buttonText: text(card.button_text),\n coverPhotoId: text(rec(card.cover_photo).id),\n });\n}\n\nfunction disclaimerFromLive(d: Raw): Raw | undefined {\n const body = text(rec(d.body).text);\n if (!body) return undefined;\n const links = list(rec(d.body).url_entities).flatMap((entity) => {\n const offset = Number(entity.offset);\n const length = Number(entity.length);\n const url = text(entity.url);\n return url && Number.isInteger(offset) && length > 0 ? [{ text: body.slice(offset, offset + length), url }] : [];\n });\n const checkboxes = list(d.checkboxes).map((box) =>\n defined({\n text: text(box.text),\n key: text(box.key),\n required: flag(box.is_required),\n checkedByDefault: flag(box.is_checked_by_default),\n }),\n );\n return defined({\n title: text(d.title),\n body,\n links: links.length > 0 ? links : undefined,\n checkboxes: checkboxes.length > 0 ? checkboxes : undefined,\n });\n}\n\nfunction thankYouFromLive(t: Raw, notCopied: string[]): Raw | undefined {\n if (!text(t.title)) return undefined;\n if (t.gated_file) notCopied.push(\"the thank-you screen's downloadable file\");\n return defined({\n title: text(t.title),\n body: text(t.body),\n buttonType: text(t.button_type),\n buttonText: text(t.button_text),\n websiteUrl: text(t.website_url),\n businessPhoneNumber: text(t.business_phone_number),\n countryCode: text(t.country_code),\n enableMessenger: flag(t.enable_messenger) || undefined,\n });\n}\n\nfunction trackingFromLive(value: unknown): Record<string, string> | undefined {\n const pairs = list(value).flatMap((pair) => {\n const key = text(pair.key);\n const v = text(pair.value);\n return key && v ? [[key, v] as const] : [];\n });\n return pairs.length > 0 ? Object.fromEntries(pairs) : undefined;\n}\n\n/** Meta returns the form's language as `en_US`; Baker stages it as `EN_US`. */\nfunction localeFromLive(value: unknown): string | undefined {\n const locale = text(value)?.toUpperCase();\n return locale && (LEAD_FORM_LOCALES as readonly string[]).includes(locale) ? locale : undefined;\n}\n\n/**\n * A live form (read with `LEAD_FORM_SPEC_FIELDS`) as a `leadForm.create`\n * payload, ready to change and stage as a new form — the only way Meta lets a\n * form change. What cannot be carried over is named, never silently dropped.\n */\nexport function leadFormSpecFromLive(live: Raw): { spec: Raw; notCopied: string[] } {\n const notCopied: string[] = [];\n const questions = list(live.questions).flatMap((q) => {\n const { question, skipped } = questionFromLive(q);\n if (skipped) notCopied.push(skipped);\n return question ? [question] : [];\n });\n const legal = rec(live.legal_content);\n const privacy = rec(legal.privacy_policy);\n const blocked = flag(live.block_display_for_non_targeted_viewer);\n const spec = defined({\n page_id: text(rec(live.page).id) ?? text(live.page_id),\n name: text(live.name),\n locale: localeFromLive(live.locale),\n questionPageHeadline: text(live.question_page_custom_headline),\n questions,\n privacyPolicyUrl: text(privacy.url) ?? text(live.privacy_policy_url),\n privacyPolicyLinkText: text(privacy.link_text),\n followUpActionUrl: text(live.follow_up_action_url),\n optimizedForQuality: flag(live.is_optimized_for_quality),\n intro: introFromLive(rec(live.context_card)),\n disclaimer: disclaimerFromLive(rec(legal.custom_disclaimer)),\n thankYou: thankYouFromLive(rec(live.thank_you_page), notCopied),\n sharing: blocked === undefined ? undefined : blocked ? \"restricted\" : \"open\",\n trackingParameters: trackingFromLive(live.tracking_parameters),\n });\n // Meta takes `is_phone_sms_verify_enabled` on a create and never returns it\n // (\"(#100) Tried accessing nonexisting field\", live on v25.0, 2026-10-15).\n if (questions.some((question) => question.type === \"PHONE\")) {\n notCopied.push(\n \"whether the phone number is confirmed by text message — Meta does not say; set smsVerification again if the original form asked for it\",\n );\n }\n return { spec, notCopied };\n}\n\n/** What `leadFormSpecFromLive` reads off a form node. */\nexport const LEAD_FORM_SPEC_FIELDS =\n \"id,name,status,locale,page{id,name},questions,privacy_policy_url,follow_up_action_url,context_card,legal_content,\" +\n \"thank_you_page,is_optimized_for_quality,block_display_for_non_targeted_viewer,tracking_parameters,\" +\n \"question_page_custom_headline\";\n\n/** Each form language in plain words, for the review. */\nexport const LEAD_FORM_LOCALE_NAMES: Readonly<Record<LeadFormLocale, string>> = {\n AR_AR: \"Arabic\",\n CS_CZ: \"Czech\",\n DA_DK: \"Danish\",\n DE_DE: \"German\",\n EL_GR: \"Greek\",\n EN_GB: \"English (UK)\",\n EN_US: \"English (US)\",\n ES_ES: \"Spanish (Spain)\",\n ES_LA: \"Spanish (Latin America)\",\n FI_FI: \"Finnish\",\n FR_FR: \"French\",\n HE_IL: \"Hebrew\",\n HI_IN: \"Hindi\",\n HU_HU: \"Hungarian\",\n ID_ID: \"Indonesian\",\n IT_IT: \"Italian\",\n JA_JP: \"Japanese\",\n KO_KR: \"Korean\",\n NB_NO: \"Norwegian\",\n NL_NL: \"Dutch\",\n PL_PL: \"Polish\",\n PT_BR: \"Portuguese (Brazil)\",\n PT_PT: \"Portuguese (Portugal)\",\n RO_RO: \"Romanian\",\n RU_RU: \"Russian\",\n SV_SE: \"Swedish\",\n TH_TH: \"Thai\",\n TR_TR: \"Turkish\",\n VI_VN: \"Vietnamese\",\n ZH_CN: \"Chinese (Simplified)\",\n ZH_HK: \"Chinese (Hong Kong)\",\n ZH_TW: \"Chinese (Traditional)\",\n};\n","/**\n * What Meta does with a picture or a video in each placement — the published\n * Ads Guide numbers, corrected where Meta was measured doing something else.\n *\n * Image crops were read off `generatepreviews` on v25.0 (2026-10-14), from the\n * `stp=c<x>.<y>.<w>.<h>` crop Meta serves each placement's picture with:\n *\n * | Picture | Feed (FB mobile, IG, Explore) | Stories & Reels card | Right column |\n * |----------------|-------------------------------|----------------------|--------------|\n * | 9:16 1440×2560 | cut to 4:5 (c0.380.1440.1800) | full screen | cut to 1:1 |\n * | 2:3 1024×1536 | cut to 4:5 (c0.128.1024.1280) | cut to 4:5 | cut to 1:1 |\n * | 4:5 1440×1800 | whole | whole, as a card | cut to 1:1 |\n * | 1:1, 1.91:1, 16:9 | whole | whole, as a card | whole |\n *\n * So a feed never shows more than 4:5 of height, a Stories/Reels slot is full\n * screen only for 9:16, and the right column never more than 1:1.\n */\n\nexport type PlacementGroup = \"feed\" | \"stories_reels\" | \"right_column\";\n\nexport const PLACEMENT_GROUP_LABELS: Record<PlacementGroup, string> = {\n feed: \"Feeds (Facebook, Instagram, Explore, Marketplace)\",\n stories_reels: \"Stories & Reels\",\n right_column: \"Facebook right column\",\n};\n\nexport interface PlacementFit {\n group: PlacementGroup;\n /**\n * `native`: the placement's own shape, edge to edge. `fits`: shown whole.\n * `card`: shown whole but smaller than the screen (Stories/Reels for anything\n * but 9:16). `cropped`: Meta cuts `cropPercent`% of the picture away.\n */\n fit: \"native\" | \"fits\" | \"card\" | \"cropped\";\n cropPercent?: number;\n}\n\n/** Width over height. */\nconst RATIO_4_5 = 4 / 5;\nconst RATIO_9_16 = 9 / 16;\nconst RATIO_1_91 = 1.91;\n/** Meta's tolerance for \"this is the 9:16 / 4:5 shape\" in the Ads Guide is 1%. */\nconst TOLERANCE = 0.01;\n\nfunction near(ratio: number, target: number): boolean {\n return Math.abs(ratio - target) / target <= TOLERANCE;\n}\n\n/** How much of the picture survives being cut to `[minRatio, maxRatio]`, as a whole percent cut away. */\nfunction cutPercent(ratio: number, minRatio: number, maxRatio: number): number {\n if (ratio < minRatio * (1 - TOLERANCE)) return Math.round((1 - ratio / minRatio) * 100);\n if (ratio > maxRatio * (1 + TOLERANCE)) return Math.round((1 - maxRatio / ratio) * 100);\n return 0;\n}\n\nfunction fitWithin(group: PlacementGroup, ratio: number, minRatio: number, maxRatio: number): PlacementFit {\n const cut = cutPercent(ratio, minRatio, maxRatio);\n return cut > 0 ? { group, fit: \"cropped\", cropPercent: cut } : { group, fit: \"fits\" };\n}\n\n/** Where a picture of this size fits, and where Meta crops it. */\nexport function imagePlacementFit(width: number, height: number): PlacementFit[] {\n const ratio = width / height;\n const feed = fitWithin(\"feed\", ratio, RATIO_4_5, RATIO_1_91);\n const stories: PlacementFit = near(ratio, RATIO_9_16)\n ? { group: \"stories_reels\", fit: \"native\" }\n : ratio < RATIO_4_5 * (1 - TOLERANCE)\n ? { group: \"stories_reels\", fit: \"cropped\", cropPercent: cutPercent(ratio, RATIO_4_5, RATIO_1_91) }\n : { group: \"stories_reels\", fit: \"card\" };\n return [\n near(ratio, RATIO_4_5) ? { group: \"feed\", fit: \"native\" } : feed,\n stories,\n fitWithin(\"right_column\", ratio, 1, RATIO_1_91),\n ];\n}\n\n/** Below this width no feed, Stories or Reels placement takes a picture (Instagram's minimum; Facebook Feed's is 600). */\nexport const IMAGE_MIN_WIDTH = 500;\nconst FACEBOOK_FEED_MIN_WIDTH = 600;\n/** Meta's recommended resolution starts at 1080 px wide (1440 for the newest specs). */\nconst RECOMMENDED_MIN_WIDTH = 1080;\n\nexport interface MediaCheck {\n /** Refuse the change: Meta would refuse it, or no placement can show it. */\n errors: string[];\n /** Publishable, with a consequence the reviewer should know about. */\n warnings: string[];\n}\n\nfunction ratioName(width: number, height: number): string {\n const ratio = width / height;\n const named: [number, string][] = [\n [1, \"1:1\"],\n [RATIO_4_5, \"4:5\"],\n [RATIO_9_16, \"9:16\"],\n [2 / 3, \"2:3\"],\n [3 / 4, \"3:4\"],\n [16 / 9, \"16:9\"],\n [RATIO_1_91, \"1.91:1\"],\n ];\n return named.find(([value]) => near(ratio, value))?.[1] ?? `${ratio.toFixed(2)}:1`;\n}\n\n/** Stage-time check of a picture's size and shape against every placement it may serve. */\nexport function imageCheck(width: number, height: number): MediaCheck {\n const errors: string[] = [];\n const warnings: string[] = [];\n if (width < IMAGE_MIN_WIDTH) {\n errors.push(\n `the picture is ${width}×${height} — narrower than ${IMAGE_MIN_WIDTH} px, the smallest any Facebook or Instagram placement takes. Use a picture at least 1080 px wide`,\n );\n return { errors, warnings };\n }\n if (width < FACEBOOK_FEED_MIN_WIDTH) {\n warnings.push(`the picture is ${width} px wide — the Facebook feed needs at least ${FACEBOOK_FEED_MIN_WIDTH} px`);\n } else if (width < RECOMMENDED_MIN_WIDTH) {\n warnings.push(\n `the picture is ${width} px wide — Meta recommends at least ${RECOMMENDED_MIN_WIDTH} px, so it may look soft`,\n );\n }\n const shape = `${ratioName(width, height)} picture (${width}×${height})`;\n const cropped = imagePlacementFit(width, height).filter((fit) => fit.fit === \"cropped\");\n const mainCrops = cropped.filter((fit) => fit.group !== \"right_column\");\n if (mainCrops.length > 0) {\n const where = mainCrops.map((fit) => `${fit.cropPercent}% in ${PLACEMENT_GROUP_LABELS[fit.group]}`).join(\" and \");\n warnings.push(\n `Meta cuts about ${where} of this ${shape}, keeping the middle — use a 4:5 for feeds and a 9:16 for Stories & Reels (a placement-customized creative carries both)`,\n );\n }\n const rightColumn = cropped.find((fit) => fit.group === \"right_column\");\n if (rightColumn && mainCrops.length === 0) {\n warnings.push(\n `the Facebook right column shows this ${shape} cut to a square (about ${rightColumn.cropPercent}% cut away)`,\n );\n }\n return { errors, warnings };\n}\n\n/**\n * The longest video each placement shows (Ads Guide, 2026-10-14). Past it Meta\n * does not refuse the ad — with Advantage+ placements it quietly keeps the ad\n * out of that placement.\n */\nconst VIDEO_MAX_SECONDS: readonly [string, number][] = [\n [\"Facebook Stories\", 3 * 60],\n [\"Reels\", 15 * 60],\n [\"Instagram feed and Stories\", 60 * 60],\n [\"Facebook feed\", 241 * 60],\n];\nconst VIDEO_MIN_SECONDS = 1;\n/** Mux's default ceiling: the library's full-quality copy is at most 1080p. */\nconst SENT_MAX_SHORT_SIDE = 1080;\nconst SENT_MAX_LONG_SIDE = 1920;\n/** Below this short side a video looks soft in every placement. */\nconst VIDEO_MIN_SHORT_SIDE = 720;\n\n/** The size of the copy Meta receives: the source, scaled down into Mux's 1080p box. */\nexport function sentVideoDimensions(width: number, height: number): { width: number; height: number } {\n const short = Math.min(width, height);\n const long = Math.max(width, height);\n const scale = Math.min(1, SENT_MAX_SHORT_SIDE / short, SENT_MAX_LONG_SIDE / long);\n return { width: Math.round(width * scale), height: Math.round(height * scale) };\n}\n\nfunction formatDuration(seconds: number): string {\n const whole = Math.round(seconds);\n const minutes = Math.floor(whole / 60);\n const rest = whole % 60;\n if (minutes === 0) return `${whole} seconds`;\n return rest === 0 ? `${minutes} minute${minutes === 1 ? \"\" : \"s\"}` : `${minutes} min ${rest} s`;\n}\n\nfunction videoDurationCheck(durationSec: number, check: MediaCheck): void {\n if (durationSec < VIDEO_MIN_SECONDS) {\n check.errors.push(`the video is ${durationSec}s long — Meta needs at least 1 second`);\n }\n const tooLong = VIDEO_MAX_SECONDS.filter(([, max]) => durationSec > max);\n if (tooLong.length === VIDEO_MAX_SECONDS.length) {\n check.errors.push(`the video is ${formatDuration(durationSec)} long — longer than any Meta placement shows`);\n } else if (tooLong.length > 0) {\n const limits = tooLong.map(([name, max]) => `${name} shows up to ${formatDuration(max)}`).join(\", \");\n check.warnings.push(\n `the video is ${formatDuration(durationSec)} long — ${limits}, so Meta keeps the ad out of ${tooLong.length > 1 ? \"those placements\" : \"that placement\"}`,\n );\n }\n}\n\nfunction videoShapeCheck(width: number, height: number, check: MediaCheck): void {\n const sent = sentVideoDimensions(width, height);\n if (Math.min(sent.width, sent.height) < VIDEO_MIN_SHORT_SIDE) {\n check.warnings.push(\n `the video reaches Meta at ${sent.width}×${sent.height} — under 720p it looks soft in every placement; Meta recommends 1080 px or more`,\n );\n }\n const ratio = width / height;\n if (ratio > 1 + TOLERANCE) {\n check.warnings.push(\n \"the video is landscape — Stories & Reels show it with bars above and below; a 9:16 version fills the screen\",\n );\n } else if (ratio < RATIO_4_5 * (1 - TOLERANCE)) {\n check.warnings.push(\"the video is taller than 4:5 — feeds show at most a 4:5 of it, cutting the top and bottom\");\n }\n}\n\n/**\n * The longest video each manual placement shows (Ads Guide, 2026-10-14), by the\n * platform and position an ad set names. A position not listed has no\n * published limit and counts as one that shows the video.\n */\nconst POSITION_MAX_SECONDS: Readonly<Record<string, Readonly<Record<string, [string, number]>>>> = {\n facebook: {\n feed: [\"Facebook feed\", 241 * 60],\n story: [\"Facebook Stories\", 3 * 60],\n facebook_reels: [\"Facebook Reels\", 15 * 60],\n instream_video: [\"Facebook in-stream\", 10 * 60],\n },\n instagram: {\n stream: [\"Instagram feed\", 60 * 60],\n story: [\"Instagram Stories\", 60 * 60],\n explore: [\"Instagram Explore\", 60 * 60],\n reels: [\"Instagram Reels\", 15 * 60],\n profile_reels: [\"Instagram profile Reels\", 15 * 60],\n },\n messenger: { story: [\"Messenger Stories\", 60] },\n};\n\n/**\n * Why no placement the ad set names can show a video this long, or undefined.\n * With Advantage+ placements Meta just keeps the ad out of the placements that\n * cannot show it; when every one the ad set names is such a placement, the ad\n * has nowhere to run and Meta refuses it (\"provide a supported creative or\n * change your targeting\"). Only an ad set that names its platforms and, for\n * each, its positions is judged — anything left to Meta can show it somewhere.\n */\nexport function videoPlacementRefusal(durationSec: number, targeting: Record<string, unknown>): string | undefined {\n const platforms = Array.isArray(targeting.publisher_platforms) ? (targeting.publisher_platforms as string[]) : [];\n if (platforms.length === 0) return undefined;\n const tooShort: string[] = [];\n for (const platform of platforms) {\n const positions = targeting[`${platform}_positions`];\n const limits = POSITION_MAX_SECONDS[platform];\n if (!Array.isArray(positions) || positions.length === 0 || !limits) return undefined;\n for (const position of positions as string[]) {\n const limit = limits[position];\n if (!limit || durationSec <= limit[1]) return undefined;\n tooShort.push(`${limit[0]} (up to ${formatDuration(limit[1])})`);\n }\n }\n return `the video is ${formatDuration(durationSec)} long and every placement this ad set names shows less — ${tooShort.join(\", \")} — so Meta would refuse the ad. Add a placement that shows it (Facebook or Instagram feed), leave placements to Meta, or use a shorter video`;\n}\n\n/** Stage-time check of a library video against the placements it may serve. */\nexport function videoCheck(video: { durationSec?: number; width?: number; height?: number }): MediaCheck {\n const check: MediaCheck = { errors: [], warnings: [] };\n if (video.durationSec !== undefined) videoDurationCheck(video.durationSec, check);\n if (video.width !== undefined && video.height !== undefined) videoShapeCheck(video.width, video.height, check);\n return check;\n}\n\n/**\n * The placement groups a placement-customized creative assigns assets to, and\n * the `customization_spec` each becomes (Meta's placement asset customization:\n * `asset_feed_spec.asset_customization_rules`). `default` is the asset every\n * placement no other rule names gets — a rule with an empty\n * `customization_spec`, as in Meta's own Threads example.\n */\nexport const PLACEMENT_SLOTS = [\"feed\", \"stories\", \"reels\", \"right_column\", \"default\"] as const;\nexport type PlacementSlot = (typeof PLACEMENT_SLOTS)[number];\n\nexport interface CustomizationSpec {\n publisher_platforms?: string[];\n facebook_positions?: string[];\n instagram_positions?: string[];\n messenger_positions?: string[];\n}\n\nconst SLOT_POSITIONS: Record<Exclude<PlacementSlot, \"default\">, CustomizationSpec> = {\n // Retired surfaces (Facebook video feeds, Instagram Explore, Messenger\n // Stories — `RETIRED_PLACEMENTS`) are left out: they no longer run anywhere.\n feed: {\n publisher_platforms: [\"facebook\", \"instagram\"],\n facebook_positions: [\"feed\", \"marketplace\", \"search\"],\n instagram_positions: [\"stream\", \"explore_home\", \"profile_feed\", \"ig_search\"],\n },\n stories: {\n publisher_platforms: [\"facebook\", \"instagram\"],\n facebook_positions: [\"story\"],\n instagram_positions: [\"story\"],\n },\n reels: {\n publisher_platforms: [\"facebook\", \"instagram\"],\n facebook_positions: [\"facebook_reels\"],\n instagram_positions: [\"reels\"],\n },\n right_column: { publisher_platforms: [\"facebook\"], facebook_positions: [\"right_hand_column\"] },\n};\n\nexport const PLACEMENT_SLOT_LABELS: Record<PlacementSlot, string> = {\n feed: \"Feeds\",\n stories: \"Stories\",\n reels: \"Reels\",\n right_column: \"Facebook right column\",\n default: \"Every other placement\",\n};\n\nfunction union(a: string[] | undefined, b: string[] | undefined): string[] | undefined {\n const merged = [...new Set([...(a ?? []), ...(b ?? [])])];\n return merged.length > 0 ? merged : undefined;\n}\n\n/** The `customization_spec` for an asset shown in these placements. Empty for `default`. */\nexport function customizationSpecFor(slots: readonly PlacementSlot[]): CustomizationSpec {\n let spec: CustomizationSpec = {};\n for (const slot of slots) {\n if (slot === \"default\") continue;\n const add = SLOT_POSITIONS[slot];\n spec = {\n publisher_platforms: union(spec.publisher_platforms, add.publisher_platforms),\n facebook_positions: union(spec.facebook_positions, add.facebook_positions),\n instagram_positions: union(spec.instagram_positions, add.instagram_positions),\n messenger_positions: union(spec.messenger_positions, add.messenger_positions),\n };\n }\n return Object.fromEntries(Object.entries(spec).filter(([, value]) => value !== undefined)) as CustomizationSpec;\n}\n","/**\n * Click-to-message ads: where a click opens a conversation (Messenger,\n * WhatsApp, Instagram Direct) and what the person reads first there.\n *\n * Meta's guides (ad-creative/messaging-ads/click-to-*, v25.0): the ad set says\n * which apps the conversation may open in (`destination_type` MESSENGER,\n * WHATSAPP, INSTAGRAM_DIRECT or a MESSAGING_* mix) and promotes the Page; the\n * creative's button says which app this ad opens\n * (`call_to_action.value.app_destination`) and its `page_welcome_message` is the\n * greeting, with ice breakers (questions the person taps) or a message\n * pre-filled for them to send.\n */\nimport { z } from \"zod\";\n\n/** The app a messaging ad's button opens — `call_to_action.value.app_destination`. */\nexport const APP_DESTINATIONS = [\"MESSENGER\", \"WHATSAPP\", \"INSTAGRAM_DIRECT\"] as const;\nexport type MetaAppDestination = (typeof APP_DESTINATIONS)[number];\n\n/** The button each messaging app's ads carry (Meta's click-to-* guides). */\nexport const MESSAGING_CTA_DESTINATION: Readonly<Record<string, MetaAppDestination>> = {\n MESSAGE_PAGE: \"MESSENGER\",\n WHATSAPP_MESSAGE: \"WHATSAPP\",\n INSTAGRAM_MESSAGE: \"INSTAGRAM_DIRECT\",\n};\n\n/**\n * The ad set destinations that send a click into a conversation. Each needs\n * the Page the conversation is with as `promoted_object.page_id`.\n */\nexport const MESSAGING_DESTINATION_TYPES = [\n \"MESSENGER\",\n \"WHATSAPP\",\n \"INSTAGRAM_DIRECT\",\n \"MESSAGING_MESSENGER_WHATSAPP\",\n \"MESSAGING_INSTAGRAM_DIRECT_MESSENGER\",\n \"MESSAGING_INSTAGRAM_DIRECT_WHATSAPP\",\n \"MESSAGING_INSTAGRAM_DIRECT_MESSENGER_WHATSAPP\",\n] as const;\n\n/** Meta's limits on a greeting (click-to-messenger guide, \"Limitations\"). */\nexport const WELCOME_LIMITS = { textMax: 300, iceBreakerTitleMax: 80, iceBreakerResponseMax: 300, iceBreakersMax: 4 };\n\n/**\n * What a person reads when the conversation opens: a greeting, and either\n * questions to tap (each with the answer the business sends back) or one\n * message pre-filled for them to send.\n */\nexport const welcomeMessageSchema = z\n .strictObject({\n greeting: z.string().trim().min(1).max(WELCOME_LIMITS.textMax),\n iceBreakers: z\n .array(\n z.strictObject({\n question: z.string().trim().min(1).max(WELCOME_LIMITS.iceBreakerTitleMax),\n answer: z.string().trim().min(1).max(WELCOME_LIMITS.iceBreakerResponseMax),\n }),\n )\n .min(1)\n .max(WELCOME_LIMITS.iceBreakersMax)\n .optional(),\n autofill: z.string().trim().min(1).max(WELCOME_LIMITS.textMax).optional(),\n })\n .refine((p) => !(p.iceBreakers && p.autofill), {\n message: \"a greeting offers questions to tap OR a message to send, not both\",\n path: [\"autofill\"],\n });\nexport type MetaWelcomeMessage = z.infer<typeof welcomeMessageSchema>;\n\n/** The greeting as Meta's `page_welcome_message`: its visual-editor JSON, sent as a string. */\nexport function pageWelcomeMessage(welcome: MetaWelcomeMessage): string {\n const message = welcome.autofill\n ? { autofill_message: { content: welcome.autofill }, text: welcome.greeting }\n : {\n ice_breakers: (welcome.iceBreakers ?? []).map((entry) => ({ title: entry.question, response: entry.answer })),\n quick_replies: [],\n text: welcome.greeting,\n };\n return JSON.stringify({\n type: \"VISUAL_EDITOR\",\n version: 2,\n landing_screen_type: \"welcome_message\",\n media_type: \"text\",\n text_format: { customer_action_type: welcome.autofill ? \"autofill_message\" : \"ice_breakers\", message },\n user_edit: false,\n surface: \"visual_editor_new\",\n });\n}\n","/**\n * Photos put on a Facebook Page without posting them — the only picture an\n * Instant Experience's photo element takes (`instantExperiences.ts`), and what\n * a collection ad's four-photo experience is built from.\n *\n * Live on v26.0 (2026-10-15) on Baker's own Page, with the Page token:\n * - `POST /{page_id}/photos` with `url` and `published: false` uploads the\n * picture without a post on the Page's timeline; it IGNORES `validate_only`\n * (the photo was made), so it is never dry-run;\n * - Meta fetches `url` itself, and refused a public Wikimedia address (\"Missing\n * or invalid image file\", 324 / 2069019) while taking Baker's own media\n * address — so a library image goes by its Baker address;\n * - `DELETE /{photo_id}` with the Page token removes it, and it then reads as\n * gone (subcode 33). An unpublished photo does not show in the Page's photo\n * list, so it is read by id.\n */\nimport { z } from \"zod\";\nimport { NUMERIC_ID_REGEX } from \"./limits\";\n\nconst httpsUrlSchema = z\n .string()\n .url()\n .refine((value) => value.startsWith(\"https://\"), \"must be an https URL\");\n\nexport const pagePhotoCreateSchema = z\n .strictObject({\n page_id: z.string().regex(NUMERIC_ID_REGEX),\n /** A Baker library image — staging fills `url` with its Baker address. */\n bakerImageId: z.string().min(1).max(64).optional(),\n /** A public https picture address Meta can fetch. */\n url: httpsUrlSchema.optional(),\n /** Shown with the photo in the Page's library only; it is never posted. */\n caption: z.string().trim().min(1).max(2000).optional(),\n })\n .refine((p) => p.bakerImageId !== undefined || p.url !== undefined, \"a Page photo names bakerImageId or url\");\nexport type PagePhotoCreate = z.infer<typeof pagePhotoCreateSchema>;\n\n/** Delete a Page photo. */\nexport const pagePhotoUpdateSchema = z.strictObject({ status: z.literal(\"DELETED\") });\nexport type PagePhotoUpdate = z.infer<typeof pagePhotoUpdateSchema>;\n","/**\n * Reach and frequency buying (\"Reservation\" in Ads Manager): Meta quotes a\n * reach for a budget (or the budget for a reach) over fixed dates, at a\n * frequency the advertiser chooses, and holds that price once reserved.\n *\n * Three steps, two kinds of call. Live on v26.0 (2026-10-15) on\n * act_1342210013621203 (which carries `CAN_USE_REACH_AND_FREQUENCY`):\n * - A PREDICTION — `POST /act_<id>/reachfrequencypredictions` — is a forecast:\n * €1,000 over 7 days in Spain, Facebook feed, at most 2 a week, came back at\n * once (`status` 1) with `external_reach` 1,833,660 and the bounds Meta will\n * quote (`external_minimum_budget` €76.63 … `external_maximum_budget`). It\n * holds no inventory, spends nothing, cannot be deleted (subcode 33) and\n * lapses on its own, so Baker asks for it as a read (`ads meta reach-frequency\n * predict`), like the delivery estimate.\n * - A RESERVATION — the same edge with `action=reserve` and the prediction's\n * `rf_prediction_id` — holds the price until `expiration_time` (two weeks\n * out) and answers a NEW id (`reservation_status` 1). That is a commitment, so\n * it is a staged op, applied at Publish: `reachFrequencyReservation.create`.\n * - `action=cancel` with the reservation's id releases it (`reservation_status`\n * back to 0): `reachFrequencyReservation.update` `{ status: \"CANCELLED\" }`.\n *\n * A reserved campaign is `buying_type: RESERVED` and its ad set names the\n * reservation in `rf_prediction_id`. Meta bills delivered impressions only; a\n * reservation with no live ad at its start costs nothing, but Meta can refuse\n * an advertiser who keeps reserving and not running.\n */\nimport { z } from \"zod\";\nimport { NUMERIC_ID_REGEX } from \"./limits\";\n\nconst unixSeconds = z.number().int().positive();\n\n/** Meta's in-stream video packages for a reach-and-frequency buy (`instream_packages`). */\nexport const INSTREAM_PACKAGES = [\n \"NORMAL\",\n \"PREMIUM\",\n \"SPORTS\",\n \"ENTERTAINMENT\",\n \"BEAUTY\",\n \"FOOD\",\n \"SPANISH\",\n \"REGULAR_ANIMALS_PETS\",\n \"REGULAR_FOOD\",\n \"REGULAR_GAMES\",\n \"REGULAR_POLITICS\",\n \"REGULAR_SPORTS\",\n \"REGULAR_STYLE\",\n \"REGULAR_TV_MOVIES\",\n] as const;\n\n/** What to forecast. Money in major units of the account currency; the backend sends minor units. */\nexport const reachFrequencyPredictionRequestSchema = z\n .strictObject({\n accountId: z.string().regex(NUMERIC_ID_REGEX),\n /** `reach`: how many people a budget reaches. `budget`: what a reach costs. */\n solveFor: z.enum([\"reach\", \"budget\"]),\n /** Lifetime budget, major units — with solveFor reach. */\n budget: z\n .string()\n .regex(/^\\d+(\\.\\d{1,2})?$/)\n .optional(),\n /** People to reach — with solveFor budget. Meta's floor is usually 200,000 per country. */\n reach: z.number().int().positive().optional(),\n start_time: unixSeconds,\n end_time: unixSeconds,\n /** Most times one person sees the ad in each `frequencyCapDays`. */\n frequencyCap: z.number().int().min(1).max(90).optional(),\n frequencyCapDays: z.number().int().min(1).max(90).optional(),\n objective: z\n .enum([\n \"REACH\",\n \"BRAND_AWARENESS\",\n \"VIDEO_VIEWS\",\n \"POST_ENGAGEMENT\",\n \"LINK_CLICKS\",\n \"OUTCOME_AWARENESS\",\n \"OUTCOME_ENGAGEMENT\",\n ])\n .default(\"REACH\"),\n /**\n * Balanced frequency (`is_balanced_frequency` + `target_frequency`): Meta\n * aims each person at this many views per `targetFrequencyDays` rather than\n * capping. Live on v26.0 (2026-10-15) it quoted only under\n * OUTCOME_AWARENESS / OUTCOME_ENGAGEMENT with a REACH or THRUPLAY goal\n * (\"Target frequency can only be used when…\"), and a plain quote without it\n * needs a frequency cap.\n */\n targetFrequency: z.number().int().min(1).max(90).optional(),\n targetFrequencyDays: z.number().int().min(1).max(90).optional(),\n optimization_goal: z.string().min(1).max(64).optional(),\n /** The Page (and Instagram account) the ads run as. */\n page_id: z.string().regex(NUMERIC_ID_REGEX),\n instagram_user_id: z.string().regex(NUMERIC_ID_REGEX).optional(),\n /** Meta targeting: ONE country, no website custom audiences. */\n targeting: z.record(z.string(), z.unknown()),\n /**\n * Run only in these hours (`day_parting_schedule`): minutes from midnight\n * and days (0 = Sunday). Live on v26.0 (2026-10-15) a weekday 09–18 quote\n * came back with its own reach.\n */\n day_parting_schedule: z\n .array(\n z.strictObject({\n start_minute: z.number().int().min(0).max(1440),\n end_minute: z.number().int().min(0).max(1440),\n days: z.array(z.number().int().min(0).max(6)).min(1),\n }),\n )\n .min(1)\n .optional(),\n /** In-stream video content packages the ads may run in (`instream_packages`). */\n instream_packages: z.array(z.enum(INSTREAM_PACKAGES)).min(1).optional(),\n })\n .superRefine((p, ctx) => {\n if (p.solveFor === \"reach\" && p.budget === undefined) {\n ctx.addIssue({ code: \"custom\", path: [\"budget\"], message: \"solving for reach needs --budget\" });\n }\n if (p.solveFor === \"budget\" && p.reach === undefined) {\n ctx.addIssue({ code: \"custom\", path: [\"reach\"], message: \"solving for budget needs --reach\" });\n }\n if (p.end_time <= p.start_time) {\n ctx.addIssue({ code: \"custom\", path: [\"end_time\"], message: \"the end comes after the start\" });\n }\n if (p.targetFrequency !== undefined) {\n const objectiveOk = p.objective === \"OUTCOME_AWARENESS\" || p.objective === \"OUTCOME_ENGAGEMENT\";\n const goalOk = p.optimization_goal === \"REACH\" || p.optimization_goal === \"THRUPLAY\";\n if (!objectiveOk || !goalOk) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"targetFrequency\"],\n message:\n \"balanced frequency needs --objective OUTCOME_AWARENESS (or OUTCOME_ENGAGEMENT) and --optimization-goal REACH (or THRUPLAY)\",\n });\n }\n }\n if (p.end_time - p.start_time > 90 * 86_400) {\n ctx.addIssue({ code: \"custom\", path: [\"end_time\"], message: \"Meta reserves at most 90 days\" });\n }\n });\nexport type ReachFrequencyPredictionRequest = z.infer<typeof reachFrequencyPredictionRequestSchema>;\n\n/** Hold the price of a prediction (by its id, from `reach-frequency predict` or the list). */\nexport const reachFrequencyReservationCreateSchema = z.strictObject({\n prediction_id: z.string().regex(NUMERIC_ID_REGEX),\n});\nexport type ReachFrequencyReservationCreate = z.infer<typeof reachFrequencyReservationCreateSchema>;\n\n/** Release a reservation. */\nexport const reachFrequencyReservationUpdateSchema = z.strictObject({ status: z.literal(\"CANCELLED\") });\nexport type ReachFrequencyReservationUpdate = z.infer<typeof reachFrequencyReservationUpdateSchema>;\n"],"mappings":"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","names":["z","z","z","z","z","z","base","isRecord","z","z","z","z","z","z","z","tempRefSchema","z","httpsUrlSchema","z","httpsUrlSchema","z","z","z","httpsUrlSchema","z","z","z","tempRefSchema","z","httpsUrlSchema","z","z","z","tempRefSchema","MINUTES_PER_DAY","httpsUrlSchema","z","httpsUrlSchema","tempRefSchema"]}