@koda-sl/baker-cli 0.384.0-dev.4699b7308 → 0.384.0-dev.557795bef

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 (964) hide show
  1. package/README.md +1098 -217
  2. package/canvas/tiktok-captions-composition/index.html +5 -6
  3. package/canvas/tiktok-captions-composition/meta.json +5 -0
  4. package/dist/account-4UEZAY5T.js +49 -0
  5. package/dist/account-4UEZAY5T.js.map +1 -0
  6. package/dist/account-OINZG6UP.js +80 -0
  7. package/dist/account-OINZG6UP.js.map +1 -0
  8. package/dist/account-QMDCUUSG.js +79 -0
  9. package/dist/account-QMDCUUSG.js.map +1 -0
  10. package/dist/account-reads-ZKKDYHK5.js +218 -0
  11. package/dist/account-reads-ZKKDYHK5.js.map +1 -0
  12. package/dist/account-writes-N4JDIDRB.js +66 -0
  13. package/dist/account-writes-N4JDIDRB.js.map +1 -0
  14. package/dist/accounts-AEBQFCNH.js +114 -0
  15. package/dist/accounts-AEBQFCNH.js.map +1 -0
  16. package/dist/accounts-EBGJ2YO7.js +611 -0
  17. package/dist/accounts-EBGJ2YO7.js.map +1 -0
  18. package/dist/accounts-HP4BLKK5.js +75 -0
  19. package/dist/accounts-HP4BLKK5.js.map +1 -0
  20. package/dist/accounts-YE2SQ3UQ.js +77 -0
  21. package/dist/accounts-YE2SQ3UQ.js.map +1 -0
  22. package/dist/accounts-Z4CLGQXJ.js +115 -0
  23. package/dist/accounts-Z4CLGQXJ.js.map +1 -0
  24. package/dist/actions-ADRIEQZX.js +55 -0
  25. package/dist/actions-ADRIEQZX.js.map +1 -0
  26. package/dist/active-entities-YB46ADQN.js +103 -0
  27. package/dist/active-entities-YB46ADQN.js.map +1 -0
  28. package/dist/activities-DUAIQJLN.js +74 -0
  29. package/dist/activities-DUAIQJLN.js.map +1 -0
  30. package/dist/ad-group-writes-HL3EZ3BT.js +170 -0
  31. package/dist/ad-group-writes-HL3EZ3BT.js.map +1 -0
  32. package/dist/ad-groups-FGS5JJGN.js +68 -0
  33. package/dist/ad-groups-FGS5JJGN.js.map +1 -0
  34. package/dist/ad-writes-LX4ACUHB.js +174 -0
  35. package/dist/ad-writes-LX4ACUHB.js.map +1 -0
  36. package/dist/add-5CUXNOUM.js +97 -0
  37. package/dist/add-5CUXNOUM.js.map +1 -0
  38. package/dist/add-6OXOQNET.js +302 -0
  39. package/dist/add-6OXOQNET.js.map +1 -0
  40. package/dist/add-E66HBIZV.js +105 -0
  41. package/dist/add-E66HBIZV.js.map +1 -0
  42. package/dist/add-ROK3ETQC.js +104 -0
  43. package/dist/add-ROK3ETQC.js.map +1 -0
  44. package/dist/add-accounts-YME5SCXD.js +91 -0
  45. package/dist/add-accounts-YME5SCXD.js.map +1 -0
  46. package/dist/ads-65R3WMDU.js +128 -0
  47. package/dist/ads-65R3WMDU.js.map +1 -0
  48. package/dist/ads-O63J7BDF.js +113 -0
  49. package/dist/ads-O63J7BDF.js.map +1 -0
  50. package/dist/ads-TFZ5PXKS.js +77 -0
  51. package/dist/ads-TFZ5PXKS.js.map +1 -0
  52. package/dist/ads-XSVRH45E.js +40 -0
  53. package/dist/ads-XSVRH45E.js.map +1 -0
  54. package/dist/adsets-Y62JOOTV.js +176 -0
  55. package/dist/adsets-Y62JOOTV.js.map +1 -0
  56. package/dist/advertisers-AIC4QPEK.js +120 -0
  57. package/dist/advertisers-AIC4QPEK.js.map +1 -0
  58. package/dist/advertisers-LJ2HKJ4W.js +125 -0
  59. package/dist/advertisers-LJ2HKJ4W.js.map +1 -0
  60. package/dist/analytics-N4PGXXEQ.js +1976 -0
  61. package/dist/analytics-N4PGXXEQ.js.map +1 -0
  62. package/dist/analytics-X3DR3UVG.js +433 -0
  63. package/dist/analytics-X3DR3UVG.js.map +1 -0
  64. package/dist/animate-E3SKQ6SI.js +480 -0
  65. package/dist/animate-E3SKQ6SI.js.map +1 -0
  66. package/dist/assign-Y7HGSQVJ.js +77 -0
  67. package/dist/assign-Y7HGSQVJ.js.map +1 -0
  68. package/dist/audience-size-SWX5YJQF.js +94 -0
  69. package/dist/audience-size-SWX5YJQF.js.map +1 -0
  70. package/dist/audiences-5A6BCWSA.js +268 -0
  71. package/dist/audiences-5A6BCWSA.js.map +1 -0
  72. package/dist/audiences-6QOCASVV.js +78 -0
  73. package/dist/audiences-6QOCASVV.js.map +1 -0
  74. package/dist/audiences-O67NGIP5.js +85 -0
  75. package/dist/audiences-O67NGIP5.js.map +1 -0
  76. package/dist/audit-2KVLWSAI.js +151 -0
  77. package/dist/audit-2KVLWSAI.js.map +1 -0
  78. package/dist/audit-HWK24VXI.js +88 -0
  79. package/dist/audit-HWK24VXI.js.map +1 -0
  80. package/dist/autocomplete-JJSGC5WU.js +111 -0
  81. package/dist/autocomplete-JJSGC5WU.js.map +1 -0
  82. package/dist/avatars-XIEKQ77J.js +38 -0
  83. package/dist/avatars-XIEKQ77J.js.map +1 -0
  84. package/dist/bid-pricing-D2HGRWZL.js +99 -0
  85. package/dist/bid-pricing-D2HGRWZL.js.map +1 -0
  86. package/dist/brand-AYYWRGIE.js +22 -0
  87. package/dist/brand-AYYWRGIE.js.map +1 -0
  88. package/dist/brief-3HUIDK5F.js +490 -0
  89. package/dist/brief-3HUIDK5F.js.map +1 -0
  90. package/dist/businesses-65EWTK5E.js +53 -0
  91. package/dist/businesses-65EWTK5E.js.map +1 -0
  92. package/dist/campaign-groups-6HCYR2JX.js +95 -0
  93. package/dist/campaign-groups-6HCYR2JX.js.map +1 -0
  94. package/dist/campaign-writes-M6JLF5AC.js +170 -0
  95. package/dist/campaign-writes-M6JLF5AC.js.map +1 -0
  96. package/dist/campaign-writes-Y6QPRQ4E.js +165 -0
  97. package/dist/campaign-writes-Y6QPRQ4E.js.map +1 -0
  98. package/dist/campaigns-6SM2ZSIH.js +76 -0
  99. package/dist/campaigns-6SM2ZSIH.js.map +1 -0
  100. package/dist/campaigns-7RKJZRY2.js +107 -0
  101. package/dist/campaigns-7RKJZRY2.js.map +1 -0
  102. package/dist/campaigns-KRI25JDZ.js +109 -0
  103. package/dist/campaigns-KRI25JDZ.js.map +1 -0
  104. package/dist/campaigns-TD7ZB5DG.js +110 -0
  105. package/dist/campaigns-TD7ZB5DG.js.map +1 -0
  106. package/dist/canvas-DMYY2DWI.js +46 -0
  107. package/dist/canvas-DMYY2DWI.js.map +1 -0
  108. package/dist/capabilities-3WJTXS2O.js +144 -0
  109. package/dist/capabilities-3WJTXS2O.js.map +1 -0
  110. package/dist/cards-7HRC4UQQ.js +85 -0
  111. package/dist/cards-7HRC4UQQ.js.map +1 -0
  112. package/dist/catalog-N6MDMIVL.js +64 -0
  113. package/dist/catalog-N6MDMIVL.js.map +1 -0
  114. package/dist/catalogs-PB46L7FH.js +128 -0
  115. package/dist/catalogs-PB46L7FH.js.map +1 -0
  116. package/dist/changes-SASUQK62.js +135 -0
  117. package/dist/changes-SASUQK62.js.map +1 -0
  118. package/dist/chatgpt-JKBSAG25.js +47 -0
  119. package/dist/chatgpt-JKBSAG25.js.map +1 -0
  120. package/dist/chats-WRVSQQB2.js +262 -0
  121. package/dist/chats-WRVSQQB2.js.map +1 -0
  122. package/dist/chunk-2FGKJY63.js +455 -0
  123. package/dist/chunk-2FGKJY63.js.map +1 -0
  124. package/dist/chunk-2GVXNKAE.js +42 -0
  125. package/dist/chunk-2GVXNKAE.js.map +1 -0
  126. package/dist/chunk-2J3PTIQB.js +479 -0
  127. package/dist/chunk-2J3PTIQB.js.map +1 -0
  128. package/dist/chunk-2J7XC2NO.js +346 -0
  129. package/dist/chunk-2J7XC2NO.js.map +1 -0
  130. package/dist/{chunk-VLUGGVJL.js → chunk-2UFRHW3T.js} +12 -4
  131. package/dist/chunk-2UFRHW3T.js.map +1 -0
  132. package/dist/chunk-2Y5V23PU.js +29 -0
  133. package/dist/chunk-2Y5V23PU.js.map +1 -0
  134. package/dist/chunk-3ACMDRSE.js +39 -0
  135. package/dist/chunk-3ACMDRSE.js.map +1 -0
  136. package/dist/chunk-3EWF7VII.js +1079 -0
  137. package/dist/chunk-3EWF7VII.js.map +1 -0
  138. package/dist/chunk-3LYMIKKN.js +625 -0
  139. package/dist/chunk-3LYMIKKN.js.map +1 -0
  140. package/dist/chunk-3M6RNCDD.js +26 -0
  141. package/dist/chunk-3M6RNCDD.js.map +1 -0
  142. package/dist/chunk-3MDO4RR2.js +310 -0
  143. package/dist/chunk-3MDO4RR2.js.map +1 -0
  144. package/dist/chunk-3NPOIHSX.js +6667 -0
  145. package/dist/chunk-3NPOIHSX.js.map +1 -0
  146. package/dist/chunk-3SK7TWGP.js +103 -0
  147. package/dist/chunk-3SK7TWGP.js.map +1 -0
  148. package/dist/chunk-3VXQYDJN.js +1743 -0
  149. package/dist/chunk-3VXQYDJN.js.map +1 -0
  150. package/dist/chunk-44VXKO65.js +106 -0
  151. package/dist/chunk-44VXKO65.js.map +1 -0
  152. package/dist/chunk-4NZ47VXO.js +137 -0
  153. package/dist/chunk-4NZ47VXO.js.map +1 -0
  154. package/dist/chunk-4X3UR372.js +225 -0
  155. package/dist/chunk-4X3UR372.js.map +1 -0
  156. package/dist/chunk-553XSIFW.js +304 -0
  157. package/dist/chunk-553XSIFW.js.map +1 -0
  158. package/dist/chunk-5FEBUCJU.js +25 -0
  159. package/dist/chunk-5FEBUCJU.js.map +1 -0
  160. package/dist/chunk-5HYSKH77.js +315 -0
  161. package/dist/chunk-5HYSKH77.js.map +1 -0
  162. package/dist/chunk-5MBPIONY.js +29 -0
  163. package/dist/chunk-5MBPIONY.js.map +1 -0
  164. package/dist/chunk-5UCP4EEQ.js +111 -0
  165. package/dist/chunk-5UCP4EEQ.js.map +1 -0
  166. package/dist/chunk-5VPJNNJL.js +494 -0
  167. package/dist/chunk-5VPJNNJL.js.map +1 -0
  168. package/dist/{chunk-VZEDAFAR.js → chunk-6YYSUISH.js} +47 -8
  169. package/dist/chunk-6YYSUISH.js.map +1 -0
  170. package/dist/chunk-7OHWEF3I.js +98 -0
  171. package/dist/chunk-7OHWEF3I.js.map +1 -0
  172. package/dist/chunk-A636XRD7.js +159 -0
  173. package/dist/chunk-A636XRD7.js.map +1 -0
  174. package/dist/chunk-A76FRBSF.js +297 -0
  175. package/dist/chunk-A76FRBSF.js.map +1 -0
  176. package/dist/chunk-AADVCEL4.js +817 -0
  177. package/dist/chunk-AADVCEL4.js.map +1 -0
  178. package/dist/chunk-AG62YO7C.js +96 -0
  179. package/dist/chunk-AG62YO7C.js.map +1 -0
  180. package/dist/chunk-AIRIT4GF.js +75 -0
  181. package/dist/chunk-AIRIT4GF.js.map +1 -0
  182. package/dist/chunk-AMCY5YCB.js +206 -0
  183. package/dist/chunk-AMCY5YCB.js.map +1 -0
  184. package/dist/chunk-AP3TP6VG.js +139 -0
  185. package/dist/chunk-AP3TP6VG.js.map +1 -0
  186. package/dist/chunk-APP475IQ.js +474 -0
  187. package/dist/chunk-APP475IQ.js.map +1 -0
  188. package/dist/chunk-AR7PU7BB.js +76 -0
  189. package/dist/chunk-AR7PU7BB.js.map +1 -0
  190. package/dist/chunk-B4S72KSS.js +172 -0
  191. package/dist/chunk-B4S72KSS.js.map +1 -0
  192. package/dist/chunk-BIPIL4QA.js +486 -0
  193. package/dist/chunk-BIPIL4QA.js.map +1 -0
  194. package/dist/chunk-BPUSL5Y2.js +58 -0
  195. package/dist/chunk-BPUSL5Y2.js.map +1 -0
  196. package/dist/chunk-BR32GHYD.js +65 -0
  197. package/dist/chunk-BR32GHYD.js.map +1 -0
  198. package/dist/chunk-CAMX6OHF.js +3182 -0
  199. package/dist/chunk-CAMX6OHF.js.map +1 -0
  200. package/dist/{chunk-MF7YA62W.js → chunk-CUL3VB4L.js} +10 -5
  201. package/dist/chunk-CUL3VB4L.js.map +1 -0
  202. package/dist/chunk-CVEY353K.js +66 -0
  203. package/dist/chunk-CVEY353K.js.map +1 -0
  204. package/dist/chunk-CWXADUKL.js +1599 -0
  205. package/dist/chunk-CWXADUKL.js.map +1 -0
  206. package/dist/chunk-D5FY4FAK.js +24 -0
  207. package/dist/chunk-D5FY4FAK.js.map +1 -0
  208. package/dist/chunk-DGCUPJZD.js +39 -0
  209. package/dist/chunk-DGCUPJZD.js.map +1 -0
  210. package/dist/chunk-DNCLWSHO.js +41 -0
  211. package/dist/chunk-DNCLWSHO.js.map +1 -0
  212. package/dist/chunk-DUPURL26.js +97 -0
  213. package/dist/chunk-DUPURL26.js.map +1 -0
  214. package/dist/chunk-E2ZOSNF5.js +96 -0
  215. package/dist/chunk-E2ZOSNF5.js.map +1 -0
  216. package/dist/chunk-E3HYHT7C.js +274 -0
  217. package/dist/chunk-E3HYHT7C.js.map +1 -0
  218. package/dist/chunk-EDLZGTGN.js +216 -0
  219. package/dist/chunk-EDLZGTGN.js.map +1 -0
  220. package/dist/chunk-EI5QN4UO.js +363 -0
  221. package/dist/chunk-EI5QN4UO.js.map +1 -0
  222. package/dist/{chunk-XHC4LMK4.js → chunk-EIGXX6KI.js} +16 -8
  223. package/dist/chunk-EIGXX6KI.js.map +1 -0
  224. package/dist/chunk-EPDE7ZRU.js +174 -0
  225. package/dist/chunk-EPDE7ZRU.js.map +1 -0
  226. package/dist/chunk-ERSX3MKH.js +34 -0
  227. package/dist/chunk-ERSX3MKH.js.map +1 -0
  228. package/dist/chunk-EVDRF4CI.js +509 -0
  229. package/dist/chunk-EVDRF4CI.js.map +1 -0
  230. package/dist/chunk-F4IEILTR.js +382 -0
  231. package/dist/chunk-F4IEILTR.js.map +1 -0
  232. package/dist/chunk-F7HRLPR5.js +67 -0
  233. package/dist/chunk-F7HRLPR5.js.map +1 -0
  234. package/dist/chunk-FEG6MN4H.js +84 -0
  235. package/dist/chunk-FEG6MN4H.js.map +1 -0
  236. package/dist/chunk-FKOECEVC.js +126 -0
  237. package/dist/chunk-FKOECEVC.js.map +1 -0
  238. package/dist/chunk-FMGW2NZI.js +106 -0
  239. package/dist/chunk-FMGW2NZI.js.map +1 -0
  240. package/dist/chunk-FPZKKNDK.js +98 -0
  241. package/dist/chunk-FPZKKNDK.js.map +1 -0
  242. package/dist/chunk-FUVCY63N.js +169 -0
  243. package/dist/chunk-FUVCY63N.js.map +1 -0
  244. package/dist/chunk-GBNJQNDS.js +19 -0
  245. package/dist/chunk-GBNJQNDS.js.map +1 -0
  246. package/dist/chunk-GIWHHCD6.js +145 -0
  247. package/dist/chunk-GIWHHCD6.js.map +1 -0
  248. package/dist/chunk-GOJXKIFQ.js +1605 -0
  249. package/dist/chunk-GOJXKIFQ.js.map +1 -0
  250. package/dist/chunk-GRQ2AXDX.js +9 -0
  251. package/dist/chunk-GRQ2AXDX.js.map +1 -0
  252. package/dist/chunk-GXDLWBOY.js +73 -0
  253. package/dist/chunk-GXDLWBOY.js.map +1 -0
  254. package/dist/chunk-HAE4WWFQ.js +455 -0
  255. package/dist/chunk-HAE4WWFQ.js.map +1 -0
  256. package/dist/chunk-I2DNBEV6.js +4227 -0
  257. package/dist/chunk-I2DNBEV6.js.map +1 -0
  258. package/dist/chunk-I4FTS5EE.js +455 -0
  259. package/dist/chunk-I4FTS5EE.js.map +1 -0
  260. package/dist/chunk-IELPT4K2.js +74 -0
  261. package/dist/chunk-IELPT4K2.js.map +1 -0
  262. package/dist/chunk-IJMWEO4P.js +57 -0
  263. package/dist/chunk-IJMWEO4P.js.map +1 -0
  264. package/dist/chunk-IREMSVKW.js +175 -0
  265. package/dist/chunk-IREMSVKW.js.map +1 -0
  266. package/dist/chunk-IVIJJXXT.js +62 -0
  267. package/dist/chunk-IVIJJXXT.js.map +1 -0
  268. package/dist/chunk-JD3W3ON7.js +188 -0
  269. package/dist/chunk-JD3W3ON7.js.map +1 -0
  270. package/dist/chunk-JLWBK3VC.js +5187 -0
  271. package/dist/chunk-JLWBK3VC.js.map +1 -0
  272. package/dist/chunk-JPK34QPS.js +134 -0
  273. package/dist/chunk-JPK34QPS.js.map +1 -0
  274. package/dist/chunk-JUY47NZ2.js +183 -0
  275. package/dist/chunk-JUY47NZ2.js.map +1 -0
  276. package/dist/chunk-JXMZEOHV.js +333 -0
  277. package/dist/chunk-JXMZEOHV.js.map +1 -0
  278. package/dist/chunk-K37K447U.js +51 -0
  279. package/dist/chunk-K37K447U.js.map +1 -0
  280. package/dist/chunk-K6TDB2KV.js +1442 -0
  281. package/dist/chunk-K6TDB2KV.js.map +1 -0
  282. package/dist/chunk-KIGGMKAE.js +66 -0
  283. package/dist/chunk-KIGGMKAE.js.map +1 -0
  284. package/dist/chunk-KKJ4KJCW.js +29 -0
  285. package/dist/chunk-KKJ4KJCW.js.map +1 -0
  286. package/dist/chunk-KONA5PSR.js +55 -0
  287. package/dist/chunk-KONA5PSR.js.map +1 -0
  288. package/dist/chunk-KVHRW7KO.js +60 -0
  289. package/dist/chunk-KVHRW7KO.js.map +1 -0
  290. package/dist/chunk-LA6PPSNA.js +65 -0
  291. package/dist/chunk-LA6PPSNA.js.map +1 -0
  292. package/dist/chunk-LKPJADL2.js +74 -0
  293. package/dist/chunk-LKPJADL2.js.map +1 -0
  294. package/dist/chunk-LWAEHLKV.js +74 -0
  295. package/dist/chunk-LWAEHLKV.js.map +1 -0
  296. package/dist/chunk-M6UNISGO.js +66 -0
  297. package/dist/chunk-M6UNISGO.js.map +1 -0
  298. package/dist/chunk-MIJAGBEP.js +23992 -0
  299. package/dist/chunk-MIJAGBEP.js.map +1 -0
  300. package/dist/chunk-MP4EXZ45.js +3151 -0
  301. package/dist/chunk-MP4EXZ45.js.map +1 -0
  302. package/dist/chunk-MYTDK3AL.js +2102 -0
  303. package/dist/chunk-MYTDK3AL.js.map +1 -0
  304. package/dist/chunk-MZQ5DX6S.js +125 -0
  305. package/dist/chunk-MZQ5DX6S.js.map +1 -0
  306. package/dist/chunk-NFSLRRIE.js +77 -0
  307. package/dist/chunk-NFSLRRIE.js.map +1 -0
  308. package/dist/chunk-NOK7MSVJ.js +533 -0
  309. package/dist/chunk-NOK7MSVJ.js.map +1 -0
  310. package/dist/chunk-NR5RZDAW.js +592 -0
  311. package/dist/chunk-NR5RZDAW.js.map +1 -0
  312. package/dist/chunk-O2EVJALZ.js +133 -0
  313. package/dist/chunk-O2EVJALZ.js.map +1 -0
  314. package/dist/chunk-O6UM5WWH.js +275 -0
  315. package/dist/chunk-O6UM5WWH.js.map +1 -0
  316. package/dist/chunk-O6XZIQXZ.js +6212 -0
  317. package/dist/chunk-O6XZIQXZ.js.map +1 -0
  318. package/dist/chunk-OIL6PU5W.js +35 -0
  319. package/dist/chunk-OIL6PU5W.js.map +1 -0
  320. package/dist/chunk-P4NSJS54.js +20 -0
  321. package/dist/chunk-P4NSJS54.js.map +1 -0
  322. package/dist/chunk-P5T7OZKV.js +26 -0
  323. package/dist/chunk-P5T7OZKV.js.map +1 -0
  324. package/dist/chunk-PFBQERWX.js +10 -0
  325. package/dist/chunk-PFBQERWX.js.map +1 -0
  326. package/dist/chunk-PSWVSLJU.js +56 -0
  327. package/dist/chunk-PSWVSLJU.js.map +1 -0
  328. package/dist/chunk-PY2NJ6XZ.js +191 -0
  329. package/dist/chunk-PY2NJ6XZ.js.map +1 -0
  330. package/dist/chunk-PZ4OM2LK.js +45 -0
  331. package/dist/chunk-PZ4OM2LK.js.map +1 -0
  332. package/dist/chunk-PZNOJ76W.js +541 -0
  333. package/dist/chunk-PZNOJ76W.js.map +1 -0
  334. package/dist/chunk-Q6ULQMWG.js +41 -0
  335. package/dist/chunk-Q6ULQMWG.js.map +1 -0
  336. package/dist/chunk-QKFD6PPX.js +57 -0
  337. package/dist/chunk-QKFD6PPX.js.map +1 -0
  338. package/dist/chunk-QMLGJ5OW.js +2891 -0
  339. package/dist/chunk-QMLGJ5OW.js.map +1 -0
  340. package/dist/chunk-R4TPDVBD.js +207 -0
  341. package/dist/chunk-R4TPDVBD.js.map +1 -0
  342. package/dist/chunk-R7QV5N2S.js +846 -0
  343. package/dist/chunk-R7QV5N2S.js.map +1 -0
  344. package/dist/chunk-RR3KT2E7.js +665 -0
  345. package/dist/chunk-RR3KT2E7.js.map +1 -0
  346. package/dist/chunk-SEPPFM5S.js +228 -0
  347. package/dist/chunk-SEPPFM5S.js.map +1 -0
  348. package/dist/chunk-SQ7DRYCC.js +150 -0
  349. package/dist/chunk-SQ7DRYCC.js.map +1 -0
  350. package/dist/chunk-SYULM665.js +610 -0
  351. package/dist/chunk-SYULM665.js.map +1 -0
  352. package/dist/chunk-TKT3OHZ6.js +170 -0
  353. package/dist/chunk-TKT3OHZ6.js.map +1 -0
  354. package/dist/chunk-TNOSX3PJ.js +136 -0
  355. package/dist/chunk-TNOSX3PJ.js.map +1 -0
  356. package/dist/chunk-TTVKI54A.js +160 -0
  357. package/dist/chunk-TTVKI54A.js.map +1 -0
  358. package/dist/chunk-U7ZVXFS3.js +23 -0
  359. package/dist/chunk-U7ZVXFS3.js.map +1 -0
  360. package/dist/chunk-UI6BKYQD.js +225 -0
  361. package/dist/chunk-UI6BKYQD.js.map +1 -0
  362. package/dist/chunk-UKLDW4UW.js +46 -0
  363. package/dist/chunk-UKLDW4UW.js.map +1 -0
  364. package/dist/chunk-V6XXXEXZ.js +76 -0
  365. package/dist/chunk-V6XXXEXZ.js.map +1 -0
  366. package/dist/chunk-V7BW2CIQ.js +92 -0
  367. package/dist/chunk-V7BW2CIQ.js.map +1 -0
  368. package/dist/chunk-VSU5R34H.js +76 -0
  369. package/dist/chunk-VSU5R34H.js.map +1 -0
  370. package/dist/chunk-W4SA4CMR.js +296 -0
  371. package/dist/chunk-W4SA4CMR.js.map +1 -0
  372. package/dist/chunk-WFUMNDCE.js +111 -0
  373. package/dist/chunk-WFUMNDCE.js.map +1 -0
  374. package/dist/chunk-WHWNXLTD.js +166 -0
  375. package/dist/chunk-WHWNXLTD.js.map +1 -0
  376. package/dist/chunk-WN4KX7GE.js +25 -0
  377. package/dist/chunk-WN4KX7GE.js.map +1 -0
  378. package/dist/chunk-XIY7P54H.js +84 -0
  379. package/dist/chunk-XIY7P54H.js.map +1 -0
  380. package/dist/chunk-YFPLNMPZ.js +337 -0
  381. package/dist/chunk-YFPLNMPZ.js.map +1 -0
  382. package/dist/chunk-YMBB4JBD.js +1830 -0
  383. package/dist/chunk-YMBB4JBD.js.map +1 -0
  384. package/dist/chunk-YQFM2P5W.js +197 -0
  385. package/dist/chunk-YQFM2P5W.js.map +1 -0
  386. package/dist/chunk-YQSBHWOI.js +41 -0
  387. package/dist/chunk-YTF3IVMF.js +149 -0
  388. package/dist/chunk-YTF3IVMF.js.map +1 -0
  389. package/dist/chunk-Z3ENMCFE.js +94 -0
  390. package/dist/chunk-Z3ENMCFE.js.map +1 -0
  391. package/dist/chunk-Z7MWSXLG.js +94 -0
  392. package/dist/chunk-Z7MWSXLG.js.map +1 -0
  393. package/dist/chunk-ZIXHS6AM.js +42 -0
  394. package/dist/chunk-ZIXHS6AM.js.map +1 -0
  395. package/dist/chunk-ZJ7TQUCU.js +4410 -0
  396. package/dist/chunk-ZJ7TQUCU.js.map +1 -0
  397. package/dist/chunk-ZNQRDLSS.js +52 -0
  398. package/dist/chunk-ZNQRDLSS.js.map +1 -0
  399. package/dist/claim-ROWH6JVB.js +197 -0
  400. package/dist/claim-ROWH6JVB.js.map +1 -0
  401. package/dist/cli.js +104 -69986
  402. package/dist/cli.js.map +1 -1
  403. package/dist/client-EURRWXPW.js +19 -0
  404. package/dist/code-FKQW7V7N.js +76 -0
  405. package/dist/code-FKQW7V7N.js.map +1 -0
  406. package/dist/companies-MD2MZKU6.js +195 -0
  407. package/dist/companies-MD2MZKU6.js.map +1 -0
  408. package/dist/complete-FCAJM6Z4.js +81 -0
  409. package/dist/complete-FCAJM6Z4.js.map +1 -0
  410. package/dist/config-OZOHIAOJ.js +88 -0
  411. package/dist/config-OZOHIAOJ.js.map +1 -0
  412. package/dist/connect-4YXFMXYX.js +42 -0
  413. package/dist/content-PCGSX2QU.js +85 -0
  414. package/dist/content-PCGSX2QU.js.map +1 -0
  415. package/dist/conversation-UX5NZ3IO.js +93 -0
  416. package/dist/conversation-UX5NZ3IO.js.map +1 -0
  417. package/dist/conversion-report-7QSWB2FY.js +125 -0
  418. package/dist/conversion-report-7QSWB2FY.js.map +1 -0
  419. package/dist/conversion-upload-command-XESIAQPU.js +438 -0
  420. package/dist/conversion-upload-command-XESIAQPU.js.map +1 -0
  421. package/dist/conversion-writes-BGOVLBS5.js +120 -0
  422. package/dist/conversion-writes-BGOVLBS5.js.map +1 -0
  423. package/dist/conversions-IYIWW4O7.js +76 -0
  424. package/dist/conversions-IYIWW4O7.js.map +1 -0
  425. package/dist/conversions-RLIJAE7E.js +135 -0
  426. package/dist/conversions-RLIJAE7E.js.map +1 -0
  427. package/dist/countries-5OBUVLLD.js +82 -0
  428. package/dist/countries-5OBUVLLD.js.map +1 -0
  429. package/dist/create-CUJLJUAQ.js +138 -0
  430. package/dist/create-CUJLJUAQ.js.map +1 -0
  431. package/dist/create-FENOT6DX.js +236 -0
  432. package/dist/create-FENOT6DX.js.map +1 -0
  433. package/dist/create-OFZQMOWO.js +59 -0
  434. package/dist/create-OFZQMOWO.js.map +1 -0
  435. package/dist/create-Z5SS2AWB.js +207 -0
  436. package/dist/create-Z5SS2AWB.js.map +1 -0
  437. package/dist/creatives-UJW2QBLH.js +182 -0
  438. package/dist/creatives-UJW2QBLH.js.map +1 -0
  439. package/dist/creatives-XI2DGQUZ.js +87 -0
  440. package/dist/creatives-XI2DGQUZ.js.map +1 -0
  441. package/dist/creatives-YLXQSROD.js +51 -0
  442. package/dist/creatives-YLXQSROD.js.map +1 -0
  443. package/dist/credentials-CH73QMD2.js +287 -0
  444. package/dist/credentials-CH73QMD2.js.map +1 -0
  445. package/dist/critique-C4WRQ4AJ.js +1449 -0
  446. package/dist/critique-C4WRQ4AJ.js.map +1 -0
  447. package/dist/critique-ZBNJ6MQ3.js +213 -0
  448. package/dist/critique-ZBNJ6MQ3.js.map +1 -0
  449. package/dist/crm-MJTT6GOJ.js +224 -0
  450. package/dist/crm-MJTT6GOJ.js.map +1 -0
  451. package/dist/crm-ZXHSEFYI.js +318 -0
  452. package/dist/crm-ZXHSEFYI.js.map +1 -0
  453. package/dist/crop-B52KIQ4O.js +113 -0
  454. package/dist/crop-B52KIQ4O.js.map +1 -0
  455. package/dist/currency-GGWF5DMU.js +88 -0
  456. package/dist/currency-GGWF5DMU.js.map +1 -0
  457. package/dist/custom-conversions-7WDBTC4X.js +125 -0
  458. package/dist/custom-conversions-7WDBTC4X.js.map +1 -0
  459. package/dist/customers-7E4HBSEY.js +56 -0
  460. package/dist/decide-PK7WNSQ2.js +199 -0
  461. package/dist/decide-PK7WNSQ2.js.map +1 -0
  462. package/dist/delete-56LKNEGA.js +71 -0
  463. package/dist/delete-56LKNEGA.js.map +1 -0
  464. package/dist/delete-DQY4ZSFN.js +54 -0
  465. package/dist/delete-DQY4ZSFN.js.map +1 -0
  466. package/dist/delete-EZ7HHOOD.js +69 -0
  467. package/dist/delete-EZ7HHOOD.js.map +1 -0
  468. package/dist/delete-JV4KAA6Y.js +66 -0
  469. package/dist/delete-JV4KAA6Y.js.map +1 -0
  470. package/dist/delete-YONJW4UZ.js +63 -0
  471. package/dist/delete-YONJW4UZ.js.map +1 -0
  472. package/dist/delete-YSYVFL6W.js +71 -0
  473. package/dist/delete-YSYVFL6W.js.map +1 -0
  474. package/dist/demographics-6N3TTYWC.js +138 -0
  475. package/dist/demographics-6N3TTYWC.js.map +1 -0
  476. package/dist/describe-AAVYIFE3.js +97 -0
  477. package/dist/describe-AAVYIFE3.js.map +1 -0
  478. package/dist/describe-UQFLWVFR.js +97 -0
  479. package/dist/describe-UQFLWVFR.js.map +1 -0
  480. package/dist/dimensions-QDXBG2XC.js +101 -0
  481. package/dist/dimensions-QDXBG2XC.js.map +1 -0
  482. package/dist/discard-S3NGGUSK.js +66 -0
  483. package/dist/discard-S3NGGUSK.js.map +1 -0
  484. package/dist/discover-6TEBPVNC.js +93 -0
  485. package/dist/discover-6TEBPVNC.js.map +1 -0
  486. package/dist/discover-SBZPB7T2.js +172 -0
  487. package/dist/discover-SBZPB7T2.js.map +1 -0
  488. package/dist/domain-AMAR76PB.js +98 -0
  489. package/dist/domain-AMAR76PB.js.map +1 -0
  490. package/dist/download-LV3GPOWV.js +299 -0
  491. package/dist/download-LV3GPOWV.js.map +1 -0
  492. package/dist/draft-6QZ7WMWM.js +217 -0
  493. package/dist/draft-6QZ7WMWM.js.map +1 -0
  494. package/dist/draft-DDFFTZ43.js +233 -0
  495. package/dist/draft-DDFFTZ43.js.map +1 -0
  496. package/dist/draft-FIKJXNIQ.js +281 -0
  497. package/dist/draft-FIKJXNIQ.js.map +1 -0
  498. package/dist/draft-GYGWTMBU.js +307 -0
  499. package/dist/draft-GYGWTMBU.js.map +1 -0
  500. package/dist/draft-KXL62WFS.js +328 -0
  501. package/dist/draft-KXL62WFS.js.map +1 -0
  502. package/dist/draft-N4LFPKTA.js +100 -0
  503. package/dist/draft-N4LFPKTA.js.map +1 -0
  504. package/dist/draft-POSLJCWG.js +306 -0
  505. package/dist/draft-POSLJCWG.js.map +1 -0
  506. package/dist/draft-XPO5RWST.js +103 -0
  507. package/dist/draft-XPO5RWST.js.map +1 -0
  508. package/dist/engine/index.d.ts +213 -127
  509. package/dist/engine/index.js +18 -4
  510. package/dist/{env-4P5HOGNA.js → env-TQ2XS2KY.js} +12 -2
  511. package/dist/env-TQ2XS2KY.js.map +1 -0
  512. package/dist/experiment-FQNKMORZ.js +1397 -0
  513. package/dist/experiment-FQNKMORZ.js.map +1 -0
  514. package/dist/export-4IZQZAPF.js +168 -0
  515. package/dist/export-4IZQZAPF.js.map +1 -0
  516. package/dist/extract-DZMGVQ7D.js +113 -0
  517. package/dist/extract-DZMGVQ7D.js.map +1 -0
  518. package/dist/facets-223V5P47.js +114 -0
  519. package/dist/facets-223V5P47.js.map +1 -0
  520. package/dist/favorites-DD2LNSTG.js +178 -0
  521. package/dist/favorites-DD2LNSTG.js.map +1 -0
  522. package/dist/feed-TUVFNX2U.js +177 -0
  523. package/dist/feed-TUVFNX2U.js.map +1 -0
  524. package/dist/feedback-MIW23MI2.js +66 -0
  525. package/dist/feedback-MIW23MI2.js.map +1 -0
  526. package/dist/feedback-record-RGKRKPGZ.js +175 -0
  527. package/dist/feedback-record-RGKRKPGZ.js.map +1 -0
  528. package/dist/fetch-O6UHNXWB.js +139 -0
  529. package/dist/fetch-O6UHNXWB.js.map +1 -0
  530. package/dist/fetch-TZ4UCMJK.js +176 -0
  531. package/dist/fetch-TZ4UCMJK.js.map +1 -0
  532. package/dist/find-4XKIBF4D.js +134 -0
  533. package/dist/find-4XKIBF4D.js.map +1 -0
  534. package/dist/fit-ODVVXV2Q.js +45 -0
  535. package/dist/fit-ODVVXV2Q.js.map +1 -0
  536. package/dist/flows-HVWBFZ7T.js +247 -0
  537. package/dist/flows-HVWBFZ7T.js.map +1 -0
  538. package/dist/follow-RCOXTZGY.js +94 -0
  539. package/dist/follow-RCOXTZGY.js.map +1 -0
  540. package/dist/follow-competitors-SQ5XBFTK.js +112 -0
  541. package/dist/follow-competitors-SQ5XBFTK.js.map +1 -0
  542. package/dist/following-VDU3BHC4.js +113 -0
  543. package/dist/following-VDU3BHC4.js.map +1 -0
  544. package/dist/fonts-NBIQAVQN.js +34 -0
  545. package/dist/fonts-NBIQAVQN.js.map +1 -0
  546. package/dist/forecast-2GJKBNBM.js +168 -0
  547. package/dist/forecast-2GJKBNBM.js.map +1 -0
  548. package/dist/forecast-76MUJBPO.js +104 -0
  549. package/dist/forecast-76MUJBPO.js.map +1 -0
  550. package/dist/funding-HTFVZLLG.js +85 -0
  551. package/dist/funding-HTFVZLLG.js.map +1 -0
  552. package/dist/funnel-FE2HIRVQ.js +394 -0
  553. package/dist/funnel-FE2HIRVQ.js.map +1 -0
  554. package/dist/ga4-2RC4EH7V.js +55 -0
  555. package/dist/ga4-2RC4EH7V.js.map +1 -0
  556. package/dist/generate-TPDOBCKQ.js +262 -0
  557. package/dist/generate-TPDOBCKQ.js.map +1 -0
  558. package/dist/get-6JNOVI27.js +56 -0
  559. package/dist/get-6JNOVI27.js.map +1 -0
  560. package/dist/get-FH2LIEYL.js +63 -0
  561. package/dist/get-FH2LIEYL.js.map +1 -0
  562. package/dist/get-GZLCDXXW.js +61 -0
  563. package/dist/get-GZLCDXXW.js.map +1 -0
  564. package/dist/get-KVAOPAQW.js +78 -0
  565. package/dist/get-KVAOPAQW.js.map +1 -0
  566. package/dist/get-TSPQYEKC.js +59 -0
  567. package/dist/get-TSPQYEKC.js.map +1 -0
  568. package/dist/get-TY3RXYNZ.js +63 -0
  569. package/dist/get-TY3RXYNZ.js.map +1 -0
  570. package/dist/get-VPW33XTN.js +92 -0
  571. package/dist/get-VPW33XTN.js.map +1 -0
  572. package/dist/gif-JFEYPFFI.js +94 -0
  573. package/dist/gif-JFEYPFFI.js.map +1 -0
  574. package/dist/google-R6RD4L6Z.js +136 -0
  575. package/dist/google-R6RD4L6Z.js.map +1 -0
  576. package/dist/google-VPQNRVIB.js +3190 -0
  577. package/dist/google-VPQNRVIB.js.map +1 -0
  578. package/dist/google-ads-JEQMNNMN.js +195 -0
  579. package/dist/google-ads-JEQMNNMN.js.map +1 -0
  580. package/dist/group-7AV6UL26.js +43 -0
  581. package/dist/group-7AV6UL26.js.map +1 -0
  582. package/dist/group-BVQZEZIC.js +43 -0
  583. package/dist/group-BVQZEZIC.js.map +1 -0
  584. package/dist/gsc-SQ42WAQE.js +30 -0
  585. package/dist/gsc-SQ42WAQE.js.map +1 -0
  586. package/dist/history-BNNHFURR.js +67 -0
  587. package/dist/history-BNNHFURR.js.map +1 -0
  588. package/dist/history-EHUQG4CE.js +133 -0
  589. package/dist/history-EHUQG4CE.js.map +1 -0
  590. package/dist/hubspot-JABE4USC.js +779 -0
  591. package/dist/hubspot-JABE4USC.js.map +1 -0
  592. package/dist/icon-OYTTSNSL.js +137 -0
  593. package/dist/icon-OYTTSNSL.js.map +1 -0
  594. package/dist/ideas-OD76WOQ3.js +32 -0
  595. package/dist/ideas-OD76WOQ3.js.map +1 -0
  596. package/dist/images-LY7AWWBK.js +90 -0
  597. package/dist/images-LY7AWWBK.js.map +1 -0
  598. package/dist/improve-W6GZNT2A.js +86 -0
  599. package/dist/improve-W6GZNT2A.js.map +1 -0
  600. package/dist/ingest-47WON6HT.js +23 -0
  601. package/dist/ingest-47WON6HT.js.map +1 -0
  602. package/dist/ingest-HDGGHBSJ.js +107 -0
  603. package/dist/ingest-HDGGHBSJ.js.map +1 -0
  604. package/dist/insights-IW7LGAWU.js +423 -0
  605. package/dist/insights-IW7LGAWU.js.map +1 -0
  606. package/dist/insights-QH54F56A.js +122 -0
  607. package/dist/insights-QH54F56A.js.map +1 -0
  608. package/dist/inspect-AJLG2HGL.js +189 -0
  609. package/dist/inspect-AJLG2HGL.js.map +1 -0
  610. package/dist/inspiration-RDQ3Y3N3.js +53 -0
  611. package/dist/inspiration-RDQ3Y3N3.js.map +1 -0
  612. package/dist/intent-5GSSCFZ2.js +95 -0
  613. package/dist/intent-5GSSCFZ2.js.map +1 -0
  614. package/dist/job-URVXJP75.js +202 -0
  615. package/dist/job-URVXJP75.js.map +1 -0
  616. package/dist/job-create-S4SECUVF.js +109 -0
  617. package/dist/job-create-S4SECUVF.js.map +1 -0
  618. package/dist/job-status-253SUCTJ.js +74 -0
  619. package/dist/job-status-253SUCTJ.js.map +1 -0
  620. package/dist/keep-GPSYDIGJ.js +78 -0
  621. package/dist/keep-GPSYDIGJ.js.map +1 -0
  622. package/dist/keyword-gap-NTFDX43B.js +130 -0
  623. package/dist/keyword-gap-NTFDX43B.js.map +1 -0
  624. package/dist/keyword-metrics-XSFLMBZX.js +197 -0
  625. package/dist/keyword-metrics-XSFLMBZX.js.map +1 -0
  626. package/dist/keywords-for-site-U4JLYXVE.js +128 -0
  627. package/dist/keywords-for-site-U4JLYXVE.js.map +1 -0
  628. package/dist/landing-AO72EGJ6.js +28 -0
  629. package/dist/landing-AO72EGJ6.js.map +1 -0
  630. package/dist/landings-NEF4PQL2.js +151 -0
  631. package/dist/landings-NEF4PQL2.js.map +1 -0
  632. package/dist/languages-3RDPPPTE.js +55 -0
  633. package/dist/languages-3RDPPPTE.js.map +1 -0
  634. package/dist/languages-CQX3YOIT.js +40 -0
  635. package/dist/languages-CQX3YOIT.js.map +1 -0
  636. package/dist/launches-GBHLJH5S.js +19 -0
  637. package/dist/launches-GBHLJH5S.js.map +1 -0
  638. package/dist/layerize-Q56C6LFG.js +190 -0
  639. package/dist/layerize-Q56C6LFG.js.map +1 -0
  640. package/dist/leads-JHUM6FYR.js +293 -0
  641. package/dist/leads-JHUM6FYR.js.map +1 -0
  642. package/dist/leads-UYZM2XQX.js +90 -0
  643. package/dist/leads-UYZM2XQX.js.map +1 -0
  644. package/dist/learn-D2KBGJHZ.js +203 -0
  645. package/dist/learn-D2KBGJHZ.js.map +1 -0
  646. package/dist/library-6VUFHTEK.js +109 -0
  647. package/dist/library-6VUFHTEK.js.map +1 -0
  648. package/dist/lighthouse-57U2GMPV.js +75 -0
  649. package/dist/lighthouse-57U2GMPV.js.map +1 -0
  650. package/dist/line-item-writes-R5GO6GTL.js +208 -0
  651. package/dist/line-item-writes-R5GO6GTL.js.map +1 -0
  652. package/dist/line-items-RBMH6YBZ.js +103 -0
  653. package/dist/line-items-RBMH6YBZ.js.map +1 -0
  654. package/dist/link-WS2RMCOP.js +64 -0
  655. package/dist/link-WS2RMCOP.js.map +1 -0
  656. package/dist/linkedin-FSIALZTS.js +1008 -0
  657. package/dist/linkedin-FSIALZTS.js.map +1 -0
  658. package/dist/list-2AE2Q4ZD.js +151 -0
  659. package/dist/list-2AE2Q4ZD.js.map +1 -0
  660. package/dist/list-E635Y6M4.js +303 -0
  661. package/dist/list-E635Y6M4.js.map +1 -0
  662. package/dist/list-G57ZO4PG.js +50 -0
  663. package/dist/list-G57ZO4PG.js.map +1 -0
  664. package/dist/list-JCSWZWDI.js +57 -0
  665. package/dist/list-JCSWZWDI.js.map +1 -0
  666. package/dist/list-KT6NXVLV.js +63 -0
  667. package/dist/list-KT6NXVLV.js.map +1 -0
  668. package/dist/list-RINCJOAC.js +76 -0
  669. package/dist/list-RINCJOAC.js.map +1 -0
  670. package/dist/list-SRNXHS6L.js +51 -0
  671. package/dist/list-SRNXHS6L.js.map +1 -0
  672. package/dist/list-YJSO4M5Q.js +65 -0
  673. package/dist/list-YJSO4M5Q.js.map +1 -0
  674. package/dist/locations-HW2Y5OJO.js +67 -0
  675. package/dist/locations-HW2Y5OJO.js.map +1 -0
  676. package/dist/locations-XOHI3VWI.js +40 -0
  677. package/dist/locations-XOHI3VWI.js.map +1 -0
  678. package/dist/log-3HX5BIO6.js +92 -0
  679. package/dist/log-3HX5BIO6.js.map +1 -0
  680. package/dist/logo-KXTGIYBI.js +18 -0
  681. package/dist/logo-KXTGIYBI.js.map +1 -0
  682. package/dist/lookup-X6O5UNJH.js +22 -0
  683. package/dist/lookup-X6O5UNJH.js.map +1 -0
  684. package/dist/make-QH77XOWM.js +633 -0
  685. package/dist/make-QH77XOWM.js.map +1 -0
  686. package/dist/map-QABBPYZM.js +404 -0
  687. package/dist/map-QABBPYZM.js.map +1 -0
  688. package/dist/mcp-HSD3W3OB.js +463 -0
  689. package/dist/mcp-HSD3W3OB.js.map +1 -0
  690. package/dist/media-MI4EE7L4.js +89 -0
  691. package/dist/media-MI4EE7L4.js.map +1 -0
  692. package/dist/media-QUTQOBA7.js +15 -0
  693. package/dist/media-QUTQOBA7.js.map +1 -0
  694. package/dist/media-sources-HO4DXRX5.js +32 -0
  695. package/dist/media-sources-HO4DXRX5.js.map +1 -0
  696. package/dist/members-YEYYJGY6.js +44 -0
  697. package/dist/members-YEYYJGY6.js.map +1 -0
  698. package/dist/meta-E3JOUOSS.js +69 -0
  699. package/dist/meta-E3JOUOSS.js.map +1 -0
  700. package/dist/metrics-HQ7XJAYQ.js +152 -0
  701. package/dist/metrics-HQ7XJAYQ.js.map +1 -0
  702. package/dist/models-PGX3FBHU.js +155 -0
  703. package/dist/models-PGX3FBHU.js.map +1 -0
  704. package/dist/normalize-FPJ6GSOY.js +806 -0
  705. package/dist/normalize-FPJ6GSOY.js.map +1 -0
  706. package/dist/normalize-GSQWN77S.js +141 -0
  707. package/dist/normalize-GSQWN77S.js.map +1 -0
  708. package/dist/options-F5XZMQLK.js +121 -0
  709. package/dist/options-F5XZMQLK.js.map +1 -0
  710. package/dist/output-GQFJ2T5B.js +24 -0
  711. package/dist/output-GQFJ2T5B.js.map +1 -0
  712. package/dist/page-VTTSBC6Y.js +105 -0
  713. package/dist/page-VTTSBC6Y.js.map +1 -0
  714. package/dist/pages-PMZVNVQM.js +66 -0
  715. package/dist/pages-PMZVNVQM.js.map +1 -0
  716. package/dist/performance-G67JQE5J.js +24 -0
  717. package/dist/performance-G67JQE5J.js.map +1 -0
  718. package/dist/pinterest-UDNGOWDM.js +96 -0
  719. package/dist/pinterest-UDNGOWDM.js.map +1 -0
  720. package/dist/pixels-OYZDGCH3.js +108 -0
  721. package/dist/pixels-OYZDGCH3.js.map +1 -0
  722. package/dist/pixels-XKGNTCFX.js +60 -0
  723. package/dist/pixels-XKGNTCFX.js.map +1 -0
  724. package/dist/plan-DZS3TVIJ.js +207 -0
  725. package/dist/plan-DZS3TVIJ.js.map +1 -0
  726. package/dist/preview-DR6MXOGI.js +169 -0
  727. package/dist/preview-DR6MXOGI.js.map +1 -0
  728. package/dist/profile-VOVZG44G.js +159 -0
  729. package/dist/profile-VOVZG44G.js.map +1 -0
  730. package/dist/promoted-tweet-writes-VCK2ADVJ.js +180 -0
  731. package/dist/promoted-tweet-writes-VCK2ADVJ.js.map +1 -0
  732. package/dist/promoted-tweets-4ACBP2RV.js +119 -0
  733. package/dist/promoted-tweets-4ACBP2RV.js.map +1 -0
  734. package/dist/properties-MKVF7MUK.js +101 -0
  735. package/dist/properties-MKVF7MUK.js.map +1 -0
  736. package/dist/publish-6XVA35T6.js +322 -0
  737. package/dist/publish-6XVA35T6.js.map +1 -0
  738. package/dist/query-CNWQ6STR.js +61 -0
  739. package/dist/query-CNWQ6STR.js.map +1 -0
  740. package/dist/query-DBSBZ73C.js +247 -0
  741. package/dist/query-DBSBZ73C.js.map +1 -0
  742. package/dist/query-QK4U4TEL.js +236 -0
  743. package/dist/query-QK4U4TEL.js.map +1 -0
  744. package/dist/questionnaire-OVJWNUVV.js +93 -0
  745. package/dist/questionnaire-OVJWNUVV.js.map +1 -0
  746. package/dist/read-L2QIVJTL.js +141 -0
  747. package/dist/read-L2QIVJTL.js.map +1 -0
  748. package/dist/reddit-SCEB2JQL.js +26 -0
  749. package/dist/reddit-SCEB2JQL.js.map +1 -0
  750. package/dist/refresh-TIH5Y3NP.js +94 -0
  751. package/dist/refresh-TIH5Y3NP.js.map +1 -0
  752. package/dist/release-LKMUKVXM.js +60 -0
  753. package/dist/release-LKMUKVXM.js.map +1 -0
  754. package/dist/relevant-pages-CRI2NLWG.js +99 -0
  755. package/dist/relevant-pages-CRI2NLWG.js.map +1 -0
  756. package/dist/remove-6ABOB7TZ.js +50 -0
  757. package/dist/remove-6ABOB7TZ.js.map +1 -0
  758. package/dist/remove-JKSCGKQG.js +48 -0
  759. package/dist/remove-JKSCGKQG.js.map +1 -0
  760. package/dist/reopen-27TDNXFP.js +63 -0
  761. package/dist/reopen-27TDNXFP.js.map +1 -0
  762. package/dist/rerun-XHECBJD5.js +84 -0
  763. package/dist/rerun-XHECBJD5.js.map +1 -0
  764. package/dist/research-4MOXIMDX.js +62 -0
  765. package/dist/research-4MOXIMDX.js.map +1 -0
  766. package/dist/research-XYXP7D4R.js +262 -0
  767. package/dist/research-XYXP7D4R.js.map +1 -0
  768. package/dist/reset-NLYEBPLX.js +54 -0
  769. package/dist/reset-NLYEBPLX.js.map +1 -0
  770. package/dist/reset-RDQOYBXX.js +54 -0
  771. package/dist/reset-RDQOYBXX.js.map +1 -0
  772. package/dist/resolve-VHKWC5KW.js +121 -0
  773. package/dist/resolve-VHKWC5KW.js.map +1 -0
  774. package/dist/retry-MTQSHXKH.js +60 -0
  775. package/dist/retry-MTQSHXKH.js.map +1 -0
  776. package/dist/retry-ZI5ECSFD.js +62 -0
  777. package/dist/retry-ZI5ECSFD.js.map +1 -0
  778. package/dist/retry-failed-2OYMCB55.js +45 -0
  779. package/dist/retry-failed-2OYMCB55.js.map +1 -0
  780. package/dist/run-BMJJRJL2.js +65 -0
  781. package/dist/run-BMJJRJL2.js.map +1 -0
  782. package/dist/run-IHXS6F5V.js +59 -0
  783. package/dist/run-IHXS6F5V.js.map +1 -0
  784. package/dist/scaffold-ad-QEADKYPL.js +1548 -0
  785. package/dist/scaffold-ad-QEADKYPL.js.map +1 -0
  786. package/dist/scaffold-static-ad-PTJ73ZNF.js +971 -0
  787. package/dist/scaffold-static-ad-PTJ73ZNF.js.map +1 -0
  788. package/dist/scaffold-video-ZQEZRVD6.js +872 -0
  789. package/dist/scaffold-video-ZQEZRVD6.js.map +1 -0
  790. package/dist/schedule-JD2EQJCT.js +61 -0
  791. package/dist/schedule-JD2EQJCT.js.map +1 -0
  792. package/dist/schedule-TLYT5UXM.js +66 -0
  793. package/dist/schedule-TLYT5UXM.js.map +1 -0
  794. package/dist/scheduled-agents-GIVKWTXX.js +49 -0
  795. package/dist/scheduled-agents-GIVKWTXX.js.map +1 -0
  796. package/dist/schema-MZTVCNP4.js +63 -0
  797. package/dist/schema-MZTVCNP4.js.map +1 -0
  798. package/dist/schema-RYTVKPLZ.js +132 -0
  799. package/dist/schema-RYTVKPLZ.js.map +1 -0
  800. package/dist/scrape-T3DA7ER7.js +2241 -0
  801. package/dist/scrape-T3DA7ER7.js.map +1 -0
  802. package/dist/screenshot-EIGC6SZB.js +102 -0
  803. package/dist/screenshot-EIGC6SZB.js.map +1 -0
  804. package/dist/search-2SVUDZIX.js +224 -0
  805. package/dist/search-2SVUDZIX.js.map +1 -0
  806. package/dist/search-34NFJ5F6.js +26 -0
  807. package/dist/search-34NFJ5F6.js.map +1 -0
  808. package/dist/search-AOFAN5NB.js +174 -0
  809. package/dist/search-AOFAN5NB.js.map +1 -0
  810. package/dist/search-BWE3OPOY.js +91 -0
  811. package/dist/search-BWE3OPOY.js.map +1 -0
  812. package/dist/search-EYYAOZND.js +92 -0
  813. package/dist/search-EYYAOZND.js.map +1 -0
  814. package/dist/search-copy-VKQ2OOBM.js +168 -0
  815. package/dist/search-copy-VKQ2OOBM.js.map +1 -0
  816. package/dist/seeds-HQYSVFIX.js +101 -0
  817. package/dist/seeds-HQYSVFIX.js.map +1 -0
  818. package/dist/select-HJMOAWAU.js +94 -0
  819. package/dist/select-HJMOAWAU.js.map +1 -0
  820. package/dist/sends-I7VQFE4S.js +309 -0
  821. package/dist/sends-I7VQFE4S.js.map +1 -0
  822. package/dist/sequences-JHSEJJGN.js +146 -0
  823. package/dist/sequences-JHSEJJGN.js.map +1 -0
  824. package/dist/set-prompt-TSS33JQZ.js +185 -0
  825. package/dist/set-prompt-TSS33JQZ.js.map +1 -0
  826. package/dist/setup-links-IW4BUANK.js +141 -0
  827. package/dist/setup-links-IW4BUANK.js.map +1 -0
  828. package/dist/{shared-J7DQZ2ED.js → shared-AT3FXPAG.js} +8 -6
  829. package/dist/shared-AT3FXPAG.js.map +1 -0
  830. package/dist/shopify-RQKO5TMR.js +3819 -0
  831. package/dist/shopify-RQKO5TMR.js.map +1 -0
  832. package/dist/site-3NU2BDAR.js +177 -0
  833. package/dist/site-3NU2BDAR.js.map +1 -0
  834. package/dist/sitemaps-FG37N5EB.js +87 -0
  835. package/dist/sitemaps-FG37N5EB.js.map +1 -0
  836. package/dist/sites-FIXK4Y3O.js +101 -0
  837. package/dist/sites-FIXK4Y3O.js.map +1 -0
  838. package/dist/skills-OKVCVQVD.js +47 -0
  839. package/dist/skills-OKVCVQVD.js.map +1 -0
  840. package/dist/sources-SEODRUIC.js +30 -0
  841. package/dist/sources-SEODRUIC.js.map +1 -0
  842. package/dist/sources-Z6BGTBGO.js +421 -0
  843. package/dist/sources-Z6BGTBGO.js.map +1 -0
  844. package/dist/stale-SWPDWXG7.js +63 -0
  845. package/dist/stale-SWPDWXG7.js.map +1 -0
  846. package/dist/stats-ZWZ7BAHV.js +34 -0
  847. package/dist/stats-ZWZ7BAHV.js.map +1 -0
  848. package/dist/status-7Y7UNSO6.js +62 -0
  849. package/dist/status-7Y7UNSO6.js.map +1 -0
  850. package/dist/sticker-FLRZM3BI.js +94 -0
  851. package/dist/sticker-FLRZM3BI.js.map +1 -0
  852. package/dist/stock-2CSMWRWV.js +179 -0
  853. package/dist/stock-2CSMWRWV.js.map +1 -0
  854. package/dist/studio-TTTR6N7D.js +49 -0
  855. package/dist/studio-TTTR6N7D.js.map +1 -0
  856. package/dist/sync-FH773IFH.js +54 -0
  857. package/dist/sync-FH773IFH.js.map +1 -0
  858. package/dist/sync-G5CS2RYV.js +54 -0
  859. package/dist/sync-G5CS2RYV.js.map +1 -0
  860. package/dist/sync-UADA6M33.js +265 -0
  861. package/dist/sync-UADA6M33.js.map +1 -0
  862. package/dist/sync-definition-77KLGPMA.js +52 -0
  863. package/dist/sync-definition-77KLGPMA.js.map +1 -0
  864. package/dist/tag-manager-NK3ZHSJB.js +43 -0
  865. package/dist/tag-manager-NK3ZHSJB.js.map +1 -0
  866. package/dist/tags-ANGHHLAC.js +20 -0
  867. package/dist/tags-ANGHHLAC.js.map +1 -0
  868. package/dist/tags-DKPUSQTJ.js +20 -0
  869. package/dist/tags-DKPUSQTJ.js.map +1 -0
  870. package/dist/tags-HSCV4ZAQ.js +20 -0
  871. package/dist/tags-HSCV4ZAQ.js.map +1 -0
  872. package/dist/tags-J3RMQEQM.js +26 -0
  873. package/dist/tags-J3RMQEQM.js.map +1 -0
  874. package/dist/tags-VZGTR3VJ.js +224 -0
  875. package/dist/tags-VZGTR3VJ.js.map +1 -0
  876. package/dist/targeting-constants-ZGBX3VWU.js +118 -0
  877. package/dist/targeting-constants-ZGBX3VWU.js.map +1 -0
  878. package/dist/targeting-criteria-BSG3CLHU.js +113 -0
  879. package/dist/targeting-criteria-BSG3CLHU.js.map +1 -0
  880. package/dist/targets-DVOAFYZQ.js +102 -0
  881. package/dist/targets-DVOAFYZQ.js.map +1 -0
  882. package/dist/templates-KJ5O44FF.js +178 -0
  883. package/dist/templates-KJ5O44FF.js.map +1 -0
  884. package/dist/testimonials-NB7V3DUO.js +32 -0
  885. package/dist/testimonials-NB7V3DUO.js.map +1 -0
  886. package/dist/themes-3RV3HNNE.js +94 -0
  887. package/dist/themes-3RV3HNNE.js.map +1 -0
  888. package/dist/top-companies-KRB3OZOT.js +108 -0
  889. package/dist/top-companies-KRB3OZOT.js.map +1 -0
  890. package/dist/translate-5FP32BIA.js +598 -0
  891. package/dist/translate-5FP32BIA.js.map +1 -0
  892. package/dist/triggers-EURHTCYC.js +141 -0
  893. package/dist/triggers-EURHTCYC.js.map +1 -0
  894. package/dist/tweets-X64YDEAA.js +123 -0
  895. package/dist/tweets-X64YDEAA.js.map +1 -0
  896. package/dist/unfollow-PIONCSBL.js +46 -0
  897. package/dist/unfollow-PIONCSBL.js.map +1 -0
  898. package/dist/unlink-HVVTZ3MB.js +67 -0
  899. package/dist/unlink-HVVTZ3MB.js.map +1 -0
  900. package/dist/unstage-BJJ5M7MK.js +95 -0
  901. package/dist/unstage-BJJ5M7MK.js.map +1 -0
  902. package/dist/unstage-Y7ZE3NUJ.js +84 -0
  903. package/dist/unstage-Y7ZE3NUJ.js.map +1 -0
  904. package/dist/update-3IP7FB6Y.js +98 -0
  905. package/dist/update-3IP7FB6Y.js.map +1 -0
  906. package/dist/update-CSDSK5NO.js +63 -0
  907. package/dist/update-CSDSK5NO.js.map +1 -0
  908. package/dist/update-FGJXVDB7.js +142 -0
  909. package/dist/update-FGJXVDB7.js.map +1 -0
  910. package/dist/update-MF7LY2OT.js +155 -0
  911. package/dist/update-MF7LY2OT.js.map +1 -0
  912. package/dist/upload-DDPI7KJV.js +126 -0
  913. package/dist/upload-DDPI7KJV.js.map +1 -0
  914. package/dist/upload-IWFYKD7A.js +150 -0
  915. package/dist/upload-IWFYKD7A.js.map +1 -0
  916. package/dist/upscale-EYCEYRWE.js +109 -0
  917. package/dist/upscale-EYCEYRWE.js.map +1 -0
  918. package/dist/url-options-RA3XISLN.js +130 -0
  919. package/dist/url-options-RA3XISLN.js.map +1 -0
  920. package/dist/url-params-SN4APXCK.js +98 -0
  921. package/dist/url-params-SN4APXCK.js.map +1 -0
  922. package/dist/use-E2TA2K6J.js +95 -0
  923. package/dist/use-E2TA2K6J.js.map +1 -0
  924. package/dist/validate-W52JOEXI.js +88 -0
  925. package/dist/validate-W52JOEXI.js.map +1 -0
  926. package/dist/variant-ETHB6XUM.js +338 -0
  927. package/dist/variant-ETHB6XUM.js.map +1 -0
  928. package/dist/videos-653WAFPG.js +39 -0
  929. package/dist/videos-653WAFPG.js.map +1 -0
  930. package/dist/view-BVEZRRV2.js +121 -0
  931. package/dist/view-BVEZRRV2.js.map +1 -0
  932. package/dist/viewer-check-W4ICSBHO.js +68 -0
  933. package/dist/viewer-check-W4ICSBHO.js.map +1 -0
  934. package/dist/web-JWIGFGIU.js +140 -0
  935. package/dist/web-JWIGFGIU.js.map +1 -0
  936. package/dist/winners-MJDKCGEZ.js +113 -0
  937. package/dist/winners-MJDKCGEZ.js.map +1 -0
  938. package/dist/winning-ads-O3IMUGGO.js +84 -0
  939. package/dist/winning-ads-O3IMUGGO.js.map +1 -0
  940. package/dist/write-commands-DA6FIFAO.js +737 -0
  941. package/dist/write-commands-DA6FIFAO.js.map +1 -0
  942. package/dist/write-commands-EMN2WENA.js +1015 -0
  943. package/dist/write-commands-EMN2WENA.js.map +1 -0
  944. package/dist/write-commands-KTPISQRE.js +206 -0
  945. package/dist/write-commands-KTPISQRE.js.map +1 -0
  946. package/dist/write-commands-QBGIWU27.js +713 -0
  947. package/dist/write-commands-QBGIWU27.js.map +1 -0
  948. package/dist/x-BT3SNCTU.js +47 -0
  949. package/dist/x-BT3SNCTU.js.map +1 -0
  950. package/package.json +9 -2
  951. package/dist/chunk-CHJOTJTZ.js +0 -9989
  952. package/dist/chunk-CHJOTJTZ.js.map +0 -1
  953. package/dist/chunk-HJEMOSPH.js +0 -1292
  954. package/dist/chunk-HJEMOSPH.js.map +0 -1
  955. package/dist/chunk-MF7YA62W.js.map +0 -1
  956. package/dist/chunk-VLUGGVJL.js.map +0 -1
  957. package/dist/chunk-VZEDAFAR.js.map +0 -1
  958. package/dist/chunk-XHC4LMK4.js.map +0 -1
  959. package/dist/client-GR6YL3YX.js +0 -17
  960. package/dist/output-NMQXZF3Z.js +0 -18
  961. /package/dist/{client-GR6YL3YX.js.map → chunk-YQSBHWOI.js.map} +0 -0
  962. /package/dist/{env-4P5HOGNA.js.map → client-EURRWXPW.js.map} +0 -0
  963. /package/dist/{output-NMQXZF3Z.js.map → connect-4YXFMXYX.js.map} +0 -0
  964. /package/dist/{shared-J7DQZ2ED.js.map → customers-7E4HBSEY.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/vimeoCookie.ts","../src/lib/ytDlpSignal.ts","../src/lib/ytDlp.ts","../src/lib/ytDlpFormat.ts","../src/lib/ytDlpPlayerClient.ts"],"sourcesContent":["import { writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\n/**\n * Vimeo's session cookie, as a file yt-dlp can read.\n *\n * Vimeo is the only platform with no anonymous route left: every yt-dlp client\n * either cannot mint a token any more or refuses without a login, and the\n * failure is identical through direct, datacenter and residential exits, so it\n * is neither our IP nor our TLS fingerprint. A logged-in cookie is the whole\n * fix — measured, `vimeo` alone is sufficient and `vuid`/`auth_xsrft` without it\n * are worthless.\n *\n * The cookie arrives as a value, never as a path: the backend owns the secret\n * and the sandbox owns its filesystem, so nothing outside writes into the\n * Runtime. `--cookies <path>` then puts only the path in argv, keeping the\n * credential out of `ps` — the same rule that governs proxy passwords.\n */\n\n/** The single cookie yt-dlp's `_is_logged_in` actually checks. */\nconst COOKIE_NAME = \"vimeo\";\n\n/**\n * Write the cookie jar, returning its path — or undefined when unconfigured.\n *\n * Undefined rather than an empty file, because an empty jar is not the same as\n * no jar: yt-dlp would read it, find no session, and fail with the anonymous\n * error while looking as though credentials had been supplied.\n */\nexport async function writeVimeoCookieFile(cookie: string | undefined, workDir: string): Promise<string | undefined> {\n const value = cookie?.trim();\n if (!value) return undefined;\n\n // A year out. The jar's own expiry is a formality — Vimeo expires the session\n // server-side on its own schedule, and `isVimeoAuthFailure` is what notices.\n const expires = Math.floor(Date.now() / 1000) + 365 * 24 * 60 * 60;\n const jar = [\n \"# Netscape HTTP Cookie File\",\n [\".vimeo.com\", \"TRUE\", \"/\", \"TRUE\", String(expires), COOKIE_NAME, value].join(\"\\t\"),\n \"\",\n ].join(\"\\n\");\n\n const filePath = path.join(workDir, \"vimeo-cookies.txt\");\n // 0o600 at creation, not chmod-after: the sandbox runs the agent's own shell,\n // and a world-readable window between write and chmod is a window.\n await writeFile(filePath, jar, { mode: 0o600 });\n return filePath;\n}\n\n/**\n * Whether a Vimeo failure is about authentication rather than the video.\n *\n * Every one of these phrasings means the same thing to whoever pasted the link —\n * Vimeo would not talk to us — but Vimeo's own wording (\"Failed to fetch macos\n * OAuth token\") names an internal detail that sends the reader nowhere. The\n * distinction earns its place because this credential *expires*: without it, the\n * day the cookie lapses looks like a brand-new mystery instead of a five-minute\n * re-export.\n *\n * Scoped to `[vimeo]` so another platform's 401 cannot inherit advice about a\n * cookie that has nothing to do with it.\n */\nconst VIMEO_AUTH_SIGNATURES = [\"oauth token\", \"only works when logged-in\", \"unable to fetch new oauth tokens\"] as const;\n\nexport function isVimeoAuthFailure(detail: string): boolean {\n const haystack = detail.toLowerCase();\n if (!haystack.includes(\"[vimeo]\")) return false;\n return VIMEO_AUTH_SIGNATURES.some((signature) => haystack.includes(signature));\n}\n","import type { BlockSignal } from \"@baker/proxy\";\n\n/**\n * yt-dlp's stderr, read as the same signal every other surface produces.\n *\n * Deliberately only extraction — `shouldEscalate` still makes the decision, so\n * yt-dlp cannot drift into its own private idea of what a block is. The two\n * halves have to stay separate: a downloader that decided for itself would be\n * the one surface where a 404 could cost money.\n *\n * The parsing exists because yt-dlp gives us prose and an exit code, not a\n * response. There is no status line to read, so the status has to be recovered\n * from the sentence it was printed into.\n */\n\n/** `HTTP Error 403: Forbidden`, in any of the shapes yt-dlp writes it. */\nconst HTTP_ERROR = /HTTP Error (\\d{3})/i;\n\n/**\n * Refusals that arrive as prose with no status at all.\n *\n * YouTube's bot check is the one that matters: it is the single most common\n * reason a datacenter IP fails a download that a residential one completes, and\n * it looks like an ordinary successful page to everything except a human\n * reading the text.\n */\nconst CHALLENGE_PHRASES = [\n \"sign in to confirm you're not a bot\",\n \"sign in to confirm you’re not a bot\",\n \"confirm you are not a bot\",\n \"unusual traffic\",\n \"captcha\",\n];\n\n/**\n * Prose that must never escalate, checked *before* the phrases above.\n *\n * \"Private video. Sign in if you've been granted access\" contains a sign-in\n * demand and is not a block — no exit IP on earth opens it, and treating it as\n * one would spend the expensive rung on every private link an agent is handed.\n */\nconst NOT_A_BLOCK_PHRASES = [\"private video\", \"video unavailable\", \"members-only\", \"this video is available to\"];\n\n/**\n * Our own proxy refusing us, which yt-dlp writes without an `HTTP Error` prefix.\n *\n * Checked before everything else. A 407 cannot come from an origin server, so\n * recovering it is what lets `isProxyFailure` separate \"the platform's egress\n * credentials are wrong\" from \"this site blocked us\" — opposite remediations,\n * and the first is otherwise invisible: a rotated password reads downstream as\n * every site having simultaneously started refusing us.\n */\nconst PROXY_TUNNEL_FAILURE = /tunnel connection failed: 407|proxy authentication required|http error 407/i;\n\nexport function ytDlpBlockSignal(stderr: string): BlockSignal {\n const text = stderr.toLowerCase();\n\n if (PROXY_TUNNEL_FAILURE.test(stderr)) return { status: 407 };\n\n if (NOT_A_BLOCK_PHRASES.some((phrase) => text.includes(phrase))) return {};\n\n // First, not last. yt-dlp prints a line per retry, so the final line is\n // usually \"giving up after 3 retries\" — the verdict that started the sequence\n // is the one that says why.\n const status = HTTP_ERROR.exec(stderr);\n if (status) return { status: Number(status[1]) };\n\n if (CHALLENGE_PHRASES.some((phrase) => text.includes(phrase))) return { challenge: true };\n return {};\n}\n","import { spawn } from \"node:child_process\";\nimport { readdir, readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { ProxyCredentials, ProxyRoute, ProxyTier } from \"@baker/proxy\";\nimport { DIRECT_ROUTE, plannedRoutes, shouldEscalate } from \"@baker/proxy\";\nimport { captureProxyCredentials, childEnvWith } from \"../env.ts\";\nimport { writeVimeoCookieFile } from \"./vimeoCookie.ts\";\nimport { videoFormatArgs } from \"./ytDlpFormat.ts\";\nimport { needsPlayerClientRetry, YOUTUBE_FALLBACK_CLIENT_ARGS } from \"./ytDlpPlayerClient.ts\";\nimport { ytDlpBlockSignal } from \"./ytDlpSignal.ts\";\n\n/**\n * yt-dlp, run through the egress ladder, shared by the canvas `ingest` node and\n * `baker videos ingest`.\n *\n * Both download the same kinds of URL from the same sandbox and must agree about\n * what \"blocked\" means and how a credential is written down — and the second of\n * those is a decision that silently means two different passwords if it is made\n * twice (see `proxyEnvFor`). One copy is the point.\n *\n * Callers own how a failure is reported: the node wraps `YtDlpError` in a\n * `NodeExecutionError`, the command turns it into a `{ ok: false }` envelope.\n */\n\nexport const YT_DLP_BIN = \"yt-dlp\";\nexport const YT_DLP_TIMEOUT_MS = 10 * 60 * 1000;\n/** A probe fetches no media, so it gets a much shorter leash than a download. */\nexport const YT_DLP_PROBE_TIMEOUT_MS = 60 * 1000;\n\nexport type YtDlpInfo = Record<string, unknown>;\n\n/**\n * Verify TLS against the system bundle, never certifi's.\n *\n * The Runtime reads HTTPS through the credential broker, and the broker's CA is\n * installed in the system bundle (`SSL_CERT_FILE`) and nowhere else. yt-dlp is\n * installed with certifi and, left alone, verifies against certifi's own copy —\n * so once the broker shipped, every direct download in a Runtime failed with\n * `CERTIFICATE_VERIFY_FAILED` while `curl` to the same host answered. The agent\n * that hit it on our own CDN worked around it by pointing a committed canvas at\n * its gitignored local cache, which broke the next Session's publish. The\n * impersonating (curl_cffi) path reads `CURL_CA_BUNDLE`, which the broker also\n * sets, so it needs nothing here.\n */\nconst TRUST_SYSTEM_CERTS = [\"--compat-options\", \"no-certifi\"] as const;\n\nexport class YtDlpError extends Error {\n constructor(\n message: string,\n readonly stderrTail: string,\n ) {\n super(message);\n this.name = \"YtDlpError\";\n }\n}\n\nexport function tail(text: string, maxLines: number): string {\n return text.split(\"\\n\").slice(-maxLines).join(\"\\n\");\n}\n\n/**\n * Download `url` into `workDir`, climbing to a paid exit only if the host\n * refused the cheaper one. Returns the media file and yt-dlp's info.json\n * (best-effort — yt-dlp omits it for some direct file URLs).\n *\n * By default the best the site will release: `bv*+ba/b`. There used to be an\n * optional height cap here, on the reasoning that a 4K master is bytes we\n * re-encode anyway — but both callers now want the master, because capping\n * discards source pixels before the systems that make renditions from them ever\n * see them, and that loss is permanent while the saving is one download.\n * The one exception is opt-in: a bulk import may pass `maxHeight`.\n */\nexport async function runYtDlp(args: {\n url: string;\n audioOnly: boolean;\n workDir: string;\n timeoutMs?: number;\n onLog?: (message: string) => void;\n country?: string;\n /** Vimeo session cookie value; written to a jar in `workDir` when present. */\n vimeoCookie?: string;\n /** Opt-in resolution cap (shorter side) for bulk imports — see `videoFormatArgs`. */\n maxHeight?: number;\n}): Promise<{ filePath: string; info: YtDlpInfo; tier: EgressTier; reducedQuality: boolean }> {\n const outTemplate = path.join(args.workDir, \"out.%(ext)s\");\n const infoPath = path.join(args.workDir, \"out.info.json\");\n\n const argv: string[] = [\n args.url,\n \"--no-playlist\",\n \"--no-progress\",\n \"--no-warnings\",\n \"--quiet\",\n \"--write-info-json\",\n ...TRUST_SYSTEM_CERTS,\n \"-o\",\n outTemplate,\n ];\n\n if (args.audioOnly) {\n argv.push(\"-x\", \"--audio-format\", \"m4a\");\n } else {\n argv.push(...videoFormatArgs(args.maxHeight));\n }\n\n const cookieFile = await writeVimeoCookieFile(args.vimeoCookie, args.workDir);\n if (cookieFile) argv.push(\"--cookies\", cookieFile);\n\n args.onLog?.(`yt-dlp: downloading ${args.audioOnly ? \"audio\" : \"video\"}`);\n const timeoutMs = args.timeoutMs ?? YT_DLP_TIMEOUT_MS;\n const { code, stderr, tier, reducedQuality } = await downloadWithClientFallback({\n url: args.url,\n argv,\n onLog: args.onLog,\n ladder: (attemptArgv) =>\n runViaLadder({ url: args.url, argv: attemptArgv, timeoutMs, onLog: args.onLog, country: args.country }),\n repeat: (attemptArgv, route) => spawnAndWait(YT_DLP_BIN, attemptArgv, timeoutMs, { extraEnv: proxyEnvFor(route) }),\n });\n\n if (code !== 0) {\n throw new YtDlpError(`yt-dlp exited ${code}`, tail(stderr, 40));\n }\n\n const files = await readdir(args.workDir);\n const wanted = args.audioOnly ? \".m4a\" : \".mp4\";\n const downloaded = files.find((f) => f.startsWith(\"out.\") && f.endsWith(wanted));\n if (!downloaded) {\n throw new YtDlpError(`yt-dlp finished but produced no ${wanted} file (saw: ${files.join(\", \")})`, \"\");\n }\n\n let info: YtDlpInfo = {};\n try {\n info = JSON.parse(await readFile(infoPath, \"utf-8\")) as YtDlpInfo;\n } catch {\n // info.json is best-effort — yt-dlp sometimes omits it for direct file URLs.\n }\n\n return { filePath: path.join(args.workDir, downloaded), info, tier, reducedQuality };\n}\n\n/**\n * Read a URL's metadata without fetching any media.\n *\n * Worth its own round trip because it settles the one thing that has to be known\n * before the expensive part starts: how long the video is. Measured, a ten-hour\n * link is now refused in ~3s, where the byte ceiling it replaced could only\n * refuse it after the download it was meant to avoid. It also carries the\n * provider id, which used to be readable only from the download's own info.json.\n *\n * Climbs the same egress ladder as the download, so a host that answers only a\n * paid exit is probed through one too.\n */\nexport async function probeYtDlp(args: {\n url: string;\n timeoutMs?: number;\n onLog?: (message: string) => void;\n country?: string;\n /** Vimeo session cookie value. `cookieDir` must be set for it to be used. */\n vimeoCookie?: string;\n cookieDir?: string;\n}): Promise<{ info: YtDlpInfo; tier: EgressTier }> {\n const argv = [\n args.url,\n \"--no-playlist\",\n \"--no-warnings\",\n \"--dump-single-json\",\n \"--skip-download\",\n // Without this the probe fails wherever the *download* would fail, which\n // defeats the point of probing: yt-dlp still runs format selection for\n // `--dump-single-json`, so a binary too old to read a site's format list\n // exits \"Requested format is not available\" and we learn nothing — measured\n // against a stale build, which returned full metadata the moment this flag\n // was added. Duration and id come from the page, not from a format.\n \"--ignore-no-formats-error\",\n ...TRUST_SYSTEM_CERTS,\n ];\n\n // The probe needs the same credential as the download: Vimeo refuses metadata\n // to an anonymous caller too, so probing without it fails before the duration\n // gate ever runs.\n if (args.cookieDir) {\n const cookieFile = await writeVimeoCookieFile(args.vimeoCookie, args.cookieDir);\n if (cookieFile) argv.push(\"--cookies\", cookieFile);\n }\n\n let stdout = \"\";\n const { code, stderr, tier } = await walkYtDlpLadder({\n url: args.url,\n credentials: captureProxyCredentials(),\n attempt: async (route) => {\n const result = await spawnAndWait(YT_DLP_BIN, argv, args.timeoutMs ?? YT_DLP_PROBE_TIMEOUT_MS, {\n extraEnv: proxyEnvFor(route),\n captureStdout: true,\n });\n stdout = result.stdout ?? \"\";\n return result;\n },\n onLog: args.onLog,\n country: args.country,\n });\n\n if (code !== 0) {\n throw new YtDlpError(`yt-dlp exited ${code}`, tail(stderr, 40));\n }\n\n // Parsed, not trusted: yt-dlp prints a bare `null` for a page it recognised\n // but could not extract, and on at least one site it pairs that with a\n // non-zero exit — so the exit code alone is not enough to promise an object.\n let parsed: unknown;\n try {\n parsed = JSON.parse(stdout);\n } catch {\n throw new YtDlpError(\"yt-dlp returned metadata that could not be read\", tail(stdout, 5));\n }\n if (parsed === null || typeof parsed !== \"object\") {\n throw new YtDlpError(\"yt-dlp returned no metadata for that link\", tail(stderr, 40));\n }\n return { info: parsed as YtDlpInfo, tier };\n}\n\n/**\n * True only when the source explicitly says it carries no video.\n *\n * `vcodec: \"none\"` is the assertion; a *missing* vcodec is not, and that\n * distinction is the whole function. Measured: SoundCloud reports `\"none\"`,\n * while Streamable reports `null` and is perfectly good video. The obvious\n * version of this check — \"no format has a video codec\" — matches both and\n * would refuse Streamable, which ingests fine today.\n *\n * Caught at probe time because the alternative is what it replaces: the\n * download succeeds, produces an `.m4a`, and the caller fails looking for an\n * `.mp4` — surfaced as \"yt-dlp finished but produced no .mp4 file\", which names\n * an internal expectation rather than the fact that someone linked to audio.\n */\nexport function isAudioOnly(info: YtDlpInfo): boolean {\n return info.vcodec === \"none\";\n}\n\n/** The probed duration in seconds, when the site reported one that can be read. */\nexport function durationSeconds(info: YtDlpInfo): number | undefined {\n const raw = info.duration;\n return typeof raw === \"number\" && Number.isFinite(raw) && raw > 0 ? raw : undefined;\n}\n\n/**\n * The canonical page URL for what was probed, when the extractor resolved one.\n *\n * Worth preferring over the URL a person pasted, because yt-dlp has already done\n * the normalising: measured, it turns `youtu.be/<id>?si=…&t=42`,\n * `/shorts/<id>` and `m.youtube.com/watch?v=<id>&feature=share` all into the one\n * `www.youtube.com/watch?v=<id>`. Storing the raw paste instead files the same\n * video under a different `externalUrl` depending on where the link was copied\n * from, which is exactly the provenance question this field exists to answer.\n */\nexport function canonicalUrl(info: YtDlpInfo): string | undefined {\n const raw = info.webpage_url;\n return typeof raw === \"string\" && raw.length > 0 ? raw : undefined;\n}\n\n/**\n * Walk the ladder: direct first, then each configured tier, stopping the moment\n * the failure is one a different exit IP cannot fix.\n *\n * The escalation decision is `shouldEscalate`'s, not ours — the same closed\n * allow-list every other egress surface uses. A downloader that decided for\n * itself would be the one surface where a 404 could cost money.\n */\nexport type EgressTier = \"direct\" | ProxyTier;\n\n/**\n * Which rung produced this result — so a paid exit is never spent invisibly.\n *\n * The `route` is here, and not just the tier's name, because one caller needs to\n * *repeat* the rung rather than merely report it: the player-client fallback\n * re-runs on whichever exit already got far enough to be refused at the media\n * stage. A name cannot be handed back to `proxyEnvFor`; the route can.\n */\nexport type LadderResult = SpawnResult & { tier: EgressTier; route: ProxyRoute };\n\nexport async function walkYtDlpLadder(args: {\n url: string;\n credentials: ProxyCredentials;\n attempt: (route: ProxyRoute) => Promise<SpawnResult>;\n onLog?: (message: string) => void;\n /**\n * ISO-3166 alpha-2 exit country for the paid rungs. Omit for \"wherever\".\n *\n * Not inferred and never automatic: a country is only right when someone\n * knows *which* one opens the video, and guessing would multiply the cost of\n * every failure by the length of the guess list. `@baker/proxy` owns the\n * per-product syntax — datacenter and residential spell geo differently and\n * each rejects the other's token.\n */\n country?: string;\n}): Promise<LadderResult> {\n const routes = plannedRoutes(args.url, args.credentials, args.country ? { country: args.country } : undefined);\n let last: LadderResult = { code: -1, stderr: \"\", tier: \"direct\", route: DIRECT_ROUTE };\n\n for (const route of routes) {\n const tier: EgressTier = route.kind === \"proxy\" ? route.tier : \"direct\";\n if (route.kind === \"proxy\") args.onLog?.(`yt-dlp: retrying via ${tier}`);\n last = { ...(await args.attempt(route)), tier, route };\n if (last.code === 0) return last;\n if (!shouldEscalate(ytDlpBlockSignal(last.stderr))) return last;\n }\n return last;\n}\n\n/**\n * The download, plus the one retry that changes the player instead of the exit.\n *\n * Split out from `runYtDlp` with its two runners injected because the decision\n * this makes is the expensive one to get wrong and the hardest to observe: it\n * spends egress. A test can drive both branches here; it cannot drive them\n * through a function that spawns a binary.\n *\n * **The retry repeats one rung and opens no new one.** It re-runs on\n * `first.route` — whichever exit already got far enough to be refused at the\n * media stage — rather than walking the ladder again. Walking it again was the\n * first version of this and it was wrong in exactly the way this whole change\n * exists to stop: the trigger is a 403, `shouldEscalate` treats a 403 as\n * escalatable, so a fallback client that was also refused would climb through\n * datacenter and residential a second time, paying twice more for a verdict\n * that has already been shown not to depend on the address. Re-using the rung\n * is also what makes the retry correct when the *only* rung that reached the\n * media stage was a paid one — a direct-only retry would land back on the bot\n * wall that made us leave direct in the first place.\n */\nexport async function downloadWithClientFallback(args: {\n url: string;\n argv: readonly string[];\n ladder: (argv: readonly string[]) => Promise<LadderResult>;\n repeat: (argv: readonly string[], route: ProxyRoute) => Promise<SpawnResult>;\n onLog?: (message: string) => void;\n}): Promise<LadderResult & { reducedQuality: boolean }> {\n const first = await args.ladder(args.argv);\n if (first.code === 0 || !needsPlayerClientRetry(args.url, first.stderr)) {\n return { ...first, reducedQuality: false };\n }\n\n args.onLog?.(\"yt-dlp: retrying with the fallback player client\");\n const again = await args.repeat([...args.argv, ...YOUTUBE_FALLBACK_CLIENT_ARGS], first.route);\n\n // `tier` and `route` stay the first attempt's: the retry deliberately did not\n // move, so reporting a different rung would misstate what was spent.\n return { ...again, tier: first.tier, route: first.route, reducedQuality: again.code === 0 };\n}\n\nfunction runViaLadder(args: {\n url: string;\n argv: readonly string[];\n timeoutMs: number;\n onLog?: (message: string) => void;\n country?: string;\n}): Promise<LadderResult> {\n return walkYtDlpLadder({\n url: args.url,\n credentials: captureProxyCredentials(),\n attempt: (route) => spawnAndWait(YT_DLP_BIN, args.argv, args.timeoutMs, { extraEnv: proxyEnvFor(route) }),\n onLog: args.onLog,\n country: args.country,\n });\n}\n\n/**\n * A route as the environment a child process reads it from.\n *\n * Env, never `--proxy`: the flag would put the password in `argv`, readable by\n * any `ps` sharing the sandbox and printed by yt-dlp into the very stderr this\n * module reads back and attaches to an error. Both spellings, because \"which\n * case does this tool read\" is not worth being wrong about once — and `NO_PROXY`\n * is deliberately unset, since `plannedRoutes` has already refused to build a\n * proxy route for a private address.\n *\n * The percent-encoding is correct here and is deliberately **not** the same\n * decision as `browserProxyUrl` in `@baker/proxy`. Measured against both readers\n * with a proxy that logs what it receives: given `ab%3Dcd`, yt-dlp (Python)\n * authenticates as `ab=cd` — it decodes — while Chromium authenticates as the\n * literal `ab%3Dcd`. The same URL means two different passwords depending on who\n * reads it, so each side is written for its own reader. Do not harmonise them.\n */\nexport function proxyEnvFor(route: ProxyRoute): Record<string, string> | undefined {\n if (route.kind !== \"proxy\") return undefined;\n const uri = new URL(route.server);\n uri.username = encodeURIComponent(route.username);\n uri.password = encodeURIComponent(route.password);\n return {\n HTTP_PROXY: uri.toString(),\n HTTPS_PROXY: uri.toString(),\n http_proxy: uri.toString(),\n https_proxy: uri.toString(),\n };\n}\n\nexport type SpawnResult = { code: number; stderr: string; stdout?: string };\n\n/**\n * Spawn helper local to yt-dlp: the engine's `cli-runner` rejects URL arguments\n * by policy, which is directly at odds with yt-dlp's job.\n *\n * stdout is discarded unless asked for, because on a download it is the media\n * progress firehose; the probe is the one caller that actually wants it.\n */\nexport function spawnAndWait(\n bin: string,\n argv: readonly string[],\n timeoutMs: number,\n options: { extraEnv?: Record<string, string>; captureStdout?: boolean } = {},\n): Promise<SpawnResult> {\n return new Promise((resolve, reject) => {\n const child = spawn(bin, argv, {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n // `childEnvWith` because `spawn`'s `env` REPLACES the environment rather\n // than extending it — passing only the additions would strip PATH.\n ...(options.extraEnv ? { env: childEnvWith(options.extraEnv) } : {}),\n });\n const stderrChunks: Buffer[] = [];\n const stdoutChunks: Buffer[] = [];\n let stderrLen = 0;\n const MAX_STDERR = 256 * 1024;\n\n child.stdout.on(\"data\", (chunk: Buffer) => {\n if (options.captureStdout) stdoutChunks.push(chunk);\n });\n child.stderr.on(\"data\", (chunk: Buffer) => {\n if (stderrLen < MAX_STDERR) {\n stderrChunks.push(chunk);\n stderrLen += chunk.length;\n }\n });\n\n const timer = setTimeout(() => {\n child.kill(\"SIGKILL\");\n reject(new Error(`${bin} timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n\n child.on(\"error\", (err) => {\n clearTimeout(timer);\n reject(new Error(`failed to spawn \"${bin}\" — ${err.message}`));\n });\n\n child.on(\"close\", (code) => {\n clearTimeout(timer);\n resolve({\n code: code ?? -1,\n stderr: Buffer.concat(stderrChunks).toString(\"utf-8\"),\n ...(options.captureStdout ? { stdout: Buffer.concat(stdoutChunks).toString(\"utf-8\") } : {}),\n });\n });\n });\n}\n","/**\n * Which video yt-dlp keeps. By default the best the site releases — see\n * `runYtDlp` for why the master matters. A caller importing in bulk may cap\n * the resolution instead: a whole channel of 4K masters is five times the bytes\n * of 1080p, and those bytes are what overruns a download's time budget.\n *\n * The cap is on the shorter side (yt-dlp's `res` sort field), not the height: a\n * vertical Short's 1080p is 1080×1920, and a height cap would keep its 608×1080\n * rendition instead. A sort rather than a filter, so when nothing fits the cap\n * the closest there is still beats no video.\n */\nexport function videoFormatArgs(maxResolution?: number): string[] {\n const sort = maxResolution ? [\"-S\", `res:${maxResolution}`] : [];\n return [\"--format\", \"bv*+ba/b\", ...sort, \"--merge-output-format\", \"mp4\"];\n}\n","/**\n * The second thing to try when YouTube hands us a video and then refuses it.\n *\n * Distinct from the egress ladder, and the distinction is the whole point. The\n * ladder answers \"would a different IP help\"; this answers \"would a different\n * *client* help\" — and measured inside a Runtime, the second question is the one\n * that was failing. yt-dlp's default client selection lands on `android_vr`,\n * whose media URLs YouTube now signs and then rejects, so extraction succeeds,\n * a format is chosen, and the byte fetch comes back\n * `unable to download video data: HTTP Error 403: Forbidden`. That failure is\n * identical from every exit: direct, datacenter and residential all produced it,\n * so climbing the ladder spent both paid rungs to reproduce it.\n *\n * The `android` client resolves a progressive format whose URL is honoured from\n * the same address — verified on two unrelated videos from the Runtime's own IP\n * after the default clients had 403'd. It is a *fallback*, not the default: it\n * currently offers only 360p, so it is worth reaching for once the good formats\n * have already been refused and worth nothing before that.\n */\n\n/** yt-dlp's argv for the fallback client. Appended, never substituted. */\nexport const YOUTUBE_FALLBACK_CLIENT_ARGS = [\"--extractor-args\", \"youtube:player_client=android\"] as const;\n\n/**\n * The refusal that happens *after* a format was chosen.\n *\n * Deliberately this exact phrase rather than a bare 403: a 403 raised while\n * fetching the page is a block on us, which the egress ladder already owns and\n * can actually fix. This one is raised on the media URL yt-dlp was just given,\n * which no exit IP changes.\n */\nconst MEDIA_FETCH_REFUSED = \"unable to download video data\";\n\nconst YOUTUBE_HOSTS = [\"youtube.com\", \"youtu.be\"];\n\nfunction isYouTube(url: string): boolean {\n let host: string;\n try {\n host = new URL(url).hostname.toLowerCase();\n } catch {\n return false;\n }\n return YOUTUBE_HOSTS.some((known) => host === known || host.endsWith(`.${known}`));\n}\n\n/** True when re-running with the fallback client is worth one more attempt. */\nexport function needsPlayerClientRetry(url: string, stderr: string): boolean {\n return isYouTube(url) && stderr.toLowerCase().includes(MEDIA_FETCH_REFUSED);\n}\n"],"mappings":"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","names":["path","path"]}
