@koda-sl/baker-cli 0.387.0 → 0.389.0-dev.8065ad8f0
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.
- package/README.md +1090 -211
- package/canvas/tiktok-captions-composition/index.html +5 -6
- package/canvas/tiktok-captions-composition/meta.json +5 -0
- package/dist/account-CLOKMTTC.js +49 -0
- package/dist/account-CLOKMTTC.js.map +1 -0
- package/dist/account-V5Y2QHAK.js +79 -0
- package/dist/account-V5Y2QHAK.js.map +1 -0
- package/dist/account-XFK6VX2R.js +80 -0
- package/dist/account-XFK6VX2R.js.map +1 -0
- package/dist/account-reads-S5VXX2QU.js +218 -0
- package/dist/account-reads-S5VXX2QU.js.map +1 -0
- package/dist/account-writes-Y7EQXDXF.js +66 -0
- package/dist/account-writes-Y7EQXDXF.js.map +1 -0
- package/dist/accounts-7YD457YN.js +114 -0
- package/dist/accounts-7YD457YN.js.map +1 -0
- package/dist/accounts-BJ3X5JQT.js +115 -0
- package/dist/accounts-BJ3X5JQT.js.map +1 -0
- package/dist/accounts-LOJ4WLIX.js +77 -0
- package/dist/accounts-LOJ4WLIX.js.map +1 -0
- package/dist/accounts-RYBDLQ6H.js +75 -0
- package/dist/accounts-RYBDLQ6H.js.map +1 -0
- package/dist/accounts-UO4XBWM2.js +611 -0
- package/dist/accounts-UO4XBWM2.js.map +1 -0
- package/dist/actions-3AW3R63U.js +55 -0
- package/dist/actions-3AW3R63U.js.map +1 -0
- package/dist/active-entities-R6GZIO6Z.js +103 -0
- package/dist/active-entities-R6GZIO6Z.js.map +1 -0
- package/dist/activities-ESBF3GFS.js +74 -0
- package/dist/activities-ESBF3GFS.js.map +1 -0
- package/dist/ad-group-writes-I225OYDZ.js +170 -0
- package/dist/ad-group-writes-I225OYDZ.js.map +1 -0
- package/dist/ad-groups-O35MWNF6.js +68 -0
- package/dist/ad-groups-O35MWNF6.js.map +1 -0
- package/dist/ad-writes-SS5YZO5W.js +174 -0
- package/dist/ad-writes-SS5YZO5W.js.map +1 -0
- package/dist/add-43DUOVNR.js +104 -0
- package/dist/add-43DUOVNR.js.map +1 -0
- package/dist/add-IE5WDELB.js +302 -0
- package/dist/add-IE5WDELB.js.map +1 -0
- package/dist/add-QZHAWUBA.js +97 -0
- package/dist/add-QZHAWUBA.js.map +1 -0
- package/dist/add-TGQIVVXH.js +105 -0
- package/dist/add-TGQIVVXH.js.map +1 -0
- package/dist/add-accounts-6QYPOPR2.js +91 -0
- package/dist/add-accounts-6QYPOPR2.js.map +1 -0
- package/dist/ads-AUSRB4GU.js +128 -0
- package/dist/ads-AUSRB4GU.js.map +1 -0
- package/dist/ads-COYOTEKE.js +77 -0
- package/dist/ads-COYOTEKE.js.map +1 -0
- package/dist/ads-MALHYD2D.js +40 -0
- package/dist/ads-MALHYD2D.js.map +1 -0
- package/dist/ads-XZCMSPM5.js +113 -0
- package/dist/ads-XZCMSPM5.js.map +1 -0
- package/dist/adsets-AKR75THA.js +176 -0
- package/dist/adsets-AKR75THA.js.map +1 -0
- package/dist/advertisers-52FMMBTQ.js +120 -0
- package/dist/advertisers-52FMMBTQ.js.map +1 -0
- package/dist/advertisers-BCGKUMEH.js +125 -0
- package/dist/advertisers-BCGKUMEH.js.map +1 -0
- package/dist/analytics-JPDBKETM.js +1980 -0
- package/dist/analytics-JPDBKETM.js.map +1 -0
- package/dist/analytics-YVQ6H4BG.js +433 -0
- package/dist/analytics-YVQ6H4BG.js.map +1 -0
- package/dist/animate-JXIT77Y5.js +480 -0
- package/dist/animate-JXIT77Y5.js.map +1 -0
- package/dist/assign-66NTWTR2.js +77 -0
- package/dist/assign-66NTWTR2.js.map +1 -0
- package/dist/audience-size-LVQJWQAS.js +94 -0
- package/dist/audience-size-LVQJWQAS.js.map +1 -0
- package/dist/audiences-DC3IOG34.js +85 -0
- package/dist/audiences-DC3IOG34.js.map +1 -0
- package/dist/audiences-NEW3LLQR.js +268 -0
- package/dist/audiences-NEW3LLQR.js.map +1 -0
- package/dist/audiences-NYGMBGQ3.js +79 -0
- package/dist/audiences-NYGMBGQ3.js.map +1 -0
- package/dist/audit-UIPMTI5C.js +88 -0
- package/dist/audit-UIPMTI5C.js.map +1 -0
- package/dist/audit-XGN2OFLN.js +151 -0
- package/dist/audit-XGN2OFLN.js.map +1 -0
- package/dist/autocomplete-LVPDV3JE.js +111 -0
- package/dist/autocomplete-LVPDV3JE.js.map +1 -0
- package/dist/avatars-S6NSLMJK.js +38 -0
- package/dist/avatars-S6NSLMJK.js.map +1 -0
- package/dist/bid-pricing-2LYULXU2.js +99 -0
- package/dist/bid-pricing-2LYULXU2.js.map +1 -0
- package/dist/brand-WWHUZ72R.js +22 -0
- package/dist/brand-WWHUZ72R.js.map +1 -0
- package/dist/brief-XY3TFWBC.js +492 -0
- package/dist/brief-XY3TFWBC.js.map +1 -0
- package/dist/businesses-J7OP7MSK.js +53 -0
- package/dist/businesses-J7OP7MSK.js.map +1 -0
- package/dist/campaign-groups-N4TZ2F3L.js +95 -0
- package/dist/campaign-groups-N4TZ2F3L.js.map +1 -0
- package/dist/campaign-writes-5XA727KI.js +170 -0
- package/dist/campaign-writes-5XA727KI.js.map +1 -0
- package/dist/campaign-writes-7YFRQIQT.js +165 -0
- package/dist/campaign-writes-7YFRQIQT.js.map +1 -0
- package/dist/campaigns-JPYNVFQI.js +76 -0
- package/dist/campaigns-JPYNVFQI.js.map +1 -0
- package/dist/campaigns-L43ZUKAI.js +107 -0
- package/dist/campaigns-L43ZUKAI.js.map +1 -0
- package/dist/campaigns-OD7Z332M.js +109 -0
- package/dist/campaigns-OD7Z332M.js.map +1 -0
- package/dist/campaigns-R4DXIR2Q.js +110 -0
- package/dist/campaigns-R4DXIR2Q.js.map +1 -0
- package/dist/canvas-J7SLIVL7.js +46 -0
- package/dist/canvas-J7SLIVL7.js.map +1 -0
- package/dist/capabilities-FVTZAFPV.js +144 -0
- package/dist/capabilities-FVTZAFPV.js.map +1 -0
- package/dist/cards-7H32TNMO.js +85 -0
- package/dist/cards-7H32TNMO.js.map +1 -0
- package/dist/catalog-OTICZPJA.js +64 -0
- package/dist/catalog-OTICZPJA.js.map +1 -0
- package/dist/catalogs-ABCQLCDU.js +128 -0
- package/dist/catalogs-ABCQLCDU.js.map +1 -0
- package/dist/changes-7ZIGNUW6.js +135 -0
- package/dist/changes-7ZIGNUW6.js.map +1 -0
- package/dist/chatgpt-B3NHRJUE.js +47 -0
- package/dist/chatgpt-B3NHRJUE.js.map +1 -0
- package/dist/chats-E7DBRHBF.js +262 -0
- package/dist/chats-E7DBRHBF.js.map +1 -0
- package/dist/chunk-2CV7LX23.js +474 -0
- package/dist/chunk-2CV7LX23.js.map +1 -0
- package/dist/chunk-2HCI5BXB.js +479 -0
- package/dist/chunk-2HCI5BXB.js.map +1 -0
- package/dist/chunk-2SQJL7ZN.js +56 -0
- package/dist/chunk-2SQJL7ZN.js.map +1 -0
- package/dist/chunk-2Y5V23PU.js +29 -0
- package/dist/chunk-2Y5V23PU.js.map +1 -0
- package/dist/chunk-32CPGJPL.js +149 -0
- package/dist/chunk-32CPGJPL.js.map +1 -0
- package/dist/chunk-3ACMDRSE.js +39 -0
- package/dist/chunk-3ACMDRSE.js.map +1 -0
- package/dist/chunk-3CIXGQJS.js +150 -0
- package/dist/chunk-3CIXGQJS.js.map +1 -0
- package/dist/chunk-3U7TDBIB.js +275 -0
- package/dist/chunk-3U7TDBIB.js.map +1 -0
- package/dist/chunk-3UDSYYND.js +42 -0
- package/dist/chunk-3UDSYYND.js.map +1 -0
- package/dist/chunk-3ZWWXAQZ.js +150 -0
- package/dist/chunk-3ZWWXAQZ.js.map +1 -0
- package/dist/chunk-4MH6LONO.js +274 -0
- package/dist/chunk-4MH6LONO.js.map +1 -0
- package/dist/chunk-4NZ47VXO.js +137 -0
- package/dist/chunk-4NZ47VXO.js.map +1 -0
- package/dist/chunk-564AEU2Q.js +541 -0
- package/dist/chunk-564AEU2Q.js.map +1 -0
- package/dist/chunk-5HYSKH77.js +315 -0
- package/dist/chunk-5HYSKH77.js.map +1 -0
- package/dist/chunk-5MBPIONY.js +29 -0
- package/dist/chunk-5MBPIONY.js.map +1 -0
- package/dist/chunk-5OVOLYY3.js +74 -0
- package/dist/chunk-5OVOLYY3.js.map +1 -0
- package/dist/chunk-66USKCVY.js +4410 -0
- package/dist/chunk-66USKCVY.js.map +1 -0
- package/dist/chunk-6I7SYEYN.js +166 -0
- package/dist/chunk-6I7SYEYN.js.map +1 -0
- package/dist/chunk-6O7ISBC7.js +65 -0
- package/dist/chunk-6O7ISBC7.js.map +1 -0
- package/dist/chunk-752S7JF6.js +35 -0
- package/dist/chunk-752S7JF6.js.map +1 -0
- package/dist/chunk-77DN7R35.js +228 -0
- package/dist/chunk-77DN7R35.js.map +1 -0
- package/dist/chunk-7F7MFMLI.js +175 -0
- package/dist/chunk-7F7MFMLI.js.map +1 -0
- package/dist/chunk-7THBBTJJ.js +183 -0
- package/dist/chunk-7THBBTJJ.js.map +1 -0
- package/dist/chunk-7XU3HKMX.js +1599 -0
- package/dist/chunk-7XU3HKMX.js.map +1 -0
- package/dist/chunk-A2CBZLQ6.js +111 -0
- package/dist/chunk-A2CBZLQ6.js.map +1 -0
- package/dist/chunk-AFJGYJ7Z.js +45 -0
- package/dist/chunk-AFJGYJ7Z.js.map +1 -0
- package/dist/chunk-AR7PU7BB.js +76 -0
- package/dist/chunk-AR7PU7BB.js.map +1 -0
- package/dist/chunk-ASL7JFBD.js +96 -0
- package/dist/chunk-ASL7JFBD.js.map +1 -0
- package/dist/chunk-AUSKKFVH.js +84 -0
- package/dist/chunk-AUSKKFVH.js.map +1 -0
- package/dist/chunk-B52DCYL2.js +159 -0
- package/dist/chunk-B52DCYL2.js.map +1 -0
- package/dist/{chunk-XHC4LMK4.js → chunk-BVM5IRZW.js} +16 -8
- package/dist/chunk-BVM5IRZW.js.map +1 -0
- package/dist/chunk-CAMX6OHF.js +3182 -0
- package/dist/chunk-CAMX6OHF.js.map +1 -0
- package/dist/chunk-CYBLKMXQ.js +310 -0
- package/dist/chunk-CYBLKMXQ.js.map +1 -0
- package/dist/chunk-CZENWCBS.js +333 -0
- package/dist/chunk-CZENWCBS.js.map +1 -0
- package/dist/chunk-D5FY4FAK.js +24 -0
- package/dist/chunk-D5FY4FAK.js.map +1 -0
- package/dist/chunk-DGCUPJZD.js +39 -0
- package/dist/chunk-DGCUPJZD.js.map +1 -0
- package/dist/chunk-DNCLWSHO.js +41 -0
- package/dist/chunk-DNCLWSHO.js.map +1 -0
- package/dist/chunk-DX4GIDO7.js +296 -0
- package/dist/chunk-DX4GIDO7.js.map +1 -0
- package/dist/chunk-EDLZGTGN.js +216 -0
- package/dist/chunk-EDLZGTGN.js.map +1 -0
- package/dist/chunk-EDNKALM6.js +304 -0
- package/dist/chunk-EDNKALM6.js.map +1 -0
- package/dist/chunk-EDNX3AOS.js +76 -0
- package/dist/chunk-EDNX3AOS.js.map +1 -0
- package/dist/chunk-EF5DP6EB.js +52 -0
- package/dist/chunk-EF5DP6EB.js.map +1 -0
- package/dist/chunk-ERSX3MKH.js +34 -0
- package/dist/chunk-ERSX3MKH.js.map +1 -0
- package/dist/chunk-F3IJSR7O.js +346 -0
- package/dist/chunk-F3IJSR7O.js.map +1 -0
- package/dist/chunk-FKOECEVC.js +126 -0
- package/dist/chunk-FKOECEVC.js.map +1 -0
- package/dist/chunk-FWT55B3O.js +509 -0
- package/dist/chunk-FWT55B3O.js.map +1 -0
- package/dist/chunk-FYWWTMXP.js +2902 -0
- package/dist/chunk-FYWWTMXP.js.map +1 -0
- package/dist/chunk-FZGCAW46.js +64 -0
- package/dist/chunk-FZGCAW46.js.map +1 -0
- package/dist/chunk-G7AFVTUS.js +106 -0
- package/dist/chunk-G7AFVTUS.js.map +1 -0
- package/dist/chunk-GIW7ABMM.js +74 -0
- package/dist/chunk-GIW7ABMM.js.map +1 -0
- package/dist/chunk-GIWHHCD6.js +145 -0
- package/dist/chunk-GIWHHCD6.js.map +1 -0
- package/dist/chunk-GRQ2AXDX.js +9 -0
- package/dist/chunk-GRQ2AXDX.js.map +1 -0
- package/dist/chunk-GXDLWBOY.js +73 -0
- package/dist/chunk-GXDLWBOY.js.map +1 -0
- package/dist/chunk-GYABNLWW.js +629 -0
- package/dist/chunk-GYABNLWW.js.map +1 -0
- package/dist/chunk-H7MLHG2I.js +94 -0
- package/dist/chunk-H7MLHG2I.js.map +1 -0
- package/dist/chunk-H7XVKLIY.js +206 -0
- package/dist/chunk-H7XVKLIY.js.map +1 -0
- package/dist/chunk-HAE4WWFQ.js +455 -0
- package/dist/chunk-HAE4WWFQ.js.map +1 -0
- package/dist/chunk-HDHWIEJJ.js +136 -0
- package/dist/chunk-HDHWIEJJ.js.map +1 -0
- package/dist/chunk-HJTIBTF7.js +98 -0
- package/dist/chunk-HJTIBTF7.js.map +1 -0
- package/dist/{chunk-VZEDAFAR.js → chunk-HLXWKMTK.js} +47 -8
- package/dist/chunk-HLXWKMTK.js.map +1 -0
- package/dist/{chunk-MF7YA62W.js → chunk-HREWXNTO.js} +10 -5
- package/dist/chunk-HREWXNTO.js.map +1 -0
- package/dist/chunk-HYXKRNRV.js +176 -0
- package/dist/chunk-HYXKRNRV.js.map +1 -0
- package/dist/chunk-I3DIZWN5.js +97 -0
- package/dist/chunk-I3DIZWN5.js.map +1 -0
- package/dist/chunk-IJMWEO4P.js +57 -0
- package/dist/chunk-IJMWEO4P.js.map +1 -0
- package/dist/chunk-IOCSDFF2.js +23992 -0
- package/dist/chunk-IOCSDFF2.js.map +1 -0
- package/dist/chunk-IVIJJXXT.js +62 -0
- package/dist/chunk-IVIJJXXT.js.map +1 -0
- package/dist/chunk-J57GWTPK.js +106 -0
- package/dist/chunk-J57GWTPK.js.map +1 -0
- package/dist/chunk-JPK34QPS.js +134 -0
- package/dist/chunk-JPK34QPS.js.map +1 -0
- package/dist/chunk-JRCFCIE3.js +188 -0
- package/dist/chunk-JRCFCIE3.js.map +1 -0
- package/dist/chunk-JUAIGJ2A.js +76 -0
- package/dist/chunk-JUAIGJ2A.js.map +1 -0
- package/dist/chunk-K5OQES4V.js +58 -0
- package/dist/chunk-K5OQES4V.js.map +1 -0
- package/dist/chunk-KBS5GH4T.js +1626 -0
- package/dist/chunk-KBS5GH4T.js.map +1 -0
- package/dist/chunk-KIGGMKAE.js +66 -0
- package/dist/chunk-KIGGMKAE.js.map +1 -0
- package/dist/chunk-KKJ4KJCW.js +29 -0
- package/dist/chunk-KKJ4KJCW.js.map +1 -0
- package/dist/chunk-KLK6KQLQ.js +55 -0
- package/dist/chunk-KLK6KQLQ.js.map +1 -0
- package/dist/chunk-KXGG6EQM.js +382 -0
- package/dist/chunk-KXGG6EQM.js.map +1 -0
- package/dist/chunk-KXRKPZZY.js +169 -0
- package/dist/chunk-KXRKPZZY.js.map +1 -0
- package/dist/chunk-KZUHRZ2C.js +5187 -0
- package/dist/chunk-KZUHRZ2C.js.map +1 -0
- package/dist/chunk-L45A3IYV.js +1079 -0
- package/dist/chunk-L45A3IYV.js.map +1 -0
- package/dist/chunk-LA6PPSNA.js +65 -0
- package/dist/chunk-LA6PPSNA.js.map +1 -0
- package/dist/chunk-LEIQAHWF.js +25 -0
- package/dist/chunk-LEIQAHWF.js.map +1 -0
- package/dist/chunk-LERWCRY5.js +297 -0
- package/dist/chunk-LERWCRY5.js.map +1 -0
- package/dist/chunk-LLPFY3NI.js +207 -0
- package/dist/chunk-LLPFY3NI.js.map +1 -0
- package/dist/chunk-M6UNISGO.js +66 -0
- package/dist/chunk-M6UNISGO.js.map +1 -0
- package/dist/chunk-MDATIJPM.js +92 -0
- package/dist/chunk-MDATIJPM.js.map +1 -0
- package/dist/chunk-MGKHFGLV.js +75 -0
- package/dist/chunk-MGKHFGLV.js.map +1 -0
- package/dist/chunk-MZWC6HHA.js +455 -0
- package/dist/chunk-MZWC6HHA.js.map +1 -0
- package/dist/chunk-N3XJ434P.js +197 -0
- package/dist/chunk-N3XJ434P.js.map +1 -0
- package/dist/chunk-NFSLRRIE.js +77 -0
- package/dist/chunk-NFSLRRIE.js.map +1 -0
- package/dist/chunk-NHU33T2S.js +60 -0
- package/dist/chunk-NHU33T2S.js.map +1 -0
- package/dist/chunk-NJEZM4OB.js +51 -0
- package/dist/chunk-NJEZM4OB.js.map +1 -0
- package/dist/chunk-O6QKCJE4.js +455 -0
- package/dist/chunk-O6QKCJE4.js.map +1 -0
- package/dist/chunk-OFFAMC5H.js +225 -0
- package/dist/chunk-OFFAMC5H.js.map +1 -0
- package/dist/chunk-OHGTCFFE.js +57 -0
- package/dist/chunk-OHGTCFFE.js.map +1 -0
- package/dist/chunk-P4NSJS54.js +20 -0
- package/dist/chunk-P4NSJS54.js.map +1 -0
- package/dist/chunk-P5T7OZKV.js +26 -0
- package/dist/chunk-P5T7OZKV.js.map +1 -0
- package/dist/chunk-PFBQERWX.js +10 -0
- package/dist/chunk-PFBQERWX.js.map +1 -0
- package/dist/chunk-PUPEGICD.js +103 -0
- package/dist/chunk-PUPEGICD.js.map +1 -0
- package/dist/chunk-Q6ULQMWG.js +41 -0
- package/dist/chunk-Q6ULQMWG.js.map +1 -0
- package/dist/chunk-QO23YHLK.js +84 -0
- package/dist/chunk-QO23YHLK.js.map +1 -0
- package/dist/chunk-QSGIWV4P.js +337 -0
- package/dist/chunk-QSGIWV4P.js.map +1 -0
- package/dist/chunk-R4Y5P3PB.js +19 -0
- package/dist/chunk-R4Y5P3PB.js.map +1 -0
- package/dist/chunk-R5OQM7FF.js +179 -0
- package/dist/chunk-R5OQM7FF.js.map +1 -0
- package/dist/chunk-RODLBWIR.js +592 -0
- package/dist/chunk-RODLBWIR.js.map +1 -0
- package/dist/chunk-RY7TYEIX.js +504 -0
- package/dist/chunk-RY7TYEIX.js.map +1 -0
- package/dist/chunk-S4LZ7KTG.js +160 -0
- package/dist/chunk-S4LZ7KTG.js.map +1 -0
- package/dist/chunk-SHTESUB6.js +1442 -0
- package/dist/chunk-SHTESUB6.js.map +1 -0
- package/dist/chunk-SJH4EOZH.js +23 -0
- package/dist/chunk-SJH4EOZH.js.map +1 -0
- package/dist/chunk-SMIENBNX.js +6212 -0
- package/dist/chunk-SMIENBNX.js.map +1 -0
- package/dist/chunk-T7GT22KA.js +494 -0
- package/dist/chunk-T7GT22KA.js.map +1 -0
- package/dist/chunk-T7M4WFNV.js +172 -0
- package/dist/chunk-T7M4WFNV.js.map +1 -0
- package/dist/chunk-TIFVHGQL.js +6683 -0
- package/dist/chunk-TIFVHGQL.js.map +1 -0
- package/dist/chunk-TMIDUSOR.js +665 -0
- package/dist/chunk-TMIDUSOR.js.map +1 -0
- package/dist/{chunk-WLDM2TRF.js → chunk-TPXI2GCW.js} +4 -4
- package/dist/chunk-U6VRBDNQ.js +1830 -0
- package/dist/chunk-U6VRBDNQ.js.map +1 -0
- package/dist/chunk-U7BBXM67.js +1743 -0
- package/dist/chunk-U7BBXM67.js.map +1 -0
- package/dist/chunk-UI6BKYQD.js +225 -0
- package/dist/chunk-UI6BKYQD.js.map +1 -0
- package/dist/chunk-UOI5S62H.js +846 -0
- package/dist/chunk-UOI5S62H.js.map +1 -0
- package/dist/chunk-USL5ARRE.js +26 -0
- package/dist/chunk-USL5ARRE.js.map +1 -0
- package/dist/chunk-UYC45JNS.js +139 -0
- package/dist/chunk-UYC45JNS.js.map +1 -0
- package/dist/chunk-VNKVBY54.js +363 -0
- package/dist/chunk-VNKVBY54.js.map +1 -0
- package/dist/chunk-VS4C7VAR.js +533 -0
- package/dist/chunk-VS4C7VAR.js.map +1 -0
- package/dist/chunk-VZMDYVNS.js +3151 -0
- package/dist/chunk-VZMDYVNS.js.map +1 -0
- package/dist/chunk-W4W4ZRBP.js +191 -0
- package/dist/chunk-W4W4ZRBP.js.map +1 -0
- package/dist/chunk-WN4KX7GE.js +25 -0
- package/dist/chunk-WN4KX7GE.js.map +1 -0
- package/dist/chunk-WNFTXSGR.js +111 -0
- package/dist/chunk-WNFTXSGR.js.map +1 -0
- package/dist/chunk-WOTDHRNF.js +2109 -0
- package/dist/chunk-WOTDHRNF.js.map +1 -0
- package/dist/chunk-XGWKTYXQ.js +67 -0
- package/dist/chunk-XGWKTYXQ.js.map +1 -0
- package/dist/chunk-XIGIJJSF.js +66 -0
- package/dist/chunk-XIGIJJSF.js.map +1 -0
- package/dist/chunk-XNUXB63I.js +817 -0
- package/dist/chunk-XNUXB63I.js.map +1 -0
- package/dist/chunk-XQ3CCNJD.js +610 -0
- package/dist/chunk-XQ3CCNJD.js.map +1 -0
- package/dist/chunk-XX6ZMCY5.js +4227 -0
- package/dist/chunk-XX6ZMCY5.js.map +1 -0
- package/dist/chunk-Y362QH54.js +98 -0
- package/dist/chunk-Y362QH54.js.map +1 -0
- package/dist/chunk-Y4T6ATDQ.js +74 -0
- package/dist/chunk-Y4T6ATDQ.js.map +1 -0
- package/dist/chunk-YQSBHWOI.js +41 -0
- package/dist/chunk-YU26SDNT.js +46 -0
- package/dist/chunk-YU26SDNT.js.map +1 -0
- package/dist/chunk-YULENNA7.js +501 -0
- package/dist/chunk-YULENNA7.js.map +1 -0
- package/dist/chunk-Z3ENMCFE.js +94 -0
- package/dist/chunk-Z3ENMCFE.js.map +1 -0
- package/dist/chunk-ZH7ZM3ZM.js +125 -0
- package/dist/chunk-ZH7ZM3ZM.js.map +1 -0
- package/dist/chunk-ZIXHS6AM.js +42 -0
- package/dist/chunk-ZIXHS6AM.js.map +1 -0
- package/dist/chunk-ZLLJKSNS.js +96 -0
- package/dist/chunk-ZLLJKSNS.js.map +1 -0
- package/dist/claim-LF6VQ7OR.js +197 -0
- package/dist/claim-LF6VQ7OR.js.map +1 -0
- package/dist/cli.js +104 -70041
- package/dist/cli.js.map +1 -1
- package/dist/client-26SAJ46D.js +19 -0
- package/dist/code-MOWYJMDH.js +76 -0
- package/dist/code-MOWYJMDH.js.map +1 -0
- package/dist/companies-6HSK5BLK.js +195 -0
- package/dist/companies-6HSK5BLK.js.map +1 -0
- package/dist/complete-2PUAFQEC.js +81 -0
- package/dist/complete-2PUAFQEC.js.map +1 -0
- package/dist/config-X6GKOVQ6.js +88 -0
- package/dist/config-X6GKOVQ6.js.map +1 -0
- package/dist/connect-RXPMAJQI.js +42 -0
- package/dist/content-UYZC4AKN.js +85 -0
- package/dist/content-UYZC4AKN.js.map +1 -0
- package/dist/conversation-Y3NB2VDI.js +93 -0
- package/dist/conversation-Y3NB2VDI.js.map +1 -0
- package/dist/conversion-report-R4GJWWTK.js +125 -0
- package/dist/conversion-report-R4GJWWTK.js.map +1 -0
- package/dist/conversion-upload-command-YP4DGTPP.js +438 -0
- package/dist/conversion-upload-command-YP4DGTPP.js.map +1 -0
- package/dist/conversion-writes-WHFFUWWL.js +120 -0
- package/dist/conversion-writes-WHFFUWWL.js.map +1 -0
- package/dist/conversions-K7C32DPW.js +135 -0
- package/dist/conversions-K7C32DPW.js.map +1 -0
- package/dist/conversions-OXJAX5GB.js +76 -0
- package/dist/conversions-OXJAX5GB.js.map +1 -0
- package/dist/countries-PBXNB3BR.js +82 -0
- package/dist/countries-PBXNB3BR.js.map +1 -0
- package/dist/create-AJ4KPSJ4.js +59 -0
- package/dist/create-AJ4KPSJ4.js.map +1 -0
- package/dist/create-ALKOAD5J.js +138 -0
- package/dist/create-ALKOAD5J.js.map +1 -0
- package/dist/create-HTKZMXKB.js +207 -0
- package/dist/create-HTKZMXKB.js.map +1 -0
- package/dist/create-TZMAOFBR.js +236 -0
- package/dist/create-TZMAOFBR.js.map +1 -0
- package/dist/creatives-MBTZTIAA.js +51 -0
- package/dist/creatives-MBTZTIAA.js.map +1 -0
- package/dist/creatives-OZHVU4WB.js +182 -0
- package/dist/creatives-OZHVU4WB.js.map +1 -0
- package/dist/creatives-VMGY5SU4.js +87 -0
- package/dist/creatives-VMGY5SU4.js.map +1 -0
- package/dist/credentials-FY4UH6TF.js +287 -0
- package/dist/credentials-FY4UH6TF.js.map +1 -0
- package/dist/critique-2UTP4DR3.js +216 -0
- package/dist/critique-2UTP4DR3.js.map +1 -0
- package/dist/critique-B3H7QFM2.js +1449 -0
- package/dist/critique-B3H7QFM2.js.map +1 -0
- package/dist/crm-2IBLUHDB.js +318 -0
- package/dist/crm-2IBLUHDB.js.map +1 -0
- package/dist/crm-YMYO4U53.js +224 -0
- package/dist/crm-YMYO4U53.js.map +1 -0
- package/dist/crop-U3AD4DDR.js +113 -0
- package/dist/crop-U3AD4DDR.js.map +1 -0
- package/dist/currency-S6KWZSZ6.js +88 -0
- package/dist/currency-S6KWZSZ6.js.map +1 -0
- package/dist/custom-conversions-FABS6YVT.js +125 -0
- package/dist/custom-conversions-FABS6YVT.js.map +1 -0
- package/dist/customers-P6LLLJHK.js +56 -0
- package/dist/decide-YTHCBKM6.js +199 -0
- package/dist/decide-YTHCBKM6.js.map +1 -0
- package/dist/delete-B2TDEW7H.js +63 -0
- package/dist/delete-B2TDEW7H.js.map +1 -0
- package/dist/delete-DZUDLYPC.js +69 -0
- package/dist/delete-DZUDLYPC.js.map +1 -0
- package/dist/delete-NZGZP4YP.js +71 -0
- package/dist/delete-NZGZP4YP.js.map +1 -0
- package/dist/delete-SDOZNDWQ.js +54 -0
- package/dist/delete-SDOZNDWQ.js.map +1 -0
- package/dist/delete-VQMU56OH.js +71 -0
- package/dist/delete-VQMU56OH.js.map +1 -0
- package/dist/delete-WKQPMVAM.js +66 -0
- package/dist/delete-WKQPMVAM.js.map +1 -0
- package/dist/demographics-Q3DCXULY.js +138 -0
- package/dist/demographics-Q3DCXULY.js.map +1 -0
- package/dist/describe-JNTCQZNL.js +97 -0
- package/dist/describe-JNTCQZNL.js.map +1 -0
- package/dist/describe-MT4334NG.js +97 -0
- package/dist/describe-MT4334NG.js.map +1 -0
- package/dist/dimensions-FEZUJRAG.js +101 -0
- package/dist/dimensions-FEZUJRAG.js.map +1 -0
- package/dist/discard-NEZM5CHF.js +66 -0
- package/dist/discard-NEZM5CHF.js.map +1 -0
- package/dist/discover-4GD7QSF5.js +93 -0
- package/dist/discover-4GD7QSF5.js.map +1 -0
- package/dist/discover-6K3IOYXR.js +172 -0
- package/dist/discover-6K3IOYXR.js.map +1 -0
- package/dist/domain-7Y256IDR.js +98 -0
- package/dist/domain-7Y256IDR.js.map +1 -0
- package/dist/download-L27HWEOE.js +299 -0
- package/dist/download-L27HWEOE.js.map +1 -0
- package/dist/draft-25G2P2TE.js +281 -0
- package/dist/draft-25G2P2TE.js.map +1 -0
- package/dist/draft-F6TUGXAY.js +307 -0
- package/dist/draft-F6TUGXAY.js.map +1 -0
- package/dist/draft-KLULNBWP.js +233 -0
- package/dist/draft-KLULNBWP.js.map +1 -0
- package/dist/draft-LY5ZPF73.js +217 -0
- package/dist/draft-LY5ZPF73.js.map +1 -0
- package/dist/draft-M4ZHDQ46.js +306 -0
- package/dist/draft-M4ZHDQ46.js.map +1 -0
- package/dist/draft-MI7RWY2K.js +100 -0
- package/dist/draft-MI7RWY2K.js.map +1 -0
- package/dist/draft-P4IVYTY3.js +103 -0
- package/dist/draft-P4IVYTY3.js.map +1 -0
- package/dist/draft-QQMCVDDS.js +328 -0
- package/dist/draft-QQMCVDDS.js.map +1 -0
- package/dist/engine/index.d.ts +213 -127
- package/dist/engine/index.js +18 -4
- package/dist/{env-4P5HOGNA.js → env-FBTHZKGN.js} +12 -2
- package/dist/env-FBTHZKGN.js.map +1 -0
- package/dist/experiment-HDYTJPUY.js +1397 -0
- package/dist/experiment-HDYTJPUY.js.map +1 -0
- package/dist/export-TS5GYEMA.js +168 -0
- package/dist/export-TS5GYEMA.js.map +1 -0
- package/dist/extract-QVQFUOIK.js +113 -0
- package/dist/extract-QVQFUOIK.js.map +1 -0
- package/dist/facets-7MBSM7BP.js +114 -0
- package/dist/facets-7MBSM7BP.js.map +1 -0
- package/dist/favorites-7QP7BY5K.js +178 -0
- package/dist/favorites-7QP7BY5K.js.map +1 -0
- package/dist/feed-EETRO2FG.js +177 -0
- package/dist/feed-EETRO2FG.js.map +1 -0
- package/dist/feedback-PLMFRAQW.js +66 -0
- package/dist/feedback-PLMFRAQW.js.map +1 -0
- package/dist/feedback-record-QEHHGVYC.js +177 -0
- package/dist/feedback-record-QEHHGVYC.js.map +1 -0
- package/dist/fetch-QE3EB756.js +176 -0
- package/dist/fetch-QE3EB756.js.map +1 -0
- package/dist/fetch-Z7O3ZL4D.js +139 -0
- package/dist/fetch-Z7O3ZL4D.js.map +1 -0
- package/dist/find-KAQ6JDMO.js +134 -0
- package/dist/find-KAQ6JDMO.js.map +1 -0
- package/dist/fit-MY5GVZZZ.js +45 -0
- package/dist/fit-MY5GVZZZ.js.map +1 -0
- package/dist/flows-C67KEMDU.js +247 -0
- package/dist/flows-C67KEMDU.js.map +1 -0
- package/dist/follow-IX4XVK5Y.js +94 -0
- package/dist/follow-IX4XVK5Y.js.map +1 -0
- package/dist/follow-competitors-UZBUOYTH.js +112 -0
- package/dist/follow-competitors-UZBUOYTH.js.map +1 -0
- package/dist/following-VGOIUCIZ.js +113 -0
- package/dist/following-VGOIUCIZ.js.map +1 -0
- package/dist/fonts-UR7XZ5XZ.js +34 -0
- package/dist/fonts-UR7XZ5XZ.js.map +1 -0
- package/dist/forecast-3F4SZNAK.js +104 -0
- package/dist/forecast-3F4SZNAK.js.map +1 -0
- package/dist/forecast-K5E7CTKX.js +168 -0
- package/dist/forecast-K5E7CTKX.js.map +1 -0
- package/dist/funding-H5YO37OW.js +85 -0
- package/dist/funding-H5YO37OW.js.map +1 -0
- package/dist/funnel-2PPEPAMY.js +394 -0
- package/dist/funnel-2PPEPAMY.js.map +1 -0
- package/dist/ga4-YHJ2XMLC.js +55 -0
- package/dist/ga4-YHJ2XMLC.js.map +1 -0
- package/dist/generate-M2ZX5DMI.js +262 -0
- package/dist/generate-M2ZX5DMI.js.map +1 -0
- package/dist/get-4EYKCZ6F.js +59 -0
- package/dist/get-4EYKCZ6F.js.map +1 -0
- package/dist/get-637GALM2.js +63 -0
- package/dist/get-637GALM2.js.map +1 -0
- package/dist/get-AZARFR6O.js +61 -0
- package/dist/get-AZARFR6O.js.map +1 -0
- package/dist/get-BPMEHRUG.js +56 -0
- package/dist/get-BPMEHRUG.js.map +1 -0
- package/dist/get-MQ6MMIZ7.js +78 -0
- package/dist/get-MQ6MMIZ7.js.map +1 -0
- package/dist/get-N4BPOQCB.js +63 -0
- package/dist/get-N4BPOQCB.js.map +1 -0
- package/dist/get-RPZHLQ56.js +92 -0
- package/dist/get-RPZHLQ56.js.map +1 -0
- package/dist/gif-6PRTB2VR.js +94 -0
- package/dist/gif-6PRTB2VR.js.map +1 -0
- package/dist/google-52JRH7X3.js +136 -0
- package/dist/google-52JRH7X3.js.map +1 -0
- package/dist/google-X2AQR3RB.js +3190 -0
- package/dist/google-X2AQR3RB.js.map +1 -0
- package/dist/google-ads-PWX7OF5Z.js +195 -0
- package/dist/google-ads-PWX7OF5Z.js.map +1 -0
- package/dist/group-AAZ5QKC3.js +43 -0
- package/dist/group-AAZ5QKC3.js.map +1 -0
- package/dist/group-GSYCZORC.js +43 -0
- package/dist/group-GSYCZORC.js.map +1 -0
- package/dist/gsc-TS5T7ML2.js +30 -0
- package/dist/gsc-TS5T7ML2.js.map +1 -0
- package/dist/history-EW6LFFCX.js +67 -0
- package/dist/history-EW6LFFCX.js.map +1 -0
- package/dist/history-XI5ABCFO.js +133 -0
- package/dist/history-XI5ABCFO.js.map +1 -0
- package/dist/hubspot-AVUOILRE.js +779 -0
- package/dist/hubspot-AVUOILRE.js.map +1 -0
- package/dist/icon-K75KI6BV.js +137 -0
- package/dist/icon-K75KI6BV.js.map +1 -0
- package/dist/ideas-L3SZSIZP.js +35 -0
- package/dist/ideas-L3SZSIZP.js.map +1 -0
- package/dist/images-CD53I2W5.js +90 -0
- package/dist/images-CD53I2W5.js.map +1 -0
- package/dist/improve-L3BW4EQG.js +86 -0
- package/dist/improve-L3BW4EQG.js.map +1 -0
- package/dist/ingest-KRJOYTCQ.js +107 -0
- package/dist/ingest-KRJOYTCQ.js.map +1 -0
- package/dist/ingest-WE3SPPND.js +23 -0
- package/dist/ingest-WE3SPPND.js.map +1 -0
- package/dist/insights-PELVD4RY.js +122 -0
- package/dist/insights-PELVD4RY.js.map +1 -0
- package/dist/insights-XCA4BUJW.js +423 -0
- package/dist/insights-XCA4BUJW.js.map +1 -0
- package/dist/inspect-QKETG5UJ.js +189 -0
- package/dist/inspect-QKETG5UJ.js.map +1 -0
- package/dist/inspiration-Y2J2PUPC.js +53 -0
- package/dist/inspiration-Y2J2PUPC.js.map +1 -0
- package/dist/intent-YJOJGNVJ.js +95 -0
- package/dist/intent-YJOJGNVJ.js.map +1 -0
- package/dist/job-E2U4FS5P.js +202 -0
- package/dist/job-E2U4FS5P.js.map +1 -0
- package/dist/job-create-DFYCHVQ7.js +109 -0
- package/dist/job-create-DFYCHVQ7.js.map +1 -0
- package/dist/job-status-FFPMTSHB.js +74 -0
- package/dist/job-status-FFPMTSHB.js.map +1 -0
- package/dist/keep-GYZS2UTL.js +78 -0
- package/dist/keep-GYZS2UTL.js.map +1 -0
- package/dist/keyword-gap-QU7O7UKC.js +130 -0
- package/dist/keyword-gap-QU7O7UKC.js.map +1 -0
- package/dist/keyword-metrics-HLCM3QU7.js +197 -0
- package/dist/keyword-metrics-HLCM3QU7.js.map +1 -0
- package/dist/keywords-for-site-BDKPQKWB.js +128 -0
- package/dist/keywords-for-site-BDKPQKWB.js.map +1 -0
- package/dist/landing-4K6XYNFM.js +28 -0
- package/dist/landing-4K6XYNFM.js.map +1 -0
- package/dist/landings-F7LOAEJE.js +151 -0
- package/dist/landings-F7LOAEJE.js.map +1 -0
- package/dist/languages-P3ZM6R2A.js +40 -0
- package/dist/languages-P3ZM6R2A.js.map +1 -0
- package/dist/languages-XEJKTIFP.js +55 -0
- package/dist/languages-XEJKTIFP.js.map +1 -0
- package/dist/launches-TCFAYUA5.js +19 -0
- package/dist/launches-TCFAYUA5.js.map +1 -0
- package/dist/layerize-ZSKFIPZA.js +190 -0
- package/dist/layerize-ZSKFIPZA.js.map +1 -0
- package/dist/leads-GDF4S2AM.js +90 -0
- package/dist/leads-GDF4S2AM.js.map +1 -0
- package/dist/leads-TPB5OFSQ.js +293 -0
- package/dist/leads-TPB5OFSQ.js.map +1 -0
- package/dist/learn-NMFEA5H5.js +203 -0
- package/dist/learn-NMFEA5H5.js.map +1 -0
- package/dist/library-IP2UKNRU.js +109 -0
- package/dist/library-IP2UKNRU.js.map +1 -0
- package/dist/lighthouse-57XBJRCO.js +75 -0
- package/dist/lighthouse-57XBJRCO.js.map +1 -0
- package/dist/line-item-writes-O6SSS5NQ.js +208 -0
- package/dist/line-item-writes-O6SSS5NQ.js.map +1 -0
- package/dist/line-items-ZZAKH3YZ.js +103 -0
- package/dist/line-items-ZZAKH3YZ.js.map +1 -0
- package/dist/link-CRY57R3E.js +64 -0
- package/dist/link-CRY57R3E.js.map +1 -0
- package/dist/linkedin-WC7LGYPP.js +1008 -0
- package/dist/linkedin-WC7LGYPP.js.map +1 -0
- package/dist/list-6IKPWQGG.js +57 -0
- package/dist/list-6IKPWQGG.js.map +1 -0
- package/dist/list-CAUH3BMG.js +65 -0
- package/dist/list-CAUH3BMG.js.map +1 -0
- package/dist/list-CWAKX5TH.js +63 -0
- package/dist/list-CWAKX5TH.js.map +1 -0
- package/dist/list-FJ5FSVL6.js +151 -0
- package/dist/list-FJ5FSVL6.js.map +1 -0
- package/dist/list-GTOSN7DP.js +50 -0
- package/dist/list-GTOSN7DP.js.map +1 -0
- package/dist/list-HLJP4NVE.js +51 -0
- package/dist/list-HLJP4NVE.js.map +1 -0
- package/dist/list-LCUPF7EF.js +76 -0
- package/dist/list-LCUPF7EF.js.map +1 -0
- package/dist/list-NH4ZRZTL.js +303 -0
- package/dist/list-NH4ZRZTL.js.map +1 -0
- package/dist/locations-2BYWKIYA.js +67 -0
- package/dist/locations-2BYWKIYA.js.map +1 -0
- package/dist/locations-LVVDOSXO.js +40 -0
- package/dist/locations-LVVDOSXO.js.map +1 -0
- package/dist/log-6JOWOY5G.js +92 -0
- package/dist/log-6JOWOY5G.js.map +1 -0
- package/dist/logo-AJK2TDQU.js +18 -0
- package/dist/logo-AJK2TDQU.js.map +1 -0
- package/dist/lookup-H5GEM77H.js +22 -0
- package/dist/lookup-H5GEM77H.js.map +1 -0
- package/dist/make-N3WZ6OSS.js +640 -0
- package/dist/make-N3WZ6OSS.js.map +1 -0
- package/dist/map-4KOYFHAN.js +404 -0
- package/dist/map-4KOYFHAN.js.map +1 -0
- package/dist/mcp-LSS2DHYL.js +463 -0
- package/dist/mcp-LSS2DHYL.js.map +1 -0
- package/dist/media-JBCN6V4X.js +15 -0
- package/dist/media-JBCN6V4X.js.map +1 -0
- package/dist/media-RAGEJTZX.js +89 -0
- package/dist/media-RAGEJTZX.js.map +1 -0
- package/dist/media-sources-GSPAV7HT.js +32 -0
- package/dist/media-sources-GSPAV7HT.js.map +1 -0
- package/dist/members-GUUVEK2Y.js +44 -0
- package/dist/members-GUUVEK2Y.js.map +1 -0
- package/dist/meta-Z37ZR3PJ.js +69 -0
- package/dist/meta-Z37ZR3PJ.js.map +1 -0
- package/dist/metrics-KW6SDULI.js +152 -0
- package/dist/metrics-KW6SDULI.js.map +1 -0
- package/dist/models-5J4WFUD3.js +155 -0
- package/dist/models-5J4WFUD3.js.map +1 -0
- package/dist/normalize-DSFVTRXN.js +806 -0
- package/dist/normalize-DSFVTRXN.js.map +1 -0
- package/dist/normalize-EUDI5HEM.js +141 -0
- package/dist/normalize-EUDI5HEM.js.map +1 -0
- package/dist/options-P4PPJQH4.js +121 -0
- package/dist/options-P4PPJQH4.js.map +1 -0
- package/dist/output-DTCLVPUF.js +24 -0
- package/dist/output-DTCLVPUF.js.map +1 -0
- package/dist/page-N2ZO3O7F.js +105 -0
- package/dist/page-N2ZO3O7F.js.map +1 -0
- package/dist/pages-FQ4CBAJ2.js +66 -0
- package/dist/pages-FQ4CBAJ2.js.map +1 -0
- package/dist/performance-A66LYIZX.js +24 -0
- package/dist/performance-A66LYIZX.js.map +1 -0
- package/dist/pinterest-NV5XTNJE.js +96 -0
- package/dist/pinterest-NV5XTNJE.js.map +1 -0
- package/dist/pixels-CTJ43FZ4.js +108 -0
- package/dist/pixels-CTJ43FZ4.js.map +1 -0
- package/dist/pixels-HKINGZCH.js +60 -0
- package/dist/pixels-HKINGZCH.js.map +1 -0
- package/dist/plan-ZYTWLGWK.js +207 -0
- package/dist/plan-ZYTWLGWK.js.map +1 -0
- package/dist/preview-5ROBOQG7.js +169 -0
- package/dist/preview-5ROBOQG7.js.map +1 -0
- package/dist/profile-Q3PHR6FU.js +159 -0
- package/dist/profile-Q3PHR6FU.js.map +1 -0
- package/dist/promoted-tweet-writes-AEOUK2LK.js +180 -0
- package/dist/promoted-tweet-writes-AEOUK2LK.js.map +1 -0
- package/dist/promoted-tweets-L2CEC2BJ.js +119 -0
- package/dist/promoted-tweets-L2CEC2BJ.js.map +1 -0
- package/dist/properties-WLL6M2P6.js +101 -0
- package/dist/properties-WLL6M2P6.js.map +1 -0
- package/dist/publish-KHNR5ARF.js +322 -0
- package/dist/publish-KHNR5ARF.js.map +1 -0
- package/dist/query-A34J7BGX.js +61 -0
- package/dist/query-A34J7BGX.js.map +1 -0
- package/dist/query-IYZN5KHO.js +236 -0
- package/dist/query-IYZN5KHO.js.map +1 -0
- package/dist/query-UN2P6DBA.js +247 -0
- package/dist/query-UN2P6DBA.js.map +1 -0
- package/dist/questionnaire-Z2ZIKNBV.js +93 -0
- package/dist/questionnaire-Z2ZIKNBV.js.map +1 -0
- package/dist/read-GM7PQYJA.js +141 -0
- package/dist/read-GM7PQYJA.js.map +1 -0
- package/dist/reddit-5NPFULGD.js +26 -0
- package/dist/reddit-5NPFULGD.js.map +1 -0
- package/dist/refresh-FGXW4Y4X.js +94 -0
- package/dist/refresh-FGXW4Y4X.js.map +1 -0
- package/dist/release-OKZMC73N.js +60 -0
- package/dist/release-OKZMC73N.js.map +1 -0
- package/dist/relevant-pages-J76ZKNKF.js +99 -0
- package/dist/relevant-pages-J76ZKNKF.js.map +1 -0
- package/dist/remove-CA2J6ACH.js +50 -0
- package/dist/remove-CA2J6ACH.js.map +1 -0
- package/dist/remove-GOYW2G4R.js +48 -0
- package/dist/remove-GOYW2G4R.js.map +1 -0
- package/dist/reopen-XPKSOE6O.js +63 -0
- package/dist/reopen-XPKSOE6O.js.map +1 -0
- package/dist/rerun-QA6ISKVO.js +86 -0
- package/dist/rerun-QA6ISKVO.js.map +1 -0
- package/dist/research-FZ63UZTE.js +62 -0
- package/dist/research-FZ63UZTE.js.map +1 -0
- package/dist/research-YGQQ6CNG.js +262 -0
- package/dist/research-YGQQ6CNG.js.map +1 -0
- package/dist/reset-BGPZ4HMA.js +54 -0
- package/dist/reset-BGPZ4HMA.js.map +1 -0
- package/dist/reset-HTD6LCIT.js +54 -0
- package/dist/reset-HTD6LCIT.js.map +1 -0
- package/dist/resolve-NRDZ6N2B.js +121 -0
- package/dist/resolve-NRDZ6N2B.js.map +1 -0
- package/dist/retry-PF4BGKJV.js +60 -0
- package/dist/retry-PF4BGKJV.js.map +1 -0
- package/dist/retry-XL26JDAV.js +62 -0
- package/dist/retry-XL26JDAV.js.map +1 -0
- package/dist/retry-failed-BEFWRV4Z.js +45 -0
- package/dist/retry-failed-BEFWRV4Z.js.map +1 -0
- package/dist/run-3ZDGCCTH.js +61 -0
- package/dist/run-3ZDGCCTH.js.map +1 -0
- package/dist/run-EMJLI7LR.js +65 -0
- package/dist/run-EMJLI7LR.js.map +1 -0
- package/dist/scaffold-ad-QW75LLYR.js +1550 -0
- package/dist/scaffold-ad-QW75LLYR.js.map +1 -0
- package/dist/scaffold-static-ad-S3UOKLJ3.js +973 -0
- package/dist/scaffold-static-ad-S3UOKLJ3.js.map +1 -0
- package/dist/scaffold-video-3BJQOUAA.js +874 -0
- package/dist/scaffold-video-3BJQOUAA.js.map +1 -0
- package/dist/schedule-KQ7UIR3N.js +66 -0
- package/dist/schedule-KQ7UIR3N.js.map +1 -0
- package/dist/schedule-PKPNSISL.js +61 -0
- package/dist/schedule-PKPNSISL.js.map +1 -0
- package/dist/scheduled-agents-LP5LITA3.js +49 -0
- package/dist/scheduled-agents-LP5LITA3.js.map +1 -0
- package/dist/schema-B6J6VPTO.js +132 -0
- package/dist/schema-B6J6VPTO.js.map +1 -0
- package/dist/schema-QXTDLZVC.js +63 -0
- package/dist/schema-QXTDLZVC.js.map +1 -0
- package/dist/scrape-7YKJWFZE.js +2241 -0
- package/dist/scrape-7YKJWFZE.js.map +1 -0
- package/dist/screenshot-ZHBSG3SI.js +102 -0
- package/dist/screenshot-ZHBSG3SI.js.map +1 -0
- package/dist/search-332KFYZ6.js +224 -0
- package/dist/search-332KFYZ6.js.map +1 -0
- package/dist/search-4PBMXXUY.js +91 -0
- package/dist/search-4PBMXXUY.js.map +1 -0
- package/dist/search-6WNUKCMP.js +174 -0
- package/dist/search-6WNUKCMP.js.map +1 -0
- package/dist/search-AVNUU6TJ.js +26 -0
- package/dist/search-AVNUU6TJ.js.map +1 -0
- package/dist/search-F5INRFFK.js +92 -0
- package/dist/search-F5INRFFK.js.map +1 -0
- package/dist/search-copy-DZVBYG2B.js +168 -0
- package/dist/search-copy-DZVBYG2B.js.map +1 -0
- package/dist/seeds-5JTQN5WI.js +101 -0
- package/dist/seeds-5JTQN5WI.js.map +1 -0
- package/dist/select-2V6CHATD.js +96 -0
- package/dist/select-2V6CHATD.js.map +1 -0
- package/dist/sends-3L6QBS46.js +309 -0
- package/dist/sends-3L6QBS46.js.map +1 -0
- package/dist/sequences-YKFV7BDH.js +146 -0
- package/dist/sequences-YKFV7BDH.js.map +1 -0
- package/dist/set-prompt-XGZXW63I.js +188 -0
- package/dist/set-prompt-XGZXW63I.js.map +1 -0
- package/dist/setup-links-6H5ONDCQ.js +141 -0
- package/dist/setup-links-6H5ONDCQ.js.map +1 -0
- package/dist/{shared-6762QE6R.js → shared-QAMP7FZV.js} +8 -6
- package/dist/shared-QAMP7FZV.js.map +1 -0
- package/dist/shopify-D3GNV5O6.js +3715 -0
- package/dist/shopify-D3GNV5O6.js.map +1 -0
- package/dist/site-TBPERLY3.js +177 -0
- package/dist/site-TBPERLY3.js.map +1 -0
- package/dist/sitemaps-XPGLW24S.js +87 -0
- package/dist/sitemaps-XPGLW24S.js.map +1 -0
- package/dist/sites-WMBY2HJV.js +101 -0
- package/dist/sites-WMBY2HJV.js.map +1 -0
- package/dist/skills-3HEILQCU.js +47 -0
- package/dist/skills-3HEILQCU.js.map +1 -0
- package/dist/sources-JFQKTK2L.js +421 -0
- package/dist/sources-JFQKTK2L.js.map +1 -0
- package/dist/sources-Q3I6DDV7.js +30 -0
- package/dist/sources-Q3I6DDV7.js.map +1 -0
- package/dist/stale-4SERZW2D.js +66 -0
- package/dist/stale-4SERZW2D.js.map +1 -0
- package/dist/stats-GNILHSKK.js +34 -0
- package/dist/stats-GNILHSKK.js.map +1 -0
- package/dist/status-LIZWJYS4.js +62 -0
- package/dist/status-LIZWJYS4.js.map +1 -0
- package/dist/sticker-KCV3VZHY.js +94 -0
- package/dist/sticker-KCV3VZHY.js.map +1 -0
- package/dist/stock-VTORKR4C.js +179 -0
- package/dist/stock-VTORKR4C.js.map +1 -0
- package/dist/studio-QCRA6BY5.js +49 -0
- package/dist/studio-QCRA6BY5.js.map +1 -0
- package/dist/sync-455DB46Y.js +54 -0
- package/dist/sync-455DB46Y.js.map +1 -0
- package/dist/sync-A4KKQ3B6.js +265 -0
- package/dist/sync-A4KKQ3B6.js.map +1 -0
- package/dist/sync-ULKWDFXM.js +54 -0
- package/dist/sync-ULKWDFXM.js.map +1 -0
- package/dist/sync-definition-YTBLMLX2.js +55 -0
- package/dist/sync-definition-YTBLMLX2.js.map +1 -0
- package/dist/tag-manager-E7QTXBWQ.js +43 -0
- package/dist/tag-manager-E7QTXBWQ.js.map +1 -0
- package/dist/tags-4Q4I5GQJ.js +20 -0
- package/dist/tags-4Q4I5GQJ.js.map +1 -0
- package/dist/tags-AMEVAQZ4.js +26 -0
- package/dist/tags-AMEVAQZ4.js.map +1 -0
- package/dist/tags-DPLOLH3E.js +20 -0
- package/dist/tags-DPLOLH3E.js.map +1 -0
- package/dist/tags-LDHXONR3.js +224 -0
- package/dist/tags-LDHXONR3.js.map +1 -0
- package/dist/tags-UW3WJTAQ.js +20 -0
- package/dist/tags-UW3WJTAQ.js.map +1 -0
- package/dist/targeting-constants-D64YO3E7.js +118 -0
- package/dist/targeting-constants-D64YO3E7.js.map +1 -0
- package/dist/targeting-criteria-BP6VJA7X.js +113 -0
- package/dist/targeting-criteria-BP6VJA7X.js.map +1 -0
- package/dist/targets-CQWO2UXD.js +102 -0
- package/dist/targets-CQWO2UXD.js.map +1 -0
- package/dist/templates-WZSTNRNZ.js +178 -0
- package/dist/templates-WZSTNRNZ.js.map +1 -0
- package/dist/testimonials-ETHSNWUH.js +32 -0
- package/dist/testimonials-ETHSNWUH.js.map +1 -0
- package/dist/themes-YU663LQH.js +94 -0
- package/dist/themes-YU663LQH.js.map +1 -0
- package/dist/top-companies-KTXHS472.js +108 -0
- package/dist/top-companies-KTXHS472.js.map +1 -0
- package/dist/translate-6QAJ5ZUU.js +600 -0
- package/dist/translate-6QAJ5ZUU.js.map +1 -0
- package/dist/triggers-4EDFLNGH.js +141 -0
- package/dist/triggers-4EDFLNGH.js.map +1 -0
- package/dist/tweets-ZUKQAAUQ.js +123 -0
- package/dist/tweets-ZUKQAAUQ.js.map +1 -0
- package/dist/unfollow-A4JVCJBF.js +46 -0
- package/dist/unfollow-A4JVCJBF.js.map +1 -0
- package/dist/unlink-KY2OEKMD.js +67 -0
- package/dist/unlink-KY2OEKMD.js.map +1 -0
- package/dist/unstage-FHUG67RI.js +84 -0
- package/dist/unstage-FHUG67RI.js.map +1 -0
- package/dist/unstage-ZRLLCSQF.js +95 -0
- package/dist/unstage-ZRLLCSQF.js.map +1 -0
- package/dist/update-27LGM65V.js +63 -0
- package/dist/update-27LGM65V.js.map +1 -0
- package/dist/update-AIY46I2Q.js +155 -0
- package/dist/update-AIY46I2Q.js.map +1 -0
- package/dist/update-QYD2XZFM.js +142 -0
- package/dist/update-QYD2XZFM.js.map +1 -0
- package/dist/update-W2OSRNFO.js +98 -0
- package/dist/update-W2OSRNFO.js.map +1 -0
- package/dist/upload-JGBTSKGH.js +126 -0
- package/dist/upload-JGBTSKGH.js.map +1 -0
- package/dist/upload-XEHWYMJG.js +150 -0
- package/dist/upload-XEHWYMJG.js.map +1 -0
- package/dist/upscale-I5P2OHTN.js +109 -0
- package/dist/upscale-I5P2OHTN.js.map +1 -0
- package/dist/url-options-QHGA42RP.js +130 -0
- package/dist/url-options-QHGA42RP.js.map +1 -0
- package/dist/url-params-NWSUHWRE.js +98 -0
- package/dist/url-params-NWSUHWRE.js.map +1 -0
- package/dist/use-U4HG2NF3.js +95 -0
- package/dist/use-U4HG2NF3.js.map +1 -0
- package/dist/validate-DOQ6AI62.js +91 -0
- package/dist/validate-DOQ6AI62.js.map +1 -0
- package/dist/variant-FOVE6URJ.js +338 -0
- package/dist/variant-FOVE6URJ.js.map +1 -0
- package/dist/videos-DP3VCSYG.js +39 -0
- package/dist/videos-DP3VCSYG.js.map +1 -0
- package/dist/view-HRI3FHCH.js +121 -0
- package/dist/view-HRI3FHCH.js.map +1 -0
- package/dist/viewer-check-JYUE24M6.js +68 -0
- package/dist/viewer-check-JYUE24M6.js.map +1 -0
- package/dist/web-AFUIWPFU.js +140 -0
- package/dist/web-AFUIWPFU.js.map +1 -0
- package/dist/winners-SMMDN6LW.js +113 -0
- package/dist/winners-SMMDN6LW.js.map +1 -0
- package/dist/winning-ads-PCIJUYVA.js +84 -0
- package/dist/winning-ads-PCIJUYVA.js.map +1 -0
- package/dist/write-commands-7Z34WG2J.js +206 -0
- package/dist/write-commands-7Z34WG2J.js.map +1 -0
- package/dist/write-commands-BLT2SEC4.js +713 -0
- package/dist/write-commands-BLT2SEC4.js.map +1 -0
- package/dist/write-commands-N4FSGRVQ.js +743 -0
- package/dist/write-commands-N4FSGRVQ.js.map +1 -0
- package/dist/write-commands-Q4MQ3BGM.js +1015 -0
- package/dist/write-commands-Q4MQ3BGM.js.map +1 -0
- package/dist/x-AUOZJNWE.js +47 -0
- package/dist/x-AUOZJNWE.js.map +1 -0
- package/package.json +9 -2
- package/dist/chunk-FGHMWBUD.js +0 -9989
- package/dist/chunk-FGHMWBUD.js.map +0 -1
- package/dist/chunk-HJEMOSPH.js +0 -1292
- package/dist/chunk-HJEMOSPH.js.map +0 -1
- package/dist/chunk-MF7YA62W.js.map +0 -1
- package/dist/chunk-VZEDAFAR.js.map +0 -1
- package/dist/chunk-XHC4LMK4.js.map +0 -1
- package/dist/client-GR6YL3YX.js +0 -17
- package/dist/output-NMQXZF3Z.js +0 -18
- /package/dist/{chunk-WLDM2TRF.js.map → chunk-TPXI2GCW.js.map} +0 -0
- /package/dist/{client-GR6YL3YX.js.map → chunk-YQSBHWOI.js.map} +0 -0
- /package/dist/{env-4P5HOGNA.js.map → client-26SAJ46D.js.map} +0 -0
- /package/dist/{output-NMQXZF3Z.js.map → connect-RXPMAJQI.js.map} +0 -0
- /package/dist/{shared-6762QE6R.js.map → customers-P6LLLJHK.js.map} +0 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import {
|
|
2
|
+
MODEL_REGISTRY,
|
|
3
|
+
isRegisteredModel
|
|
4
|
+
} from "./chunk-CAMX6OHF.js";
|
|
5
|
+
|
|
6
|
+
// src/commands/canvas/scaffold-common.ts
|
|
7
|
+
import { access, readFile } from "fs/promises";
|
|
8
|
+
|
|
9
|
+
// src/commands/canvas/composition-path.ts
|
|
10
|
+
import { existsSync } from "fs";
|
|
11
|
+
import path from "path";
|
|
12
|
+
function resolveShippedCanvasDir(name, startDir, exists = existsSync, maxDepth = 8) {
|
|
13
|
+
const rel = path.join("canvas", name);
|
|
14
|
+
let dir = startDir;
|
|
15
|
+
for (let i = 0; i < maxDepth; i++) {
|
|
16
|
+
const candidate = path.join(dir, rel);
|
|
17
|
+
if (exists(path.join(candidate, "meta.json"))) return candidate;
|
|
18
|
+
const parent = path.dirname(dir);
|
|
19
|
+
if (parent === dir) break;
|
|
20
|
+
dir = parent;
|
|
21
|
+
}
|
|
22
|
+
return path.resolve(startDir, "../../../", rel);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// src/commands/canvas/scaffold-common.ts
|
|
26
|
+
var SHIPPED_OVERLAY_COMPOSITION_DIR = resolveShippedCanvasDir(
|
|
27
|
+
"video-overlay-composition",
|
|
28
|
+
import.meta.dirname
|
|
29
|
+
);
|
|
30
|
+
var SHIPPED_CAPTIONS_DIR = resolveShippedCanvasDir("tiktok-captions-composition", import.meta.dirname);
|
|
31
|
+
function resolveModel(kind, requested, fallback) {
|
|
32
|
+
const model = requested ? String(requested) : fallback;
|
|
33
|
+
if (isRegisteredModel(kind, model)) return model;
|
|
34
|
+
const known = Object.keys(MODEL_REGISTRY[kind]).join(", ");
|
|
35
|
+
throw new Error(`"${model}" is not a ${kind} model. Use one of: ${known}`);
|
|
36
|
+
}
|
|
37
|
+
async function loadAssetText(ref, label) {
|
|
38
|
+
const r = ref;
|
|
39
|
+
if (typeof r?.path === "string") return readFile(r.path, "utf8");
|
|
40
|
+
if (typeof r?.url === "string") {
|
|
41
|
+
const res = await fetch(r.url);
|
|
42
|
+
if (!res.ok) throw new Error(`failed to fetch ${label} (${res.status})`);
|
|
43
|
+
return res.text();
|
|
44
|
+
}
|
|
45
|
+
throw new Error(`${label}: output had no readable path or url`);
|
|
46
|
+
}
|
|
47
|
+
function parseElements(raw) {
|
|
48
|
+
const parsed = JSON.parse(raw);
|
|
49
|
+
if (Array.isArray(parsed)) return parsed;
|
|
50
|
+
if (parsed && typeof parsed === "object" && Array.isArray(parsed.elements)) {
|
|
51
|
+
return parsed.elements;
|
|
52
|
+
}
|
|
53
|
+
return [];
|
|
54
|
+
}
|
|
55
|
+
function fail(code, message, fix) {
|
|
56
|
+
process.stderr.write(`${JSON.stringify({ ok: false, error: { code, message, ...fix ? { fix } : {} } }, null, 2)}
|
|
57
|
+
`);
|
|
58
|
+
process.exit(2);
|
|
59
|
+
}
|
|
60
|
+
function fileExists(target) {
|
|
61
|
+
return access(target).then(
|
|
62
|
+
() => true,
|
|
63
|
+
() => false
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export {
|
|
68
|
+
SHIPPED_OVERLAY_COMPOSITION_DIR,
|
|
69
|
+
SHIPPED_CAPTIONS_DIR,
|
|
70
|
+
resolveModel,
|
|
71
|
+
loadAssetText,
|
|
72
|
+
parseElements,
|
|
73
|
+
fail,
|
|
74
|
+
fileExists
|
|
75
|
+
};
|
|
76
|
+
//# sourceMappingURL=chunk-AR7PU7BB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/canvas/scaffold-common.ts","../src/commands/canvas/composition-path.ts"],"sourcesContent":["// What the three scaffold commands (`scaffold-video`, `scaffold-static-ad`,\n// `scaffold-ad`) share: the compositions they ship, how a model flag resolves, and\n// how an analysis pass's output is read back.\n\nimport { access, readFile } from \"node:fs/promises\";\nimport { isRegisteredModel, MODEL_REGISTRY, type NodeKind } from \"@baker/canvas-contract\";\nimport { resolveShippedCanvasDir } from \"./composition-path.ts\";\n\n// The composition templates that ship with the CLI, resolved by walking up to the\n// package's `canvas/` dir so they work in both the dev (tsx) and bundled dist layout.\n/** The ad's text and brand overlay. */\nexport const SHIPPED_OVERLAY_COMPOSITION_DIR = resolveShippedCanvasDir(\n \"video-overlay-composition\",\n import.meta.dirname,\n);\n/** The TikTok-style word-by-word caption track (sound-off feeds). */\nexport const SHIPPED_CAPTIONS_DIR = resolveShippedCanvasDir(\"tiktok-captions-composition\", import.meta.dirname);\n\n/**\n * The model a scaffold node runs on: the one the caller named, else the role default.\n *\n * Either must be registered for `kind`, and an unknown one is an error naming what\n * the registry does have. This used to fall back to the registry's first id, so a\n * typo in a model flag rendered every node on a model nobody chose.\n */\nexport function resolveModel(kind: NodeKind, requested: unknown, fallback: string): string {\n const model = requested ? String(requested) : fallback;\n if (isRegisteredModel(kind, model)) return model;\n const known = Object.keys(MODEL_REGISTRY[kind]).join(\", \");\n throw new Error(`\"${model}\" is not a ${kind} model. Use one of: ${known}`);\n}\n\ntype LoadableRef = { path?: unknown; url?: unknown };\n\n/** Read an asset's content as text: the locally-ingested file first, else its URL. */\nexport async function loadAssetText(ref: unknown, label: string): Promise<string> {\n const r = ref as LoadableRef;\n if (typeof r?.path === \"string\") return readFile(r.path, \"utf8\");\n if (typeof r?.url === \"string\") {\n const res = await fetch(r.url);\n if (!res.ok) throw new Error(`failed to fetch ${label} (${res.status})`);\n return res.text();\n }\n throw new Error(`${label}: output had no readable path or url`);\n}\n\n/** Parse the selection pass output into the elements array ({elements:[...]} or a bare array). */\nexport function parseElements(raw: string): unknown[] {\n const parsed = JSON.parse(raw) as unknown;\n if (Array.isArray(parsed)) return parsed;\n if (parsed && typeof parsed === \"object\" && Array.isArray((parsed as { elements?: unknown }).elements)) {\n return (parsed as { elements: unknown[] }).elements;\n }\n return [];\n}\n\n/** Print the `{ ok: false, error }` envelope and exit 2. */\nexport function fail(code: string, message: string, fix?: string): never {\n process.stderr.write(`${JSON.stringify({ ok: false, error: { code, message, ...(fix ? { fix } : {}) } }, null, 2)}\\n`);\n process.exit(2);\n}\n\nexport function fileExists(target: string): Promise<boolean> {\n return access(target).then(\n () => true,\n () => false,\n );\n}\n","import { existsSync } from \"node:fs\";\nimport path from \"node:path\";\n\n/**\n * Resolve a shipped `canvas/<name>` asset dir, robust to BOTH module layouts:\n * - dev (tsx): this code lives at `src/commands/canvas/`, so the asset is at\n * `<package root>/canvas/<name>` — three levels up.\n * - published (tsup): `src/**` is flattened into a single `dist/cli.js`, so the\n * same code now lives at `<package root>/dist/`, and the asset is `../canvas/<name>`.\n *\n * A single hardcoded relative path cannot satisfy both layouts (the previous\n * `../../../canvas` worked from src but overshot the package entirely from the\n * bundled dist, throwing ENOENT after the billed deconstruct already ran). So\n * instead of guessing the nesting, walk UP from the module dir until we find a\n * `canvas/<name>` that actually exists on disk. `canvas` must stay in\n * package.json `files` for the published build to ship the asset at all.\n */\nexport function resolveShippedCanvasDir(\n name: string,\n startDir: string,\n exists: (p: string) => boolean = existsSync,\n maxDepth = 8,\n): string {\n const rel = path.join(\"canvas\", name);\n let dir = startDir;\n for (let i = 0; i < maxDepth; i++) {\n const candidate = path.join(dir, rel);\n // `meta.json` is the composition's manifest — its presence proves we found\n // the real asset dir, not an empty `canvas/` that happens to exist higher up.\n if (exists(path.join(candidate, \"meta.json\"))) return candidate;\n const parent = path.dirname(dir);\n if (parent === dir) break; // reached filesystem root\n dir = parent;\n }\n // Fall back to the dev src-relative location so a missing asset still produces\n // a clear \"no such file\" at copy time rather than a silently-wrong path.\n return path.resolve(startDir, \"../../../\", rel);\n}\n"],"mappings":";;;;;;AAIA,SAAS,QAAQ,gBAAgB;;;ACJjC,SAAS,kBAAkB;AAC3B,OAAO,UAAU;AAgBV,SAAS,wBACd,MACA,UACA,SAAiC,YACjC,WAAW,GACH;AACR,QAAM,MAAM,KAAK,KAAK,UAAU,IAAI;AACpC,MAAI,MAAM;AACV,WAAS,IAAI,GAAG,IAAI,UAAU,KAAK;AACjC,UAAM,YAAY,KAAK,KAAK,KAAK,GAAG;AAGpC,QAAI,OAAO,KAAK,KAAK,WAAW,WAAW,CAAC,EAAG,QAAO;AACtD,UAAM,SAAS,KAAK,QAAQ,GAAG;AAC/B,QAAI,WAAW,IAAK;AACpB,UAAM;AAAA,EACR;AAGA,SAAO,KAAK,QAAQ,UAAU,aAAa,GAAG;AAChD;;;AD1BO,IAAM,kCAAkC;AAAA,EAC7C;AAAA,EACA,YAAY;AACd;AAEO,IAAM,uBAAuB,wBAAwB,+BAA+B,YAAY,OAAO;AASvG,SAAS,aAAa,MAAgB,WAAoB,UAA0B;AACzF,QAAM,QAAQ,YAAY,OAAO,SAAS,IAAI;AAC9C,MAAI,kBAAkB,MAAM,KAAK,EAAG,QAAO;AAC3C,QAAM,QAAQ,OAAO,KAAK,eAAe,IAAI,CAAC,EAAE,KAAK,IAAI;AACzD,QAAM,IAAI,MAAM,IAAI,KAAK,cAAc,IAAI,uBAAuB,KAAK,EAAE;AAC3E;AAKA,eAAsB,cAAc,KAAc,OAAgC;AAChF,QAAM,IAAI;AACV,MAAI,OAAO,GAAG,SAAS,SAAU,QAAO,SAAS,EAAE,MAAM,MAAM;AAC/D,MAAI,OAAO,GAAG,QAAQ,UAAU;AAC9B,UAAM,MAAM,MAAM,MAAM,EAAE,GAAG;AAC7B,QAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,mBAAmB,KAAK,KAAK,IAAI,MAAM,GAAG;AACvE,WAAO,IAAI,KAAK;AAAA,EAClB;AACA,QAAM,IAAI,MAAM,GAAG,KAAK,sCAAsC;AAChE;AAGO,SAAS,cAAc,KAAwB;AACpD,QAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,MAAI,MAAM,QAAQ,MAAM,EAAG,QAAO;AAClC,MAAI,UAAU,OAAO,WAAW,YAAY,MAAM,QAAS,OAAkC,QAAQ,GAAG;AACtG,WAAQ,OAAmC;AAAA,EAC7C;AACA,SAAO,CAAC;AACV;AAGO,SAAS,KAAK,MAAc,SAAiB,KAAqB;AACvE,UAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,EAAE,IAAI,OAAO,OAAO,EAAE,MAAM,SAAS,GAAI,MAAM,EAAE,IAAI,IAAI,CAAC,EAAG,EAAE,GAAG,MAAM,CAAC,CAAC;AAAA,CAAI;AACrH,UAAQ,KAAK,CAAC;AAChB;AAEO,SAAS,WAAW,QAAkC;AAC3D,SAAO,OAAO,MAAM,EAAE;AAAA,IACpB,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AACF;","names":[]}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import {
|
|
2
|
+
loadCompositionMeta
|
|
3
|
+
} from "./chunk-KZUHRZ2C.js";
|
|
4
|
+
import {
|
|
5
|
+
parseRefExpr
|
|
6
|
+
} from "./chunk-66USKCVY.js";
|
|
7
|
+
import {
|
|
8
|
+
resolveAdaptFormats
|
|
9
|
+
} from "./chunk-CAMX6OHF.js";
|
|
10
|
+
|
|
11
|
+
// src/commands/canvas/output-ratio.ts
|
|
12
|
+
import { readFile } from "fs/promises";
|
|
13
|
+
import path from "path";
|
|
14
|
+
function definitionFormats(markdown) {
|
|
15
|
+
const front = markdown.match(/^---\n([\s\S]*?)\n---/)?.[1];
|
|
16
|
+
if (!front) return [];
|
|
17
|
+
const clean = (s) => s.trim().replace(/^["']|["']$/g, "");
|
|
18
|
+
const flow = front.match(/^formats:\s*\[([^\]]*)\]/m);
|
|
19
|
+
if (flow) return (flow[1] ?? "").split(",").map(clean).filter(Boolean);
|
|
20
|
+
const block = front.match(/^formats:\s*\n((?:\s+-\s+.*\n?)+)/m);
|
|
21
|
+
if (!block) return [];
|
|
22
|
+
return (block[1] ?? "").split("\n").map((l) => l.replace(/^\s+-\s+/, "")).map(clean).filter(Boolean);
|
|
23
|
+
}
|
|
24
|
+
function reduce(width, height) {
|
|
25
|
+
const gcd = (a, b) => b === 0 ? a : gcd(b, a % b);
|
|
26
|
+
const d = gcd(width, height);
|
|
27
|
+
return `${width / d}:${height / d}`;
|
|
28
|
+
}
|
|
29
|
+
async function ratiosOf(nodes, id, seen) {
|
|
30
|
+
const node = nodes.get(id);
|
|
31
|
+
if (!node || seen.has(id)) return null;
|
|
32
|
+
seen.add(id);
|
|
33
|
+
const p = node.params ?? {};
|
|
34
|
+
switch (node.type) {
|
|
35
|
+
case "image_generate":
|
|
36
|
+
return typeof p.aspect_ratio === "string" ? [p.aspect_ratio] : null;
|
|
37
|
+
case "image_aspect_adapt":
|
|
38
|
+
return [...resolveAdaptFormats(p)];
|
|
39
|
+
case "hyperframe_snapshot": {
|
|
40
|
+
if (typeof p.composition !== "string") return null;
|
|
41
|
+
const meta = await loadCompositionMeta(p.composition).catch(() => null);
|
|
42
|
+
return meta ? [reduce(meta.width, meta.height)] : null;
|
|
43
|
+
}
|
|
44
|
+
case "collect": {
|
|
45
|
+
const images = node.inputs?.images;
|
|
46
|
+
if (!Array.isArray(images)) return null;
|
|
47
|
+
const out = [];
|
|
48
|
+
for (const entry of images) {
|
|
49
|
+
const ref = typeof entry === "string" ? parseRefExpr(entry) : null;
|
|
50
|
+
if (!ref || ref.kind !== "ref") return null;
|
|
51
|
+
const upstream = await ratiosOf(nodes, ref.nodeId, seen);
|
|
52
|
+
if (!upstream) return null;
|
|
53
|
+
out.push(ref.index !== void 0 && upstream.length > 1 ? upstream[ref.index] ?? "" : upstream[0] ?? "");
|
|
54
|
+
}
|
|
55
|
+
return out.filter(Boolean);
|
|
56
|
+
}
|
|
57
|
+
default:
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
async function producedRatios(canvas) {
|
|
62
|
+
const c = canvas;
|
|
63
|
+
if (!Array.isArray(c?.nodes) || typeof c?.output?.node !== "string") return null;
|
|
64
|
+
const nodes = new Map(c.nodes.flatMap((n) => typeof n.id === "string" ? [[n.id, n]] : []));
|
|
65
|
+
return ratiosOf(nodes, c.output.node, /* @__PURE__ */ new Set());
|
|
66
|
+
}
|
|
67
|
+
function value(ratio) {
|
|
68
|
+
const [w, h] = ratio.split(":").map(Number);
|
|
69
|
+
return w && h ? w / h : null;
|
|
70
|
+
}
|
|
71
|
+
function outputRatioWarnings(declared, produced) {
|
|
72
|
+
if (!produced || produced.length === 0) return [];
|
|
73
|
+
const shapes = produced.flatMap((r) => value(r) ?? []);
|
|
74
|
+
return declared.flatMap((format) => {
|
|
75
|
+
const want = value(format);
|
|
76
|
+
if (want === null || shapes.some((s) => Math.abs(s / want - 1) <= 0.02)) return [];
|
|
77
|
+
return [
|
|
78
|
+
{
|
|
79
|
+
path: "output",
|
|
80
|
+
code: "OUTPUT_RATIO_MISMATCH",
|
|
81
|
+
severity: "warning",
|
|
82
|
+
message: `_definition.md declares ${format}, but this canvas delivers ${produced.join(", ")}. A ${format} placement would get the wrong shape: re-scaffold with that format, or fix the formats the creative declares.`
|
|
83
|
+
}
|
|
84
|
+
];
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
async function outputRatioWarningsFor(canvas, canvasPath) {
|
|
88
|
+
const definition = await readFile(path.join(path.dirname(canvasPath), "_definition.md"), "utf8").catch(() => null);
|
|
89
|
+
if (!definition) return [];
|
|
90
|
+
return outputRatioWarnings(definitionFormats(definition), await producedRatios(canvas));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export {
|
|
94
|
+
outputRatioWarningsFor
|
|
95
|
+
};
|
|
96
|
+
//# sourceMappingURL=chunk-ASL7JFBD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/canvas/output-ratio.ts"],"sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { resolveAdaptFormats } from \"@baker/canvas-contract\";\nimport type { ValidationIssue } from \"../../engine/engine/errors.ts\";\nimport { loadCompositionMeta } from \"../../engine/engine/composition-meta.ts\";\nimport { parseRefExpr } from \"../../engine/schema/canvas.ts\";\n\n/**\n * Does the canvas deliver the formats its creative says it delivers?\n *\n * A creative declared `formats: [\"4:5\"]` shipped a 1024x1536 image into a staged Meta ad:\n * its hero was generated at 3:4 (gpt-image has no 4:5) and nothing converted it, and\n * `validate` answered `warnings: []`. This compares the shapes the canvas's output is\n * rendered at with the formats `_definition.md` declares, and warns before anything bills.\n */\n\n/** The `formats` a `_definition.md` frontmatter declares (flow or block list). */\nexport function definitionFormats(markdown: string): string[] {\n const front = markdown.match(/^---\\n([\\s\\S]*?)\\n---/)?.[1];\n if (!front) return [];\n const clean = (s: string) => s.trim().replace(/^[\"']|[\"']$/g, \"\");\n const flow = front.match(/^formats:\\s*\\[([^\\]]*)\\]/m);\n if (flow) return (flow[1] ?? \"\").split(\",\").map(clean).filter(Boolean);\n const block = front.match(/^formats:\\s*\\n((?:\\s+-\\s+.*\\n?)+)/m);\n if (!block) return [];\n return (block[1] ?? \"\")\n .split(\"\\n\")\n .map((l) => l.replace(/^\\s+-\\s+/, \"\"))\n .map(clean)\n .filter(Boolean);\n}\n\ntype Node = { id?: unknown; type?: unknown; params?: Record<string, unknown>; inputs?: Record<string, unknown> };\n\nfunction reduce(width: number, height: number): string {\n const gcd = (a: number, b: number): number => (b === 0 ? a : gcd(b, a % b));\n const d = gcd(width, height);\n return `${width / d}:${height / d}`;\n}\n\n/** The ratios one node renders at, or null when its shape cannot be known before the run. */\nasync function ratiosOf(nodes: Map<string, Node>, id: string, seen: Set<string>): Promise<string[] | null> {\n const node = nodes.get(id);\n if (!node || seen.has(id)) return null;\n seen.add(id);\n const p = node.params ?? {};\n switch (node.type) {\n case \"image_generate\":\n return typeof p.aspect_ratio === \"string\" ? [p.aspect_ratio] : null;\n case \"image_aspect_adapt\":\n return [...resolveAdaptFormats(p as Parameters<typeof resolveAdaptFormats>[0])];\n case \"hyperframe_snapshot\": {\n if (typeof p.composition !== \"string\") return null;\n const meta = await loadCompositionMeta(p.composition).catch(() => null);\n return meta ? [reduce(meta.width, meta.height)] : null;\n }\n case \"collect\": {\n const images = node.inputs?.images;\n if (!Array.isArray(images)) return null;\n const out: string[] = [];\n for (const entry of images) {\n const ref = typeof entry === \"string\" ? parseRefExpr(entry) : null;\n if (!ref || ref.kind !== \"ref\") return null;\n const upstream = await ratiosOf(nodes, ref.nodeId, seen);\n if (!upstream) return null;\n out.push(ref.index !== undefined && upstream.length > 1 ? (upstream[ref.index] ?? \"\") : (upstream[0] ?? \"\"));\n }\n return out.filter(Boolean);\n }\n default:\n return null;\n }\n}\n\n/**\n * The ratios the canvas's output is rendered at, in order, or null when any of them\n * cannot be known before the run (a local transform, a hand-built node). Composition\n * paths must already be resolved.\n */\nexport async function producedRatios(canvas: unknown): Promise<string[] | null> {\n const c = canvas as { nodes?: unknown; output?: { node?: unknown } } | null;\n if (!Array.isArray(c?.nodes) || typeof c?.output?.node !== \"string\") return null;\n const nodes = new Map((c.nodes as Node[]).flatMap((n) => (typeof n.id === \"string\" ? [[n.id, n] as const] : [])));\n return ratiosOf(nodes, c.output.node, new Set());\n}\n\nfunction value(ratio: string): number | null {\n const [w, h] = ratio.split(\":\").map(Number);\n return w && h ? w / h : null;\n}\n\n/** One warning per declared format no output is within 2% of. Pure. */\nexport function outputRatioWarnings(declared: string[], produced: string[] | null): ValidationIssue[] {\n if (!produced || produced.length === 0) return [];\n const shapes = produced.flatMap((r) => value(r) ?? []);\n return declared.flatMap((format) => {\n const want = value(format);\n if (want === null || shapes.some((s) => Math.abs(s / want - 1) <= 0.02)) return [];\n return [\n {\n path: \"output\",\n code: \"OUTPUT_RATIO_MISMATCH\",\n severity: \"warning\" as const,\n message: `_definition.md declares ${format}, but this canvas delivers ${produced.join(\", \")}. A ${format} placement would get the wrong shape: re-scaffold with that format, or fix the formats the creative declares.`,\n },\n ];\n });\n}\n\n/** The warnings for the canvas at `canvasPath`, read against its own `_definition.md`. */\nexport async function outputRatioWarningsFor(canvas: unknown, canvasPath: string): Promise<ValidationIssue[]> {\n const definition = await readFile(path.join(path.dirname(canvasPath), \"_definition.md\"), \"utf8\").catch(() => null);\n if (!definition) return [];\n return outputRatioWarnings(definitionFormats(definition), await producedRatios(canvas));\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import {
|
|
2
|
+
findWorkspaceRoot
|
|
3
|
+
} from "./chunk-HDHWIEJJ.js";
|
|
4
|
+
|
|
5
|
+
// src/commands/canvas/unbilled-spend.ts
|
|
6
|
+
import { randomUUID } from "crypto";
|
|
7
|
+
import { mkdir, readdir, readFile, rename, unlink, writeFile } from "fs/promises";
|
|
8
|
+
import path from "path";
|
|
9
|
+
import { z } from "zod";
|
|
10
|
+
var DIR = "unbilled-spend";
|
|
11
|
+
var Held = z.array(
|
|
12
|
+
z.object({ model: z.string(), inputTokens: z.number(), outputTokens: z.number(), costUsd: z.number() })
|
|
13
|
+
);
|
|
14
|
+
async function holdUnbilledSpend(cacheDir, usage) {
|
|
15
|
+
if (usage.length === 0) return;
|
|
16
|
+
const dir = path.join(cacheDir, DIR);
|
|
17
|
+
await mkdir(dir, { recursive: true });
|
|
18
|
+
await writeFile(path.join(dir, `${Date.now()}-${randomUUID()}.json`), JSON.stringify(usage), "utf8");
|
|
19
|
+
}
|
|
20
|
+
async function holdWorkspaceSpend(usage) {
|
|
21
|
+
const root = findWorkspaceRoot(process.cwd()) ?? process.cwd();
|
|
22
|
+
await holdUnbilledSpend(path.join(root, "canvas", ".cache"), usage).catch(() => {
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
async function takeUnbilledSpend(cacheDir) {
|
|
26
|
+
const dir = path.join(cacheDir, DIR);
|
|
27
|
+
const files = await readdir(dir).catch(() => []);
|
|
28
|
+
const byModel = /* @__PURE__ */ new Map();
|
|
29
|
+
for (const file of files.filter((f) => f.endsWith(".json"))) {
|
|
30
|
+
const claimed = path.join(dir, `${file}.${randomUUID()}.taken`);
|
|
31
|
+
try {
|
|
32
|
+
await rename(path.join(dir, file), claimed);
|
|
33
|
+
} catch {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const parsed = Held.safeParse(await readFile(claimed, "utf8").then(JSON.parse, () => null).catch(() => null));
|
|
37
|
+
await unlink(claimed).catch(() => {
|
|
38
|
+
});
|
|
39
|
+
for (const call of parsed.success ? parsed.data : []) {
|
|
40
|
+
const sum = byModel.get(call.model);
|
|
41
|
+
byModel.set(
|
|
42
|
+
call.model,
|
|
43
|
+
sum ? {
|
|
44
|
+
model: call.model,
|
|
45
|
+
inputTokens: sum.inputTokens + call.inputTokens,
|
|
46
|
+
outputTokens: sum.outputTokens + call.outputTokens,
|
|
47
|
+
costUsd: sum.costUsd + call.costUsd
|
|
48
|
+
} : { ...call }
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return [...byModel.values()];
|
|
53
|
+
}
|
|
54
|
+
async function sendBillingSpend(cacheDir, usage, send) {
|
|
55
|
+
try {
|
|
56
|
+
await send();
|
|
57
|
+
return null;
|
|
58
|
+
} catch (e) {
|
|
59
|
+
await holdUnbilledSpend(cacheDir, usage).catch(() => {
|
|
60
|
+
});
|
|
61
|
+
return e instanceof Error ? e.message : String(e);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function holdWhenSettled(cacheDir, spendOf) {
|
|
65
|
+
const pending = [];
|
|
66
|
+
return {
|
|
67
|
+
settled: (run, outputs) => {
|
|
68
|
+
pending.push(holdUnbilledSpend(cacheDir, spendOf(run, outputs)).catch(() => {
|
|
69
|
+
}));
|
|
70
|
+
},
|
|
71
|
+
drained: async () => {
|
|
72
|
+
await Promise.all(pending);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export {
|
|
78
|
+
holdUnbilledSpend,
|
|
79
|
+
holdWorkspaceSpend,
|
|
80
|
+
takeUnbilledSpend,
|
|
81
|
+
sendBillingSpend,
|
|
82
|
+
holdWhenSettled
|
|
83
|
+
};
|
|
84
|
+
//# sourceMappingURL=chunk-AUSKKFVH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/canvas/unbilled-spend.ts"],"sourcesContent":["/**\n * Gateway spend the CLI made with no run record to carry it: the viewer check run on its\n * own (`baker canvas viewer-check`) or one that refused the render before any run existed.\n *\n * The run record's `reviewUsage` is how a call made in the Runtime reaches the credits\n * ledger (`POST /api/canvas/runs` bills it once, when the terminal record is accepted). So\n * the spend waits here, in the workspace's canvas cache, and the next run record of this\n * workspace takes it. One file per hold and a rename to claim it: two processes never take\n * the same call, and a hold never overwrites another.\n */\nimport { randomUUID } from \"node:crypto\";\nimport { mkdir, readdir, readFile, rename, unlink, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport type { NodeRunRecord } from \"../../engine/engine/executor.ts\";\nimport type { ReviewUsage } from \"../../engine/nodes/local/lib/render-review.ts\";\nimport { findWorkspaceRoot } from \"./normalize-paths.ts\";\n\nconst DIR = \"unbilled-spend\";\n\nconst Held = z.array(\n z.object({ model: z.string(), inputTokens: z.number(), outputTokens: z.number(), costUsd: z.number() }),\n);\n\n/** Keep `usage` for the next run record of this workspace; nothing is written when it is empty. */\nexport async function holdUnbilledSpend(cacheDir: string, usage: readonly ReviewUsage[]): Promise<void> {\n if (usage.length === 0) return;\n const dir = path.join(cacheDir, DIR);\n await mkdir(dir, { recursive: true });\n await writeFile(path.join(dir, `${Date.now()}-${randomUUID()}.json`), JSON.stringify(usage), \"utf8\");\n}\n\n/**\n * One call made by a command with no canvas of its own (`baker actions create`, a feedback note,\n * a CRM file check), held in the workspace the command ran in. Never throws: a lost hold is a\n * call Baker absorbs, never a failed command.\n */\nexport async function holdWorkspaceSpend(usage: readonly ReviewUsage[]): Promise<void> {\n const root = findWorkspaceRoot(process.cwd()) ?? process.cwd();\n await holdUnbilledSpend(path.join(root, \"canvas\", \".cache\"), usage).catch(() => {});\n}\n\n/** Every held call, claimed and removed, summed per model (one record entry each). */\nexport async function takeUnbilledSpend(cacheDir: string): Promise<ReviewUsage[]> {\n const dir = path.join(cacheDir, DIR);\n const files = await readdir(dir).catch(() => [] as string[]);\n const byModel = new Map<string, ReviewUsage>();\n for (const file of files.filter((f) => f.endsWith(\".json\"))) {\n const claimed = path.join(dir, `${file}.${randomUUID()}.taken`);\n try {\n await rename(path.join(dir, file), claimed);\n } catch {\n continue;\n }\n const parsed = Held.safeParse(await readFile(claimed, \"utf8\").then(JSON.parse, () => null).catch(() => null));\n await unlink(claimed).catch(() => {});\n for (const call of parsed.success ? parsed.data : []) {\n const sum = byModel.get(call.model);\n byModel.set(\n call.model,\n sum\n ? {\n model: call.model,\n inputTokens: sum.inputTokens + call.inputTokens,\n outputTokens: sum.outputTokens + call.outputTokens,\n costUsd: sum.costUsd + call.costUsd,\n }\n : { ...call },\n );\n }\n }\n return [...byModel.values()];\n}\n\n/**\n * Send the record that carries `usage`: null when it landed, else why not. When it never does, the\n * spend is held again for the next one; the failure is reported, never thrown, because a\n * record that did not land must not turn a finished render into a failed one.\n */\nexport async function sendBillingSpend(\n cacheDir: string,\n usage: readonly ReviewUsage[],\n send: () => Promise<void>,\n): Promise<string | null> {\n try {\n await send();\n return null;\n } catch (e) {\n await holdUnbilledSpend(cacheDir, usage).catch(() => {});\n return e instanceof Error ? e.message : String(e);\n }\n}\n\n/**\n * Hold what a node's own gateway calls cost the moment it settles, so the spend survives the\n * run failing or being stopped after it: the resumed run takes that node from the cache and\n * bills nothing for it. `spendOf` returns [] for a cached node or one that calls nothing.\n */\nexport function holdWhenSettled(\n cacheDir: string,\n spendOf: (run: NodeRunRecord, outputs: Record<string, unknown>) => readonly ReviewUsage[],\n): { settled: (run: NodeRunRecord, outputs: Record<string, unknown>) => void; drained: () => Promise<void> } {\n const pending: Promise<void>[] = [];\n return {\n settled: (run, outputs) => {\n pending.push(holdUnbilledSpend(cacheDir, spendOf(run, outputs)).catch(() => {}));\n },\n drained: async () => {\n await Promise.all(pending);\n },\n };\n}\n"],"mappings":";;;;;AAUA,SAAS,kBAAkB;AAC3B,SAAS,OAAO,SAAS,UAAU,QAAQ,QAAQ,iBAAiB;AACpE,OAAO,UAAU;AACjB,SAAS,SAAS;AAKlB,IAAM,MAAM;AAEZ,IAAM,OAAO,EAAE;AAAA,EACb,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,aAAa,EAAE,OAAO,GAAG,cAAc,EAAE,OAAO,GAAG,SAAS,EAAE,OAAO,EAAE,CAAC;AACxG;AAGA,eAAsB,kBAAkB,UAAkB,OAA8C;AACtG,MAAI,MAAM,WAAW,EAAG;AACxB,QAAM,MAAM,KAAK,KAAK,UAAU,GAAG;AACnC,QAAM,MAAM,KAAK,EAAE,WAAW,KAAK,CAAC;AACpC,QAAM,UAAU,KAAK,KAAK,KAAK,GAAG,KAAK,IAAI,CAAC,IAAI,WAAW,CAAC,OAAO,GAAG,KAAK,UAAU,KAAK,GAAG,MAAM;AACrG;AAOA,eAAsB,mBAAmB,OAA8C;AACrF,QAAM,OAAO,kBAAkB,QAAQ,IAAI,CAAC,KAAK,QAAQ,IAAI;AAC7D,QAAM,kBAAkB,KAAK,KAAK,MAAM,UAAU,QAAQ,GAAG,KAAK,EAAE,MAAM,MAAM;AAAA,EAAC,CAAC;AACpF;AAGA,eAAsB,kBAAkB,UAA0C;AAChF,QAAM,MAAM,KAAK,KAAK,UAAU,GAAG;AACnC,QAAM,QAAQ,MAAM,QAAQ,GAAG,EAAE,MAAM,MAAM,CAAC,CAAa;AAC3D,QAAM,UAAU,oBAAI,IAAyB;AAC7C,aAAW,QAAQ,MAAM,OAAO,CAAC,MAAM,EAAE,SAAS,OAAO,CAAC,GAAG;AAC3D,UAAM,UAAU,KAAK,KAAK,KAAK,GAAG,IAAI,IAAI,WAAW,CAAC,QAAQ;AAC9D,QAAI;AACF,YAAM,OAAO,KAAK,KAAK,KAAK,IAAI,GAAG,OAAO;AAAA,IAC5C,QAAQ;AACN;AAAA,IACF;AACA,UAAM,SAAS,KAAK,UAAU,MAAM,SAAS,SAAS,MAAM,EAAE,KAAK,KAAK,OAAO,MAAM,IAAI,EAAE,MAAM,MAAM,IAAI,CAAC;AAC5G,UAAM,OAAO,OAAO,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AACpC,eAAW,QAAQ,OAAO,UAAU,OAAO,OAAO,CAAC,GAAG;AACpD,YAAM,MAAM,QAAQ,IAAI,KAAK,KAAK;AAClC,cAAQ;AAAA,QACN,KAAK;AAAA,QACL,MACI;AAAA,UACE,OAAO,KAAK;AAAA,UACZ,aAAa,IAAI,cAAc,KAAK;AAAA,UACpC,cAAc,IAAI,eAAe,KAAK;AAAA,UACtC,SAAS,IAAI,UAAU,KAAK;AAAA,QAC9B,IACA,EAAE,GAAG,KAAK;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AACA,SAAO,CAAC,GAAG,QAAQ,OAAO,CAAC;AAC7B;AAOA,eAAsB,iBACpB,UACA,OACA,MACwB;AACxB,MAAI;AACF,UAAM,KAAK;AACX,WAAO;AAAA,EACT,SAAS,GAAG;AACV,UAAM,kBAAkB,UAAU,KAAK,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AACvD,WAAO,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC;AAAA,EAClD;AACF;AAOO,SAAS,gBACd,UACA,SAC2G;AAC3G,QAAM,UAA2B,CAAC;AAClC,SAAO;AAAA,IACL,SAAS,CAAC,KAAK,YAAY;AACzB,cAAQ,KAAK,kBAAkB,UAAU,QAAQ,KAAK,OAAO,CAAC,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC,CAAC;AAAA,IACjF;AAAA,IACA,SAAS,YAAY;AACnB,YAAM,QAAQ,IAAI,OAAO;AAAA,IAC3B;AAAA,EACF;AACF;","names":[]}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import {
|
|
2
|
+
failApi
|
|
3
|
+
} from "./chunk-7THBBTJJ.js";
|
|
4
|
+
import {
|
|
5
|
+
CREATIVE_PERFORMANCE_DEFAULT_DAYS,
|
|
6
|
+
CREATIVE_PERFORMANCE_MAX_DAYS
|
|
7
|
+
} from "./chunk-SMIENBNX.js";
|
|
8
|
+
import {
|
|
9
|
+
apiPost
|
|
10
|
+
} from "./chunk-HREWXNTO.js";
|
|
11
|
+
import {
|
|
12
|
+
registerSchema,
|
|
13
|
+
writeJson
|
|
14
|
+
} from "./chunk-WOTDHRNF.js";
|
|
15
|
+
|
|
16
|
+
// src/commands/creatives/performance.ts
|
|
17
|
+
import { readFileSync } from "fs";
|
|
18
|
+
import path from "path";
|
|
19
|
+
import { defineCommand } from "citty";
|
|
20
|
+
import { parse as parseYaml } from "yaml";
|
|
21
|
+
var DESCRIPTION = `How each Baker creative is doing in the live Meta ads that show it: spend, impressions, CTR, CPC, results, cost per result, frequency and a fatigue verdict, next to the angle, hook, mechanism and dominant slot its definition set out to test. Video creatives add hookRate (percent of impressions that watched 3 seconds) and holdRate (percent of those that reached a ThruPlay). Use it before briefing new creatives, to learn which angle and mechanism to make next and which creatives to replace.
|
|
22
|
+
|
|
23
|
+
Start here:
|
|
24
|
+
baker creatives performance # every creative in an ad, last 30 days
|
|
25
|
+
baker creatives performance --slug spring-offer # one creative
|
|
26
|
+
baker creatives performance --days 14 --full # ids, last-7-day figures, a video's watch funnel, one row per ad
|
|
27
|
+
|
|
28
|
+
Fatigue follows the Meta playbook (07-creative-audit.md): fresh, fading, fatigued, dead, or too_early (under 14 days or 1,000 impressions) and no_delivery. A low hook rate means the first 3 seconds need new hooks; a working hook with a low hold rate means the body loses people. A creative counts once a Session's publish created an ad with it.`;
|
|
29
|
+
var ARGS = {
|
|
30
|
+
slug: { type: "string", description: "Only this creative (src/creatives/<slug>/)", required: false },
|
|
31
|
+
days: {
|
|
32
|
+
type: "string",
|
|
33
|
+
description: `Reporting window in days, ending today (1-${CREATIVE_PERFORMANCE_MAX_DAYS}, default ${CREATIVE_PERFORMANCE_DEFAULT_DAYS})`,
|
|
34
|
+
required: false
|
|
35
|
+
},
|
|
36
|
+
full: {
|
|
37
|
+
type: "boolean",
|
|
38
|
+
description: "Add ids, last-7-day CTR and cost per result, and one row per ad",
|
|
39
|
+
required: false,
|
|
40
|
+
default: false
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
registerSchema({ command: "creatives.performance", description: DESCRIPTION, args: ARGS });
|
|
44
|
+
var INSIGHT_KEYS = [
|
|
45
|
+
"idea",
|
|
46
|
+
"message",
|
|
47
|
+
"evidence",
|
|
48
|
+
"angle",
|
|
49
|
+
"hook",
|
|
50
|
+
"mechanism",
|
|
51
|
+
"dominantSlot",
|
|
52
|
+
"persona",
|
|
53
|
+
"awareness",
|
|
54
|
+
"hypothesis"
|
|
55
|
+
];
|
|
56
|
+
var FRONTMATTER = /^---\r?\n([\s\S]*?)\r?\n---/;
|
|
57
|
+
function insightValue(value) {
|
|
58
|
+
if (typeof value === "string") return value.trim() || null;
|
|
59
|
+
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
function definitionInsights(markdown) {
|
|
63
|
+
const block = FRONTMATTER.exec(markdown)?.[1];
|
|
64
|
+
if (!block) return null;
|
|
65
|
+
let parsed;
|
|
66
|
+
try {
|
|
67
|
+
parsed = parseYaml(block);
|
|
68
|
+
} catch {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
if (parsed === null || typeof parsed !== "object") return null;
|
|
72
|
+
const insights = {};
|
|
73
|
+
for (const [key, raw] of Object.entries(parsed)) {
|
|
74
|
+
if (!(INSIGHT_KEYS.includes(key) || key.startsWith("source") || key.startsWith("reference"))) continue;
|
|
75
|
+
const value = insightValue(raw);
|
|
76
|
+
if (value !== null) insights[key] = value;
|
|
77
|
+
}
|
|
78
|
+
return Object.keys(insights).length > 0 ? insights : null;
|
|
79
|
+
}
|
|
80
|
+
function readLocalDefinition(slug) {
|
|
81
|
+
try {
|
|
82
|
+
return readFileSync(path.join(process.cwd(), "src", "creatives", slug, "_definition.md"), "utf8");
|
|
83
|
+
} catch {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
var COMPARED_FIELDS = [
|
|
88
|
+
{ key: "angle", label: "angle", advice: "Brief the next creative on the cheapest angle with a new hook." },
|
|
89
|
+
{ key: "mechanism", label: "mechanism", advice: "Brief the next creative on the cheapest mechanism." },
|
|
90
|
+
{ key: "dominantSlot", label: "dominant slot", advice: "Lead the next creative with the cheapest dominant slot." }
|
|
91
|
+
];
|
|
92
|
+
function cheapestHint(creatives, { key, label, advice }) {
|
|
93
|
+
const byValue = /* @__PURE__ */ new Map();
|
|
94
|
+
for (const creative of creatives) {
|
|
95
|
+
const value = creative.definition?.[key];
|
|
96
|
+
if (!value || creative.costPerResult === null) continue;
|
|
97
|
+
const best = byValue.get(value);
|
|
98
|
+
if (!best || (best.costPerResult ?? Number.POSITIVE_INFINITY) > creative.costPerResult)
|
|
99
|
+
byValue.set(value, creative);
|
|
100
|
+
}
|
|
101
|
+
if (byValue.size < 2) return null;
|
|
102
|
+
const ranked = [...byValue.entries()].sort(([, a], [, b]) => (a.costPerResult ?? 0) - (b.costPerResult ?? 0)).map(
|
|
103
|
+
([value, creative]) => `"${value}" ${creative.costPerResult}${creative.currency ? ` ${creative.currency}` : ""} (${creative.slug ?? creative.title})`
|
|
104
|
+
);
|
|
105
|
+
return `Cost per result by ${label}: ${ranked.join(", ")}. ${advice}`;
|
|
106
|
+
}
|
|
107
|
+
function withDefinitions(response, readDefinition) {
|
|
108
|
+
const creatives = response.data.creatives.map((creative) => {
|
|
109
|
+
const markdown = creative.slug ? readDefinition(creative.slug) : null;
|
|
110
|
+
const definition = markdown ? definitionInsights(markdown) : null;
|
|
111
|
+
return definition ? { ...creative, definition } : creative;
|
|
112
|
+
});
|
|
113
|
+
const hints = [...response.hints ?? []];
|
|
114
|
+
for (const field of COMPARED_FIELDS) {
|
|
115
|
+
const hint = cheapestHint(creatives, field);
|
|
116
|
+
if (hint) hints.push(hint);
|
|
117
|
+
}
|
|
118
|
+
const unnamed = creatives.filter((creative) => !creative.definition?.angle).map((c) => c.slug ?? c.title);
|
|
119
|
+
if (unnamed.length > 0) {
|
|
120
|
+
hints.push(
|
|
121
|
+
`No angle recorded for: ${unnamed.join(", ")}. Add angle and hook to src/creatives/<slug>/_definition.md so results show which angle works.`
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
return { ...response, data: { ...response.data, creatives }, ...hints.length > 0 ? { hints } : {} };
|
|
125
|
+
}
|
|
126
|
+
function parseDays(raw) {
|
|
127
|
+
if (raw === void 0) return void 0;
|
|
128
|
+
const days = Number(raw);
|
|
129
|
+
if (!Number.isInteger(days) || days < 1 || days > CREATIVE_PERFORMANCE_MAX_DAYS) {
|
|
130
|
+
throw new Error(`--days must be a whole number from 1 to ${CREATIVE_PERFORMANCE_MAX_DAYS}`);
|
|
131
|
+
}
|
|
132
|
+
return days;
|
|
133
|
+
}
|
|
134
|
+
var performanceCommand = defineCommand({
|
|
135
|
+
meta: { name: "performance", description: DESCRIPTION },
|
|
136
|
+
args: ARGS,
|
|
137
|
+
run: async ({ args }) => {
|
|
138
|
+
try {
|
|
139
|
+
const body = {};
|
|
140
|
+
const slug = args.slug;
|
|
141
|
+
if (slug) body.slug = slug;
|
|
142
|
+
const days = parseDays(args.days);
|
|
143
|
+
if (days !== void 0) body.days = days;
|
|
144
|
+
if (args.full) body.full = true;
|
|
145
|
+
const response = await apiPost("/api/creatives/performance", body);
|
|
146
|
+
writeJson(withDefinitions(response, readLocalDefinition));
|
|
147
|
+
} catch (err) {
|
|
148
|
+
failApi(err);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
export {
|
|
154
|
+
definitionInsights,
|
|
155
|
+
withDefinitions,
|
|
156
|
+
parseDays,
|
|
157
|
+
performanceCommand
|
|
158
|
+
};
|
|
159
|
+
//# sourceMappingURL=chunk-B52DCYL2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/creatives/performance.ts"],"sourcesContent":["import { readFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport {\n CREATIVE_PERFORMANCE_DEFAULT_DAYS,\n CREATIVE_PERFORMANCE_MAX_DAYS,\n type CreativePerformance,\n type CreativesPerformanceRequest,\n type CreativesPerformanceResponse,\n} from \"@baker/api\";\nimport { defineCommand } from \"citty\";\nimport { parse as parseYaml } from \"yaml\";\nimport { apiPost } from \"../../client.ts\";\nimport { writeJson } from \"../../output.ts\";\nimport { registerSchema } from \"../../schemas.ts\";\nimport { failApi } from \"../actions/shared.ts\";\n\nconst DESCRIPTION = `How each Baker creative is doing in the live Meta ads that show it: spend, impressions, CTR, CPC, results, cost per result, frequency and a fatigue verdict, next to the angle, hook, mechanism and dominant slot its definition set out to test. Video creatives add hookRate (percent of impressions that watched 3 seconds) and holdRate (percent of those that reached a ThruPlay). Use it before briefing new creatives, to learn which angle and mechanism to make next and which creatives to replace.\n\nStart here:\n baker creatives performance # every creative in an ad, last 30 days\n baker creatives performance --slug spring-offer # one creative\n baker creatives performance --days 14 --full # ids, last-7-day figures, a video's watch funnel, one row per ad\n\nFatigue follows the Meta playbook (07-creative-audit.md): fresh, fading, fatigued, dead, or too_early (under 14 days or 1,000 impressions) and no_delivery. A low hook rate means the first 3 seconds need new hooks; a working hook with a low hold rate means the body loses people. A creative counts once a Session's publish created an ad with it.`;\n\nconst ARGS = {\n slug: { type: \"string\", description: \"Only this creative (src/creatives/<slug>/)\", required: false },\n days: {\n type: \"string\",\n description: `Reporting window in days, ending today (1-${CREATIVE_PERFORMANCE_MAX_DAYS}, default ${CREATIVE_PERFORMANCE_DEFAULT_DAYS})`,\n required: false,\n },\n full: {\n type: \"boolean\",\n description: \"Add ids, last-7-day CTR and cost per result, and one row per ad\",\n required: false,\n default: false,\n },\n} as const;\n\nregisterSchema({ command: \"creatives.performance\", description: DESCRIPTION, args: ARGS });\n\n/**\n * Frontmatter keys that say what a creative set out to test (angle, hook, the\n * mechanism it uses and the slot it leads with) and which reference\n * ad it adapted. Anything named `source…` or `reference…` is kept too, so\n * reference fields added to the collection later come through without a CLI\n * release.\n */\nconst INSIGHT_KEYS = [\n \"idea\",\n \"message\",\n \"evidence\",\n \"angle\",\n \"hook\",\n \"mechanism\",\n \"dominantSlot\",\n \"persona\",\n \"awareness\",\n \"hypothesis\",\n];\nconst FRONTMATTER = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---/;\n\nfunction insightValue(value: unknown): string | null {\n if (typeof value === \"string\") return value.trim() || null;\n if (typeof value === \"number\" || typeof value === \"boolean\") return String(value);\n return null;\n}\n\n/** The insight fields of a `_definition.md`, or null when it names none. */\nexport function definitionInsights(markdown: string): Record<string, string> | null {\n const block = FRONTMATTER.exec(markdown)?.[1];\n if (!block) return null;\n let parsed: unknown;\n try {\n parsed = parseYaml(block);\n } catch {\n return null;\n }\n if (parsed === null || typeof parsed !== \"object\") return null;\n const insights: Record<string, string> = {};\n for (const [key, raw] of Object.entries(parsed as Record<string, unknown>)) {\n if (!(INSIGHT_KEYS.includes(key) || key.startsWith(\"source\") || key.startsWith(\"reference\"))) continue;\n const value = insightValue(raw);\n if (value !== null) insights[key] = value;\n }\n return Object.keys(insights).length > 0 ? insights : null;\n}\n\nfunction readLocalDefinition(slug: string): string | null {\n try {\n return readFileSync(path.join(process.cwd(), \"src\", \"creatives\", slug, \"_definition.md\"), \"utf8\");\n } catch {\n return null;\n }\n}\n\n/**\n * Definition fields whose values are compared by cost per result, each with\n * the advice its hint closes on. `label` is how the hint names the field.\n */\nconst COMPARED_FIELDS = [\n { key: \"angle\", label: \"angle\", advice: \"Brief the next creative on the cheapest angle with a new hook.\" },\n { key: \"mechanism\", label: \"mechanism\", advice: \"Brief the next creative on the cheapest mechanism.\" },\n { key: \"dominantSlot\", label: \"dominant slot\", advice: \"Lead the next creative with the cheapest dominant slot.\" },\n] as const;\n\nfunction cheapestHint(\n creatives: readonly CreativePerformance[],\n { key, label, advice }: (typeof COMPARED_FIELDS)[number],\n): string | null {\n const byValue = new Map<string, CreativePerformance>();\n for (const creative of creatives) {\n const value = creative.definition?.[key];\n if (!value || creative.costPerResult === null) continue;\n const best = byValue.get(value);\n if (!best || (best.costPerResult ?? Number.POSITIVE_INFINITY) > creative.costPerResult)\n byValue.set(value, creative);\n }\n if (byValue.size < 2) return null;\n const ranked = [...byValue.entries()]\n .sort(([, a], [, b]) => (a.costPerResult ?? 0) - (b.costPerResult ?? 0))\n .map(\n ([value, creative]) =>\n `\"${value}\" ${creative.costPerResult}${creative.currency ? ` ${creative.currency}` : \"\"} (${creative.slug ?? creative.title})`,\n );\n return `Cost per result by ${label}: ${ranked.join(\", \")}. ${advice}`;\n}\n\n/**\n * Adds each creative's definition (read from the local repo, where the agent\n * works) and the hints that need it: which angle, mechanism and dominant slot\n * are cheapest, and which creatives say nothing about what they test.\n */\nexport function withDefinitions(\n response: CreativesPerformanceResponse,\n readDefinition: (slug: string) => string | null,\n): CreativesPerformanceResponse {\n const creatives = response.data.creatives.map((creative) => {\n const markdown = creative.slug ? readDefinition(creative.slug) : null;\n const definition = markdown ? definitionInsights(markdown) : null;\n return definition ? { ...creative, definition } : creative;\n });\n const hints = [...(response.hints ?? [])];\n for (const field of COMPARED_FIELDS) {\n const hint = cheapestHint(creatives, field);\n if (hint) hints.push(hint);\n }\n const unnamed = creatives.filter((creative) => !creative.definition?.angle).map((c) => c.slug ?? c.title);\n if (unnamed.length > 0) {\n hints.push(\n `No angle recorded for: ${unnamed.join(\", \")}. Add angle and hook to src/creatives/<slug>/_definition.md so results show which angle works.`,\n );\n }\n return { ...response, data: { ...response.data, creatives }, ...(hints.length > 0 ? { hints } : {}) };\n}\n\nexport function parseDays(raw: string | undefined): number | undefined {\n if (raw === undefined) return undefined;\n const days = Number(raw);\n if (!Number.isInteger(days) || days < 1 || days > CREATIVE_PERFORMANCE_MAX_DAYS) {\n throw new Error(`--days must be a whole number from 1 to ${CREATIVE_PERFORMANCE_MAX_DAYS}`);\n }\n return days;\n}\n\nexport const performanceCommand = defineCommand({\n meta: { name: \"performance\", description: DESCRIPTION },\n args: ARGS,\n run: async ({ args }) => {\n try {\n const body: CreativesPerformanceRequest = {};\n const slug = args.slug as string | undefined;\n if (slug) body.slug = slug;\n const days = parseDays(args.days as string | undefined);\n if (days !== undefined) body.days = days;\n if (args.full) body.full = true;\n const response = await apiPost<CreativesPerformanceResponse>(\"/api/creatives/performance\", body);\n writeJson(withDefinitions(response, readLocalDefinition));\n } catch (err) {\n failApi(err);\n }\n },\n});\n"],"mappings":"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","names":[]}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ApiError,
|
|
3
3
|
apiGet
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-HREWXNTO.js";
|
|
5
5
|
import {
|
|
6
6
|
getEnv
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-O6QKCJE4.js";
|
|
8
8
|
|
|
9
9
|
// src/error-handler.ts
|
|
10
10
|
var REQUEST_CONNECTION_PLATFORM = {
|
|
@@ -153,6 +153,12 @@ function writeJsonEnvelope(envelope) {
|
|
|
153
153
|
process.stdout.write(`${JSON.stringify(envelope, null, 2)}
|
|
154
154
|
`);
|
|
155
155
|
}
|
|
156
|
+
var TABLE_OUTPUT_FORMATS = ["json", "csv", "jsonl", "md"];
|
|
157
|
+
function outputFormatRefusal(format, supported) {
|
|
158
|
+
if (supported.includes(format)) return null;
|
|
159
|
+
const list = supported.length > 1 ? `${supported.slice(0, -1).join(", ")} or ${supported.at(-1)}` : supported.join("");
|
|
160
|
+
return `--output ${format} is not supported \u2014 use ${list}`;
|
|
161
|
+
}
|
|
156
162
|
function toCsvRow(values) {
|
|
157
163
|
return values.map((v) => {
|
|
158
164
|
if (v.includes(",") || v.includes('"') || v.includes("\n")) {
|
|
@@ -288,14 +294,16 @@ export {
|
|
|
288
294
|
getQueryTtl,
|
|
289
295
|
buildQueryCacheKey,
|
|
290
296
|
getManagerIdForCustomer,
|
|
291
|
-
connectionFixExplanation,
|
|
292
|
-
handleConnectionError,
|
|
293
|
-
isNotConnectedError,
|
|
294
|
-
needsConnectionFix,
|
|
295
297
|
writeAdsJson,
|
|
296
298
|
writeJsonEnvelope,
|
|
299
|
+
TABLE_OUTPUT_FORMATS,
|
|
300
|
+
outputFormatRefusal,
|
|
297
301
|
toCsvRow,
|
|
298
302
|
writeAdsOutput,
|
|
299
|
-
resolveCustomerId
|
|
303
|
+
resolveCustomerId,
|
|
304
|
+
connectionFixExplanation,
|
|
305
|
+
handleConnectionError,
|
|
306
|
+
isNotConnectedError,
|
|
307
|
+
needsConnectionFix
|
|
300
308
|
};
|
|
301
|
-
//# sourceMappingURL=chunk-
|
|
309
|
+
//# sourceMappingURL=chunk-BVM5IRZW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/error-handler.ts","../src/commands/ads/cache.ts","../src/commands/ads/output.ts"],"sourcesContent":["import { writeJsonEnvelope } from \"./commands/ads/output.ts\";\n\ntype ConnectionPlatform = \"google_ads\" | \"ga4\" | \"gsc\" | \"x_ads\" | \"meta_ads\" | \"linkedin_ads\";\n\n/**\n * Platforms the agent can get connected without the user leaving the chat, via\n * the blocking `request_connection` tool, and the id that tool expects. Every\n * platform this CLI can talk to is here — keep it in step with\n * `CONNECTION_PLATFORMS` in `packages/bridge/src/hono/connection-input.ts`: a\n * platform the tool accepts but this map omits sends the user to Settings for a\n * door the agent could have opened itself.\n */\nconst REQUEST_CONNECTION_PLATFORM: Record<ConnectionPlatform, string> = {\n google_ads: \"google-ads\",\n ga4: \"google-analytics\",\n gsc: \"google-search-console\",\n linkedin_ads: \"linkedin\",\n meta_ads: \"meta\",\n x_ads: \"x-ads\",\n};\n\nconst PLATFORM_NAME: Record<ConnectionPlatform, string> = {\n google_ads: \"Google Ads\",\n ga4: \"Google Analytics 4\",\n gsc: \"Google Search Console\",\n x_ads: \"X Ads\",\n meta_ads: \"Meta Ads\",\n linkedin_ads: \"LinkedIn Ads\",\n};\n\n/**\n * How to tell the agent to get a platform connected. Never \"send them to\n * Settings\" for a platform `request_connection` covers — that ends the turn on a\n * wall the agent could have opened itself, and it now covers every platform this\n * CLI talks to. The fallback line matters too: if the `request_connection` call\n * fails, the agent must still be able to say where the connect button is instead\n * of stalling.\n */\nexport function connectionFixExplanation(platform: ConnectionPlatform): string {\n const name = PLATFORM_NAME[platform];\n const slug = REQUEST_CONNECTION_PLATFORM[platform];\n return (\n `${name} is not connected for this company (or no account has been picked). Don't send the user to Settings ` +\n `or end the turn here — call the \\`request_connection\\` tool with { platform: \"${slug}\", reason } and ` +\n `they connect and pick their accounts from inside the chat. If the \\`request_connection\\` call fails, say so ` +\n `plainly and give the exact route: dashboard → Brain → Integrations → Platforms → ${name}. Then carry on with the ` +\n `rest of the task and say what stays unavailable until it is connected.`\n );\n}\n\n/**\n * Shared error handler for \"No Connection\" scenarios.\n * Provides a structured error for AI agents with a suggested fix and alternative commands.\n */\nexport function handleConnectionError(platform: ConnectionPlatform, originalMessage?: string): never {\n const platformName = PLATFORM_NAME[platform];\n\n const alternative = {\n google_ads: \"keywords-for-site or research advertisers\",\n ga4: \"lighthouse for page performance\",\n gsc: \"keywords-for-site or research keyword-gap\",\n x_ads: \"research advertisers\",\n meta_ads: \"research advertisers or research keyword-ideas\",\n linkedin_ads: \"research advertisers (LinkedIn Ad Library) or research keyword-ideas\",\n }[platform];\n\n const code = {\n google_ads: \"NO_GOOGLE_ADS_CONNECTION\",\n ga4: \"NO_GA4_CONNECTION\",\n gsc: \"NO_GSC_CONNECTION\",\n x_ads: \"NO_X_ADS_CONNECTION\",\n meta_ads: \"NO_META_ADS_CONNECTION\",\n linkedin_ads: \"NO_LINKEDIN_ADS_CONNECTION\",\n }[platform];\n\n const envelope = {\n ok: false,\n error: {\n code,\n message: originalMessage || `No ${platformName} connection found for this company.`,\n fix: {\n action: \"request_connection\",\n explanation: `${connectionFixExplanation(platform)} (Optional fallback for estimated external insights: 'baker research ${alternative}'.)`,\n },\n retryable: false,\n },\n };\n\n writeJsonEnvelope(envelope);\n process.exit(1);\n}\n\n/**\n * Does this API failure mean \"the platform isn't connected\"? The read commands\n * surface the backend's own 404/403 verbatim, so the connect fix has to be\n * recognised from the code the client mapped it to plus the message.\n */\nexport function isNotConnectedError(code: string, message: string): boolean {\n if (code !== \"NOT_FOUND\" && code !== \"UNAUTHORIZED\" && code !== \"FORBIDDEN\") {\n return false;\n }\n // The last alternative is the write-path 403 (\"customer X is not in this\n // company's connected Google Ads accounts\") — a different sentence for the\n // same remedy: connect, and pick the account.\n return /no .* connection found|not connected|no .* (selected|picked)|is not in .* connected/i.test(message);\n}\n\n/**\n * Does this failure warrant the connect form? A dead token (401) always does —\n * whatever the wording, the remedy is to sign in again.\n *\n * A 404 or 403 only does when the backend says so. Both codes are overloaded:\n * 403 is also an asset-level refusal on a live connection (reconnecting cannot\n * grant it), and 404 is also how \"no staged op <ref> in this draft\" and a\n * mistyped `--chat` come back. Answering either with \"ask the user to connect\n * Meta Ads\" sends the agent to fix something that was never broken, and the\n * real missing-connection 404 says \"No <platform> connection found\" anyway.\n */\nexport function needsConnectionFix(code: string, message: string): boolean {\n if (code === \"UNAUTHORIZED\") {\n return true;\n }\n return isNotConnectedError(code, message);\n}\n","import { createHash } from \"node:crypto\";\nimport { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { CacheEntry } from \"./types.ts\";\n\nconst CACHE_DIR = join(homedir(), \".baker\", \"cache\", \"ads\");\n\nfunction ensureDir(dir: string): void {\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n}\n\nfunction hashKey(key: string): string {\n return createHash(\"sha256\").update(key).digest(\"hex\").slice(0, 16);\n}\n\nfunction cachePath(category: string, key: string): string {\n const dir = join(CACHE_DIR, category);\n ensureDir(dir);\n return join(dir, `${hashKey(key)}.json`);\n}\n\nexport function cacheGet<T>(category: string, key: string): CacheEntry<T> | null {\n const path = cachePath(category, key);\n if (!existsSync(path)) {\n return null;\n }\n try {\n const raw = readFileSync(path, \"utf-8\");\n const entry = JSON.parse(raw) as CacheEntry<T>;\n if (entry.expiresAt < Date.now()) {\n rmSync(path, { force: true });\n return null;\n }\n return entry;\n } catch {\n rmSync(path, { force: true });\n return null;\n }\n}\n\nexport function cacheSet<T>(\n category: string,\n key: string,\n data: T,\n ttlMs: number,\n fields?: Record<string, string>,\n): void {\n const path = cachePath(category, key);\n const entry: CacheEntry<T> = {\n expiresAt: Date.now() + ttlMs,\n data,\n fields,\n };\n writeFileSync(path, JSON.stringify(entry), \"utf-8\");\n}\n\nconst HOUR = 60 * 60 * 1000;\nconst MINUTE = 60 * 1000;\n\nexport function getQueryTtl(query: string): number {\n const upper = query.toUpperCase();\n if (upper.includes(\"TODAY\")) {\n return 15 * MINUTE;\n }\n if (upper.includes(\"LAST_7_DAYS\") || upper.includes(\"LAST_14_DAYS\")) {\n return 1 * HOUR;\n }\n // Historical data (BETWEEN, LAST_30_DAYS, LAST_90_DAYS, etc.)\n return 6 * HOUR;\n}\n\nexport function buildQueryCacheKey(customerId: string, query: string): string {\n const today = new Date().toISOString().slice(0, 10);\n return `${customerId}:${today}:${query.trim().replace(/\\s+/g, \" \")}`;\n}\n\ninterface CachedAccount {\n id: string;\n access_type: \"direct\" | \"managed\";\n manager_id?: string;\n}\n\nexport function getManagerIdForCustomer(customerId: string): string | undefined {\n const cached = cacheGet<CachedAccount[]>(\"accounts\", \"list\");\n if (!cached) return undefined;\n const account = cached.data.find((a) => a.id === customerId);\n if (account?.access_type === \"managed\") return account.manager_id;\n return undefined;\n}\n","import { ApiError, apiGet } from \"../../client.ts\";\nimport { getEnv } from \"../../env.ts\";\nimport { handleConnectionError, isNotConnectedError } from \"../../error-handler.ts\";\nimport type { QueryContext } from \"../../geo-context.ts\";\nimport { cacheGet, cacheSet } from \"./cache.ts\";\nimport type { AdsErrorEnvelope, AdsFileSummary, AdsSuccessEnvelope } from \"./types.ts\";\n\ntype AdsOutput =\n | AdsSuccessEnvelope<unknown>\n | AdsErrorEnvelope\n | AdsFileSummary\n | { ok: true; data: unknown; query_context?: QueryContext; cached?: true; fields?: Record<string, string> }\n | { ok: false; error: { code: string; message: string } };\n\nexport function writeAdsJson(envelope: AdsOutput): void {\n process.stdout.write(`${JSON.stringify(envelope, null, 2)}\\n`);\n}\n\nexport function writeJsonEnvelope(envelope: Record<string, unknown>): void {\n process.stdout.write(`${JSON.stringify(envelope, null, 2)}\\n`);\n}\n\n/** The formats `writeAdsOutput` prints. */\nexport const TABLE_OUTPUT_FORMATS = [\"json\", \"csv\", \"jsonl\", \"md\"] as const;\n\n/** Why `--output <format>` cannot be printed, or null — rather than quietly falling back to JSON. */\nexport function outputFormatRefusal(format: string, supported: readonly string[]): string | null {\n if (supported.includes(format)) return null;\n const list =\n supported.length > 1 ? `${supported.slice(0, -1).join(\", \")} or ${supported.at(-1)}` : supported.join(\"\");\n return `--output ${format} is not supported — use ${list}`;\n}\n\nexport function toCsvRow(values: string[]): string {\n return values\n .map((v) => {\n if (v.includes(\",\") || v.includes('\"') || v.includes(\"\\n\")) {\n return `\"${v.replace(/\"/g, '\"\"')}\"`;\n }\n return v;\n })\n .join(\",\");\n}\n\nfunction flattenRow(row: Record<string, unknown>): Record<string, string> {\n const flat: Record<string, string> = {};\n for (const [key, val] of Object.entries(row)) {\n flat[key] = typeof val === \"object\" && val !== null ? JSON.stringify(val) : String(val ?? \"\");\n }\n return flat;\n}\n\n/**\n * One write per table: a line-by-line write piped into `head` hits a closed pipe on\n * the next line and crashes with EPIPE, where a single write lands in the pipe buffer.\n */\nfunction writeWhole(lines: string[]): void {\n process.stdout.write(`${lines.join(\"\\n\")}\\n`);\n}\n\nfunction writeAdsCsv(data: Array<Record<string, unknown>>, fields?: string[]): void {\n if (data.length === 0) return;\n const cols = fields ?? Object.keys(data[0] ?? {});\n const lines = [toCsvRow(cols)];\n for (const row of data) {\n const flat = flattenRow(row);\n lines.push(toCsvRow(cols.map((f) => flat[f] ?? \"\")));\n }\n writeWhole(lines);\n}\n\nfunction writeAdsJsonl(data: Array<Record<string, unknown>>): void {\n if (data.length === 0) return;\n writeWhole(data.map((row) => JSON.stringify(row)));\n}\n\n/** A `|` or line break in a name would split its cell and shift every later column. */\nfunction mdCell(value: string): string {\n return value.replace(/\\|/g, \"\\\\|\").replace(/\\r?\\n/g, \" \");\n}\n\nfunction writeAdsMd(data: Array<Record<string, unknown>>, fields?: string[]): void {\n if (data.length === 0) return;\n const cols = fields ?? Object.keys(data[0] ?? {});\n const lines = [`| ${cols.join(\" | \")} |`, `| ${cols.map(() => \"---\").join(\" | \")} |`];\n for (const row of data) {\n const flat = flattenRow(row);\n lines.push(`| ${cols.map((f) => mdCell(flat[f] ?? \"\")).join(\" | \")} |`);\n }\n writeWhole(lines);\n}\n\n/**\n * `hints` ride in the JSON envelope; csv/jsonl/md stdout has no room for them,\n * and an empty result is exactly when the hint matters, so they go to stderr.\n */\nexport function writeAdsOutput(\n data: Array<Record<string, unknown>>,\n format: string,\n fields?: string[],\n hints: string[] = [],\n): void {\n switch (format) {\n case \"csv\":\n writeAdsCsv(data, fields);\n break;\n case \"jsonl\":\n writeAdsJsonl(data);\n break;\n case \"md\":\n writeAdsMd(data, fields);\n break;\n default:\n writeJsonEnvelope(hints.length > 0 ? { ok: true, data, hints } : { ok: true, data });\n return;\n }\n for (const hint of hints) process.stderr.write(`${hint}\\n`);\n}\n\ninterface AccountInfo {\n id: string;\n name: string;\n access_type: \"direct\" | \"managed\";\n level: number;\n manager_id?: string;\n}\n\nasync function fetchAccounts(useCache = true): Promise<AccountInfo[]> {\n if (useCache) {\n const cached = cacheGet<AccountInfo[]>(\"accounts\", \"list\");\n if (cached) return cached.data;\n }\n const params = !useCache ? { \"skip-cache\": \"true\" } : undefined;\n const data = await apiGet<AccountInfo[]>(\"/api/ads/google/accounts\", params);\n if (useCache) {\n cacheSet(\"accounts\", \"list\", data, 60 * 60 * 1000);\n }\n return data;\n}\n\nexport async function resolveCustomerId(args: Record<string, unknown>): Promise<string> {\n const fromArgs = args[\"customer-id\"] as string | undefined;\n const customerId = fromArgs || getEnv().BAKER_GOOGLE_ADS_CUSTOMER_ID;\n\n if (customerId) {\n if (!/^\\d{10}$/.test(customerId)) {\n writeAdsJson({\n ok: false,\n error: {\n code: \"INVALID_CUSTOMER_ID\",\n message:\n \"Customer ID must be exactly 10 digits without dashes. Pass --customer-id or set BAKER_GOOGLE_ADS_CUSTOMER_ID.\",\n },\n });\n process.exit(1);\n }\n return customerId;\n }\n\n const useCache = !args[\"no-cache\"];\n\n try {\n const accounts = await fetchAccounts(useCache);\n const [single] = accounts;\n if (accounts.length === 1 && single) {\n process.stderr.write(`Using account \"${single.name}\" (${single.id})\\n`);\n return single.id;\n }\n if (accounts.length === 0) {\n handleConnectionError(\"google_ads\");\n }\n const list = accounts.map((a) => ` ${a.id} ${a.name}`).join(\"\\n\");\n writeAdsJson({\n ok: false,\n error: {\n code: \"MULTIPLE_ACCOUNTS\",\n message: `Multiple accounts found. Pass --customer-id or set BAKER_GOOGLE_ADS_CUSTOMER_ID:\\n${list}`,\n },\n });\n process.exit(1);\n } catch (err) {\n // \"No connection\" reaches here as a 404/403 from the accounts lookup. Reporting it as\n // an unusable customer id sends the agent hunting for an id that cannot exist yet.\n if (err instanceof ApiError && isNotConnectedError(err.code, err.message)) {\n handleConnectionError(\"google_ads\", err.message);\n }\n writeAdsJson({\n ok: false,\n error: {\n code: \"INVALID_CUSTOMER_ID\",\n message: \"Could not auto-detect account. Pass --customer-id or set BAKER_GOOGLE_ADS_CUSTOMER_ID.\",\n },\n });\n process.exit(1);\n }\n}\n"],"mappings":"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","names":[]}
|