@koda-sl/baker-cli 0.489.0 → 0.491.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (859) hide show
  1. package/README.md +169 -7
  2. package/dist/account-3H6BZO5H.js +80 -0
  3. package/dist/account-IKFDY52P.js +138 -0
  4. package/dist/account-IKFDY52P.js.map +1 -0
  5. package/dist/account-VGSYM7LY.js +79 -0
  6. package/dist/account-assets-LKZVWZAR.js +289 -0
  7. package/dist/account-assets-LKZVWZAR.js.map +1 -0
  8. package/dist/account-level-UJOZDVXY.js +608 -0
  9. package/dist/account-level-UJOZDVXY.js.map +1 -0
  10. package/dist/account-writes-AE5IJGGW.js +66 -0
  11. package/dist/accounts-2ARS6XP2.js +77 -0
  12. package/dist/accounts-AQFW4ZUM.js +611 -0
  13. package/dist/accounts-K4INATCW.js +75 -0
  14. package/dist/actions-QMUHOAXG.js +55 -0
  15. package/dist/activecampaign-J3QN5FMG.js +935 -0
  16. package/dist/activities-T253KK4Q.js +74 -0
  17. package/dist/ad-group-writes-VRSBI2Z2.js +170 -0
  18. package/dist/ad-groups-IEBVEAMS.js +68 -0
  19. package/dist/ad-writes-ALV4KFPZ.js +174 -0
  20. package/dist/add-VDUA6OWM.js +104 -0
  21. package/dist/add-XHOKCSW5.js +302 -0
  22. package/dist/ads-CQZHD7FC.js +77 -0
  23. package/dist/ads-HGDPNIT6.js +40 -0
  24. package/dist/ads-ZEY72UBN.js +114 -0
  25. package/dist/ads-ZEY72UBN.js.map +1 -0
  26. package/dist/adsets-5H3MOT3D.js +177 -0
  27. package/dist/adsets-5H3MOT3D.js.map +1 -0
  28. package/dist/advertisers-UDSEFMP7.js +120 -0
  29. package/dist/analytics-TBETZOPJ.js +433 -0
  30. package/dist/analytics-VH74LMMC.js +1976 -0
  31. package/dist/asset-writes-L5TMKIZC.js +47 -0
  32. package/dist/assign-6IE2ASFC.js +77 -0
  33. package/dist/audience-size-CSBWDFEP.js +73 -0
  34. package/dist/audience-writes-X52VG35Y.js +324 -0
  35. package/dist/audience-writes-X52VG35Y.js.map +1 -0
  36. package/dist/audiences-AAZH56WD.js +268 -0
  37. package/dist/audiences-X3RLGOVM.js +84 -0
  38. package/dist/audiences-X3RLGOVM.js.map +1 -0
  39. package/dist/audit-AEENRVGD.js +151 -0
  40. package/dist/autocomplete-AAGTJHVL.js +111 -0
  41. package/dist/avatars-VEATUUKU.js +38 -0
  42. package/dist/bid-pricing-SZTGCZTV.js +100 -0
  43. package/dist/brand-MXGETE4R.js +22 -0
  44. package/dist/brief-3GHSHOGM.js +538 -0
  45. package/dist/businesses-H3HIDQX6.js +53 -0
  46. package/dist/campaign-groups-WRI56M5X.js +95 -0
  47. package/dist/campaign-writes-PYGKSCPS.js +165 -0
  48. package/dist/campaign-writes-PYGKSCPS.js.map +1 -0
  49. package/dist/campaign-writes-U5PUVSMT.js +170 -0
  50. package/dist/campaigns-4QWC2JE7.js +109 -0
  51. package/dist/campaigns-AV6G3AUU.js +127 -0
  52. package/dist/campaigns-AV6G3AUU.js.map +1 -0
  53. package/dist/campaigns-JEIKY2M4.js +76 -0
  54. package/dist/campaigns-Q4HN7HBY.js +107 -0
  55. package/dist/canvas-VJ3XKCAC.js +46 -0
  56. package/dist/capabilities-SNGGAOV3.js +144 -0
  57. package/dist/catalog-S32MX453.js +65 -0
  58. package/dist/catalogs-OCVXZLIF.js +128 -0
  59. package/dist/catalogs-RXJTZTVX.js +778 -0
  60. package/dist/catalogs-RXJTZTVX.js.map +1 -0
  61. package/dist/chatgpt-QVF2FD3E.js +47 -0
  62. package/dist/chats-2DRTB7GK.js +276 -0
  63. package/dist/chats-2DRTB7GK.js.map +1 -0
  64. package/dist/check-Z6UMIQKD.js +104 -0
  65. package/dist/chunk-2C7AHPM4.js +191 -0
  66. package/dist/chunk-2C7AHPM4.js.map +1 -0
  67. package/dist/chunk-2WZI36D3.js +317 -0
  68. package/dist/chunk-3AMLOCXY.js +392 -0
  69. package/dist/chunk-3CVAEQMZ.js +156 -0
  70. package/dist/chunk-3WAYZQNV.js +61 -0
  71. package/dist/chunk-46GWHUKN.js +225 -0
  72. package/dist/chunk-4O6T76A3.js +191 -0
  73. package/dist/chunk-5C35OW7L.js +205 -0
  74. package/dist/chunk-5C35OW7L.js.map +1 -0
  75. package/dist/chunk-5GQCN2QZ.js +391 -0
  76. package/dist/chunk-5GQCN2QZ.js.map +1 -0
  77. package/dist/chunk-5MCVK4A3.js +903 -0
  78. package/dist/chunk-5ZLN23V5.js +97 -0
  79. package/dist/chunk-65Y3RCWP.js +68 -0
  80. package/dist/chunk-65Y3RCWP.js.map +1 -0
  81. package/dist/chunk-77ULVP62.js +547 -0
  82. package/dist/chunk-A4MVVPJ2.js +4204 -0
  83. package/dist/chunk-A4MVVPJ2.js.map +1 -0
  84. package/dist/chunk-AQM4JH62.js +274 -0
  85. package/dist/chunk-AQM4JH62.js.map +1 -0
  86. package/dist/chunk-AW2GKIGS.js +433 -0
  87. package/dist/chunk-BRLY6XD6.js +249 -0
  88. package/dist/chunk-C7NWUCLQ.js +64 -0
  89. package/dist/chunk-CP4P6YKM.js +287 -0
  90. package/dist/chunk-CP4P6YKM.js.map +1 -0
  91. package/dist/chunk-D4HKJBEW.js +23 -0
  92. package/dist/chunk-DAO63OOP.js +6352 -0
  93. package/dist/chunk-DAO63OOP.js.map +1 -0
  94. package/dist/chunk-DCBZ5CHZ.js +139 -0
  95. package/dist/chunk-G6XKD7QE.js +77 -0
  96. package/dist/chunk-GBFL4TD2.js +172 -0
  97. package/dist/chunk-H5SCKWFT.js +224 -0
  98. package/dist/chunk-HLVRHBKL.js +1078 -0
  99. package/dist/chunk-HLVRHBKL.js.map +1 -0
  100. package/dist/chunk-HXPK6KAL.js +363 -0
  101. package/dist/chunk-I7GOSMWT.js +197 -0
  102. package/dist/chunk-IBY44U2M.js +1079 -0
  103. package/dist/chunk-ITNHIZKK.js +275 -0
  104. package/dist/chunk-J33P2JNS.js +455 -0
  105. package/dist/chunk-JH2L5CQD.js +206 -0
  106. package/dist/chunk-JQH5VG6F.js +5368 -0
  107. package/dist/chunk-JVH5A3XC.js +8914 -0
  108. package/dist/chunk-KTOYQP6D.js +169 -0
  109. package/dist/chunk-LO3IF5PS.js +399 -0
  110. package/dist/chunk-LRRFGOW3.js +604 -0
  111. package/dist/chunk-LTPTJWZC.js +942 -0
  112. package/dist/chunk-MRQHJW5U.js +159 -0
  113. package/dist/chunk-NHYI7ORL.js +346 -0
  114. package/dist/chunk-NLI7C3K2.js +51 -0
  115. package/dist/chunk-NSEMXBUB.js +91 -0
  116. package/dist/chunk-OM2BRYXJ.js +3868 -0
  117. package/dist/chunk-OY4SKCIU.js +103 -0
  118. package/dist/chunk-OYAJNTRO.js +494 -0
  119. package/dist/chunk-PL7J3DPQ.js +831 -0
  120. package/dist/chunk-PUSBUMYM.js +89 -0
  121. package/dist/chunk-QTOZ32SU.js +163 -0
  122. package/dist/chunk-QTOZ32SU.js.map +1 -0
  123. package/dist/chunk-RRADFRPI.js +297 -0
  124. package/dist/chunk-SGEPZB3D.js +344 -0
  125. package/dist/chunk-SVAB6KV5.js +219 -0
  126. package/dist/chunk-SVAB6KV5.js.map +1 -0
  127. package/dist/chunk-TFTZDWCX.js +66 -0
  128. package/dist/chunk-TG4NCHFS.js +142 -0
  129. package/dist/chunk-TTHM66TA.js +207 -0
  130. package/dist/chunk-VL2GNXZY.js +19 -0
  131. package/dist/chunk-VQPZDM6N.js +160 -0
  132. package/dist/chunk-XCKINS7K.js +57 -0
  133. package/dist/chunk-YLYXSJ6O.js +8939 -0
  134. package/dist/chunk-ZAPO6UWS.js +592 -0
  135. package/dist/chunk-ZEPUDYPL.js +122 -0
  136. package/dist/chunk-ZJSGGJ5R.js +167 -0
  137. package/dist/claim-J2LYNHZK.js +197 -0
  138. package/dist/cli.js +34 -34
  139. package/dist/companies-VYY22B6T.js +195 -0
  140. package/dist/complete-5I32XM7P.js +81 -0
  141. package/dist/connect-EUFFQQ7O.js +42 -0
  142. package/dist/conversation-D6KZHGPP.js +93 -0
  143. package/dist/conversion-writes-ECZBVY7D.js +120 -0
  144. package/dist/conversions-5QCSCRLI.js +76 -0
  145. package/dist/conversions-Y3X6ZTTF.js +135 -0
  146. package/dist/copy-writes-D2RTHAL6.js +167 -0
  147. package/dist/copy-writes-D2RTHAL6.js.map +1 -0
  148. package/dist/create-2JCRTQJL.js +59 -0
  149. package/dist/create-LMSQPHPB.js +235 -0
  150. package/dist/create-MBLNB5RY.js +132 -0
  151. package/dist/create-VR7RXKL7.js +207 -0
  152. package/dist/creatives-5C42BDMW.js +182 -0
  153. package/dist/creatives-HYPSTANO.js +58 -0
  154. package/dist/creatives-MZ6ICNSY.js +88 -0
  155. package/dist/creatives-MZ6ICNSY.js.map +1 -0
  156. package/dist/credentials-4H4AUYJN.js +287 -0
  157. package/dist/critique-UOJZWDG2.js +1458 -0
  158. package/dist/critique-WCWMQQVV.js +227 -0
  159. package/dist/crm-B7OTHMBP.js +318 -0
  160. package/dist/crm-DZRWKJ6V.js +224 -0
  161. package/dist/custom-conversions-FIP6ZS34.js +127 -0
  162. package/dist/custom-conversions-FIP6ZS34.js.map +1 -0
  163. package/dist/customers-AOFJJCGD.js +56 -0
  164. package/dist/delete-DEG5KOBY.js +64 -0
  165. package/dist/delete-EFIODCXG.js +54 -0
  166. package/dist/delete-PQIMW2LK.js +66 -0
  167. package/dist/demographics-F26DIOCM.js +138 -0
  168. package/dist/discard-2EJY6UGP.js +66 -0
  169. package/dist/domain-XLJABLWB.js +98 -0
  170. package/dist/draft-2YND6T4U.js +217 -0
  171. package/dist/draft-34CGWUVA.js +281 -0
  172. package/dist/draft-L45PGCYZ.js +237 -0
  173. package/dist/draft-L45PGCYZ.js.map +1 -0
  174. package/dist/draft-TCPK6XYW.js +332 -0
  175. package/dist/draft-TCPK6XYW.js.map +1 -0
  176. package/dist/draft-WRVEANL5.js +306 -0
  177. package/dist/engine/index.js +4 -4
  178. package/dist/experiment-7N4QFRWV.js +1397 -0
  179. package/dist/facets-OPTNDPW2.js +114 -0
  180. package/dist/feedback-43BPXNBI.js +106 -0
  181. package/dist/feedback-record-35ZSDL6Z.js +260 -0
  182. package/dist/fetch-O46XBA7S.js +176 -0
  183. package/dist/find-FSQAEGGF.js +134 -0
  184. package/dist/fit-CWJ5QQ4R.js +62 -0
  185. package/dist/flows-CVORIQ4B.js +247 -0
  186. package/dist/fonts-6TPYR6IW.js +36 -0
  187. package/dist/forecast-2VLA6NJA.js +118 -0
  188. package/dist/funnel-XLKDLXMG.js +394 -0
  189. package/dist/ga4-LPDIBNYP.js +55 -0
  190. package/dist/get-O56GGN3V.js +56 -0
  191. package/dist/get-WFQ4XEAW.js +79 -0
  192. package/dist/google-5ESVO76E.js +136 -0
  193. package/dist/google-ads-DZMOTUY5.js +195 -0
  194. package/dist/gsc-FIZTQX3N.js +30 -0
  195. package/dist/history-43BBQZOB.js +133 -0
  196. package/dist/history-QKDYBSYM.js +67 -0
  197. package/dist/hubspot-S44MPK3G.js +779 -0
  198. package/dist/icon-CSVAZ7NE.js +137 -0
  199. package/dist/ideas-SLP5WXFF.js +40 -0
  200. package/dist/images-TWZOROCT.js +92 -0
  201. package/dist/ingest-5GCZ5ZBV.js +23 -0
  202. package/dist/ingest-P54J4W3V.js +107 -0
  203. package/dist/insights-YWVJMATY.js +424 -0
  204. package/dist/insights-YWVJMATY.js.map +1 -0
  205. package/dist/inspect-S4COGUBC.js +189 -0
  206. package/dist/inspiration-IX5N724J.js +53 -0
  207. package/dist/instant-experiences-NQ2GWIWL.js +257 -0
  208. package/dist/instant-experiences-NQ2GWIWL.js.map +1 -0
  209. package/dist/keyword-metrics-26CCKFZK.js +197 -0
  210. package/dist/keywords-for-site-JWWECF63.js +128 -0
  211. package/dist/landing-VFDRADZY.js +28 -0
  212. package/dist/leads-DTKKYSKH.js +90 -0
  213. package/dist/leads-THI37ZMD.js +537 -0
  214. package/dist/leads-THI37ZMD.js.map +1 -0
  215. package/dist/learn-GQ75IPRK.js +204 -0
  216. package/dist/line-item-writes-DVVHVR3Y.js +208 -0
  217. package/dist/line-items-EOZMK7A5.js +103 -0
  218. package/dist/link-R5NGCQ5H.js +64 -0
  219. package/dist/linkedin-DHZO3IJX.js +1057 -0
  220. package/dist/list-57QBEGLM.js +303 -0
  221. package/dist/list-Q44BBHDI.js +64 -0
  222. package/dist/list-W6G2NTG5.js +151 -0
  223. package/dist/locations-HM56X2MK.js +67 -0
  224. package/dist/locations-HM56X2MK.js.map +1 -0
  225. package/dist/log-B6X5EPKA.js +92 -0
  226. package/dist/logo-VHXH4J6A.js +18 -0
  227. package/dist/make-OIFLF3QS.js +1353 -0
  228. package/dist/map-PIOZT2MQ.js +433 -0
  229. package/dist/mcp-GFKHLWDB.js +714 -0
  230. package/dist/media-H6B7VDON.js +18 -0
  231. package/dist/media-H6B7VDON.js.map +1 -0
  232. package/dist/media-sources-VMMMW5UM.js +32 -0
  233. package/dist/members-W2QBMNIW.js +44 -0
  234. package/dist/meta-YHDTGJQ6.js +122 -0
  235. package/dist/meta-YHDTGJQ6.js.map +1 -0
  236. package/dist/normalize-N6XC3SLC.js +141 -0
  237. package/dist/options-XYJY2OEQ.js +122 -0
  238. package/dist/organization-BVTXCZIV.js +942 -0
  239. package/dist/organization-BVTXCZIV.js.map +1 -0
  240. package/dist/page-photos-CXRG4AXV.js +115 -0
  241. package/dist/page-photos-CXRG4AXV.js.map +1 -0
  242. package/dist/pages-PTWRXAZT.js +66 -0
  243. package/dist/performance-7NEZTOJ5.js +24 -0
  244. package/dist/pixels-MYT3TCHZ.js +60 -0
  245. package/dist/pixels-ZZCQUS3J.js +108 -0
  246. package/dist/preview-XOXAAPMQ.js +215 -0
  247. package/dist/preview-XOXAAPMQ.js.map +1 -0
  248. package/dist/promoted-tweet-writes-X2F7R2AE.js +180 -0
  249. package/dist/promoted-tweets-XCSD6VKP.js +119 -0
  250. package/dist/publish-OBY6E43R.js +341 -0
  251. package/dist/reddit-WJ6KHYBC.js +26 -0
  252. package/dist/refresh-G5BQ2LWU.js +94 -0
  253. package/dist/release-PBZO35KY.js +60 -0
  254. package/dist/remove-VJ2MEUPM.js +50 -0
  255. package/dist/reopen-W3LYOHSR.js +63 -0
  256. package/dist/rerun-4GDNBFNM.js +90 -0
  257. package/dist/research-4YTFPGH7.js +262 -0
  258. package/dist/research-LOQRIBO6.js +62 -0
  259. package/dist/reset-55CCQGXB.js +54 -0
  260. package/dist/reset-AVTQEJPZ.js +54 -0
  261. package/dist/resolve-E6FNMFE3.js +121 -0
  262. package/dist/retry-HBJ7MKVI.js +60 -0
  263. package/dist/retry-QBRYM6MG.js +62 -0
  264. package/dist/rule-writes-6ZCAJDYZ.js +522 -0
  265. package/dist/rule-writes-6ZCAJDYZ.js.map +1 -0
  266. package/dist/rules-BMYOY2BM.js +216 -0
  267. package/dist/rules-BMYOY2BM.js.map +1 -0
  268. package/dist/rules-XNDBGOIS.js +96 -0
  269. package/dist/rules-add-UM3ZKSVD.js +462 -0
  270. package/dist/run-D4YHZ4Z4.js +66 -0
  271. package/dist/run-ZCJ7NP63.js +65 -0
  272. package/dist/scaffold-ad-VQZAP32M.js +1511 -0
  273. package/dist/scaffold-static-ad-LEU4M44N.js +1005 -0
  274. package/dist/scaffold-video-PSWSYRSC.js +883 -0
  275. package/dist/schedule-AAH7HYFK.js +61 -0
  276. package/dist/scheduled-agents-HDABMHZI.js +50 -0
  277. package/dist/schema-OH5OWMVQ.js +132 -0
  278. package/dist/search-BSDPVSGA.js +174 -0
  279. package/dist/select-EI4QF4YZ.js +101 -0
  280. package/dist/set-prompt-RKDAGUWG.js +193 -0
  281. package/dist/setup-links-CNNJA7AB.js +141 -0
  282. package/dist/shared-3IBNDEFL.js +31 -0
  283. package/dist/site-NV4U7PIF.js +177 -0
  284. package/dist/sources-ATONL7W5.js +454 -0
  285. package/dist/sources-C3TGHKLQ.js +30 -0
  286. package/dist/stale-6QPXL6BZ.js +71 -0
  287. package/dist/stats-ZAGJH4AD.js +34 -0
  288. package/dist/status-BML3F4MZ.js +62 -0
  289. package/dist/stock-6SHHLSKG.js +179 -0
  290. package/dist/studies-4NIV4D5Y.js +249 -0
  291. package/dist/studies-4NIV4D5Y.js.map +1 -0
  292. package/dist/studio-ZLCGXFAN.js +49 -0
  293. package/dist/study-writes-L2AA2PGL.js +467 -0
  294. package/dist/study-writes-L2AA2PGL.js.map +1 -0
  295. package/dist/sync-DZAOUQPE.js +54 -0
  296. package/dist/sync-definition-RFEL65JE.js +64 -0
  297. package/dist/tag-manager-3CJ66GKJ.js +43 -0
  298. package/dist/tags-2KSXCJRZ.js +20 -0
  299. package/dist/tags-662KZJLV.js +26 -0
  300. package/dist/tags-6QBVW25V.js +20 -0
  301. package/dist/tags-LQCEJGIL.js +20 -0
  302. package/dist/tags-RIVD54ZG.js +224 -0
  303. package/dist/targeting-LNDQV4EK.js +759 -0
  304. package/dist/targeting-LNDQV4EK.js.map +1 -0
  305. package/dist/targeting-criteria-XNLYPIL2.js +113 -0
  306. package/dist/targets-OYIVS5KJ.js +103 -0
  307. package/dist/testimonials-WT43CF7V.js +32 -0
  308. package/dist/top-companies-6QQMOS2Y.js +108 -0
  309. package/dist/translate-7QN7JFGU.js +604 -0
  310. package/dist/triggers-LVQY3QJ2.js +142 -0
  311. package/dist/unlink-5ASZTCS2.js +67 -0
  312. package/dist/unstage-LNZTEATR.js +85 -0
  313. package/dist/update-7BIR4GYO.js +152 -0
  314. package/dist/update-BRLM5DB3.js +98 -0
  315. package/dist/update-DRZAAJQ2.js +63 -0
  316. package/dist/update-NOWC3ICD.js +188 -0
  317. package/dist/upload-457Q4ANZ.js +126 -0
  318. package/dist/url-params-KM4NJGYC.js +98 -0
  319. package/dist/validate-COLEPJBA.js +117 -0
  320. package/dist/videos-5IDZTEWC.js +39 -0
  321. package/dist/viewer-check-433AZPBC.js +80 -0
  322. package/dist/viewer-check-433AZPBC.js.map +1 -0
  323. package/dist/web-FZYOCCYN.js +140 -0
  324. package/dist/winning-ads-I4DMP7RU.js +84 -0
  325. package/dist/write-commands-FYB6QG7K.js +1024 -0
  326. package/dist/write-commands-PEJBTME6.js +1165 -0
  327. package/dist/write-commands-PEJBTME6.js.map +1 -0
  328. package/dist/x-OMN5DDLM.js +47 -0
  329. package/package.json +1 -1
  330. package/dist/account-7LUQWY6Q.js +0 -49
  331. package/dist/account-7LUQWY6Q.js.map +0 -1
  332. package/dist/account-KNRDOUJP.js +0 -79
  333. package/dist/account-Z65CPOWE.js +0 -80
  334. package/dist/account-writes-4N2MA2ZR.js +0 -66
  335. package/dist/accounts-RTN5ZGTU.js +0 -611
  336. package/dist/accounts-RW6KXBOQ.js +0 -77
  337. package/dist/accounts-UA2ZWRN4.js +0 -75
  338. package/dist/actions-HNLISA7T.js +0 -55
  339. package/dist/activecampaign-I5CILZPU.js +0 -935
  340. package/dist/activities-IQPJPP4B.js +0 -74
  341. package/dist/ad-group-writes-EUTMPBMK.js +0 -170
  342. package/dist/ad-groups-OVPAI5RM.js +0 -68
  343. package/dist/ad-writes-DACTYFEO.js +0 -174
  344. package/dist/add-6WKPFMLG.js +0 -302
  345. package/dist/add-XF5COUAS.js +0 -104
  346. package/dist/ads-G6AS5L7G.js +0 -40
  347. package/dist/ads-HXX2IAFF.js +0 -113
  348. package/dist/ads-HXX2IAFF.js.map +0 -1
  349. package/dist/ads-L65JIKCD.js +0 -77
  350. package/dist/adsets-LPN6WFGF.js +0 -176
  351. package/dist/adsets-LPN6WFGF.js.map +0 -1
  352. package/dist/advertisers-6NUM2Q3A.js +0 -120
  353. package/dist/analytics-QKP3A5F3.js +0 -1976
  354. package/dist/analytics-VLHE5A2M.js +0 -433
  355. package/dist/assign-6HI6TNLP.js +0 -77
  356. package/dist/audience-size-25LP2OBF.js +0 -73
  357. package/dist/audiences-RPLVMO4H.js +0 -268
  358. package/dist/audiences-XEZHACKH.js +0 -78
  359. package/dist/audiences-XEZHACKH.js.map +0 -1
  360. package/dist/audit-YY6X2MPA.js +0 -151
  361. package/dist/autocomplete-SAWJK4NF.js +0 -111
  362. package/dist/avatars-MXTI74VC.js +0 -38
  363. package/dist/bid-pricing-HZ74SLEB.js +0 -100
  364. package/dist/brand-T3OACVQX.js +0 -22
  365. package/dist/brief-BN4UGUXF.js +0 -538
  366. package/dist/businesses-PRRYPR7H.js +0 -53
  367. package/dist/campaign-groups-YJK767AP.js +0 -95
  368. package/dist/campaign-writes-BAFB5E7A.js +0 -165
  369. package/dist/campaign-writes-BAFB5E7A.js.map +0 -1
  370. package/dist/campaign-writes-U5LTDTYK.js +0 -170
  371. package/dist/campaigns-4SOLY7OR.js +0 -110
  372. package/dist/campaigns-4SOLY7OR.js.map +0 -1
  373. package/dist/campaigns-GALDR5KK.js +0 -109
  374. package/dist/campaigns-NR6TNQFN.js +0 -107
  375. package/dist/campaigns-TFEQTSO3.js +0 -76
  376. package/dist/canvas-GJAQAVS6.js +0 -46
  377. package/dist/capabilities-2KT6TCGZ.js +0 -144
  378. package/dist/catalog-USZL4SGX.js +0 -65
  379. package/dist/catalogs-A7XMEEEP.js +0 -128
  380. package/dist/chatgpt-4PEWDJKP.js +0 -47
  381. package/dist/chats-INN2OHSH.js +0 -262
  382. package/dist/chats-INN2OHSH.js.map +0 -1
  383. package/dist/check-MMJGFFZS.js +0 -104
  384. package/dist/chunk-2LI6746F.js +0 -103
  385. package/dist/chunk-2PWNIEW4.js +0 -197
  386. package/dist/chunk-2XRMPSEV.js +0 -142
  387. package/dist/chunk-3TZVZXM6.js +0 -224
  388. package/dist/chunk-3UXMQ3K2.js +0 -274
  389. package/dist/chunk-3UXMQ3K2.js.map +0 -1
  390. package/dist/chunk-5HJRZFMW.js +0 -207
  391. package/dist/chunk-62JQQUAU.js +0 -5368
  392. package/dist/chunk-66QHX566.js +0 -6306
  393. package/dist/chunk-66QHX566.js.map +0 -1
  394. package/dist/chunk-6JWEGFM5.js +0 -174
  395. package/dist/chunk-6JWEGFM5.js.map +0 -1
  396. package/dist/chunk-6WCAV27H.js +0 -494
  397. package/dist/chunk-6WXV5GTA.js +0 -8914
  398. package/dist/chunk-7RBJ2Z7Z.js +0 -172
  399. package/dist/chunk-7RBJ2Z7Z.js.map +0 -1
  400. package/dist/chunk-AVNSH2JE.js +0 -8939
  401. package/dist/chunk-BITS62MF.js +0 -77
  402. package/dist/chunk-BL2MX6CR.js +0 -249
  403. package/dist/chunk-BOPC3D6I.js +0 -604
  404. package/dist/chunk-C6EYCD5J.js +0 -942
  405. package/dist/chunk-CSZFZKVX.js +0 -97
  406. package/dist/chunk-D5CUAOQX.js +0 -297
  407. package/dist/chunk-D5UXWKLQ.js +0 -903
  408. package/dist/chunk-FA4YZFRV.js +0 -392
  409. package/dist/chunk-FUKDI2UK.js +0 -122
  410. package/dist/chunk-G4STCTY3.js +0 -399
  411. package/dist/chunk-GOJXKIFQ.js +0 -1605
  412. package/dist/chunk-GOJXKIFQ.js.map +0 -1
  413. package/dist/chunk-H5HDZ7IC.js +0 -139
  414. package/dist/chunk-HSPMBLKE.js +0 -363
  415. package/dist/chunk-IJ22WP3G.js +0 -275
  416. package/dist/chunk-ILSKYRDR.js +0 -169
  417. package/dist/chunk-JQU2LUZG.js +0 -57
  418. package/dist/chunk-JWSEPW7F.js +0 -225
  419. package/dist/chunk-KIGGMKAE.js +0 -66
  420. package/dist/chunk-KIGGMKAE.js.map +0 -1
  421. package/dist/chunk-KPYDTIAI.js +0 -317
  422. package/dist/chunk-LBO2YAZY.js +0 -3868
  423. package/dist/chunk-LOMH4TTC.js +0 -1079
  424. package/dist/chunk-LPXSM2DI.js +0 -66
  425. package/dist/chunk-MVB32GPI.js +0 -592
  426. package/dist/chunk-MXH35PJ5.js +0 -51
  427. package/dist/chunk-NEIUVSDK.js +0 -206
  428. package/dist/chunk-NPMAATZG.js +0 -64
  429. package/dist/chunk-NXZCCGES.js +0 -159
  430. package/dist/chunk-OP7DNHD2.js +0 -137
  431. package/dist/chunk-OP7DNHD2.js.map +0 -1
  432. package/dist/chunk-OWA7ZLC4.js +0 -547
  433. package/dist/chunk-P3W6SRSQ.js +0 -455
  434. package/dist/chunk-PA4W7BCQ.js +0 -23
  435. package/dist/chunk-PTGYM4J6.js +0 -89
  436. package/dist/chunk-QE3JEJXF.js +0 -831
  437. package/dist/chunk-QNLJ3GNZ.js +0 -433
  438. package/dist/chunk-R3EKM2P2.js +0 -191
  439. package/dist/chunk-SISA4HQR.js +0 -61
  440. package/dist/chunk-TP7HKSBX.js +0 -172
  441. package/dist/chunk-TPANP5A2.js +0 -91
  442. package/dist/chunk-TRPJJMCS.js +0 -346
  443. package/dist/chunk-TZEVD4Q6.js +0 -160
  444. package/dist/chunk-UWXDNVS5.js +0 -167
  445. package/dist/chunk-VD73V44J.js +0 -344
  446. package/dist/chunk-X7F4Z6UM.js +0 -156
  447. package/dist/chunk-ZL23HA4N.js +0 -19
  448. package/dist/claim-SLGYOOWD.js +0 -197
  449. package/dist/companies-IVMH6YII.js +0 -195
  450. package/dist/complete-45L2FI2X.js +0 -81
  451. package/dist/connect-WBGCBBFJ.js +0 -42
  452. package/dist/conversation-RIOL3OJ7.js +0 -93
  453. package/dist/conversion-writes-JU7Q2MUO.js +0 -120
  454. package/dist/conversions-3ISBR3TS.js +0 -76
  455. package/dist/conversions-TKIXNSYR.js +0 -135
  456. package/dist/create-7JY2PTIZ.js +0 -132
  457. package/dist/create-ACLCRXQP.js +0 -59
  458. package/dist/create-KYBMFD32.js +0 -207
  459. package/dist/create-VAPJ52GJ.js +0 -235
  460. package/dist/creatives-S5QUWUL6.js +0 -58
  461. package/dist/creatives-VQO2TKE3.js +0 -182
  462. package/dist/creatives-YJ3CXZQC.js +0 -87
  463. package/dist/creatives-YJ3CXZQC.js.map +0 -1
  464. package/dist/credentials-YTQ6BHWV.js +0 -287
  465. package/dist/critique-5LCG5TYF.js +0 -227
  466. package/dist/critique-BHYJYZDV.js +0 -1458
  467. package/dist/crm-IKTWHWEB.js +0 -318
  468. package/dist/crm-N7K57LZJ.js +0 -224
  469. package/dist/custom-conversions-YRYE65PU.js +0 -125
  470. package/dist/custom-conversions-YRYE65PU.js.map +0 -1
  471. package/dist/customers-NLU7NYDC.js +0 -56
  472. package/dist/delete-26J3X3ZH.js +0 -64
  473. package/dist/delete-A4F5Z54J.js +0 -66
  474. package/dist/delete-EVXOFT2H.js +0 -54
  475. package/dist/demographics-VZKFMM4X.js +0 -138
  476. package/dist/discard-ULRVUJDV.js +0 -66
  477. package/dist/domain-L4WCCX7R.js +0 -98
  478. package/dist/draft-57OQKHZI.js +0 -306
  479. package/dist/draft-EWDOIXSH.js +0 -233
  480. package/dist/draft-EWDOIXSH.js.map +0 -1
  481. package/dist/draft-GPN3HOAG.js +0 -328
  482. package/dist/draft-GPN3HOAG.js.map +0 -1
  483. package/dist/draft-O4S5RKWK.js +0 -217
  484. package/dist/draft-Y2QJE2NM.js +0 -281
  485. package/dist/experiment-G3FQVAJU.js +0 -1397
  486. package/dist/facets-EHQKGGJ2.js +0 -114
  487. package/dist/feedback-CAOZPGTT.js +0 -106
  488. package/dist/feedback-record-EXV5H6OS.js +0 -260
  489. package/dist/fetch-ETKT2RBC.js +0 -176
  490. package/dist/find-EVY4XEIQ.js +0 -134
  491. package/dist/fit-UJQ47C4A.js +0 -62
  492. package/dist/flows-Z7355RMD.js +0 -247
  493. package/dist/fonts-7VWBQPJF.js +0 -36
  494. package/dist/forecast-OI7YWZ6F.js +0 -118
  495. package/dist/funnel-2B3JXJPX.js +0 -394
  496. package/dist/ga4-2BL5YAYN.js +0 -55
  497. package/dist/get-2RSN4N3J.js +0 -56
  498. package/dist/get-6N7QJMIP.js +0 -79
  499. package/dist/google-7STODZQR.js +0 -136
  500. package/dist/google-ads-G7REKD4A.js +0 -195
  501. package/dist/gsc-UU3T2C6B.js +0 -30
  502. package/dist/history-IQ33J5PB.js +0 -67
  503. package/dist/history-YMK2JNZU.js +0 -133
  504. package/dist/hubspot-BUFS7S33.js +0 -779
  505. package/dist/icon-GB7UH5RF.js +0 -137
  506. package/dist/ideas-F6CIGTVU.js +0 -40
  507. package/dist/images-WCKTD6Z2.js +0 -92
  508. package/dist/ingest-RQUJGS7K.js +0 -107
  509. package/dist/ingest-XLTRLCDV.js +0 -23
  510. package/dist/insights-4HT2NAYP.js +0 -423
  511. package/dist/insights-4HT2NAYP.js.map +0 -1
  512. package/dist/inspect-KFVAMD4N.js +0 -189
  513. package/dist/inspiration-XQYHBJY2.js +0 -53
  514. package/dist/keyword-metrics-WYF3QMCW.js +0 -197
  515. package/dist/keywords-for-site-G5L5EP3T.js +0 -128
  516. package/dist/landing-WUILAWDS.js +0 -28
  517. package/dist/leads-2XOSAYP4.js +0 -293
  518. package/dist/leads-2XOSAYP4.js.map +0 -1
  519. package/dist/leads-4SJ4NJOI.js +0 -90
  520. package/dist/learn-CC6Q5IK2.js +0 -204
  521. package/dist/line-item-writes-YXKYR25W.js +0 -208
  522. package/dist/line-items-CKUD2UU4.js +0 -103
  523. package/dist/link-VBYFI7AM.js +0 -64
  524. package/dist/linkedin-XKVPSCLV.js +0 -1057
  525. package/dist/list-6ZNZGRRK.js +0 -151
  526. package/dist/list-ENYDGT3F.js +0 -64
  527. package/dist/list-VSUF2IWT.js +0 -303
  528. package/dist/locations-YA7NZY44.js +0 -67
  529. package/dist/locations-YA7NZY44.js.map +0 -1
  530. package/dist/log-AACKGBDW.js +0 -92
  531. package/dist/logo-YSNUUT33.js +0 -18
  532. package/dist/make-ED7HBLH3.js +0 -1353
  533. package/dist/map-63CQHWPI.js +0 -433
  534. package/dist/mcp-RKAXC6IP.js +0 -714
  535. package/dist/media-ES2UBGYW.js +0 -15
  536. package/dist/media-ES2UBGYW.js.map +0 -1
  537. package/dist/media-sources-PEHUMH7C.js +0 -32
  538. package/dist/members-SELIA674.js +0 -44
  539. package/dist/meta-AOIPEDV5.js +0 -69
  540. package/dist/meta-AOIPEDV5.js.map +0 -1
  541. package/dist/normalize-VAZPTBDX.js +0 -141
  542. package/dist/options-6FCNFWUF.js +0 -122
  543. package/dist/organization-SHREKDST.js +0 -881
  544. package/dist/organization-SHREKDST.js.map +0 -1
  545. package/dist/pages-FTI44OSH.js +0 -66
  546. package/dist/performance-K7E5KAZW.js +0 -24
  547. package/dist/pixels-6IUB3Y3H.js +0 -60
  548. package/dist/pixels-MBKR4XPX.js +0 -108
  549. package/dist/preview-V4YBD45S.js +0 -169
  550. package/dist/preview-V4YBD45S.js.map +0 -1
  551. package/dist/promoted-tweet-writes-PKEO6WUK.js +0 -180
  552. package/dist/promoted-tweets-7MXVZRBI.js +0 -119
  553. package/dist/publish-MPMGRV72.js +0 -341
  554. package/dist/reddit-XIHRI3CN.js +0 -26
  555. package/dist/refresh-A27N75NH.js +0 -94
  556. package/dist/release-UKRB5IUN.js +0 -60
  557. package/dist/remove-AFNFVPZY.js +0 -50
  558. package/dist/reopen-M5HE6J3G.js +0 -63
  559. package/dist/rerun-A2XHGFZS.js +0 -90
  560. package/dist/research-BLDY5UWH.js +0 -62
  561. package/dist/research-U7RQXMYH.js +0 -262
  562. package/dist/reset-4CCWB2RT.js +0 -54
  563. package/dist/reset-J3KCWFMZ.js +0 -54
  564. package/dist/resolve-HEK27ANI.js +0 -121
  565. package/dist/retry-HPZIUG2S.js +0 -62
  566. package/dist/retry-VVI6N6UR.js +0 -60
  567. package/dist/rules-SK5DFFPY.js +0 -96
  568. package/dist/rules-add-YQNYSME7.js +0 -462
  569. package/dist/run-KBN5K7LE.js +0 -65
  570. package/dist/run-M7ZDE6IA.js +0 -66
  571. package/dist/scaffold-ad-6BN5LWQH.js +0 -1511
  572. package/dist/scaffold-static-ad-VVZRAWBR.js +0 -1005
  573. package/dist/scaffold-video-LFIYI4GP.js +0 -883
  574. package/dist/schedule-QMOKWTJ3.js +0 -61
  575. package/dist/scheduled-agents-FCQHQ6KR.js +0 -50
  576. package/dist/schema-THFLCMBN.js +0 -132
  577. package/dist/search-XIUYSWO6.js +0 -174
  578. package/dist/select-QBU6ED4K.js +0 -101
  579. package/dist/set-prompt-TL64CRBQ.js +0 -193
  580. package/dist/setup-links-QVI6NAOK.js +0 -141
  581. package/dist/shared-NDRFKAH7.js +0 -31
  582. package/dist/site-PZPJY33N.js +0 -177
  583. package/dist/sources-ER7ANNG3.js +0 -454
  584. package/dist/sources-RMNFV4CA.js +0 -30
  585. package/dist/stale-ITFCPOER.js +0 -71
  586. package/dist/stats-RCLQE4HJ.js +0 -34
  587. package/dist/status-ABMJBCPJ.js +0 -62
  588. package/dist/stock-ECRBD7RP.js +0 -179
  589. package/dist/studio-MARZ22J2.js +0 -49
  590. package/dist/sync-QDD3MRJ6.js +0 -54
  591. package/dist/sync-definition-C6ROLKJ4.js +0 -64
  592. package/dist/tag-manager-G3LBQZUL.js +0 -43
  593. package/dist/tags-5JYOEYIT.js +0 -20
  594. package/dist/tags-B473RWAA.js +0 -224
  595. package/dist/tags-EWHPUM2V.js +0 -20
  596. package/dist/tags-KBCX6BDU.js +0 -26
  597. package/dist/tags-PEWN6GNZ.js +0 -20
  598. package/dist/targeting-criteria-EU65WUUF.js +0 -113
  599. package/dist/targets-KVXS5QKM.js +0 -103
  600. package/dist/testimonials-YMMA5YWL.js +0 -32
  601. package/dist/top-companies-OOX3DITI.js +0 -108
  602. package/dist/translate-OXVIMYHE.js +0 -604
  603. package/dist/triggers-OX2GKG4Y.js +0 -142
  604. package/dist/unlink-3USEPJSA.js +0 -67
  605. package/dist/unstage-VSCNPTAC.js +0 -85
  606. package/dist/update-6JKTH65B.js +0 -152
  607. package/dist/update-FG4ELXYJ.js +0 -98
  608. package/dist/update-GZFKHA3A.js +0 -188
  609. package/dist/update-HZHG67N6.js +0 -63
  610. package/dist/upload-BKCQ6FRW.js +0 -126
  611. package/dist/url-params-UN4DRN2H.js +0 -98
  612. package/dist/validate-ZS2M5Q3V.js +0 -117
  613. package/dist/videos-I6YXFBFT.js +0 -39
  614. package/dist/viewer-check-7ZG7KHEN.js +0 -80
  615. package/dist/web-UGU7YMII.js +0 -140
  616. package/dist/winning-ads-ABN5OULS.js +0 -84
  617. package/dist/write-commands-6VR2UD3T.js +0 -1024
  618. package/dist/write-commands-HCQI4Y27.js +0 -737
  619. package/dist/write-commands-HCQI4Y27.js.map +0 -1
  620. package/dist/x-WK2VQDPF.js +0 -47
  621. /package/dist/{account-Z65CPOWE.js.map → account-3H6BZO5H.js.map} +0 -0
  622. /package/dist/{account-KNRDOUJP.js.map → account-VGSYM7LY.js.map} +0 -0
  623. /package/dist/{account-writes-4N2MA2ZR.js.map → account-writes-AE5IJGGW.js.map} +0 -0
  624. /package/dist/{accounts-RW6KXBOQ.js.map → accounts-2ARS6XP2.js.map} +0 -0
  625. /package/dist/{accounts-RTN5ZGTU.js.map → accounts-AQFW4ZUM.js.map} +0 -0
  626. /package/dist/{accounts-UA2ZWRN4.js.map → accounts-K4INATCW.js.map} +0 -0
  627. /package/dist/{actions-HNLISA7T.js.map → actions-QMUHOAXG.js.map} +0 -0
  628. /package/dist/{activecampaign-I5CILZPU.js.map → activecampaign-J3QN5FMG.js.map} +0 -0
  629. /package/dist/{activities-IQPJPP4B.js.map → activities-T253KK4Q.js.map} +0 -0
  630. /package/dist/{ad-group-writes-EUTMPBMK.js.map → ad-group-writes-VRSBI2Z2.js.map} +0 -0
  631. /package/dist/{ad-groups-OVPAI5RM.js.map → ad-groups-IEBVEAMS.js.map} +0 -0
  632. /package/dist/{ad-writes-DACTYFEO.js.map → ad-writes-ALV4KFPZ.js.map} +0 -0
  633. /package/dist/{add-XF5COUAS.js.map → add-VDUA6OWM.js.map} +0 -0
  634. /package/dist/{add-6WKPFMLG.js.map → add-XHOKCSW5.js.map} +0 -0
  635. /package/dist/{ads-L65JIKCD.js.map → ads-CQZHD7FC.js.map} +0 -0
  636. /package/dist/{ads-G6AS5L7G.js.map → ads-HGDPNIT6.js.map} +0 -0
  637. /package/dist/{advertisers-6NUM2Q3A.js.map → advertisers-UDSEFMP7.js.map} +0 -0
  638. /package/dist/{analytics-VLHE5A2M.js.map → analytics-TBETZOPJ.js.map} +0 -0
  639. /package/dist/{analytics-QKP3A5F3.js.map → analytics-VH74LMMC.js.map} +0 -0
  640. /package/dist/{connect-WBGCBBFJ.js.map → asset-writes-L5TMKIZC.js.map} +0 -0
  641. /package/dist/{assign-6HI6TNLP.js.map → assign-6IE2ASFC.js.map} +0 -0
  642. /package/dist/{audience-size-25LP2OBF.js.map → audience-size-CSBWDFEP.js.map} +0 -0
  643. /package/dist/{audiences-RPLVMO4H.js.map → audiences-AAZH56WD.js.map} +0 -0
  644. /package/dist/{audit-YY6X2MPA.js.map → audit-AEENRVGD.js.map} +0 -0
  645. /package/dist/{autocomplete-SAWJK4NF.js.map → autocomplete-AAGTJHVL.js.map} +0 -0
  646. /package/dist/{avatars-MXTI74VC.js.map → avatars-VEATUUKU.js.map} +0 -0
  647. /package/dist/{bid-pricing-HZ74SLEB.js.map → bid-pricing-SZTGCZTV.js.map} +0 -0
  648. /package/dist/{brand-T3OACVQX.js.map → brand-MXGETE4R.js.map} +0 -0
  649. /package/dist/{brief-BN4UGUXF.js.map → brief-3GHSHOGM.js.map} +0 -0
  650. /package/dist/{businesses-PRRYPR7H.js.map → businesses-H3HIDQX6.js.map} +0 -0
  651. /package/dist/{campaign-groups-YJK767AP.js.map → campaign-groups-WRI56M5X.js.map} +0 -0
  652. /package/dist/{campaign-writes-U5LTDTYK.js.map → campaign-writes-U5PUVSMT.js.map} +0 -0
  653. /package/dist/{campaigns-GALDR5KK.js.map → campaigns-4QWC2JE7.js.map} +0 -0
  654. /package/dist/{campaigns-TFEQTSO3.js.map → campaigns-JEIKY2M4.js.map} +0 -0
  655. /package/dist/{campaigns-NR6TNQFN.js.map → campaigns-Q4HN7HBY.js.map} +0 -0
  656. /package/dist/{canvas-GJAQAVS6.js.map → canvas-VJ3XKCAC.js.map} +0 -0
  657. /package/dist/{capabilities-2KT6TCGZ.js.map → capabilities-SNGGAOV3.js.map} +0 -0
  658. /package/dist/{catalog-USZL4SGX.js.map → catalog-S32MX453.js.map} +0 -0
  659. /package/dist/{catalogs-A7XMEEEP.js.map → catalogs-OCVXZLIF.js.map} +0 -0
  660. /package/dist/{chatgpt-4PEWDJKP.js.map → chatgpt-QVF2FD3E.js.map} +0 -0
  661. /package/dist/{check-MMJGFFZS.js.map → check-Z6UMIQKD.js.map} +0 -0
  662. /package/dist/{chunk-KPYDTIAI.js.map → chunk-2WZI36D3.js.map} +0 -0
  663. /package/dist/{chunk-FA4YZFRV.js.map → chunk-3AMLOCXY.js.map} +0 -0
  664. /package/dist/{chunk-X7F4Z6UM.js.map → chunk-3CVAEQMZ.js.map} +0 -0
  665. /package/dist/{chunk-SISA4HQR.js.map → chunk-3WAYZQNV.js.map} +0 -0
  666. /package/dist/{chunk-JWSEPW7F.js.map → chunk-46GWHUKN.js.map} +0 -0
  667. /package/dist/{chunk-R3EKM2P2.js.map → chunk-4O6T76A3.js.map} +0 -0
  668. /package/dist/{chunk-D5UXWKLQ.js.map → chunk-5MCVK4A3.js.map} +0 -0
  669. /package/dist/{chunk-CSZFZKVX.js.map → chunk-5ZLN23V5.js.map} +0 -0
  670. /package/dist/{chunk-OWA7ZLC4.js.map → chunk-77ULVP62.js.map} +0 -0
  671. /package/dist/{chunk-QNLJ3GNZ.js.map → chunk-AW2GKIGS.js.map} +0 -0
  672. /package/dist/{chunk-BL2MX6CR.js.map → chunk-BRLY6XD6.js.map} +0 -0
  673. /package/dist/{chunk-NPMAATZG.js.map → chunk-C7NWUCLQ.js.map} +0 -0
  674. /package/dist/{chunk-PA4W7BCQ.js.map → chunk-D4HKJBEW.js.map} +0 -0
  675. /package/dist/{chunk-H5HDZ7IC.js.map → chunk-DCBZ5CHZ.js.map} +0 -0
  676. /package/dist/{chunk-BITS62MF.js.map → chunk-G6XKD7QE.js.map} +0 -0
  677. /package/dist/{chunk-TP7HKSBX.js.map → chunk-GBFL4TD2.js.map} +0 -0
  678. /package/dist/{chunk-3TZVZXM6.js.map → chunk-H5SCKWFT.js.map} +0 -0
  679. /package/dist/{chunk-HSPMBLKE.js.map → chunk-HXPK6KAL.js.map} +0 -0
  680. /package/dist/{chunk-2PWNIEW4.js.map → chunk-I7GOSMWT.js.map} +0 -0
  681. /package/dist/{chunk-LOMH4TTC.js.map → chunk-IBY44U2M.js.map} +0 -0
  682. /package/dist/{chunk-IJ22WP3G.js.map → chunk-ITNHIZKK.js.map} +0 -0
  683. /package/dist/{chunk-P3W6SRSQ.js.map → chunk-J33P2JNS.js.map} +0 -0
  684. /package/dist/{chunk-NEIUVSDK.js.map → chunk-JH2L5CQD.js.map} +0 -0
  685. /package/dist/{chunk-62JQQUAU.js.map → chunk-JQH5VG6F.js.map} +0 -0
  686. /package/dist/{chunk-6WXV5GTA.js.map → chunk-JVH5A3XC.js.map} +0 -0
  687. /package/dist/{chunk-ILSKYRDR.js.map → chunk-KTOYQP6D.js.map} +0 -0
  688. /package/dist/{chunk-G4STCTY3.js.map → chunk-LO3IF5PS.js.map} +0 -0
  689. /package/dist/{chunk-BOPC3D6I.js.map → chunk-LRRFGOW3.js.map} +0 -0
  690. /package/dist/{chunk-C6EYCD5J.js.map → chunk-LTPTJWZC.js.map} +0 -0
  691. /package/dist/{chunk-NXZCCGES.js.map → chunk-MRQHJW5U.js.map} +0 -0
  692. /package/dist/{chunk-TRPJJMCS.js.map → chunk-NHYI7ORL.js.map} +0 -0
  693. /package/dist/{chunk-MXH35PJ5.js.map → chunk-NLI7C3K2.js.map} +0 -0
  694. /package/dist/{chunk-TPANP5A2.js.map → chunk-NSEMXBUB.js.map} +0 -0
  695. /package/dist/{chunk-LBO2YAZY.js.map → chunk-OM2BRYXJ.js.map} +0 -0
  696. /package/dist/{chunk-2LI6746F.js.map → chunk-OY4SKCIU.js.map} +0 -0
  697. /package/dist/{chunk-6WCAV27H.js.map → chunk-OYAJNTRO.js.map} +0 -0
  698. /package/dist/{chunk-QE3JEJXF.js.map → chunk-PL7J3DPQ.js.map} +0 -0
  699. /package/dist/{chunk-PTGYM4J6.js.map → chunk-PUSBUMYM.js.map} +0 -0
  700. /package/dist/{chunk-D5CUAOQX.js.map → chunk-RRADFRPI.js.map} +0 -0
  701. /package/dist/{chunk-VD73V44J.js.map → chunk-SGEPZB3D.js.map} +0 -0
  702. /package/dist/{chunk-LPXSM2DI.js.map → chunk-TFTZDWCX.js.map} +0 -0
  703. /package/dist/{chunk-2XRMPSEV.js.map → chunk-TG4NCHFS.js.map} +0 -0
  704. /package/dist/{chunk-5HJRZFMW.js.map → chunk-TTHM66TA.js.map} +0 -0
  705. /package/dist/{chunk-ZL23HA4N.js.map → chunk-VL2GNXZY.js.map} +0 -0
  706. /package/dist/{chunk-TZEVD4Q6.js.map → chunk-VQPZDM6N.js.map} +0 -0
  707. /package/dist/{chunk-JQU2LUZG.js.map → chunk-XCKINS7K.js.map} +0 -0
  708. /package/dist/{chunk-AVNSH2JE.js.map → chunk-YLYXSJ6O.js.map} +0 -0
  709. /package/dist/{chunk-MVB32GPI.js.map → chunk-ZAPO6UWS.js.map} +0 -0
  710. /package/dist/{chunk-FUKDI2UK.js.map → chunk-ZEPUDYPL.js.map} +0 -0
  711. /package/dist/{chunk-UWXDNVS5.js.map → chunk-ZJSGGJ5R.js.map} +0 -0
  712. /package/dist/{claim-SLGYOOWD.js.map → claim-J2LYNHZK.js.map} +0 -0
  713. /package/dist/{companies-IVMH6YII.js.map → companies-VYY22B6T.js.map} +0 -0
  714. /package/dist/{complete-45L2FI2X.js.map → complete-5I32XM7P.js.map} +0 -0
  715. /package/dist/{customers-NLU7NYDC.js.map → connect-EUFFQQ7O.js.map} +0 -0
  716. /package/dist/{conversation-RIOL3OJ7.js.map → conversation-D6KZHGPP.js.map} +0 -0
  717. /package/dist/{conversion-writes-JU7Q2MUO.js.map → conversion-writes-ECZBVY7D.js.map} +0 -0
  718. /package/dist/{conversions-3ISBR3TS.js.map → conversions-5QCSCRLI.js.map} +0 -0
  719. /package/dist/{conversions-TKIXNSYR.js.map → conversions-Y3X6ZTTF.js.map} +0 -0
  720. /package/dist/{create-ACLCRXQP.js.map → create-2JCRTQJL.js.map} +0 -0
  721. /package/dist/{create-VAPJ52GJ.js.map → create-LMSQPHPB.js.map} +0 -0
  722. /package/dist/{create-7JY2PTIZ.js.map → create-MBLNB5RY.js.map} +0 -0
  723. /package/dist/{create-KYBMFD32.js.map → create-VR7RXKL7.js.map} +0 -0
  724. /package/dist/{creatives-VQO2TKE3.js.map → creatives-5C42BDMW.js.map} +0 -0
  725. /package/dist/{creatives-S5QUWUL6.js.map → creatives-HYPSTANO.js.map} +0 -0
  726. /package/dist/{credentials-YTQ6BHWV.js.map → credentials-4H4AUYJN.js.map} +0 -0
  727. /package/dist/{critique-BHYJYZDV.js.map → critique-UOJZWDG2.js.map} +0 -0
  728. /package/dist/{critique-5LCG5TYF.js.map → critique-WCWMQQVV.js.map} +0 -0
  729. /package/dist/{crm-IKTWHWEB.js.map → crm-B7OTHMBP.js.map} +0 -0
  730. /package/dist/{crm-N7K57LZJ.js.map → crm-DZRWKJ6V.js.map} +0 -0
  731. /package/dist/{fit-UJQ47C4A.js.map → customers-AOFJJCGD.js.map} +0 -0
  732. /package/dist/{delete-26J3X3ZH.js.map → delete-DEG5KOBY.js.map} +0 -0
  733. /package/dist/{delete-EVXOFT2H.js.map → delete-EFIODCXG.js.map} +0 -0
  734. /package/dist/{delete-A4F5Z54J.js.map → delete-PQIMW2LK.js.map} +0 -0
  735. /package/dist/{demographics-VZKFMM4X.js.map → demographics-F26DIOCM.js.map} +0 -0
  736. /package/dist/{discard-ULRVUJDV.js.map → discard-2EJY6UGP.js.map} +0 -0
  737. /package/dist/{domain-L4WCCX7R.js.map → domain-XLJABLWB.js.map} +0 -0
  738. /package/dist/{draft-O4S5RKWK.js.map → draft-2YND6T4U.js.map} +0 -0
  739. /package/dist/{draft-Y2QJE2NM.js.map → draft-34CGWUVA.js.map} +0 -0
  740. /package/dist/{draft-57OQKHZI.js.map → draft-WRVEANL5.js.map} +0 -0
  741. /package/dist/{experiment-G3FQVAJU.js.map → experiment-7N4QFRWV.js.map} +0 -0
  742. /package/dist/{facets-EHQKGGJ2.js.map → facets-OPTNDPW2.js.map} +0 -0
  743. /package/dist/{feedback-CAOZPGTT.js.map → feedback-43BPXNBI.js.map} +0 -0
  744. /package/dist/{feedback-record-EXV5H6OS.js.map → feedback-record-35ZSDL6Z.js.map} +0 -0
  745. /package/dist/{fetch-ETKT2RBC.js.map → fetch-O46XBA7S.js.map} +0 -0
  746. /package/dist/{find-EVY4XEIQ.js.map → find-FSQAEGGF.js.map} +0 -0
  747. /package/dist/{fonts-7VWBQPJF.js.map → fit-CWJ5QQ4R.js.map} +0 -0
  748. /package/dist/{flows-Z7355RMD.js.map → flows-CVORIQ4B.js.map} +0 -0
  749. /package/dist/{ideas-F6CIGTVU.js.map → fonts-6TPYR6IW.js.map} +0 -0
  750. /package/dist/{forecast-OI7YWZ6F.js.map → forecast-2VLA6NJA.js.map} +0 -0
  751. /package/dist/{funnel-2B3JXJPX.js.map → funnel-XLKDLXMG.js.map} +0 -0
  752. /package/dist/{ga4-2BL5YAYN.js.map → ga4-LPDIBNYP.js.map} +0 -0
  753. /package/dist/{get-2RSN4N3J.js.map → get-O56GGN3V.js.map} +0 -0
  754. /package/dist/{get-6N7QJMIP.js.map → get-WFQ4XEAW.js.map} +0 -0
  755. /package/dist/{google-7STODZQR.js.map → google-5ESVO76E.js.map} +0 -0
  756. /package/dist/{google-ads-G7REKD4A.js.map → google-ads-DZMOTUY5.js.map} +0 -0
  757. /package/dist/{gsc-UU3T2C6B.js.map → gsc-FIZTQX3N.js.map} +0 -0
  758. /package/dist/{history-YMK2JNZU.js.map → history-43BBQZOB.js.map} +0 -0
  759. /package/dist/{history-IQ33J5PB.js.map → history-QKDYBSYM.js.map} +0 -0
  760. /package/dist/{hubspot-BUFS7S33.js.map → hubspot-S44MPK3G.js.map} +0 -0
  761. /package/dist/{icon-GB7UH5RF.js.map → icon-CSVAZ7NE.js.map} +0 -0
  762. /package/dist/{ingest-XLTRLCDV.js.map → ideas-SLP5WXFF.js.map} +0 -0
  763. /package/dist/{images-WCKTD6Z2.js.map → images-TWZOROCT.js.map} +0 -0
  764. /package/dist/{logo-YSNUUT33.js.map → ingest-5GCZ5ZBV.js.map} +0 -0
  765. /package/dist/{ingest-RQUJGS7K.js.map → ingest-P54J4W3V.js.map} +0 -0
  766. /package/dist/{inspect-KFVAMD4N.js.map → inspect-S4COGUBC.js.map} +0 -0
  767. /package/dist/{inspiration-XQYHBJY2.js.map → inspiration-IX5N724J.js.map} +0 -0
  768. /package/dist/{keyword-metrics-WYF3QMCW.js.map → keyword-metrics-26CCKFZK.js.map} +0 -0
  769. /package/dist/{keywords-for-site-G5L5EP3T.js.map → keywords-for-site-JWWECF63.js.map} +0 -0
  770. /package/dist/{landing-WUILAWDS.js.map → landing-VFDRADZY.js.map} +0 -0
  771. /package/dist/{leads-4SJ4NJOI.js.map → leads-DTKKYSKH.js.map} +0 -0
  772. /package/dist/{learn-CC6Q5IK2.js.map → learn-GQ75IPRK.js.map} +0 -0
  773. /package/dist/{line-item-writes-YXKYR25W.js.map → line-item-writes-DVVHVR3Y.js.map} +0 -0
  774. /package/dist/{line-items-CKUD2UU4.js.map → line-items-EOZMK7A5.js.map} +0 -0
  775. /package/dist/{link-VBYFI7AM.js.map → link-R5NGCQ5H.js.map} +0 -0
  776. /package/dist/{linkedin-XKVPSCLV.js.map → linkedin-DHZO3IJX.js.map} +0 -0
  777. /package/dist/{list-VSUF2IWT.js.map → list-57QBEGLM.js.map} +0 -0
  778. /package/dist/{list-ENYDGT3F.js.map → list-Q44BBHDI.js.map} +0 -0
  779. /package/dist/{list-6ZNZGRRK.js.map → list-W6G2NTG5.js.map} +0 -0
  780. /package/dist/{log-AACKGBDW.js.map → log-B6X5EPKA.js.map} +0 -0
  781. /package/dist/{performance-K7E5KAZW.js.map → logo-VHXH4J6A.js.map} +0 -0
  782. /package/dist/{make-ED7HBLH3.js.map → make-OIFLF3QS.js.map} +0 -0
  783. /package/dist/{map-63CQHWPI.js.map → map-PIOZT2MQ.js.map} +0 -0
  784. /package/dist/{mcp-RKAXC6IP.js.map → mcp-GFKHLWDB.js.map} +0 -0
  785. /package/dist/{media-sources-PEHUMH7C.js.map → media-sources-VMMMW5UM.js.map} +0 -0
  786. /package/dist/{members-SELIA674.js.map → members-W2QBMNIW.js.map} +0 -0
  787. /package/dist/{normalize-VAZPTBDX.js.map → normalize-N6XC3SLC.js.map} +0 -0
  788. /package/dist/{options-6FCNFWUF.js.map → options-XYJY2OEQ.js.map} +0 -0
  789. /package/dist/{pages-FTI44OSH.js.map → pages-PTWRXAZT.js.map} +0 -0
  790. /package/dist/{reddit-XIHRI3CN.js.map → performance-7NEZTOJ5.js.map} +0 -0
  791. /package/dist/{pixels-6IUB3Y3H.js.map → pixels-MYT3TCHZ.js.map} +0 -0
  792. /package/dist/{pixels-MBKR4XPX.js.map → pixels-ZZCQUS3J.js.map} +0 -0
  793. /package/dist/{promoted-tweet-writes-PKEO6WUK.js.map → promoted-tweet-writes-X2F7R2AE.js.map} +0 -0
  794. /package/dist/{promoted-tweets-7MXVZRBI.js.map → promoted-tweets-XCSD6VKP.js.map} +0 -0
  795. /package/dist/{publish-MPMGRV72.js.map → publish-OBY6E43R.js.map} +0 -0
  796. /package/dist/{run-KBN5K7LE.js.map → reddit-WJ6KHYBC.js.map} +0 -0
  797. /package/dist/{refresh-A27N75NH.js.map → refresh-G5BQ2LWU.js.map} +0 -0
  798. /package/dist/{release-UKRB5IUN.js.map → release-PBZO35KY.js.map} +0 -0
  799. /package/dist/{remove-AFNFVPZY.js.map → remove-VJ2MEUPM.js.map} +0 -0
  800. /package/dist/{reopen-M5HE6J3G.js.map → reopen-W3LYOHSR.js.map} +0 -0
  801. /package/dist/{rerun-A2XHGFZS.js.map → rerun-4GDNBFNM.js.map} +0 -0
  802. /package/dist/{research-U7RQXMYH.js.map → research-4YTFPGH7.js.map} +0 -0
  803. /package/dist/{research-BLDY5UWH.js.map → research-LOQRIBO6.js.map} +0 -0
  804. /package/dist/{reset-4CCWB2RT.js.map → reset-55CCQGXB.js.map} +0 -0
  805. /package/dist/{reset-J3KCWFMZ.js.map → reset-AVTQEJPZ.js.map} +0 -0
  806. /package/dist/{resolve-HEK27ANI.js.map → resolve-E6FNMFE3.js.map} +0 -0
  807. /package/dist/{retry-VVI6N6UR.js.map → retry-HBJ7MKVI.js.map} +0 -0
  808. /package/dist/{retry-HPZIUG2S.js.map → retry-QBRYM6MG.js.map} +0 -0
  809. /package/dist/{rules-SK5DFFPY.js.map → rules-XNDBGOIS.js.map} +0 -0
  810. /package/dist/{rules-add-YQNYSME7.js.map → rules-add-UM3ZKSVD.js.map} +0 -0
  811. /package/dist/{run-M7ZDE6IA.js.map → run-D4YHZ4Z4.js.map} +0 -0
  812. /package/dist/{shared-NDRFKAH7.js.map → run-ZCJ7NP63.js.map} +0 -0
  813. /package/dist/{scaffold-ad-6BN5LWQH.js.map → scaffold-ad-VQZAP32M.js.map} +0 -0
  814. /package/dist/{scaffold-static-ad-VVZRAWBR.js.map → scaffold-static-ad-LEU4M44N.js.map} +0 -0
  815. /package/dist/{scaffold-video-LFIYI4GP.js.map → scaffold-video-PSWSYRSC.js.map} +0 -0
  816. /package/dist/{schedule-QMOKWTJ3.js.map → schedule-AAH7HYFK.js.map} +0 -0
  817. /package/dist/{scheduled-agents-FCQHQ6KR.js.map → scheduled-agents-HDABMHZI.js.map} +0 -0
  818. /package/dist/{schema-THFLCMBN.js.map → schema-OH5OWMVQ.js.map} +0 -0
  819. /package/dist/{search-XIUYSWO6.js.map → search-BSDPVSGA.js.map} +0 -0
  820. /package/dist/{select-QBU6ED4K.js.map → select-EI4QF4YZ.js.map} +0 -0
  821. /package/dist/{set-prompt-TL64CRBQ.js.map → set-prompt-RKDAGUWG.js.map} +0 -0
  822. /package/dist/{setup-links-QVI6NAOK.js.map → setup-links-CNNJA7AB.js.map} +0 -0
  823. /package/dist/{sync-definition-C6ROLKJ4.js.map → shared-3IBNDEFL.js.map} +0 -0
  824. /package/dist/{site-PZPJY33N.js.map → site-NV4U7PIF.js.map} +0 -0
  825. /package/dist/{sources-ER7ANNG3.js.map → sources-ATONL7W5.js.map} +0 -0
  826. /package/dist/{sources-RMNFV4CA.js.map → sources-C3TGHKLQ.js.map} +0 -0
  827. /package/dist/{stale-ITFCPOER.js.map → stale-6QPXL6BZ.js.map} +0 -0
  828. /package/dist/{stats-RCLQE4HJ.js.map → stats-ZAGJH4AD.js.map} +0 -0
  829. /package/dist/{status-ABMJBCPJ.js.map → status-BML3F4MZ.js.map} +0 -0
  830. /package/dist/{stock-ECRBD7RP.js.map → stock-6SHHLSKG.js.map} +0 -0
  831. /package/dist/{studio-MARZ22J2.js.map → studio-ZLCGXFAN.js.map} +0 -0
  832. /package/dist/{sync-QDD3MRJ6.js.map → sync-DZAOUQPE.js.map} +0 -0
  833. /package/dist/{viewer-check-7ZG7KHEN.js.map → sync-definition-RFEL65JE.js.map} +0 -0
  834. /package/dist/{tag-manager-G3LBQZUL.js.map → tag-manager-3CJ66GKJ.js.map} +0 -0
  835. /package/dist/{tags-EWHPUM2V.js.map → tags-2KSXCJRZ.js.map} +0 -0
  836. /package/dist/{tags-KBCX6BDU.js.map → tags-662KZJLV.js.map} +0 -0
  837. /package/dist/{tags-5JYOEYIT.js.map → tags-6QBVW25V.js.map} +0 -0
  838. /package/dist/{tags-PEWN6GNZ.js.map → tags-LQCEJGIL.js.map} +0 -0
  839. /package/dist/{tags-B473RWAA.js.map → tags-RIVD54ZG.js.map} +0 -0
  840. /package/dist/{targeting-criteria-EU65WUUF.js.map → targeting-criteria-XNLYPIL2.js.map} +0 -0
  841. /package/dist/{targets-KVXS5QKM.js.map → targets-OYIVS5KJ.js.map} +0 -0
  842. /package/dist/{testimonials-YMMA5YWL.js.map → testimonials-WT43CF7V.js.map} +0 -0
  843. /package/dist/{top-companies-OOX3DITI.js.map → top-companies-6QQMOS2Y.js.map} +0 -0
  844. /package/dist/{translate-OXVIMYHE.js.map → translate-7QN7JFGU.js.map} +0 -0
  845. /package/dist/{triggers-OX2GKG4Y.js.map → triggers-LVQY3QJ2.js.map} +0 -0
  846. /package/dist/{unlink-3USEPJSA.js.map → unlink-5ASZTCS2.js.map} +0 -0
  847. /package/dist/{unstage-VSCNPTAC.js.map → unstage-LNZTEATR.js.map} +0 -0
  848. /package/dist/{update-6JKTH65B.js.map → update-7BIR4GYO.js.map} +0 -0
  849. /package/dist/{update-FG4ELXYJ.js.map → update-BRLM5DB3.js.map} +0 -0
  850. /package/dist/{update-HZHG67N6.js.map → update-DRZAAJQ2.js.map} +0 -0
  851. /package/dist/{update-GZFKHA3A.js.map → update-NOWC3ICD.js.map} +0 -0
  852. /package/dist/{upload-BKCQ6FRW.js.map → upload-457Q4ANZ.js.map} +0 -0
  853. /package/dist/{url-params-UN4DRN2H.js.map → url-params-KM4NJGYC.js.map} +0 -0
  854. /package/dist/{validate-ZS2M5Q3V.js.map → validate-COLEPJBA.js.map} +0 -0
  855. /package/dist/{videos-I6YXFBFT.js.map → videos-5IDZTEWC.js.map} +0 -0
  856. /package/dist/{web-UGU7YMII.js.map → web-FZYOCCYN.js.map} +0 -0
  857. /package/dist/{winning-ads-ABN5OULS.js.map → winning-ads-I4DMP7RU.js.map} +0 -0
  858. /package/dist/{write-commands-6VR2UD3T.js.map → write-commands-FYB6QG7K.js.map} +0 -0
  859. /package/dist/{x-WK2VQDPF.js.map → x-OMN5DDLM.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/limits.ts","../../api/src/ads-meta/ops.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\",\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\", \"story\"] 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 * 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};\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 * Instagram `explore_home` requires `explore`, and that one is not on the\n * Placement Targeting page at all — it came out of the same validate-only sweep\n * as RETIRED_PLACEMENTS (\"To place ads in Instagram Explore Home, please also\n * select Instagram Explore\", v25.0, 2026-09-18). It is exactly the shape of the\n * documented `feed` rule, so it costs a publish in exactly the same way.\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 (instagram.includes(\"explore_home\") && !instagram.includes(\"explore\")) {\n issues.push(\n 'Meta refuses Instagram \"explore_home\" without \"explore\" — add \"explore\" to instagram_positions or drop explore_home',\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 — Meta publishes no complete `ad_format`\n * enum, and inventing a value burns an API call to learn nothing.\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 // 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 * Single source of truth for Meta Marketing API write constraints\n * (Graph API v25.0). Every zod schema in `ops.ts` reads from here — no\n * scattered literals. The naming follows Meta's object graph: Campaign →\n * Ad Set → Ad Creative → Ad, plus Custom Audiences and media.\n */\n\nexport const META_LIMITS = {\n campaign: {\n nameMax: 400,\n },\n adSet: {\n nameMax: 400,\n },\n ad: {\n nameMax: 400,\n },\n creative: {\n nameMax: 400,\n /** Feed truncates the primary text past this with \"… See more\". */\n messageSoftMax: 125,\n messageHardMax: 5000,\n /** Below this, primary text reads as too thin to carry a hook + value + reason to act. */\n messageGoodMin: 40,\n headlineMax: 255,\n descriptionMax: 300,\n carouselCardsMin: 2,\n carouselCardsMax: 10,\n /** Carousels tell a fuller story and give Meta more to optimize at this many cards. */\n carouselCardsGoodMin: 3,\n dynamicTextsMin: 1,\n dynamicTextsMax: 5,\n /** Dynamic ads mix and match best with at least this many media assets. */\n dynamicAssetsGoodMin: 3,\n },\n audience: {\n nameMax: 100,\n /** Website/engagement audiences below this rarely serve. */\n minLookalikeSourceRows: 100,\n retentionDaysMax: 180,\n },\n customConversion: {\n nameMax: 100,\n descriptionMax: 500,\n /**\n * Meta's hard cap per ad account. It matters because deleting a custom\n * conversion archives it rather than removing it, so a chat that creates\n * one per campaign spends slots that only a person, in Events Manager, can\n * think about reclaiming.\n */\n perAccountMax: 100,\n },\n} as const;\n\n// --- Campaign ---\n\nexport const OBJECTIVES = [\n \"OUTCOME_TRAFFIC\",\n \"OUTCOME_ENGAGEMENT\",\n \"OUTCOME_LEADS\",\n \"OUTCOME_SALES\",\n \"OUTCOME_AWARENESS\",\n \"OUTCOME_APP_PROMOTION\",\n] as const;\nexport type MetaObjective = (typeof OBJECTIVES)[number];\n\nexport const SPECIAL_AD_CATEGORIES = [\n \"NONE\",\n \"HOUSING\",\n \"EMPLOYMENT\",\n /** Deprecated by Meta on 2025-01-14 — replaced by FINANCIAL_PRODUCTS_SERVICES. Still accepted as input and mapped on the wire. */\n \"CREDIT\",\n \"ISSUES_ELECTIONS_POLITICS\",\n \"FINANCIAL_PRODUCTS_SERVICES\",\n \"ONLINE_GAMBLING_AND_GAMING\",\n] as const;\nexport type MetaSpecialAdCategory = (typeof SPECIAL_AD_CATEGORIES)[number];\n\n/** ISO Alpha-2 country declaration is mandatory for these categories. */\nexport const SPECIAL_CATEGORIES_REQUIRING_COUNTRY: readonly MetaSpecialAdCategory[] = [\"ISSUES_ELECTIONS_POLITICS\"];\n\nexport const BUYING_TYPES = [\"AUCTION\", \"RESERVED\"] as const;\n\nexport const BID_STRATEGIES = [\n \"LOWEST_COST_WITHOUT_CAP\",\n \"LOWEST_COST_WITH_BID_CAP\",\n \"COST_CAP\",\n \"LOWEST_COST_WITH_MIN_ROAS\",\n] as const;\nexport type MetaBidStrategy = (typeof BID_STRATEGIES)[number];\n\n/** Bid strategies that require an explicit `bid_amount` on the ad set. */\nexport const BID_STRATEGIES_REQUIRING_AMOUNT: readonly MetaBidStrategy[] = [\"LOWEST_COST_WITH_BID_CAP\", \"COST_CAP\"];\n\n/**\n * Bid strategies that must NOT carry a `bid_amount` — Meta rejects one.\n * Auto-bid (`LOWEST_COST_WITHOUT_CAP`) has no cap; `LOWEST_COST_WITH_MIN_ROAS`\n * uses `bid_constraints.roas_average_floor` instead of a flat amount.\n */\nexport const BID_STRATEGIES_FORBIDDING_AMOUNT: readonly MetaBidStrategy[] = [\n \"LOWEST_COST_WITHOUT_CAP\",\n \"LOWEST_COST_WITH_MIN_ROAS\",\n];\n\n// --- Ad set ---\n\nexport const BILLING_EVENTS = [\n \"APP_INSTALLS\",\n \"CLICKS\",\n \"IMPRESSIONS\",\n \"LINK_CLICKS\",\n \"NONE\",\n \"OFFER_CLAIMS\",\n \"PAGE_LIKES\",\n \"POST_ENGAGEMENT\",\n \"THRUPLAY\",\n \"PURCHASE\",\n \"LISTING_INTERACTION\",\n] as const;\nexport type MetaBillingEvent = (typeof BILLING_EVENTS)[number];\n\nexport const OPTIMIZATION_GOALS = [\n \"NONE\",\n \"APP_INSTALLS\",\n \"AD_RECALL_LIFT\",\n \"ENGAGED_USERS\",\n \"EVENT_RESPONSES\",\n \"IMPRESSIONS\",\n \"LEAD_GENERATION\",\n \"QUALITY_LEAD\",\n \"QUALITY_CALL\",\n \"LINK_CLICKS\",\n \"OFFSITE_CONVERSIONS\",\n \"LANDING_PAGE_VIEWS\",\n \"PAGE_LIKES\",\n \"POST_ENGAGEMENT\",\n \"REACH\",\n \"THRUPLAY\",\n \"VALUE\",\n \"CONVERSATIONS\",\n \"DERIVED_EVENTS\",\n // Added 2026-09-18 from Meta's own generated enum spec\n // (facebook-business-sdk-codegen › AdSet_optimization_goal). Every one of these\n // is a goal Meta accepts and Baker used to refuse at stage time — the messaging\n // and Instagram-profile goals are the ones that cost real campaigns, because a\n // click-to-WhatsApp ad set cannot be expressed without them.\n \"ADVERTISER_SILOED_VALUE\",\n \"APP_INSTALLS_AND_OFFSITE_CONVERSIONS\",\n \"AUTOMATIC_OBJECTIVE\",\n \"ENGAGED_PAGE_VIEWS\",\n \"IN_APP_VALUE\",\n \"MEANINGFUL_CALL_ATTEMPT\",\n \"MESSAGING_APPOINTMENT_CONVERSION\",\n \"MESSAGING_DEEP_CONVERSATION_AND_FOLLOW\",\n \"MESSAGING_PURCHASE_CONVERSION\",\n \"PROFILE_AND_PAGE_ENGAGEMENT\",\n \"PROFILE_VISIT\",\n \"REMINDERS_SET\",\n \"SUBSCRIBERS\",\n \"VISIT_INSTAGRAM_PROFILE\",\n] as const;\nexport type MetaOptimizationGoal = (typeof OPTIMIZATION_GOALS)[number];\n\n/**\n * Optimization goals Meta rejects without a `promoted_object.page_id` — the\n * lead-form and page goals where the promoted object *is* the page (instant\n * forms, page likes). Missing it fails publish with subcode 1815430\n * (\"Please select a promoted object for your ad set\").\n */\nexport const OPTIMIZATION_GOALS_REQUIRING_PAGE: readonly MetaOptimizationGoal[] = [\n \"LEAD_GENERATION\",\n \"QUALITY_LEAD\",\n \"PAGE_LIKES\",\n];\n\n/**\n * Web-conversion goals Meta rejects without `promoted_object.pixel_id` +\n * `custom_event_type` — the pixel/event the ad set optimizes toward. Meta docs:\n * \"For OFFSITE_CONVERSIONS: Requires pixel_id and custom_event_type.\"\n */\nexport const OPTIMIZATION_GOALS_REQUIRING_PIXEL: readonly MetaOptimizationGoal[] = [\"OFFSITE_CONVERSIONS\"];\n\n/**\n * Value-optimization goals need `custom_event_type` plus a conversion *source* —\n * `pixel_id` for web value optimization, or `application_id` for app value\n * optimization (AEO/VO). Requiring `pixel_id` unconditionally would reject a\n * legitimate app-based VALUE campaign, so we accept either source.\n */\nexport const OPTIMIZATION_GOALS_REQUIRING_CONVERSION_SOURCE: readonly MetaOptimizationGoal[] = [\"VALUE\"];\n\n/** App-promotion goals Meta rejects without `promoted_object.application_id`. */\nexport const OPTIMIZATION_GOALS_REQUIRING_APP: readonly MetaOptimizationGoal[] = [\"APP_INSTALLS\"];\n\n/**\n * `PHONE_CALL` is CONTESTED and deliberately kept. Meta's Destination Type page\n * documents it; Meta's own generated enum spec does not list it. Neither source\n * settles it and a create is the only thing that would, so it stays accepted —\n * removing a value Meta takes breaks a campaign shape, keeping one it refuses\n * costs a single publish error that names itself.\n */\nexport const DESTINATION_TYPES = [\n \"WEBSITE\",\n \"APP\",\n \"MESSENGER\",\n \"INSTAGRAM_DIRECT\",\n \"ON_AD\",\n \"ON_PAGE\",\n \"ON_POST\",\n \"ON_VIDEO\",\n \"WHATSAPP\",\n \"PHONE_CALL\",\n \"INSTAGRAM_PROFILE\",\n \"SHOP_AUTOMATIC\",\n // Added 2026-09-18 from adcampaign_destination_type. The four MESSAGING_* values\n // are the click-to-message destinations (Messenger / Instagram Direct / WhatsApp\n // in every combination Meta ships); without them Baker could not stage a\n // click-to-WhatsApp ad set at all.\n \"APPLINKS_AUTOMATIC\",\n \"FACEBOOK\",\n \"FACEBOOK_LIVE\",\n \"FACEBOOK_PAGE\",\n \"IMAGINE\",\n \"INSTAGRAM_LIVE\",\n \"INSTAGRAM_PROFILE_AND_FACEBOOK_PAGE\",\n \"MESSAGING_INSTAGRAM_DIRECT_MESSENGER\",\n \"MESSAGING_INSTAGRAM_DIRECT_MESSENGER_WHATSAPP\",\n \"MESSAGING_INSTAGRAM_DIRECT_WHATSAPP\",\n \"MESSAGING_MESSENGER_WHATSAPP\",\n \"ON_EVENT\",\n] as const;\nexport type MetaDestinationType = (typeof DESTINATION_TYPES)[number];\n\nexport const CUSTOM_EVENT_TYPES = [\n \"PURCHASE\",\n \"LEAD\",\n \"COMPLETE_REGISTRATION\",\n \"ADD_TO_CART\",\n \"ADD_PAYMENT_INFO\",\n \"INITIATED_CHECKOUT\",\n \"CONTENT_VIEW\",\n \"SEARCH\",\n \"SUBSCRIBE\",\n \"START_TRIAL\",\n \"CONTACT\",\n \"OTHER\",\n // Added 2026-09-18 from AdPromotedObject_custom_event_type. SCHEDULE,\n // SUBMIT_APPLICATION, SERVICE_BOOKING_REQUEST and\n // MESSAGING_CONVERSATION_STARTED_7D are the conversions service businesses and\n // click-to-message campaigns actually optimize toward.\n \"ACHIEVEMENT_UNLOCKED\",\n \"ADD_TO_WISHLIST\",\n \"AD_IMPRESSION\",\n \"CUSTOMIZE_PRODUCT\",\n \"D2_RETENTION\",\n \"D7_RETENTION\",\n \"DONATE\",\n \"FIND_LOCATION\",\n \"LEVEL_ACHIEVED\",\n \"LISTING_INTERACTION\",\n \"MESSAGING_CONVERSATION_STARTED_7D\",\n \"RATE\",\n \"SCHEDULE\",\n \"SERVICE_BOOKING_REQUEST\",\n \"SPENT_CREDITS\",\n \"SUBMIT_APPLICATION\",\n \"TUTORIAL_COMPLETION\",\n] as const;\n\nexport const ATTRIBUTION_EVENT_TYPES = [\"CLICK_THROUGH\", \"VIEW_THROUGH\", \"ENGAGED_VIDEO_VIEW\"] as const;\nexport const ATTRIBUTION_WINDOW_DAYS = [1, 7, 28] as const;\n\n// --- Advantage+ Audience (targeting_automation.advantage_audience) ---\n\n/**\n * With Advantage+ Audience on (`advantage_audience: 1`, the Meta v23+ default\n * when age/gender/custom-audience/detailed inclusions are default or omitted),\n * age & gender become mere suggestions: `age_max` is pinned to 65 and `age_min`\n * is limited to 18–25. Setting a narrower `age_max`, an `age_min` above 25, or a\n * single-gender restriction is rejected (subcode 1870189, \"add a lower maximum\n * age as a suggestion instead\"). To enforce a HARD age/gender limit you must set\n * `advantage_audience: 0`.\n */\nexport const ADVANTAGE_AUDIENCE_OPEN_AGE_MAX = 65;\nexport const ADVANTAGE_AUDIENCE_MAX_HARD_AGE_MIN = 25;\n\n// --- EU Digital Services Act (DSA) ---\n\n/**\n * When an ad set targets any EU country, Meta requires `dsa_beneficiary` and\n * `dsa_payor` (who benefits from / pays for the ad) for Digital Services Act\n * compliance — the create is rejected without them. The backend auto-fills both\n * from the ad account's business name when the caller omits them.\n */\nexport const EU_DSA_COUNTRIES = new Set([\n \"AT\",\n \"BE\",\n \"BG\",\n \"HR\",\n \"CY\",\n \"CZ\",\n \"DK\",\n \"EE\",\n \"FI\",\n \"FR\",\n \"DE\",\n \"GR\",\n \"HU\",\n \"IE\",\n \"IT\",\n \"LV\",\n \"LT\",\n \"LU\",\n \"MT\",\n \"NL\",\n \"PL\",\n \"PT\",\n \"RO\",\n \"SK\",\n \"SI\",\n \"ES\",\n \"SE\",\n]);\n\n// --- Ad creative ---\n\n/**\n * Every button Meta accepts on `object_story_spec.link_data.call_to_action.type`\n * — a single ad, a video ad, and each card of a carousel.\n *\n * Read off Meta itself on 2026-09-01 by posting an invalid type and keeping the\n * list its 400 enumerates, because the published reference and the live\n * validator disagree: `SEE_DETAILS` is missing from the docs page and accepted\n * by the API, and it is the button three of one client's live ads actually use.\n * This list used to be a hand-picked 27, so those ads could not be rebuilt\n * through Baker at all — the button was the thing that stopped them.\n *\n * Meta keeps a SECOND, different list for `asset_feed_spec.call_to_action_types`\n * ({@link ASSET_FEED_CTA_TYPES}). Neither contains the other:\n * `SEE_DETAILS` is link-only, `GET_STARTED` and `VIEW_CART` are feed-only. A\n * value in the wrong slot is refused at creation, so the two are kept apart\n * rather than unioned.\n */\nexport const CTA_TYPES = [\n \"BOOK_TRAVEL\",\n \"CONTACT_US\",\n \"DONATE\",\n \"DONATE_NOW\",\n \"DOWNLOAD\",\n \"GET_DIRECTIONS\",\n \"GO_LIVE\",\n \"INTERESTED\",\n \"LEARN_MORE\",\n \"SEE_DETAILS\",\n \"LIKE_PAGE\",\n \"MESSAGE_PAGE\",\n \"RAISE_MONEY\",\n \"SAVE\",\n \"SEND_TIP\",\n \"SHOP_NOW\",\n \"SIGN_UP\",\n \"VIEW_INSTAGRAM_PROFILE\",\n \"INSTAGRAM_MESSAGE\",\n \"LOYALTY_LEARN_MORE\",\n \"PURCHASE_GIFT_CARDS\",\n \"PAY_TO_ACCESS\",\n \"SEE_MORE\",\n \"TRY_IN_CAMERA\",\n \"WHATSAPP_LINK\",\n \"GET_IN_TOUCH\",\n \"TRY_NOW\",\n \"ASK_A_QUESTION\",\n \"START_A_CHAT\",\n \"CHAT_NOW\",\n \"ASK_US\",\n \"CHAT_WITH_US\",\n \"BOOK_NOW\",\n \"CHECK_AVAILABILITY\",\n \"ORDER_NOW\",\n \"WHATSAPP_MESSAGE\",\n \"GET_MOBILE_APP\",\n \"INSTALL_MOBILE_APP\",\n \"USE_MOBILE_APP\",\n \"INSTALL_APP\",\n \"USE_APP\",\n \"PLAY_GAME\",\n \"TRY_DEMO\",\n \"WATCH_VIDEO\",\n \"WATCH_MORE\",\n \"OPEN_LINK\",\n \"NO_BUTTON\",\n \"LISTEN_MUSIC\",\n \"MOBILE_DOWNLOAD\",\n \"GET_OFFER\",\n \"GET_OFFER_VIEW\",\n \"BUY_NOW\",\n \"BUY_TICKETS\",\n \"UPDATE_APP\",\n \"BET_NOW\",\n \"ADD_TO_CART\",\n \"SELL_NOW\",\n \"GET_SHOWTIMES\",\n \"LISTEN_NOW\",\n \"GET_EVENT_TICKETS\",\n \"REMIND_ME\",\n \"SEARCH_MORE\",\n \"PRE_REGISTER\",\n \"SWIPE_UP_PRODUCT\",\n \"SWIPE_UP_SHOP\",\n \"PLAY_GAME_ON_FACEBOOK\",\n \"VISIT_WORLD\",\n \"OPEN_INSTANT_APP\",\n \"JOIN_GROUP\",\n \"GET_PROMOTIONS\",\n \"SEND_UPDATES\",\n \"INQUIRE_NOW\",\n \"VISIT_PROFILE\",\n \"CHAT_ON_WHATSAPP\",\n \"EXPLORE_MORE\",\n \"CONFIRM\",\n \"JOIN_CHANNEL\",\n \"MAKE_AN_APPOINTMENT\",\n \"ASK_ABOUT_SERVICES\",\n \"BOOK_A_CONSULTATION\",\n \"GET_A_QUOTE\",\n \"BUY_VIA_MESSAGE\",\n \"ASK_FOR_MORE_INFO\",\n \"VIEW_PRODUCT\",\n \"VIEW_CHANNEL\",\n \"WATCH_LIVE_VIDEO\",\n \"JOIN_LIVE_VIDEO\",\n \"IMAGINE\",\n \"CALL\",\n \"MISSED_CALL\",\n \"CALL_NOW\",\n \"CALL_ME\",\n \"APPLY_NOW\",\n \"BUY\",\n \"GET_QUOTE\",\n \"SUBSCRIBE\",\n \"RECORD_NOW\",\n \"VOTE_NOW\",\n \"GIVE_FREE_RIDES\",\n \"REGISTER_NOW\",\n \"OPEN_MESSENGER_EXT\",\n \"EVENT_RSVP\",\n \"CIVIC_ACTION\",\n \"SEND_INVITES\",\n \"REFER_FRIENDS\",\n \"REQUEST_TIME\",\n \"SEE_MENU\",\n \"SEARCH\",\n \"TRY_IT\",\n \"TRY_ON\",\n \"LINK_CARD\",\n \"DIAL_CODE\",\n \"FIND_YOUR_GROUPS\",\n \"START_ORDER\",\n // Added 2026-09-18 from Meta's generated enum spec\n // (AdCreative_call_to_action_type). Additive on purpose: 37 of the values above\n // are absent from that spec and present in the live 400, which is the\n // disagreement the note above is about — so the spec widens this list and never\n // prunes it.\n \"AUDIO_CALL\",\n \"BROWSE_SHOP\",\n \"CONTACT\",\n \"FIND_A_GROUP\",\n \"FIND_OUT_MORE\",\n \"FOLLOW_NEWS_STORYLINE\",\n \"FOLLOW_PAGE\",\n \"FOLLOW_USER\",\n \"GET_DETAILS\",\n \"GET_STARTED\",\n \"SAY_THANKS\",\n \"SEE_SHOP\",\n \"SEND_A_GIFT\",\n \"SEND_GIFT_MONEY\",\n \"SHARE\",\n \"SHOP_WITH_AI\",\n \"SOTTO_SUBSCRIBE\",\n \"TRY_ON_WITH_AI\",\n \"VIDEO_ANNOTATION\",\n \"VIDEO_CALL\",\n \"VIEW_CART\",\n \"VIEW_IN_CART\",\n \"VISIT_PAGES_FEED\",\n \"VISIT_WEBSITE\",\n \"WOODHENGE_SUPPORT\",\n] as const;\nexport type MetaCtaType = (typeof CTA_TYPES)[number];\n\n/**\n * The buttons a dynamic / flexible creative may list in\n * `asset_feed_spec.call_to_action_types`. Read off Meta the same way and on the\n * same day as {@link CTA_TYPES}, and deliberately a separate list — see the\n * note there.\n */\nexport const ASSET_FEED_CTA_TYPES = [\n \"OPEN_LINK\",\n \"LIKE_PAGE\",\n \"SHOP_NOW\",\n \"PLAY_GAME\",\n \"INSTALL_APP\",\n \"USE_APP\",\n \"CALL\",\n \"CALL_ME\",\n \"VIDEO_CALL\",\n \"INSTALL_MOBILE_APP\",\n \"USE_MOBILE_APP\",\n \"MOBILE_DOWNLOAD\",\n \"BOOK_TRAVEL\",\n \"LISTEN_MUSIC\",\n \"WATCH_VIDEO\",\n \"LEARN_MORE\",\n \"SIGN_UP\",\n \"DOWNLOAD\",\n \"WATCH_MORE\",\n \"NO_BUTTON\",\n \"VISIT_PAGES_FEED\",\n \"CALL_NOW\",\n \"APPLY_NOW\",\n \"CONTACT\",\n \"BUY_NOW\",\n \"GET_OFFER\",\n \"GET_OFFER_VIEW\",\n \"BUY_TICKETS\",\n \"UPDATE_APP\",\n \"GET_DIRECTIONS\",\n \"BUY\",\n \"SEND_UPDATES\",\n \"MESSAGE_PAGE\",\n \"DONATE\",\n \"SUBSCRIBE\",\n \"SAY_THANKS\",\n \"SELL_NOW\",\n \"SHARE\",\n \"DONATE_NOW\",\n \"GET_QUOTE\",\n \"CONTACT_US\",\n \"ORDER_NOW\",\n \"START_ORDER\",\n \"ADD_TO_CART\",\n \"VIEW_CART\",\n \"VIEW_IN_CART\",\n \"VIDEO_ANNOTATION\",\n \"RECORD_NOW\",\n \"INQUIRE_NOW\",\n \"CONFIRM\",\n \"REFER_FRIENDS\",\n \"REQUEST_TIME\",\n \"GET_SHOWTIMES\",\n \"LISTEN_NOW\",\n \"TRY_DEMO\",\n \"WOODHENGE_SUPPORT\",\n \"SOTTO_SUBSCRIBE\",\n \"FOLLOW_USER\",\n \"RAISE_MONEY\",\n \"SEE_SHOP\",\n \"GET_DETAILS\",\n \"FIND_OUT_MORE\",\n \"VISIT_WEBSITE\",\n \"BROWSE_SHOP\",\n \"EVENT_RSVP\",\n \"WHATSAPP_MESSAGE\",\n \"FOLLOW_NEWS_STORYLINE\",\n \"SEE_MORE\",\n \"BOOK_NOW\",\n \"FIND_A_GROUP\",\n \"FIND_YOUR_GROUPS\",\n \"PAY_TO_ACCESS\",\n \"PURCHASE_GIFT_CARDS\",\n \"FOLLOW_PAGE\",\n \"SEND_A_GIFT\",\n \"SWIPE_UP_SHOP\",\n \"SWIPE_UP_PRODUCT\",\n \"SEND_GIFT_MONEY\",\n \"PLAY_GAME_ON_FACEBOOK\",\n \"GET_STARTED\",\n \"OPEN_INSTANT_APP\",\n \"AUDIO_CALL\",\n \"GET_PROMOTIONS\",\n \"JOIN_CHANNEL\",\n \"MAKE_AN_APPOINTMENT\",\n \"ASK_ABOUT_SERVICES\",\n \"BOOK_A_CONSULTATION\",\n \"GET_A_QUOTE\",\n \"BUY_VIA_MESSAGE\",\n \"ASK_FOR_MORE_INFO\",\n \"CHAT_WITH_US\",\n \"VIEW_PRODUCT\",\n \"VIEW_CHANNEL\",\n \"GET_IN_TOUCH\",\n \"ASK_A_QUESTION\",\n \"START_A_CHAT\",\n \"CHAT_NOW\",\n \"ASK_US\",\n \"WATCH_LIVE_VIDEO\",\n \"JOIN_LIVE_VIDEO\",\n \"SHOP_WITH_AI\",\n \"TRY_ON_WITH_AI\",\n] as const;\nexport type MetaAssetFeedCtaType = (typeof ASSET_FEED_CTA_TYPES)[number];\n\n/**\n * The buttons Meta allows on a creative that opens an instant form. Meta's\n * lead-ads guide names exactly these six for `link_data.call_to_action`, and\n * anything else is refused at creation with \"Invalid value field\n * lead_gen_form_id for CTA type: <TYPE>\" (subcode 1856030) — which is a publish\n * failure, after the ad's siblings have already been created on the account.\n * One real chat staged six instant-form creatives, two of them on CONTACT_US:\n * both creatives were rejected and both of their ads were skipped, leaving four\n * of six ads live and nobody able to tell why from Meta's sentence.\n */\nexport const LEAD_FORM_CTA_TYPES = [\n \"APPLY_NOW\",\n \"DOWNLOAD\",\n \"GET_QUOTE\",\n \"LEARN_MORE\",\n \"SIGN_UP\",\n \"SUBSCRIBE\",\n] as const satisfies readonly MetaCtaType[];\n\nexport const AD_FORMATS = [\"SINGLE_IMAGE\", \"CAROUSEL\", \"SINGLE_VIDEO\"] as const;\nexport type MetaAdFormat = (typeof AD_FORMATS)[number];\n\n/** Advantage+ Creative enroll state (case-sensitive) — set per individual feature. */\nexport const ENROLL_STATUSES = [\"OPT_IN\", \"OPT_OUT\"] as const;\nexport type MetaEnrollStatus = (typeof ENROLL_STATUSES)[number];\n\n/**\n * Meta deprecated the `standard_enhancements` bundle key at Marketing API v22.0\n * — including it in `creative_features_spec` now hard-fails (error subcode\n * 3858504: \"Including standard enhancements field in creative has been\n * deprecated. Please choose to set individual features instead.\"). The bundle is\n * replaced by these individual feature keys, opted in/out one at a time.\n *\n * Meta does NOT publish a per-media eligibility matrix and validates features\n * server-side, so we expand our master toggle into ONLY keys confirmed present\n * in the current `AdCreativeFeaturesSpec`, scoped to the creative's media type.\n * Callers needing a specific feature pass it explicitly via `enhancements.features`.\n */\nexport const STANDARD_ENHANCEMENT_IMAGE_FEATURES = [\n \"image_templates\",\n \"image_touchups\",\n \"text_optimizations\",\n \"inline_comment\",\n] as const;\n/** Video keeps only the universally-valid text/comment enhancements (visual crop keys aren't in the confirmed spec list). */\nexport const STANDARD_ENHANCEMENT_VIDEO_FEATURES = [\"text_optimizations\", \"inline_comment\"] as const;\n\n// --- Statuses ---\n\nexport const ENTITY_STATUSES = [\"ACTIVE\", \"PAUSED\", \"DELETED\", \"ARCHIVED\"] as const;\nexport type MetaEntityStatus = (typeof ENTITY_STATUSES)[number];\n\n/** Statuses a create op may request (Meta forbids launching straight to DELETED/ARCHIVED). */\nexport const STAGEABLE_CREATE_STATUSES = [\"ACTIVE\", \"PAUSED\"] as const;\n/**\n * Statuses a campaign, ad set or ad update op may set. ARCHIVED keeps the entity\n * readable in Ads Manager (and counts toward Meta's archived-object limit);\n * DELETED removes it for good and cannot be undone. The CLI stages DELETED only\n * through its `delete` command; `update --status` refuses it.\n */\nexport const UPDATE_STATUSES = [\"ACTIVE\", \"PAUSED\", \"ARCHIVED\", \"DELETED\"] as const;\n/** Statuses a creative update may set: creatives have no `delete` command. */\nexport const CREATIVE_UPDATE_STATUSES = [\"ACTIVE\", \"PAUSED\", \"ARCHIVED\"] as const;\n\n// --- Custom audiences ---\n\nexport const CUSTOM_AUDIENCE_SUBTYPES = [\"CUSTOM\", \"WEBSITE\", \"ENGAGEMENT\", \"LOOKALIKE\"] as const;\nexport type MetaCustomAudienceSubtype = (typeof CUSTOM_AUDIENCE_SUBTYPES)[number];\n\n/**\n * Where the rows of a customer-file audience came from. Meta publishes exactly\n * these three, and the field is a data-provenance declaration about personal\n * data — the one place in this file where a free string was the wrong type.\n */\nexport const CUSTOMER_FILE_SOURCES = [\n \"USER_PROVIDED_ONLY\",\n \"PARTNER_PROVIDED_ONLY\",\n \"BOTH_USER_AND_PARTNER_PROVIDED\",\n] as const;\nexport type MetaCustomerFileSource = (typeof CUSTOMER_FILE_SOURCES)[number];\n\n// --- Media ---\n\nexport const MEDIA_KINDS = [\"image\", \"video\"] as const;\nexport type MetaMediaKind = (typeof MEDIA_KINDS)[number];\n\n// --- Money ---\n\n// Minor-unit conversion for the wire lives in the backend's single source of\n// truth, `ads/meta/constants.ts` CURRENCY_OFFSET (2-decimal default, zero- and\n// three-decimal exceptions). It is intentionally NOT duplicated here.\n\n/**\n * Indicative per-currency daily-budget floors (Meta enforces the authoritative\n * per-account `min_daily_budget` at stage time; these only catch obvious\n * mistakes offline). Amounts in major units.\n */\nexport const CURRENCY_MINIMUMS: Record<string, { dailyBudgetMin: number }> = {\n USD: { dailyBudgetMin: 1 },\n EUR: { dailyBudgetMin: 1 },\n GBP: { dailyBudgetMin: 1 },\n};\nexport const DEFAULT_CURRENCY_MINIMUM = { dailyBudgetMin: 1 };\n\n// --- Refs / ids ---\n\nexport const TEMP_REF_PREFIX = \"meta_temp_\";\nexport const TEMP_REF_REGEX = /^meta_temp_[A-Za-z0-9_-]{4,}$/;\n/** Meta node ids are bare numeric strings (the `act_` prefix is stripped for scoping). */\nexport const NUMERIC_ID_REGEX = /^\\d+$/;\n/** Ad-image hashes are hex; be lenient on length across Graph versions. */\nexport const IMAGE_HASH_REGEX = /^[A-Fa-f0-9]{16,}$/;\nexport const SIMULATED_ID_PREFIX = \"sim_meta_\";\n","/**\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 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 { customConversionRuleRefusal } from \"./customConversions\";\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 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 IMAGE_HASH_REGEX,\n LEAD_FORM_CTA_TYPES,\n MEDIA_KINDS,\n META_LIMITS,\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 SPECIAL_AD_CATEGORIES,\n SPECIAL_CATEGORIES_REQUIRING_COUNTRY,\n STAGEABLE_CREATE_STATUSES,\n TEMP_REF_REGEX,\n UPDATE_STATUSES,\n} from \"./limits\";\nimport {\n constrainedPlacementsIn,\n invalidPlacementValues,\n PLACEMENT_TARGETING_DOC,\n placementCoRequirementIssues,\n positionsMissingRequiredFeed,\n rightColumnIsSolePlacement,\n setsExplicitPlacements,\n} from \"./placements\";\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 three decimals, since three-decimal currencies (KWD, BHD, JOD, OMR, TND) count in thousandths.\n */\nexport const moneySchema = z.strictObject({\n amount: z\n .string()\n .regex(/^\\d+(\\.\\d{1,3})?$/, \"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.\nconst MONEY_FIELDS = [\"dailyBudget\", \"lifetimeBudget\", \"bidAmount\", \"spendCap\"] as const;\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/** 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 return MONEY_FIELDS.some((field) => isMoneyMissingCurrency((payload as Record<string, unknown>)[field]));\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 (isMoneyMissingCurrency(out[field])) {\n out[field] = { ...(out[field] as Record<string, unknown>), 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\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 * 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 exclusions: z.record(z.string(), z.unknown()).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 })\n .catchall(z.unknown());\nexport type MetaTargeting = z.infer<typeof metaTargetingSchema>;\n\n/** geo_locations inclusion keys that count as a real location (location_types is a modifier, not a place). */\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] 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/**\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// --- 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 start_time: z.number().int().positive().optional(),\n stop_time: z.number().int().positive().optional(),\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 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 });\nexport type CampaignCreate = z.infer<typeof campaignCreateSchema>;\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 start_time: z.number().int().positive().optional(),\n stop_time: z.number().int().positive().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.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 });\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: z.string().regex(NUMERIC_ID_REGEX).optional(),\n product_set_id: z.string().regex(NUMERIC_ID_REGEX).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.strictObject({\n event_type: z.enum(ATTRIBUTION_EVENT_TYPES),\n window_days: z.union([z.literal(1), z.literal(7), z.literal(28)]),\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 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};\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 };\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 const hasPixel = Boolean(po?.pixel_id) || namesConversion;\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 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\nexport const adSetCreateSchema = z.strictObject(adSetFields).superRefine((p, ctx) => {\n validateAdSetBudgetAndBid(p, ctx);\n validateAdSetPromotedObject(p, ctx);\n validateAdvantageAudience(p, ctx);\n validateAdSetPlacements(p, ctx);\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 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 })\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 validateAdSetBudgetAndBid(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 validateAdvantageAudience(p, ctx);\n validateAdSetPlacements(p, ctx);\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 })\n .superRefine((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 * Advantage+ Creative enhancements — `standard_enhancements` is the master\n * OPT_IN/OPT_OUT; `features` carries per-enhancement toggles (image_touchups,\n * text_improvements, enhance_cta, image_brightness_and_contrast, …) as Meta's\n * feature keys, so newly surfaced enhancements pass through without a schema bump.\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). */\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\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 /** Thumbnail for a video creative — image hash, ref, or public url. */\n thumbnailHash: z.string().regex(IMAGE_HASH_REGEX).optional(),\n imageUrl: z.string().url().optional(),\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 })\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: \"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 .superRefine((p, ctx) => {\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 })\n .refine((p) => countVideoRefs(p) === 1, \"each dynamic video needs exactly one reference\");\n\nconst DYN = META_LIMITS.creative;\nconst dynamicCreativeSchema = z\n .strictObject({\n creativeType: z.literal(\"dynamic\"),\n ...creativeSharedFields,\n bodies: z\n .array(z.strictObject({ text: messageSchema }))\n .min(DYN.dynamicTextsMin)\n .max(DYN.dynamicTextsMax),\n titles: z\n .array(z.strictObject({ text: headlineSchema }))\n .min(DYN.dynamicTextsMin)\n .max(DYN.dynamicTextsMax),\n descriptions: z\n .array(z.strictObject({ text: descriptionSchema }))\n .max(DYN.dynamicTextsMax)\n .optional(),\n images: z.array(dynamicImageSchema).optional(),\n videos: z.array(dynamicVideoSchema).optional(),\n /**\n * Optional: Meta infers the format from the assets when it is omitted, and\n * every flexible creative read back off a live account omits it.\n */\n ad_formats: z.array(z.enum(AD_FORMATS)).min(1).optional(),\n call_to_action_types: z.array(z.string()).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.array(z.strictObject({ website_url: httpsUrlSchema, display_url: z.string().optional() })).min(1),\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 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/** Boost an existing organic page post. */\nconst existingPostCreativeSchema = z.strictObject({\n creativeType: z.literal(\"existing_post\"),\n name: creativeSharedFields.name,\n /** \"<page_id>_<post_id>\" object story id of the post to promote. */\n object_story_id: z.string().regex(/^\\d+_\\d+$/, 'expected \"<page_id>_<post_id>\"'),\n instagram_user_id: creativeSharedFields.instagram_user_id,\n url_tags: creativeSharedFields.url_tags,\n enhancements: creativeSharedFields.enhancements,\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\nexport const creativeContentSchema = z.discriminatedUnion(\"creativeType\", [\n singleCreativeSchema,\n carouselCreativeSchema,\n dynamicCreativeSchema,\n existingPostCreativeSchema,\n specCreativeSchema,\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 })\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});\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 })\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\nconst lookalikeSpecSchema = z.strictObject({\n origin: z.array(z.strictObject({ id: parentRefSchema })).min(1),\n ratio: z.number().min(0.01).max(0.2).optional(),\n country: z.string().length(2).optional(),\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\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 })\n .superRefine((p, ctx) => {\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\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 })\n .refine((p) => Object.values(p).some((val) => val !== undefined), \"update needs at least one field\");\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// --- 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/** A Page-owned Instant Form. The form itself is created only when the Session publishes. */\nexport const leadFormCreateSchema = z\n .strictObject({\n page_id: z.string().regex(NUMERIC_ID_REGEX),\n name: z.string().min(1).max(255),\n locale: z.enum([\"EN_US\", \"EN_GB\", \"ES_ES\", \"ES_LA\", \"FR_FR\", \"DE_DE\", \"PT_BR\", \"PT_PT\"]).default(\"EN_US\"),\n questionPageHeadline: z.string().min(1).max(255).optional(),\n questions: z\n .array(\n z.strictObject({\n type: z.enum([\n \"FULL_NAME\",\n \"FIRST_NAME\",\n \"LAST_NAME\",\n \"EMAIL\",\n \"PHONE\",\n \"CITY\",\n \"STATE\",\n \"COUNTRY\",\n \"ZIP_CODE\",\n \"COMPANY_NAME\",\n \"JOB_TITLE\",\n \"CUSTOM\",\n ]),\n label: z.string().min(1).max(255).optional(),\n }),\n )\n .min(1)\n .max(15),\n privacyPolicyUrl: httpsUrlSchema,\n privacyPolicyLinkText: z.string().min(1).max(70).default(\"Privacy Policy\"),\n followUpActionUrl: httpsUrlSchema,\n optimizedForQuality: z.boolean().default(false),\n thankYou: z\n .strictObject({\n title: z.string().min(1).max(255),\n body: z.string().min(1).max(1000),\n buttonText: z.string().min(1).max(70).default(\"View website\"),\n })\n .optional(),\n })\n .superRefine((form, ctx) => {\n const seen = new Set<string>();\n for (const [index, question] of form.questions.entries()) {\n if (question.type === \"CUSTOM\" && !question.label) {\n ctx.addIssue({ code: \"custom\", path: [\"questions\", index, \"label\"], message: \"custom questions need a label\" });\n }\n const key = `${question.type}:${question.label ?? \"\"}`;\n if (seen.has(key)) ctx.addIssue({ code: \"custom\", path: [\"questions\", index], message: \"duplicate question\" });\n seen.add(key);\n }\n });\nexport type LeadFormCreate = z.infer<typeof leadFormCreateSchema>;\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 \"customConversion.create\",\n \"leadForm.create\",\n \"media.upload\",\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\nexport const metaDraftOpInputSchema = z.discriminatedUnion(\"kind\", [\n createOp(\"campaign.create\", campaignCreateSchema),\n updateOp(\"campaign.update\", campaignUpdateSchema),\n createOp(\"adSet.create\", adSetCreateSchema),\n updateOp(\"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(\"customConversion.create\", customConversionCreateSchema),\n createOp(\"leadForm.create\", leadFormCreateSchema),\n createOp(\"media.upload\", mediaUploadSchema),\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\nexport type MetaDraftEntity =\n | \"campaign\"\n | \"adSet\"\n | \"adCreative\"\n | \"ad\"\n | \"customAudience\"\n | \"customConversion\"\n | \"leadForm\"\n | \"media\";\n\nexport function entityOfKind(kind: MetaDraftOpKind): MetaDraftEntity {\n return kind.split(\".\")[0] as MetaDraftEntity;\n}\n\ntype TempRefDep = { ref: string; entity: MetaDraftEntity };\ntype AddDep = (value: string | undefined, entity: MetaDraftEntity) => void;\n\nfunction collectCreativeMediaRefs(payload: MetaCreativeContent, add: AddDep): void {\n const addImageVideo = (m: { imageRef?: string; videoRef?: string }): void => {\n add(m.imageRef, \"media\");\n add(m.videoRef, \"media\");\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 \"dynamic\":\n for (const img of payload.images ?? []) {\n add(img.imageRef, \"media\");\n }\n for (const vid of payload.videos ?? []) {\n add(vid.videoRef, \"media\");\n }\n break;\n default:\n break;\n }\n}\n\nexport function creativeFormIds(payload: MetaCreativeContent): string[] {\n if (payload.creativeType === \"existing_post\" || payload.creativeType === \"spec\") return [];\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}\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) => {\n if (value && TEMP_REF_REGEX.test(value)) {\n deps.push({ ref: value, entity });\n }\n };\n switch (op.kind) {\n case \"adSet.create\":\n add(op.payload.campaign_id, \"campaign\");\n add(op.payload.promoted_object?.custom_conversion_id, \"customConversion\");\n collectTargetingAudienceRefs(op.payload.targeting, add);\n break;\n case \"adSet.update\":\n add(op.payload.promoted_object?.custom_conversion_id, \"customConversion\");\n collectTargetingAudienceRefs(op.payload.targeting, add);\n break;\n case \"adCreative.create\":\n collectCreativeMediaRefs(op.payload, add);\n collectCreativeFormRefs(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 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\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 // A single creative holds one asset that Meta auto-crops to every placement.\n // Not a validity error (Meta adapts it), but the wrong ratio on Stories/Reels\n // wastes the frame — the fix is a dynamic creative with per-placement assets.\n warnings.push(\n \"one asset serves every placement — Meta auto-crops it, so Stories & Reels (9:16) show a cropped feed image; for placement-native ratios use a dynamic creative with asset_customization_rules\",\n );\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 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 // Dynamic is the only creative that can serve a different asset per placement.\n // Without customization rules, Meta uses the same assets everywhere — supply a\n // 9:16 for Stories/Reels and a 1:1 or 4:5 for Feed and map them per placement.\n if (!p.asset_customization_rules?.length) {\n warnings.push(\n \"no asset_customization_rules — the same assets serve every placement; map a 9:16 asset to Stories/Reels and a 1:1 or 4:5 to Feed so each placement gets its native ratio\",\n );\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 (p.creativeType === \"single\" || p.creativeType === \"carousel\") {\n warnings.push(...messageWarnings(p.message));\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 if (p.creativeType !== \"existing_post\" && p.enhancements?.standardEnhancements === \"OPT_OUT\") {\n warnings.push(\n \"Advantage+ Creative standard enhancements are OPT_OUT — leaving them on typically lifts performance\",\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 default:\n return [];\n }\n}\n"],"mappings":"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,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,0BAA0B,CAAC,iBAAiB,gBAAgB,oBAAoB;AActF,IAAM,kCAAkC;AACxC,IAAM,sCAAsC;AA2D5C,IAAM,YAAY;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AASO,IAAM,uBAAuB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA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","names":[]}