@@ -0,0 +1,111 @@
1
+ import {
2
+ reportError,
3
+ splitList
4
+ } from "./chunk-OIL6PU5W.js";
5
+ import {
6
+ apiGet
7
+ } from "./chunk-CUL3VB4L.js";
8
+ import {
9
+ registerSchema,
10
+ writeJson
11
+ } from "./chunk-MYTDK3AL.js";
12
+
13
+ // src/commands/winning-ads/launches.ts
14
+ import { defineCommand } from "citty";
15
+ registerSchema({
16
+ command: "winning-ads.launches",
17
+ description: 'What the brands you follow (or the ones named) launched in the last N days and which of those ads still run, each with its stage (new, testing, killed_early\u2026), and the tests each brand decided in that window (the version kept, what differed). The "what did competitors launch last week" report. Compact by default; --full lists every launch.',
18
+ args: {
19
+ since: { type: "number", description: "Days to look back, 1-90 (default 7)", required: false, default: 7 },
20
+ advertiser: {
21
+ type: "string",
22
+ description: "Comma list of advertiser ids instead of every followed brand",
23
+ required: false
24
+ },
25
+ platform: { type: "string", description: "Only this platform: meta|linkedin|tiktok|google", required: false },
26
+ full: { type: "boolean", description: "List every launch", required: false, default: false }
27
+ }
28
+ });
29
+ var COMPACT_LAUNCHES = 10;
30
+ function compactLaunches(report, full) {
31
+ return {
32
+ since_days: report.since_days,
33
+ advertisers: report.advertisers.map((b) => ({
34
+ advertiser_id: b.advertiser_id,
35
+ label: b.label,
36
+ launched: b.launched,
37
+ still_running: b.still_running,
38
+ launches: (full ? b.launches : b.launches.slice(0, COMPACT_LAUNCHES)).map((l) => ({
39
+ ad_id: l.ad_id,
40
+ platform: l.platform,
41
+ format: l.format,
42
+ headline: l.headline,
43
+ first_seen_at: l.first_seen_at,
44
+ stage: l.stage,
45
+ idea: l.idea ?? null,
46
+ ...full ? { media_url: l.media_url } : {}
47
+ })),
48
+ tests_decided: (b.tests_decided ?? []).map((t) => ({
49
+ concept: t.concept,
50
+ versions: t.versions,
51
+ kept_ad_id: t.winner_ad_id,
52
+ decided_at: t.decided_at ?? null,
53
+ what_differed: t.what_differed
54
+ }))
55
+ }))
56
+ };
57
+ }
58
+ var IDEA_HINT = "Idea: whether each launch was a `new` idea (the first day of its concept), another version of one the brand was still `testing`, or a version built on a `winner` it had already kept. Many launches and no new idea means the brand is iterating on what works, not testing new directions: say so.";
59
+ function launchesHints(report, named) {
60
+ if (!named && report.following_count === 0) {
61
+ return ["You follow no brands yet: `baker winning-ads follow <domain>` adds one, or pass --advertiser <id>."];
62
+ }
63
+ if (report.advertisers.length === 0) {
64
+ return [`No launches in the last ${report.since_days} days. Widen the window with --since 30.`];
65
+ }
66
+ const withIdeas = report.advertisers.some((b) => b.launches.some((l) => l.idea));
67
+ return [
68
+ ...withIdeas ? [IDEA_HINT] : [],
69
+ "Stages: new \u22647 days, testing \u226421 days, proven \u226460 days, evergreen beyond, killed_early = stopped within 2 weeks (a lost test). tests_decided is what each brand learned in the window: the version it kept (kept_ad_id) and what differed. `baker winning-ads search --survived-test` finds the versions brands kept across the library."
70
+ ];
71
+ }
72
+ var launchesCommand = defineCommand({
73
+ meta: {
74
+ name: "launches",
75
+ description: "What competitors launched lately and what still runs. Start here: baker winning-ads launches --since 7 (every followed brand), or --advertiser adv_1,adv_2"
76
+ },
77
+ args: {
78
+ since: { type: "string", description: "Days to look back, 1-90 (default 7)", required: false },
79
+ advertiser: { type: "string", description: "Comma list of advertiser ids", required: false },
80
+ platform: { type: "string", description: "Only this platform: meta|linkedin|tiktok|google", required: false },
81
+ full: { type: "boolean", description: "List every launch", required: false, default: false }
82
+ },
83
+ run: async ({ args }) => {
84
+ try {
85
+ const named = splitList(args.advertiser);
86
+ const params = { since_days: String(args.since ?? 7) };
87
+ if (named.length > 0) {
88
+ params.advertiser = named.join(",");
89
+ }
90
+ if (args.platform) {
91
+ params.platform = String(args.platform);
92
+ }
93
+ const report = await apiGet("/api/ad-library/launches", params);
94
+ writeJson({
95
+ ok: true,
96
+ data: compactLaunches(report, Boolean(args.full)),
97
+ hints: launchesHints(report, named.length > 0)
98
+ });
99
+ } catch (err) {
100
+ reportError(err);
101
+ }
102
+ }
103
+ });
104
+
105
+ export {
106
+ compactLaunches,
107
+ IDEA_HINT,
108
+ launchesHints,
109
+ launchesCommand
110
+ };
111
+ //# sourceMappingURL=chunk-WFUMNDCE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/winning-ads/launches.ts"],"sourcesContent":["import type { AdvertiserLaunches } from \"@baker/api/ad-library\";\nimport { defineCommand } from \"citty\";\nimport { apiGet } from \"../../client.ts\";\nimport { writeJson } from \"../../output.ts\";\nimport { registerSchema } from \"../../schemas.ts\";\nimport { reportError, splitList } from \"./shared.ts\";\n\nregisterSchema({\n command: \"winning-ads.launches\",\n description:\n 'What the brands you follow (or the ones named) launched in the last N days and which of those ads still run, each with its stage (new, testing, killed_early…), and the tests each brand decided in that window (the version kept, what differed). The \"what did competitors launch last week\" report. Compact by default; --full lists every launch.',\n args: {\n since: { type: \"number\", description: \"Days to look back, 1-90 (default 7)\", required: false, default: 7 },\n advertiser: {\n type: \"string\",\n description: \"Comma list of advertiser ids instead of every followed brand\",\n required: false,\n },\n platform: { type: \"string\", description: \"Only this platform: meta|linkedin|tiktok|google\", required: false },\n full: { type: \"boolean\", description: \"List every launch\", required: false, default: false },\n },\n});\n\nconst COMPACT_LAUNCHES = 10;\n\ntype LaunchesResponse = AdvertiserLaunches & { following_count?: number };\n\nexport function compactLaunches(report: AdvertiserLaunches, full: boolean) {\n return {\n since_days: report.since_days,\n advertisers: report.advertisers.map((b) => ({\n advertiser_id: b.advertiser_id,\n label: b.label,\n launched: b.launched,\n still_running: b.still_running,\n launches: (full ? b.launches : b.launches.slice(0, COMPACT_LAUNCHES)).map((l) => ({\n ad_id: l.ad_id,\n platform: l.platform,\n format: l.format,\n headline: l.headline,\n first_seen_at: l.first_seen_at,\n stage: l.stage,\n idea: l.idea ?? null,\n ...(full ? { media_url: l.media_url } : {}),\n })),\n tests_decided: (b.tests_decided ?? []).map((t) => ({\n concept: t.concept,\n versions: t.versions,\n kept_ad_id: t.winner_ad_id,\n decided_at: t.decided_at ?? null,\n what_differed: t.what_differed,\n })),\n })),\n };\n}\n\n/** How to read a launch's idea; the profile says the same. */\nexport const IDEA_HINT =\n \"Idea: whether each launch was a `new` idea (the first day of its concept), another version of one the brand was still `testing`, or a version built on a `winner` it had already kept. Many launches and no new idea means the brand is iterating on what works, not testing new directions: say so.\";\n\nexport function launchesHints(report: LaunchesResponse, named: boolean): string[] {\n if (!named && report.following_count === 0) {\n return [\"You follow no brands yet: `baker winning-ads follow <domain>` adds one, or pass --advertiser <id>.\"];\n }\n if (report.advertisers.length === 0) {\n return [`No launches in the last ${report.since_days} days. Widen the window with --since 30.`];\n }\n const withIdeas = report.advertisers.some((b) => b.launches.some((l) => l.idea));\n return [\n ...(withIdeas ? [IDEA_HINT] : []),\n \"Stages: new ≤7 days, testing ≤21 days, proven ≤60 days, evergreen beyond, killed_early = stopped within 2 weeks (a lost test). tests_decided is what each brand learned in the window: the version it kept (kept_ad_id) and what differed. `baker winning-ads search --survived-test` finds the versions brands kept across the library.\",\n ];\n}\n\nexport const launchesCommand = defineCommand({\n meta: {\n name: \"launches\",\n description:\n \"What competitors launched lately and what still runs. Start here: baker winning-ads launches --since 7 (every followed brand), or --advertiser adv_1,adv_2\",\n },\n args: {\n since: { type: \"string\", description: \"Days to look back, 1-90 (default 7)\", required: false },\n advertiser: { type: \"string\", description: \"Comma list of advertiser ids\", required: false },\n platform: { type: \"string\", description: \"Only this platform: meta|linkedin|tiktok|google\", required: false },\n full: { type: \"boolean\", description: \"List every launch\", required: false, default: false },\n },\n run: async ({ args }) => {\n try {\n const named = splitList(args.advertiser as string | undefined);\n const params: Record<string, string> = { since_days: String(args.since ?? 7) };\n if (named.length > 0) {\n params.advertiser = named.join(\",\");\n }\n if (args.platform) {\n params.platform = String(args.platform);\n }\n const report = await apiGet<LaunchesResponse>(\"/api/ad-library/launches\", params);\n writeJson({\n ok: true,\n data: compactLaunches(report, Boolean(args.full)),\n hints: launchesHints(report, named.length > 0),\n });\n } catch (err) {\n reportError(err);\n }\n },\n});\n"],"mappings":"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","names":[]}
@@ -0,0 +1,166 @@
1
+ import {
2
+ HEADLINE_SET_FLOOR,
3
+ SAME_CLAIM_HELD,
4
+ TELL_QUESTIONS,
5
+ copySentences,
6
+ sameClaimQuestion,
7
+ tellQuestionsFor
8
+ } from "./chunk-4NZ47VXO.js";
9
+ import {
10
+ rememberedJev
11
+ } from "./chunk-DUPURL26.js";
12
+ import {
13
+ holdUnbilledSpend
14
+ } from "./chunk-FEG6MN4H.js";
15
+ import {
16
+ findWorkspaceRoot
17
+ } from "./chunk-TNOSX3PJ.js";
18
+ import {
19
+ CAPABILITY_SURFACE_SPECS
20
+ } from "./chunk-UI6BKYQD.js";
21
+
22
+ // src/commands/capabilities/fix.ts
23
+ function capabilityFix(surface) {
24
+ const spec = CAPABILITY_SURFACE_SPECS[surface];
25
+ return {
26
+ action: `baker capabilities ${surface}`,
27
+ explanation: `Do not guess another field name. \`baker capabilities ${surface}\` lists every ${spec.label} change with its required and optional fields and the exact values each field accepts, plus what cannot be changed here at all and why. Read it, then either re-stage correctly or tell the user this part is out of reach \u2014 and carry on with the rest of the job either way.`
28
+ };
29
+ }
30
+
31
+ // src/commands/ads/boolean-word-positional.ts
32
+ var BOOLEAN_WORD = /^(true|false)$/i;
33
+ function booleanWordPositionalError(args, entity) {
34
+ const positionals = Array.isArray(args._) ? args._ : [];
35
+ const word = positionals.find((value2) => typeof value2 === "string" && BOOLEAN_WORD.test(value2));
36
+ if (word === void 0) {
37
+ return void 0;
38
+ }
39
+ const value = word.toLowerCase();
40
+ const raised = Object.keys(args).filter((key) => key !== "_" && args[key] === true);
41
+ const named = raised.length > 0 ? raised.map((flag) => `--${flag}`).join(" or ") : "a boolean flag";
42
+ const fix = raised.length > 0 ? raised.map((flag) => `--${flag}=${value}`).join(" or ") : `--<flag>=${value}`;
43
+ const negated = raised.length === 1 && value === "false" ? ` (or --no-${raised[0]})` : "";
44
+ return `"${word}" was read as the ${entity} target, not as a value for ${named}. A boolean flag written with a space is set to TRUE and the word is dropped \u2014 attach it instead: ${fix}${negated}.`;
45
+ }
46
+
47
+ // src/commands/ads/copy-hints.ts
48
+ import path from "path";
49
+
50
+ // src/engine/copy-tells/judge.ts
51
+ var SAMPLE_MAX = 60;
52
+ var sample = (text) => text.length <= SAMPLE_MAX ? text : `${text.slice(0, SAMPLE_MAX)}\u2026`;
53
+ async function judgedCopyTells(input, ask) {
54
+ const sentences = input.texts.flatMap((t) => copySentences(t));
55
+ const pairs = (input.headlineSets ?? []).map((set) => set.map((h) => h.trim()).filter(Boolean)).filter((set) => set.length >= HEADLINE_SET_FLOOR).flatMap((set, s) => set.flatMap((a, i) => set.slice(i + 1).map((b) => ({ set: s, a, b }))));
56
+ const questions = [...sentences.flatMap(tellQuestionsFor), ...pairs.map(({ a, b }) => sameClaimQuestion(a, b))];
57
+ if (questions.length === 0) return [];
58
+ const answers = await ask(questions);
59
+ if (answers === null) return null;
60
+ const tells = [];
61
+ TELL_QUESTIONS.forEach((tell, t) => {
62
+ const hits = sentences.filter((_, s) => (answers[s * TELL_QUESTIONS.length + t] ?? 0) >= tell.threshold);
63
+ if (hits.length > 0) tells.push({ id: tell.id, count: hits.length, sample: sample(hits[0]?.text ?? "") });
64
+ });
65
+ const offset = sentences.length * TELL_QUESTIONS.length;
66
+ const cycled = pairs.filter((_, p) => (answers[offset + p] ?? 0) >= SAME_CLAIM_HELD);
67
+ for (const set of new Set(cycled.map((p) => p.set))) {
68
+ const inSet = cycled.filter((p) => p.set === set);
69
+ const { a, b } = inSet[0] ?? { a: "", b: "" };
70
+ tells.push({ id: "synonym-cycling", count: inSet.length, sample: sample(`"${a}" / "${b}"`) });
71
+ }
72
+ return tells;
73
+ }
74
+
75
+ // src/commands/ads/copy-hints.ts
76
+ var COPY_KEYS = /* @__PURE__ */ new Set([
77
+ "headline",
78
+ "headlines",
79
+ "longheadline",
80
+ "longheadlines",
81
+ "shortheadline",
82
+ "shortheadlines",
83
+ "description",
84
+ "descriptions",
85
+ "primarytext",
86
+ "primarytexts",
87
+ "message",
88
+ "messages",
89
+ "commentary",
90
+ "body",
91
+ "bodies",
92
+ "text",
93
+ "calltoaction",
94
+ "linkdescription",
95
+ "sitelinktext",
96
+ "callout",
97
+ "callouts",
98
+ "introtext"
99
+ ]);
100
+ var HEADLINE_SET_KEYS = /* @__PURE__ */ new Set(["headlines", "longheadlines", "shortheadlines"]);
101
+ var MAX_HINTS = 5;
102
+ var SYNONYM_PAIR_FLOOR = 2;
103
+ function asStrings(value) {
104
+ const one = (v) => {
105
+ const text = typeof v === "string" ? v : v !== null && typeof v === "object" ? v.text : "";
106
+ return typeof text === "string" && text.trim() ? text : void 0;
107
+ };
108
+ const values = Array.isArray(value) ? value : [value];
109
+ return values.map(one).filter((v) => v !== void 0);
110
+ }
111
+ function collectCopy(value, depth = 0) {
112
+ const texts = [];
113
+ const headlineSets = [];
114
+ if (depth > 4 || value === null || typeof value !== "object") return { texts, headlineSets };
115
+ if (Array.isArray(value)) {
116
+ for (const item of value) {
117
+ const nested = collectCopy(item, depth + 1);
118
+ texts.push(...nested.texts);
119
+ headlineSets.push(...nested.headlineSets);
120
+ }
121
+ return { texts, headlineSets };
122
+ }
123
+ for (const [key, raw] of Object.entries(value)) {
124
+ const normalized = key.toLowerCase().replace(/[_-]/g, "");
125
+ const strings = COPY_KEYS.has(normalized) ? asStrings(raw) : [];
126
+ if (strings.length > 0) {
127
+ texts.push(...strings);
128
+ if (HEADLINE_SET_KEYS.has(normalized) && strings.length > 1) headlineSets.push(strings);
129
+ continue;
130
+ }
131
+ const nested = collectCopy(raw, depth + 1);
132
+ texts.push(...nested.texts);
133
+ headlineSets.push(...nested.headlineSets);
134
+ }
135
+ return { texts, headlineSets };
136
+ }
137
+ function hintFor(tell) {
138
+ if (tell.id === "synonym-cycling") {
139
+ return `AI COPY TELL \u2014 ${tell.count} headline pairs are the same claim reworded (${tell.sample}). A cycled set gives the auction nothing to choose between: make each headline a different claim, not a different verb.`;
140
+ }
141
+ return `AI COPY TELL (${tell.id}) \u2014 "${tell.sample}". This construction reads as machine-written; rewrite it as a plain, specific claim before publishing.`;
142
+ }
143
+ async function adCopyHints(payload, ask) {
144
+ const { texts, headlineSets } = collectCopy(payload);
145
+ if (texts.length === 0) return [];
146
+ const cacheDir = path.join(findWorkspaceRoot(process.cwd()) ?? process.cwd(), "canvas", ".cache");
147
+ const spent = [];
148
+ const judged = await judgedCopyTells(
149
+ { texts: texts.flatMap((t) => t.split("\n")), headlineSets },
150
+ ask ?? rememberedJev(path.join(cacheDir, "copy-tells.json"), (u) => spent.push(u))
151
+ ).catch(() => null);
152
+ await holdUnbilledSpend(cacheDir, spent).catch(() => void 0);
153
+ const cycled = (judged ?? []).filter((t) => t.id === "synonym-cycling" && t.count >= SYNONYM_PAIR_FLOOR).sort((a, b) => b.count - a.count).slice(0, 1);
154
+ const tells = [...cycled, ...(judged ?? []).filter((t) => t.id !== "synonym-cycling")];
155
+ tells.sort(
156
+ (a, b) => (b.id === "synonym-cycling" ? 1 : 0) - (a.id === "synonym-cycling" ? 1 : 0) || b.count - a.count
157
+ );
158
+ return tells.slice(0, MAX_HINTS).map(hintFor);
159
+ }
160
+
161
+ export {
162
+ capabilityFix,
163
+ booleanWordPositionalError,
164
+ adCopyHints
165
+ };
166
+ //# sourceMappingURL=chunk-WHWNXLTD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/capabilities/fix.ts","../src/commands/ads/boolean-word-positional.ts","../src/commands/ads/copy-hints.ts","../src/engine/copy-tells/judge.ts"],"sourcesContent":["import type { CapabilitySurfaceId } from \"@baker/api/capabilities\";\nimport { CAPABILITY_SURFACE_SPECS } from \"@baker/api/capabilities\";\n\n/**\n * A rejected change should say where the real contract is.\n *\n * The expensive version of \"this field is not valid\" is an agent trying four\n * spellings of a field that never existed, staging a bogus op, and cleaning it\n * up again — several turns, none of them work. The validation message already\n * names what was wrong with THIS attempt; this names the one call that lists\n * every field the change accepts and every value each one takes, so the next\n * attempt is informed rather than another guess.\n */\nexport function capabilityFix(surface: CapabilitySurfaceId): { action: string; explanation: string } {\n const spec = CAPABILITY_SURFACE_SPECS[surface];\n return {\n action: `baker capabilities ${surface}`,\n explanation:\n `Do not guess another field name. \\`baker capabilities ${surface}\\` lists every ${spec.label} change with its ` +\n \"required and optional fields and the exact values each field accepts, plus what cannot be changed here at all \" +\n \"and why. Read it, then either re-stage correctly or tell the user this part is out of reach — and carry on \" +\n \"with the rest of the job either way.\",\n };\n}\n","/**\n * `--flag false` — the natural way to type a negation — is a citty trap, not a typo we can honour:\n * a boolean flag written with a space parses as the flag set to **TRUE** plus a stray positional\n * nobody consumes. The word does the OPPOSITE of what was typed and nothing fails, because the\n * target still resolves and the command still reports \"staged\". No layer downstream can catch it —\n * an inverted boolean is a valid op — so it has to be caught where the positionals are read.\n *\n * This is the same rule on every ad surface (it is citty's parse, not a platform's), but each\n * surface owns its own error envelope, so this returns the message and the caller fails with it.\n */\n\nconst BOOLEAN_WORD = /^(true|false)$/i;\n\n/**\n * The refusal message for a bare `true`/`false` sitting in the positionals, or `undefined` when\n * there is none. `entity` is the surface's own noun for what the positional addresses (\"campaign\",\n * \"ad set\", …), so the message reads as that command's vocabulary.\n */\nexport function booleanWordPositionalError(args: Record<string, unknown>, entity: string): string | undefined {\n const positionals = Array.isArray(args._) ? args._ : [];\n const word = positionals.find((value): value is string => typeof value === \"string\" && BOOLEAN_WORD.test(value));\n if (word === undefined) {\n return undefined;\n }\n const value = word.toLowerCase();\n // Every flag citty just set to true, so the fix is copy-pasteable. Which one the word was meant for\n // is unknowable from parsed args — it need not even follow that flag on the command line — so with\n // several raised we list them all rather than inventing a single culprit the user never typed.\n const raised = Object.keys(args).filter((key) => key !== \"_\" && args[key] === true);\n const named = raised.length > 0 ? raised.map((flag) => `--${flag}`).join(\" or \") : \"a boolean flag\";\n const fix = raised.length > 0 ? raised.map((flag) => `--${flag}=${value}`).join(\" or \") : `--<flag>=${value}`;\n const negated = raised.length === 1 && value === \"false\" ? ` (or --no-${raised[0]})` : \"\";\n return `\"${word}\" was read as the ${entity} target, not as a value for ${named}. A boolean flag written with a space is set to TRUE and the word is dropped — attach it instead: ${fix}${negated}.`;\n}\n","/**\n * AI copy tells on staged ad copy → `hints[]`.\n *\n * Ad text is the surface where a tell costs real money and the one place we had\n * no copy check at all: staging validated character limits and policy, never\n * whether the words read like a model wrote them.\n *\n * ADVISORY BY CONSTRUCTION. These are hints, never errors — an ad refused over a\n * fallible prose heuristic costs more than a tell that ships, and the agent can\n * act on a hint in the same turn. Nothing here can fail a staged write.\n *\n * Thresholds differ from the landing gate on purpose. A landing needs a CLUSTER\n * before a tell means anything (`COPY_TELL_GATES`); a 30-character headline has\n * no room for a cluster, so one occurrence is the signal. The exclusion list\n * below is where most of the judgment lives.\n *\n * The tells that read the words are asked of the decision model, in whatever\n * language the ad is written; when it cannot answer, nothing is reported rather\n * than a guess.\n */\n\nimport path from \"node:path\";\nimport type { CopyTell } from \"../../engine/copy-tells/detect.ts\";\nimport { judgedCopyTells } from \"../../engine/copy-tells/judge.ts\";\nimport { type AskNouls, rememberedJev } from \"../../engine/lib/remembered-nouls.ts\";\nimport type { ReviewUsage } from \"../../engine/nodes/local/lib/render-review.ts\";\nimport { findWorkspaceRoot } from \"../canvas/normalize-paths.ts\";\nimport { holdUnbilledSpend } from \"../canvas/unbilled-spend.ts\";\n\n/*\n * The tells that are a shape (`structuralCopyTells`) do not apply to ad copy, and\n * none is hinted. Each is a real convention in this medium, so reporting it would\n * train the agent to ignore hints:\n * - `title-case-heading` — English search ads are conventionally Title Case.\n * - `staccato-drama` — \"Compara. Ahorra. Cambia.\" is ad rhythm, not drama.\n * - `emoji` — deliberate and effective in Meta and LinkedIn primary text.\n * - `curly-quote` — inserted automatically by every editor copy is pasted from.\n * - `inline-header-list` — a markdown shape that ad fields cannot hold.\n */\n\n/**\n * Payload keys whose values are copy a human will read in the ad. Every platform\n * names its primary text differently in `@baker/api` — Meta stages it as\n * `message`, LinkedIn as `commentary` — so the concept appears here under each\n * of its contract names, not under one invented one.\n */\nconst COPY_KEYS = new Set([\n \"headline\",\n \"headlines\",\n \"longheadline\",\n \"longheadlines\",\n \"shortheadline\",\n \"shortheadlines\",\n \"description\",\n \"descriptions\",\n \"primarytext\",\n \"primarytexts\",\n \"message\",\n \"messages\",\n \"commentary\",\n \"body\",\n \"bodies\",\n \"text\",\n \"calltoaction\",\n \"linkdescription\",\n \"sitelinktext\",\n \"callout\",\n \"callouts\",\n \"introtext\",\n]);\n\n/** Keys holding a SET of headlines, where synonym cycling is meaningful. */\nconst HEADLINE_SET_KEYS = new Set([\"headlines\", \"longheadlines\", \"shortheadlines\"]);\n\n/**\n * At most this many hints, so copy advice never crowds out the staging result.\n *\n * Five, not three: a heavily model-written ad routinely carries six tells, and a\n * cap of three showed the agent half the diagnosis. Since it already has the copy\n * in front of it, fixing six constructions in one pass is cheaper than three\n * re-stagings that each reveal the next batch.\n */\nconst MAX_HINTS = 5;\n/** Two near-duplicate pairs; one pair in a 15-headline RSA is not a pattern. */\nconst SYNONYM_PAIR_FLOOR = 2;\n\n/**\n * The copy under a copy key, whether it is a plain string or a Google text\n * asset. Google stages EVERY ad text as `{ text, pinnedField? }`\n * (`adTextAssetSchema` in `@baker/api/ads-google`), so reading only strings here\n * would skip the whole Google surface — headlines, descriptions, long headline.\n */\nfunction asStrings(value: unknown): string[] {\n const one = (v: unknown): string | undefined => {\n const text = typeof v === \"string\" ? v : v !== null && typeof v === \"object\" ? (v as { text?: unknown }).text : \"\";\n return typeof text === \"string\" && text.trim() ? text : undefined;\n };\n const values = Array.isArray(value) ? value : [value];\n return values.map(one).filter((v): v is string => v !== undefined);\n}\n\n/** Walk a staged-op payload of unknown shape and pull out the human-readable\n * copy fields plus any headline sets. Depth-limited — payloads are shallow, and\n * an unbounded walk on a hostile shape is a hang, not a hint. */\nfunction collectCopy(value: unknown, depth = 0): { texts: string[]; headlineSets: string[][] } {\n const texts: string[] = [];\n const headlineSets: string[][] = [];\n if (depth > 4 || value === null || typeof value !== \"object\") return { texts, headlineSets };\n\n if (Array.isArray(value)) {\n for (const item of value) {\n const nested = collectCopy(item, depth + 1);\n texts.push(...nested.texts);\n headlineSets.push(...nested.headlineSets);\n }\n return { texts, headlineSets };\n }\n\n for (const [key, raw] of Object.entries(value as Record<string, unknown>)) {\n const normalized = key.toLowerCase().replace(/[_-]/g, \"\");\n const strings = COPY_KEYS.has(normalized) ? asStrings(raw) : [];\n if (strings.length > 0) {\n texts.push(...strings);\n if (HEADLINE_SET_KEYS.has(normalized) && strings.length > 1) headlineSets.push(strings);\n continue;\n }\n // A copy key holding neither a string nor a text asset (`call_to_action`)\n // still gets walked — a matched key must never swallow the subtree.\n const nested = collectCopy(raw, depth + 1);\n texts.push(...nested.texts);\n headlineSets.push(...nested.headlineSets);\n }\n return { texts, headlineSets };\n}\n\nfunction hintFor(tell: CopyTell): string {\n if (tell.id === \"synonym-cycling\") {\n return `AI COPY TELL — ${tell.count} headline pairs are the same claim reworded (${tell.sample}). A cycled set gives the auction nothing to choose between: make each headline a different claim, not a different verb.`;\n }\n return `AI COPY TELL (${tell.id}) — \"${tell.sample}\". This construction reads as machine-written; rewrite it as a plain, specific claim before publishing.`;\n}\n\n/**\n * Inspect a staged ad-copy payload and return advisory hints about AI writing\n * tells. Never throws; returns `[]` when the copy reads clean or the payload\n * carries no copy at all. `ask` is the decision model (the real one, its answers\n * kept in the workspace's canvas cache and its spend billed with the next run,\n * unless given).\n */\nexport async function adCopyHints(payload: unknown, ask?: AskNouls): Promise<string[]> {\n const { texts, headlineSets } = collectCopy(payload);\n if (texts.length === 0) return [];\n\n const cacheDir = path.join(findWorkspaceRoot(process.cwd()) ?? process.cwd(), \"canvas\", \".cache\");\n const spent: ReviewUsage[] = [];\n // A line break in ad text is the author's, never a wrap: each line is read on its own.\n const judged = await judgedCopyTells(\n { texts: texts.flatMap((t) => t.split(\"\\n\")), headlineSets },\n ask ?? rememberedJev(path.join(cacheDir, \"copy-tells.json\"), (u) => spent.push(u)),\n ).catch(() => null);\n await holdUnbilledSpend(cacheDir, spent).catch(() => undefined);\n\n // The floor is per headline set (one per ad); only the most cycled set is hinted.\n const cycled = (judged ?? [])\n .filter((t) => t.id === \"synonym-cycling\" && t.count >= SYNONYM_PAIR_FLOOR)\n .sort((a, b) => b.count - a.count)\n .slice(0, 1);\n const tells: CopyTell[] = [...cycled, ...(judged ?? []).filter((t) => t.id !== \"synonym-cycling\")];\n\n // Loudest first: the cycled-headline finding is a set-level defect, and the\n // rest sort by how often the tell fired.\n tells.sort(\n (a, b) => (b.id === \"synonym-cycling\" ? 1 : 0) - (a.id === \"synonym-cycling\" ? 1 : 0) || b.count - a.count,\n );\n return tells.slice(0, MAX_HINTS).map(hintFor);\n}\n","/**\n * The AI copy tells in a piece of copy that are a reading of its words, and synonym cycling in a\n * set of headlines, asked of the decision model (Jev) in one fanned-out set of requests, in\n * whatever language the copy is written. Raw counts, like `structuralCopyTells`: the caller gates.\n */\nimport type { AskNouls } from \"../lib/remembered-nouls.ts\";\nimport type { CopyTell } from \"./detect.ts\";\nimport { HEADLINE_SET_FLOOR } from \"./patterns.ts\";\nimport { SAME_CLAIM_HELD, sameClaimQuestion, TELL_QUESTIONS, tellQuestionsFor } from \"./questions.ts\";\nimport { copySentences } from \"./sentences.ts\";\n\nconst SAMPLE_MAX = 60;\nconst sample = (text: string) => (text.length <= SAMPLE_MAX ? text : `${text.slice(0, SAMPLE_MAX)}…`);\n\n/**\n * Every judged tell in `texts` (one count per sentence that carries it) and, for each headline set\n * of at least `HEADLINE_SET_FLOOR`, one `synonym-cycling` tell counting that set's pairs that are\n * one claim reworded. Null when the model could not answer: the caller reports nothing rather than\n * guess.\n */\nexport async function judgedCopyTells(\n input: { texts: readonly string[]; headlineSets?: ReadonlyArray<readonly string[]> },\n ask: AskNouls,\n): Promise<CopyTell[] | null> {\n const sentences = input.texts.flatMap((t) => copySentences(t));\n const pairs = (input.headlineSets ?? [])\n .map((set) => set.map((h) => h.trim()).filter(Boolean))\n .filter((set) => set.length >= HEADLINE_SET_FLOOR)\n .flatMap((set, s) => set.flatMap((a, i) => set.slice(i + 1).map((b) => ({ set: s, a, b }))));\n const questions = [...sentences.flatMap(tellQuestionsFor), ...pairs.map(({ a, b }) => sameClaimQuestion(a, b))];\n if (questions.length === 0) return [];\n const answers = await ask(questions);\n if (answers === null) return null;\n\n const tells: CopyTell[] = [];\n TELL_QUESTIONS.forEach((tell, t) => {\n const hits = sentences.filter((_, s) => (answers[s * TELL_QUESTIONS.length + t] ?? 0) >= tell.threshold);\n if (hits.length > 0) tells.push({ id: tell.id, count: hits.length, sample: sample(hits[0]?.text ?? \"\") });\n });\n const offset = sentences.length * TELL_QUESTIONS.length;\n const cycled = pairs.filter((_, p) => (answers[offset + p] ?? 0) >= SAME_CLAIM_HELD);\n for (const set of new Set(cycled.map((p) => p.set))) {\n const inSet = cycled.filter((p) => p.set === set);\n const { a, b } = inSet[0] ?? { a: \"\", b: \"\" };\n tells.push({ id: \"synonym-cycling\", count: inSet.length, sample: sample(`\"${a}\" / \"${b}\"`) });\n }\n return tells;\n}\n"],"mappings":"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","names":["value"]}
@@ -0,0 +1,25 @@
1
+ // src/commands/avatars/wait.ts
2
+ var WAIT_TIMEOUT_MS = 9e4;
3
+ var WAIT_INTERVAL_MS = 3e3;
4
+ function shouldKeepWaiting(avatar, elapsedMs) {
5
+ if (avatar.status === "ready") return { done: true, reason: "ready" };
6
+ if (avatar.status === "error" || avatar.status === "archived") return { done: true, reason: "settled" };
7
+ if (avatar.needsFace) return { done: true, reason: "needs-face" };
8
+ if (elapsedMs >= WAIT_TIMEOUT_MS) return { done: false, reason: "expired" };
9
+ return { done: false, reason: "building" };
10
+ }
11
+ async function waitForSheet(first, read, sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms))) {
12
+ const startedAt = Date.now();
13
+ let latest = first;
14
+ while (!shouldKeepWaiting(latest, Date.now() - startedAt).done) {
15
+ if (shouldKeepWaiting(latest, Date.now() - startedAt).reason === "expired") return latest;
16
+ await sleep(WAIT_INTERVAL_MS);
17
+ latest = await read();
18
+ }
19
+ return latest;
20
+ }
21
+
22
+ export {
23
+ waitForSheet
24
+ };
25
+ //# sourceMappingURL=chunk-WN4KX7GE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/avatars/wait.ts"],"sourcesContent":["import type { AvatarStatus } from \"@baker/api\";\n\n/**\n * Waiting for an avatar's identity sheet, inside the command rather than in the agent.\n *\n * The sheet is a ~30s render, and the agent is told never to sleep on it — right, because\n * a turn spent standing still is a turn the user watches do nothing. But when the only\n * work left DEPENDS on that avatar, \"do the next piece of work\" names work that does not\n * exist, and the observed turn simply ended: the user had to come back and say \"ya está\n * lista\" for the clip to be made.\n *\n * A command that blocks internally is the sanctioned shape for this — it has its own\n * deadline and returns the moment the thing is ready, which a polling loop written by the\n * agent does neither of.\n */\n\n/** How long to keep asking before giving up. Twice the sheet's usual render. */\nexport const WAIT_TIMEOUT_MS = 90_000;\n/** Gap between reads. Short enough to return promptly, long enough not to hammer. */\nexport const WAIT_INTERVAL_MS = 3_000;\n\nexport type WaitDecision =\n | { done: true; reason: \"ready\" | \"settled\" | \"needs-face\" }\n | { done: false; reason: \"building\" | \"expired\" };\n\n/** Just enough of an avatar to know whether waiting on it can ever end. */\nexport interface WaitSubject {\n status: AvatarStatus;\n /**\n * The build is parked on a face the user has not picked yet.\n *\n * `generating` normally means a render is running. This is the one case where it\n * does not: the casting portraits are in front of the user and nothing starts until\n * they answer.\n */\n needsFace?: boolean;\n}\n\n/**\n * Whether to stop waiting on this avatar, given how long we have waited.\n *\n * `error` and `archived` stop it too: both are settled states, and waiting out the\n * deadline for one of them would burn 90 seconds to learn what the first read said.\n *\n * So does an avatar waiting on its face. Nothing is rendering, so the only thing that\n * can happen here is the deadline expiring — and it is the user's own turn to act, not\n * the agent's. Observed: an agent blocked the full 90 seconds twice, concluded the\n * avatar was broken, and deleted the one the user was at that moment picking a face for.\n */\nexport function shouldKeepWaiting(avatar: WaitSubject, elapsedMs: number): WaitDecision {\n if (avatar.status === \"ready\") return { done: true, reason: \"ready\" };\n if (avatar.status === \"error\" || avatar.status === \"archived\") return { done: true, reason: \"settled\" };\n if (avatar.needsFace) return { done: true, reason: \"needs-face\" };\n if (elapsedMs >= WAIT_TIMEOUT_MS) return { done: false, reason: \"expired\" };\n return { done: false, reason: \"building\" };\n}\n\n/**\n * Re-reads the avatar until its sheet settles, or the deadline passes.\n *\n * Returns whatever the last read said either way — an expired wait is not a failure, it\n * is a slow render, and the caller's own hints already say what a still-building avatar\n * can and cannot be used for.\n */\nexport async function waitForSheet<T extends WaitSubject>(\n first: T,\n read: () => Promise<T>,\n sleep: (ms: number) => Promise<void> = (ms) => new Promise((resolve) => setTimeout(resolve, ms)),\n): Promise<T> {\n const startedAt = Date.now();\n let latest = first;\n while (!shouldKeepWaiting(latest, Date.now() - startedAt).done) {\n if (shouldKeepWaiting(latest, Date.now() - startedAt).reason === \"expired\") return latest;\n await sleep(WAIT_INTERVAL_MS);\n latest = await read();\n }\n return latest;\n}\n"],"mappings":";AAiBO,IAAM,kBAAkB;AAExB,IAAM,mBAAmB;AA8BzB,SAAS,kBAAkB,QAAqB,WAAiC;AACtF,MAAI,OAAO,WAAW,QAAS,QAAO,EAAE,MAAM,MAAM,QAAQ,QAAQ;AACpE,MAAI,OAAO,WAAW,WAAW,OAAO,WAAW,WAAY,QAAO,EAAE,MAAM,MAAM,QAAQ,UAAU;AACtG,MAAI,OAAO,UAAW,QAAO,EAAE,MAAM,MAAM,QAAQ,aAAa;AAChE,MAAI,aAAa,gBAAiB,QAAO,EAAE,MAAM,OAAO,QAAQ,UAAU;AAC1E,SAAO,EAAE,MAAM,OAAO,QAAQ,WAAW;AAC3C;AASA,eAAsB,aACpB,OACA,MACA,QAAuC,CAAC,OAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC,GACnF;AACZ,QAAM,YAAY,KAAK,IAAI;AAC3B,MAAI,SAAS;AACb,SAAO,CAAC,kBAAkB,QAAQ,KAAK,IAAI,IAAI,SAAS,EAAE,MAAM;AAC9D,QAAI,kBAAkB,QAAQ,KAAK,IAAI,IAAI,SAAS,EAAE,WAAW,UAAW,QAAO;AACnF,UAAM,MAAM,gBAAgB;AAC5B,aAAS,MAAM,KAAK;AAAA,EACtB;AACA,SAAO;AACT;","names":[]}
@@ -0,0 +1,84 @@
1
+ import {
2
+ ApiError,
3
+ apiGet,
4
+ apiPost
5
+ } from "./chunk-CUL3VB4L.js";
6
+
7
+ // src/commands/videos/api.ts
8
+ import { readFile } from "fs/promises";
9
+ import { basename, extname } from "path";
10
+ var videoProcessingTimeoutMs = 18e4;
11
+ var videoReadyPollIntervalMs = 3e3;
12
+ var mimeMap = {
13
+ ".mp4": "video/mp4",
14
+ ".mov": "video/quicktime",
15
+ ".webm": "video/webm",
16
+ ".avi": "video/x-msvideo",
17
+ ".mkv": "video/x-matroska"
18
+ };
19
+ var defaultVideoApiDeps = {
20
+ readFile,
21
+ post: apiPost,
22
+ get: apiGet,
23
+ sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
24
+ putFile: async (url, contentType, body) => {
25
+ const response = await fetch(url, { method: "PUT", headers: { "Content-Type": contentType }, body });
26
+ if (!response.ok) {
27
+ throw new ApiError("INTERNAL_ERROR", `Mux upload failed: HTTP ${response.status} ${response.statusText}`);
28
+ }
29
+ }
30
+ };
31
+ function isVideoFile(filePath) {
32
+ return mimeMap[extname(filePath).toLowerCase()] !== void 0;
33
+ }
34
+ function detectVideoContentType(filePath, opts = {}) {
35
+ const ext = extname(filePath).toLowerCase();
36
+ const contentType = mimeMap[ext];
37
+ if (!contentType || opts.allowedContentTypes && !opts.allowedContentTypes.includes(contentType)) {
38
+ throw new ApiError(
39
+ "VALIDATION_ERROR",
40
+ opts.unsupportedMessage ?? `Cannot detect content type for extension "${ext}". Use --content-type.`
41
+ );
42
+ }
43
+ return contentType;
44
+ }
45
+ async function uploadLocalVideo(args, deps = defaultVideoApiDeps) {
46
+ const { uploadUrl, videoId } = await deps.post("/api/videos/upload", {
47
+ originalFilename: basename(args.file),
48
+ descriptionContext: args.descriptionContext
49
+ });
50
+ await deps.putFile(uploadUrl, args.contentType, await deps.readFile(args.file));
51
+ return { videoId };
52
+ }
53
+ var PLAYABLE_STATUSES = /* @__PURE__ */ new Set(["uploaded", "processing", "ready"]);
54
+ async function waitForPlayableVideo(deps, videoId, opts = {}) {
55
+ const timeoutMs = opts.timeoutMs ?? videoProcessingTimeoutMs;
56
+ const pollIntervalMs = opts.pollIntervalMs ?? videoReadyPollIntervalMs;
57
+ const deadline = Date.now() + timeoutMs;
58
+ let lastStatus = "unknown";
59
+ while (Date.now() <= deadline) {
60
+ const video = await deps.get("/api/videos/get", { id: videoId });
61
+ lastStatus = video.status;
62
+ if (video.muxPlaybackId && PLAYABLE_STATUSES.has(video.status)) {
63
+ return video;
64
+ }
65
+ if (video.status === "error") {
66
+ throw new ApiError(
67
+ "INTERNAL_ERROR",
68
+ "The video library could not process this file. Export it again as an MP4 (H.264) and retry."
69
+ );
70
+ }
71
+ await deps.sleep(pollIntervalMs);
72
+ }
73
+ throw new ApiError("TIMEOUT", `Video was not playable before timeout; last status: ${lastStatus}`);
74
+ }
75
+
76
+ export {
77
+ videoProcessingTimeoutMs,
78
+ defaultVideoApiDeps,
79
+ isVideoFile,
80
+ detectVideoContentType,
81
+ uploadLocalVideo,
82
+ waitForPlayableVideo
83
+ };
84
+ //# sourceMappingURL=chunk-XIY7P54H.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/videos/api.ts"],"sourcesContent":["import type { Buffer } from \"node:buffer\";\nimport { readFile } from \"node:fs/promises\";\nimport { basename, extname } from \"node:path\";\nimport type { VideosGetResponse, VideosUploadResponse } from \"@baker/api\";\nimport { ApiError, apiGet, apiPost } from \"../../client.ts\";\n\n/** Mux usually has a short render playable within a minute; this bounds the wait. */\nexport const videoProcessingTimeoutMs = 180_000;\nconst videoReadyPollIntervalMs = 3_000;\n\nconst mimeMap: Record<string, string> = {\n \".mp4\": \"video/mp4\",\n \".mov\": \"video/quicktime\",\n \".webm\": \"video/webm\",\n \".avi\": \"video/x-msvideo\",\n \".mkv\": \"video/x-matroska\",\n};\n\nexport type VideoApiDeps = {\n readFile: (path: string) => Promise<Buffer<ArrayBuffer>>;\n post: typeof apiPost;\n get: typeof apiGet;\n sleep: (ms: number) => Promise<void>;\n /** PUT the bytes to the Mux direct-upload URL. */\n putFile: (url: string, contentType: string, body: Buffer<ArrayBuffer>) => Promise<void>;\n};\n\nexport const defaultVideoApiDeps: VideoApiDeps = {\n readFile,\n post: apiPost,\n get: apiGet,\n sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),\n putFile: async (url, contentType, body) => {\n const response = await fetch(url, { method: \"PUT\", headers: { \"Content-Type\": contentType }, body });\n if (!response.ok) {\n throw new ApiError(\"INTERNAL_ERROR\", `Mux upload failed: HTTP ${response.status} ${response.statusText}`);\n }\n },\n};\n\nexport function isVideoFile(filePath: string): boolean {\n return mimeMap[extname(filePath).toLowerCase()] !== undefined;\n}\n\nexport function detectVideoContentType(\n filePath: string,\n opts: { allowedContentTypes?: readonly string[]; unsupportedMessage?: string } = {},\n): string {\n const ext = extname(filePath).toLowerCase();\n const contentType = mimeMap[ext];\n if (!contentType || (opts.allowedContentTypes && !opts.allowedContentTypes.includes(contentType))) {\n throw new ApiError(\n \"VALIDATION_ERROR\",\n opts.unsupportedMessage ?? `Cannot detect content type for extension \"${ext}\". Use --content-type.`,\n );\n }\n return contentType;\n}\n\n/**\n * Add a local video file to the company's video library: a Mux direct-upload\n * URL from Baker, then the bytes straight to Mux. The filename travels along,\n * since the bytes never pass through Baker and it is often the only statement\n * of intent there is.\n */\nexport async function uploadLocalVideo(\n args: { file: string; contentType: string; descriptionContext?: string },\n deps: VideoApiDeps = defaultVideoApiDeps,\n): Promise<{ videoId: string }> {\n const { uploadUrl, videoId } = await deps.post<VideosUploadResponse>(\"/api/videos/upload\", {\n originalFilename: basename(args.file),\n descriptionContext: args.descriptionContext,\n });\n await deps.putFile(uploadUrl, args.contentType, await deps.readFile(args.file));\n return { videoId };\n}\n\nconst PLAYABLE_STATUSES: ReadonlySet<string> = new Set([\"uploaded\", \"processing\", \"ready\"]);\n\n/**\n * Wait until Baker can play the video: Mux has produced its playback id. Its\n * description (transcript, analysis) keeps running afterwards, and nothing\n * that saves or ships the video needs to wait for that.\n */\nexport async function waitForPlayableVideo(\n deps: VideoApiDeps,\n videoId: string,\n opts: { timeoutMs?: number; pollIntervalMs?: number } = {},\n): Promise<VideosGetResponse> {\n const timeoutMs = opts.timeoutMs ?? videoProcessingTimeoutMs;\n const pollIntervalMs = opts.pollIntervalMs ?? videoReadyPollIntervalMs;\n const deadline = Date.now() + timeoutMs;\n let lastStatus = \"unknown\";\n while (Date.now() <= deadline) {\n const video = await deps.get<VideosGetResponse>(\"/api/videos/get\", { id: videoId });\n lastStatus = video.status;\n if (video.muxPlaybackId && PLAYABLE_STATUSES.has(video.status)) {\n return video;\n }\n if (video.status === \"error\") {\n throw new ApiError(\n \"INTERNAL_ERROR\",\n \"The video library could not process this file. Export it again as an MP4 (H.264) and retry.\",\n );\n }\n await deps.sleep(pollIntervalMs);\n }\n throw new ApiError(\"TIMEOUT\", `Video was not playable before timeout; last status: ${lastStatus}`);\n}\n"],"mappings":";;;;;;;AACA,SAAS,gBAAgB;AACzB,SAAS,UAAU,eAAe;AAK3B,IAAM,2BAA2B;AACxC,IAAM,2BAA2B;AAEjC,IAAM,UAAkC;AAAA,EACtC,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,QAAQ;AACV;AAWO,IAAM,sBAAoC;AAAA,EAC/C;AAAA,EACA,MAAM;AAAA,EACN,KAAK;AAAA,EACL,OAAO,CAAC,OAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AAAA,EAC/D,SAAS,OAAO,KAAK,aAAa,SAAS;AACzC,UAAM,WAAW,MAAM,MAAM,KAAK,EAAE,QAAQ,OAAO,SAAS,EAAE,gBAAgB,YAAY,GAAG,KAAK,CAAC;AACnG,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI,SAAS,kBAAkB,2BAA2B,SAAS,MAAM,IAAI,SAAS,UAAU,EAAE;AAAA,IAC1G;AAAA,EACF;AACF;AAEO,SAAS,YAAY,UAA2B;AACrD,SAAO,QAAQ,QAAQ,QAAQ,EAAE,YAAY,CAAC,MAAM;AACtD;AAEO,SAAS,uBACd,UACA,OAAiF,CAAC,GAC1E;AACR,QAAM,MAAM,QAAQ,QAAQ,EAAE,YAAY;AAC1C,QAAM,cAAc,QAAQ,GAAG;AAC/B,MAAI,CAAC,eAAgB,KAAK,uBAAuB,CAAC,KAAK,oBAAoB,SAAS,WAAW,GAAI;AACjG,UAAM,IAAI;AAAA,MACR;AAAA,MACA,KAAK,sBAAsB,6CAA6C,GAAG;AAAA,IAC7E;AAAA,EACF;AACA,SAAO;AACT;AAQA,eAAsB,iBACpB,MACA,OAAqB,qBACS;AAC9B,QAAM,EAAE,WAAW,QAAQ,IAAI,MAAM,KAAK,KAA2B,sBAAsB;AAAA,IACzF,kBAAkB,SAAS,KAAK,IAAI;AAAA,IACpC,oBAAoB,KAAK;AAAA,EAC3B,CAAC;AACD,QAAM,KAAK,QAAQ,WAAW,KAAK,aAAa,MAAM,KAAK,SAAS,KAAK,IAAI,CAAC;AAC9E,SAAO,EAAE,QAAQ;AACnB;AAEA,IAAM,oBAAyC,oBAAI,IAAI,CAAC,YAAY,cAAc,OAAO,CAAC;AAO1F,eAAsB,qBACpB,MACA,SACA,OAAwD,CAAC,GAC7B;AAC5B,QAAM,YAAY,KAAK,aAAa;AACpC,QAAM,iBAAiB,KAAK,kBAAkB;AAC9C,QAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,MAAI,aAAa;AACjB,SAAO,KAAK,IAAI,KAAK,UAAU;AAC7B,UAAM,QAAQ,MAAM,KAAK,IAAuB,mBAAmB,EAAE,IAAI,QAAQ,CAAC;AAClF,iBAAa,MAAM;AACnB,QAAI,MAAM,iBAAiB,kBAAkB,IAAI,MAAM,MAAM,GAAG;AAC9D,aAAO;AAAA,IACT;AACA,QAAI,MAAM,WAAW,SAAS;AAC5B,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,UAAM,KAAK,MAAM,cAAc;AAAA,EACjC;AACA,QAAM,IAAI,SAAS,WAAW,uDAAuD,UAAU,EAAE;AACnG;","names":[]}