@@ -1,139 +0,0 @@
1
- import {
2
- brandVerificationHints
3
- } from "./chunk-IVIJJXXT.js";
4
- import {
5
- OUTPUT_ARGS,
6
- writeProviderHits
7
- } from "./chunk-MJQBXFW6.js";
8
- import {
9
- emptyResultHints
10
- } from "./chunk-Q6ULQMWG.js";
11
- import {
12
- AUTO_INGEST_MAX,
13
- parseAutoIngest
14
- } from "./chunk-KKJ4KJCW.js";
15
- import {
16
- ApiError,
17
- apiPost
18
- } from "./chunk-XDZVBX6L.js";
19
- import {
20
- registerSchema,
21
- writeJson
22
- } from "./chunk-WNSE7N75.js";
23
-
24
- // src/commands/images/logo.ts
25
- import { defineCommand } from "citty";
26
- registerSchema({
27
- command: "images.logo",
28
- description: "Brand logo lookup via Brandfetch. Auto-ingests by default. Returns `brandMatch` \u2014 Brandfetch's own verdict on whose brand the domain is (confirmed | mismatch | unverified). Branch on it: `mismatch` means the mark is another company's, so do not place it. `confirmed` verifies the record, not the artwork \u2014 read the ingested row back to check the mark itself.",
29
- args: {
30
- domain: { type: "string", description: "Brand domain (e.g. stripe.com)", required: true },
31
- variant: { type: "string", description: "icon | logo | symbol", required: false },
32
- "auto-ingest": {
33
- type: "number",
34
- description: `Ingest top N hits (0-${AUTO_INGEST_MAX.logo}). Defaults to 1 (the first variant). Brandfetch resolves at most ${AUTO_INGEST_MAX.logo} variants, so ${AUTO_INGEST_MAX.logo} ingests every one. Keep it at 1+ \u2014 the ingested row is the only way to check the mark is the brand you asked for.`,
35
- required: false
36
- },
37
- "no-auto-ingest": {
38
- type: "boolean",
39
- description: "Skip auto-ingest (equivalent to --auto-ingest 0). Leaves the returned mark unverifiable.",
40
- required: false,
41
- default: false
42
- },
43
- context: {
44
- type: "string",
45
- description: "Free-text hint applied to ingested logo variants (e.g. 'Stripe \u2014 payments integration partner', 'Acme competitor brand mark')",
46
- required: false
47
- },
48
- output: { type: "string", description: "Output format: json|files|md", required: false, default: "json" },
49
- fields: { type: "string", description: "Comma-separated field names to include", required: false },
50
- full: { type: "boolean", description: "Include full metadata", required: false, default: false }
51
- }
52
- });
53
- var logoCommand = defineCommand({
54
- meta: {
55
- name: "logo",
56
- description: "Brand logo via Brandfetch. Returns up to 5 variants (icon, light/dark logo, light/dark symbol) plus `brandMatch`. Auto-ingests the first variant.\n\nStart here: check `brandMatch.verdict`.\n mismatch \u2192 the mark belongs to `brandMatch.name`, a different company. Do not place it.\n unverified \u2192 nothing confirmed whose logo this is. Treat as unchecked.\n confirmed \u2192 Brandfetch has this brand's record. That verifies the record, NOT the artwork \u2014 a confirmed domain has served another company's logo before.\n\n\u26A0 Whatever the verdict, read the ingested row back with `baker images get <imageId>` and check `textInImage`/`subject` before placing it. That is the only check that looks at the mark.\n\nExample: baker images logo stripe.com --variant logo"
57
- },
58
- args: {
59
- domain: { type: "positional", description: "Brand domain", required: false },
60
- variant: { type: "string", description: "icon|logo|symbol", required: false },
61
- "auto-ingest": {
62
- type: "string",
63
- description: `Ingest top N (0-${AUTO_INGEST_MAX.logo}, default 1)`,
64
- required: false
65
- },
66
- "no-auto-ingest": { type: "boolean", description: "Skip auto-ingest", required: false },
67
- context: { type: "string", description: "Description context hint applied to ingested logos", required: false },
68
- ...OUTPUT_ARGS
69
- },
70
- run: async ({ args }) => {
71
- try {
72
- const domain = args.domain;
73
- if (!domain) {
74
- writeJson({ ok: false, error: { code: "VALIDATION_ERROR", message: "Domain is required" } });
75
- process.exit(1);
76
- }
77
- const body = { domain };
78
- if (args.variant) body.variant = args.variant;
79
- if (args["auto-ingest"] !== void 0) {
80
- const parsed = parseAutoIngest(args["auto-ingest"], AUTO_INGEST_MAX.logo);
81
- if (!parsed.ok) {
82
- writeJson({
83
- ok: false,
84
- error: {
85
- code: "VALIDATION_ERROR",
86
- message: parsed.message,
87
- fix: {
88
- action: "retry_with_changes",
89
- explanation: `Brandfetch resolves at most ${AUTO_INGEST_MAX.logo} variants for a domain, so --auto-ingest ${AUTO_INGEST_MAX.logo} already ingests every one. Re-run with a value in 0-${AUTO_INGEST_MAX.logo}.`
90
- }
91
- }
92
- });
93
- process.exit(1);
94
- }
95
- body.autoIngest = parsed.value;
96
- } else if (args["no-auto-ingest"]) {
97
- body.autoIngest = 0;
98
- }
99
- if (args.context) body.descriptionContext = args.context;
100
- const data = await apiPost("/api/images/logo", body);
101
- const hints = [
102
- // `brandMatch` is Brandfetch's own answer to whose brand this domain is,
103
- // so the warning can now be graded instead of fired blind: loud on a
104
- // mismatch, honest about what a confirmation does and does not cover.
105
- ...brandVerificationHints({
106
- domain,
107
- ingested: data.ingested,
108
- hitCount: data.hits.length,
109
- brandMatch: data.brandMatch
110
- }),
111
- ...emptyResultHints({ provider: "logo", hitCount: data.hits.length, activeFilters: [], subject: domain })
112
- ];
113
- writeProviderHits(data, data.hits, args, hints);
114
- } catch (err) {
115
- if (err instanceof ApiError) {
116
- writeJson({ ok: false, error: { code: err.code, message: err.message } });
117
- process.exit(1);
118
- }
119
- writeJson({ ok: false, error: { code: "INTERNAL_ERROR", message: "Unexpected error" } });
120
- process.exit(1);
121
- }
122
- }
123
- });
124
- async function fetchBrandLogo(domain) {
125
- try {
126
- const body = { domain, variant: "logo" };
127
- const data = await apiPost("/api/images/logo", body);
128
- if (data?.brandMatch?.verdict === "mismatch") return null;
129
- return data?.ingested?.[0]?.imageUrl ?? data?.hits?.find((h) => h.imageUrl)?.imageUrl ?? null;
130
- } catch {
131
- return null;
132
- }
133
- }
134
-
135
- export {
136
- logoCommand,
137
- fetchBrandLogo
138
- };
139
- //# sourceMappingURL=chunk-H5HDZ7IC.js.map