@koda-sl/baker-cli 0.384.0 → 0.385.0-dev.f7ef4c7e1
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 +1102 -218
- package/canvas/tiktok-captions-composition/index.html +5 -6
- package/canvas/tiktok-captions-composition/meta.json +5 -0
- package/dist/account-4UEZAY5T.js +49 -0
- package/dist/account-4UEZAY5T.js.map +1 -0
- package/dist/account-G6QK2VXQ.js +79 -0
- package/dist/account-G6QK2VXQ.js.map +1 -0
- package/dist/account-OINZG6UP.js +80 -0
- package/dist/account-OINZG6UP.js.map +1 -0
- package/dist/account-reads-ZKKDYHK5.js +218 -0
- package/dist/account-reads-ZKKDYHK5.js.map +1 -0
- package/dist/account-writes-N4JDIDRB.js +66 -0
- package/dist/account-writes-N4JDIDRB.js.map +1 -0
- package/dist/accounts-7KRRRVLB.js +611 -0
- package/dist/accounts-7KRRRVLB.js.map +1 -0
- package/dist/accounts-AEBQFCNH.js +114 -0
- package/dist/accounts-AEBQFCNH.js.map +1 -0
- package/dist/accounts-CNTOHRQ2.js +77 -0
- package/dist/accounts-CNTOHRQ2.js.map +1 -0
- package/dist/accounts-HP4BLKK5.js +75 -0
- package/dist/accounts-HP4BLKK5.js.map +1 -0
- package/dist/accounts-Z4CLGQXJ.js +115 -0
- package/dist/accounts-Z4CLGQXJ.js.map +1 -0
- package/dist/actions-QO7VQ6UV.js +55 -0
- package/dist/actions-QO7VQ6UV.js.map +1 -0
- package/dist/active-entities-YB46ADQN.js +103 -0
- package/dist/active-entities-YB46ADQN.js.map +1 -0
- package/dist/activities-DUAIQJLN.js +74 -0
- package/dist/activities-DUAIQJLN.js.map +1 -0
- package/dist/ad-group-writes-HL3EZ3BT.js +170 -0
- package/dist/ad-group-writes-HL3EZ3BT.js.map +1 -0
- package/dist/ad-groups-FGS5JJGN.js +68 -0
- package/dist/ad-groups-FGS5JJGN.js.map +1 -0
- package/dist/ad-writes-LX4ACUHB.js +174 -0
- package/dist/ad-writes-LX4ACUHB.js.map +1 -0
- package/dist/add-5CUXNOUM.js +97 -0
- package/dist/add-5CUXNOUM.js.map +1 -0
- package/dist/add-5JBMJHNW.js +302 -0
- package/dist/add-5JBMJHNW.js.map +1 -0
- package/dist/add-E66HBIZV.js +105 -0
- package/dist/add-E66HBIZV.js.map +1 -0
- package/dist/add-O76R2SPE.js +104 -0
- package/dist/add-O76R2SPE.js.map +1 -0
- package/dist/add-accounts-YME5SCXD.js +91 -0
- package/dist/add-accounts-YME5SCXD.js.map +1 -0
- package/dist/ads-65R3WMDU.js +128 -0
- package/dist/ads-65R3WMDU.js.map +1 -0
- package/dist/ads-O63J7BDF.js +113 -0
- package/dist/ads-O63J7BDF.js.map +1 -0
- package/dist/ads-T5JWNFSA.js +40 -0
- package/dist/ads-T5JWNFSA.js.map +1 -0
- package/dist/ads-TFZ5PXKS.js +77 -0
- package/dist/ads-TFZ5PXKS.js.map +1 -0
- package/dist/adsets-Y62JOOTV.js +176 -0
- package/dist/adsets-Y62JOOTV.js.map +1 -0
- package/dist/advertisers-LJ2HKJ4W.js +125 -0
- package/dist/advertisers-LJ2HKJ4W.js.map +1 -0
- package/dist/advertisers-WJW5DK3Q.js +120 -0
- package/dist/advertisers-WJW5DK3Q.js.map +1 -0
- package/dist/analytics-HIOC3TUK.js +1976 -0
- package/dist/analytics-HIOC3TUK.js.map +1 -0
- package/dist/analytics-U2NLDV2V.js +433 -0
- package/dist/analytics-U2NLDV2V.js.map +1 -0
- package/dist/animate-E3SKQ6SI.js +480 -0
- package/dist/animate-E3SKQ6SI.js.map +1 -0
- package/dist/assign-V7EAR7VD.js +77 -0
- package/dist/assign-V7EAR7VD.js.map +1 -0
- package/dist/audience-size-GS7EDBDP.js +94 -0
- package/dist/audience-size-GS7EDBDP.js.map +1 -0
- package/dist/audiences-5A6BCWSA.js +268 -0
- package/dist/audiences-5A6BCWSA.js.map +1 -0
- package/dist/audiences-6QOCASVV.js +78 -0
- package/dist/audiences-6QOCASVV.js.map +1 -0
- package/dist/audiences-O67NGIP5.js +85 -0
- package/dist/audiences-O67NGIP5.js.map +1 -0
- package/dist/audit-HWK24VXI.js +88 -0
- package/dist/audit-HWK24VXI.js.map +1 -0
- package/dist/audit-WMZERUAA.js +151 -0
- package/dist/audit-WMZERUAA.js.map +1 -0
- package/dist/autocomplete-KQSTLQFS.js +111 -0
- package/dist/autocomplete-KQSTLQFS.js.map +1 -0
- package/dist/avatars-HAFQZD63.js +38 -0
- package/dist/avatars-HAFQZD63.js.map +1 -0
- package/dist/bid-pricing-5SORFAPE.js +99 -0
- package/dist/bid-pricing-5SORFAPE.js.map +1 -0
- package/dist/brand-EBG436YV.js +22 -0
- package/dist/brand-EBG436YV.js.map +1 -0
- package/dist/brief-AYXXPTHC.js +490 -0
- package/dist/brief-AYXXPTHC.js.map +1 -0
- package/dist/businesses-65EWTK5E.js +53 -0
- package/dist/businesses-65EWTK5E.js.map +1 -0
- package/dist/campaign-groups-U7723BBE.js +95 -0
- package/dist/campaign-groups-U7723BBE.js.map +1 -0
- package/dist/campaign-writes-CXS4KYB5.js +165 -0
- package/dist/campaign-writes-CXS4KYB5.js.map +1 -0
- package/dist/campaign-writes-M6JLF5AC.js +170 -0
- package/dist/campaign-writes-M6JLF5AC.js.map +1 -0
- package/dist/campaigns-6SM2ZSIH.js +76 -0
- package/dist/campaigns-6SM2ZSIH.js.map +1 -0
- package/dist/campaigns-7DWD2A5U.js +109 -0
- package/dist/campaigns-7DWD2A5U.js.map +1 -0
- package/dist/campaigns-F66OYA6N.js +107 -0
- package/dist/campaigns-F66OYA6N.js.map +1 -0
- package/dist/campaigns-TD7ZB5DG.js +110 -0
- package/dist/campaigns-TD7ZB5DG.js.map +1 -0
- package/dist/canvas-3NYM5Y7G.js +46 -0
- package/dist/canvas-3NYM5Y7G.js.map +1 -0
- package/dist/capabilities-JNFYSGRD.js +144 -0
- package/dist/capabilities-JNFYSGRD.js.map +1 -0
- package/dist/cards-7HRC4UQQ.js +85 -0
- package/dist/cards-7HRC4UQQ.js.map +1 -0
- package/dist/catalog-N6MDMIVL.js +64 -0
- package/dist/catalog-N6MDMIVL.js.map +1 -0
- package/dist/catalogs-PB46L7FH.js +128 -0
- package/dist/catalogs-PB46L7FH.js.map +1 -0
- package/dist/changes-SASUQK62.js +135 -0
- package/dist/changes-SASUQK62.js.map +1 -0
- package/dist/chatgpt-JKBSAG25.js +47 -0
- package/dist/chatgpt-JKBSAG25.js.map +1 -0
- package/dist/chats-TUZANLQH.js +262 -0
- package/dist/chats-TUZANLQH.js.map +1 -0
- package/dist/chunk-25E6SC3F.js +363 -0
- package/dist/chunk-25E6SC3F.js.map +1 -0
- package/dist/chunk-2GVXNKAE.js +42 -0
- package/dist/chunk-2GVXNKAE.js.map +1 -0
- package/dist/{chunk-VLUGGVJL.js → chunk-2UFRHW3T.js} +12 -4
- package/dist/chunk-2UFRHW3T.js.map +1 -0
- package/dist/chunk-2Y5V23PU.js +29 -0
- package/dist/chunk-2Y5V23PU.js.map +1 -0
- package/dist/chunk-35NYNRRB.js +111 -0
- package/dist/chunk-35NYNRRB.js.map +1 -0
- package/dist/chunk-3ACMDRSE.js +39 -0
- package/dist/chunk-3ACMDRSE.js.map +1 -0
- package/dist/chunk-3M6RNCDD.js +26 -0
- package/dist/chunk-3M6RNCDD.js.map +1 -0
- package/dist/chunk-3VXQYDJN.js +1743 -0
- package/dist/chunk-3VXQYDJN.js.map +1 -0
- package/dist/chunk-42DF5DF3.js +304 -0
- package/dist/chunk-42DF5DF3.js.map +1 -0
- package/dist/chunk-44VXKO65.js +106 -0
- package/dist/chunk-44VXKO65.js.map +1 -0
- package/dist/chunk-4NZ47VXO.js +137 -0
- package/dist/chunk-4NZ47VXO.js.map +1 -0
- package/dist/chunk-4X3UR372.js +225 -0
- package/dist/chunk-4X3UR372.js.map +1 -0
- package/dist/chunk-5FEBUCJU.js +25 -0
- package/dist/chunk-5FEBUCJU.js.map +1 -0
- package/dist/chunk-5HYSKH77.js +315 -0
- package/dist/chunk-5HYSKH77.js.map +1 -0
- package/dist/chunk-5LBGFQWF.js +310 -0
- package/dist/chunk-5LBGFQWF.js.map +1 -0
- package/dist/chunk-5MBPIONY.js +29 -0
- package/dist/chunk-5MBPIONY.js.map +1 -0
- package/dist/chunk-6YMHGIHP.js +346 -0
- package/dist/chunk-6YMHGIHP.js.map +1 -0
- package/dist/{chunk-VZEDAFAR.js → chunk-6YYSUISH.js} +47 -8
- package/dist/chunk-6YYSUISH.js.map +1 -0
- package/dist/chunk-7GNU3P7X.js +175 -0
- package/dist/chunk-7GNU3P7X.js.map +1 -0
- package/dist/chunk-7OHWEF3I.js +98 -0
- package/dist/chunk-7OHWEF3I.js.map +1 -0
- package/dist/chunk-7TR3QVWM.js +57 -0
- package/dist/chunk-7TR3QVWM.js.map +1 -0
- package/dist/chunk-AADVCEL4.js +817 -0
- package/dist/chunk-AADVCEL4.js.map +1 -0
- package/dist/chunk-AG62YO7C.js +96 -0
- package/dist/chunk-AG62YO7C.js.map +1 -0
- package/dist/chunk-AIRIT4GF.js +75 -0
- package/dist/chunk-AIRIT4GF.js.map +1 -0
- package/dist/chunk-AP3TP6VG.js +139 -0
- package/dist/chunk-AP3TP6VG.js.map +1 -0
- package/dist/chunk-APP475IQ.js +474 -0
- package/dist/chunk-APP475IQ.js.map +1 -0
- package/dist/chunk-AR7PU7BB.js +76 -0
- package/dist/chunk-AR7PU7BB.js.map +1 -0
- package/dist/chunk-B4S72KSS.js +172 -0
- package/dist/chunk-B4S72KSS.js.map +1 -0
- package/dist/chunk-BIPIL4QA.js +486 -0
- package/dist/chunk-BIPIL4QA.js.map +1 -0
- package/dist/chunk-BPUSL5Y2.js +58 -0
- package/dist/chunk-BPUSL5Y2.js.map +1 -0
- package/dist/chunk-BR32GHYD.js +65 -0
- package/dist/chunk-BR32GHYD.js.map +1 -0
- package/dist/chunk-CAMX6OHF.js +3182 -0
- package/dist/chunk-CAMX6OHF.js.map +1 -0
- package/dist/chunk-CE7RTOX6.js +494 -0
- package/dist/chunk-CE7RTOX6.js.map +1 -0
- package/dist/{chunk-MF7YA62W.js → chunk-CUL3VB4L.js} +10 -5
- package/dist/chunk-CUL3VB4L.js.map +1 -0
- package/dist/chunk-CVEY353K.js +66 -0
- package/dist/chunk-CVEY353K.js.map +1 -0
- package/dist/chunk-CWXADUKL.js +1599 -0
- package/dist/chunk-CWXADUKL.js.map +1 -0
- package/dist/chunk-D46NOXRY.js +6212 -0
- package/dist/chunk-D46NOXRY.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-DUPURL26.js +97 -0
- package/dist/chunk-DUPURL26.js.map +1 -0
- package/dist/chunk-DXJYQ5P2.js +625 -0
- package/dist/chunk-DXJYQ5P2.js.map +1 -0
- package/dist/chunk-E2ZOSNF5.js +96 -0
- package/dist/chunk-E2ZOSNF5.js.map +1 -0
- package/dist/chunk-E3HYHT7C.js +274 -0
- package/dist/chunk-E3HYHT7C.js.map +1 -0
- package/dist/chunk-EDLZGTGN.js +216 -0
- package/dist/chunk-EDLZGTGN.js.map +1 -0
- package/dist/{chunk-XHC4LMK4.js → chunk-EIGXX6KI.js} +16 -8
- package/dist/chunk-EIGXX6KI.js.map +1 -0
- package/dist/chunk-EPDE7ZRU.js +174 -0
- package/dist/chunk-EPDE7ZRU.js.map +1 -0
- package/dist/chunk-ERSX3MKH.js +34 -0
- package/dist/chunk-ERSX3MKH.js.map +1 -0
- package/dist/chunk-F7HRLPR5.js +67 -0
- package/dist/chunk-F7HRLPR5.js.map +1 -0
- package/dist/chunk-FEG6MN4H.js +84 -0
- package/dist/chunk-FEG6MN4H.js.map +1 -0
- package/dist/chunk-FKOECEVC.js +126 -0
- package/dist/chunk-FKOECEVC.js.map +1 -0
- package/dist/chunk-FMGW2NZI.js +106 -0
- package/dist/chunk-FMGW2NZI.js.map +1 -0
- package/dist/chunk-FPZKKNDK.js +98 -0
- package/dist/chunk-FPZKKNDK.js.map +1 -0
- package/dist/chunk-G3ZDLPNZ.js +206 -0
- package/dist/chunk-G3ZDLPNZ.js.map +1 -0
- package/dist/chunk-GIWHHCD6.js +145 -0
- package/dist/chunk-GIWHHCD6.js.map +1 -0
- package/dist/chunk-GOJXKIFQ.js +1605 -0
- package/dist/chunk-GOJXKIFQ.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-HAE4WWFQ.js +455 -0
- package/dist/chunk-HAE4WWFQ.js.map +1 -0
- package/dist/chunk-HEEAC2YG.js +541 -0
- package/dist/chunk-HEEAC2YG.js.map +1 -0
- package/dist/chunk-I2DNBEV6.js +4227 -0
- package/dist/chunk-I2DNBEV6.js.map +1 -0
- package/dist/chunk-I4FTS5EE.js +455 -0
- package/dist/chunk-I4FTS5EE.js.map +1 -0
- package/dist/chunk-IA4KJU7O.js +3151 -0
- package/dist/chunk-IA4KJU7O.js.map +1 -0
- package/dist/chunk-IELPT4K2.js +74 -0
- package/dist/chunk-IELPT4K2.js.map +1 -0
- package/dist/chunk-IJMWEO4P.js +57 -0
- package/dist/chunk-IJMWEO4P.js.map +1 -0
- package/dist/chunk-IVIJJXXT.js +62 -0
- package/dist/chunk-IVIJJXXT.js.map +1 -0
- package/dist/chunk-JAU6OAFK.js +455 -0
- package/dist/chunk-JAU6OAFK.js.map +1 -0
- package/dist/chunk-JD3W3ON7.js +188 -0
- package/dist/chunk-JD3W3ON7.js.map +1 -0
- package/dist/chunk-JLWBK3VC.js +5187 -0
- package/dist/chunk-JLWBK3VC.js.map +1 -0
- package/dist/chunk-JPK34QPS.js +134 -0
- package/dist/chunk-JPK34QPS.js.map +1 -0
- package/dist/chunk-JXJD6RC5.js +169 -0
- package/dist/chunk-JXJD6RC5.js.map +1 -0
- package/dist/chunk-JXMZEOHV.js +333 -0
- package/dist/chunk-JXMZEOHV.js.map +1 -0
- package/dist/chunk-K6TDB2KV.js +1442 -0
- package/dist/chunk-K6TDB2KV.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-KONA5PSR.js +55 -0
- package/dist/chunk-KONA5PSR.js.map +1 -0
- package/dist/chunk-KVHRW7KO.js +60 -0
- package/dist/chunk-KVHRW7KO.js.map +1 -0
- package/dist/chunk-LA6PPSNA.js +65 -0
- package/dist/chunk-LA6PPSNA.js.map +1 -0
- package/dist/chunk-LKPJADL2.js +74 -0
- package/dist/chunk-LKPJADL2.js.map +1 -0
- package/dist/chunk-LM7N7IQR.js +297 -0
- package/dist/chunk-LM7N7IQR.js.map +1 -0
- package/dist/chunk-LWAEHLKV.js +74 -0
- package/dist/chunk-LWAEHLKV.js.map +1 -0
- package/dist/chunk-M6UNISGO.js +66 -0
- package/dist/chunk-M6UNISGO.js.map +1 -0
- package/dist/chunk-MFSIACRB.js +207 -0
- package/dist/chunk-MFSIACRB.js.map +1 -0
- package/dist/chunk-MIJAGBEP.js +23992 -0
- package/dist/chunk-MIJAGBEP.js.map +1 -0
- package/dist/chunk-MYTDK3AL.js +2102 -0
- package/dist/chunk-MYTDK3AL.js.map +1 -0
- package/dist/chunk-MYURCD23.js +6667 -0
- package/dist/chunk-MYURCD23.js.map +1 -0
- package/dist/chunk-MZQ5DX6S.js +125 -0
- package/dist/chunk-MZQ5DX6S.js.map +1 -0
- package/dist/chunk-NFSLRRIE.js +77 -0
- package/dist/chunk-NFSLRRIE.js.map +1 -0
- package/dist/chunk-NMDP7FZP.js +479 -0
- package/dist/chunk-NMDP7FZP.js.map +1 -0
- package/dist/chunk-NMGELUIA.js +183 -0
- package/dist/chunk-NMGELUIA.js.map +1 -0
- package/dist/chunk-NOK7MSVJ.js +533 -0
- package/dist/chunk-NOK7MSVJ.js.map +1 -0
- package/dist/chunk-O2EVJALZ.js +133 -0
- package/dist/chunk-O2EVJALZ.js.map +1 -0
- package/dist/chunk-OIL6PU5W.js +35 -0
- package/dist/chunk-OIL6PU5W.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-PSWVSLJU.js +56 -0
- package/dist/chunk-PSWVSLJU.js.map +1 -0
- package/dist/chunk-PY2NJ6XZ.js +191 -0
- package/dist/chunk-PY2NJ6XZ.js.map +1 -0
- package/dist/chunk-PZ4OM2LK.js +45 -0
- package/dist/chunk-PZ4OM2LK.js.map +1 -0
- package/dist/chunk-Q2EKN7NI.js +1079 -0
- package/dist/chunk-Q2EKN7NI.js.map +1 -0
- package/dist/chunk-Q6ULQMWG.js +41 -0
- package/dist/chunk-Q6ULQMWG.js.map +1 -0
- package/dist/chunk-QMLGJ5OW.js +2891 -0
- package/dist/chunk-QMLGJ5OW.js.map +1 -0
- package/dist/chunk-R7QV5N2S.js +846 -0
- package/dist/chunk-R7QV5N2S.js.map +1 -0
- package/dist/chunk-RCS4JKUD.js +23 -0
- package/dist/chunk-RCS4JKUD.js.map +1 -0
- package/dist/chunk-RR3KT2E7.js +665 -0
- package/dist/chunk-RR3KT2E7.js.map +1 -0
- package/dist/chunk-SEPPFM5S.js +228 -0
- package/dist/chunk-SEPPFM5S.js.map +1 -0
- package/dist/chunk-SQ7DRYCC.js +150 -0
- package/dist/chunk-SQ7DRYCC.js.map +1 -0
- package/dist/chunk-SYULM665.js +610 -0
- package/dist/chunk-SYULM665.js.map +1 -0
- package/dist/chunk-TKT3OHZ6.js +170 -0
- package/dist/chunk-TKT3OHZ6.js.map +1 -0
- package/dist/chunk-TNOSX3PJ.js +136 -0
- package/dist/chunk-TNOSX3PJ.js.map +1 -0
- package/dist/chunk-TTVKI54A.js +160 -0
- package/dist/chunk-TTVKI54A.js.map +1 -0
- package/dist/chunk-U55UZRIB.js +592 -0
- package/dist/chunk-U55UZRIB.js.map +1 -0
- package/dist/chunk-UI6BKYQD.js +225 -0
- package/dist/chunk-UI6BKYQD.js.map +1 -0
- package/dist/chunk-UKE4IZSA.js +337 -0
- package/dist/chunk-UKE4IZSA.js.map +1 -0
- package/dist/chunk-UKLDW4UW.js +46 -0
- package/dist/chunk-UKLDW4UW.js.map +1 -0
- package/dist/chunk-V6XXXEXZ.js +76 -0
- package/dist/chunk-V6XXXEXZ.js.map +1 -0
- package/dist/chunk-VCZSZCXY.js +197 -0
- package/dist/chunk-VCZSZCXY.js.map +1 -0
- package/dist/chunk-VJQWUF66.js +92 -0
- package/dist/chunk-VJQWUF66.js.map +1 -0
- package/dist/chunk-VSU5R34H.js +76 -0
- package/dist/chunk-VSU5R34H.js.map +1 -0
- package/dist/chunk-W4SA4CMR.js +296 -0
- package/dist/chunk-W4SA4CMR.js.map +1 -0
- package/dist/chunk-WFUMNDCE.js +111 -0
- package/dist/chunk-WFUMNDCE.js.map +1 -0
- package/dist/chunk-WGCGKU3M.js +51 -0
- package/dist/chunk-WGCGKU3M.js.map +1 -0
- package/dist/chunk-WHWNXLTD.js +166 -0
- package/dist/chunk-WHWNXLTD.js.map +1 -0
- package/dist/chunk-WN42X2OE.js +509 -0
- package/dist/chunk-WN42X2OE.js.map +1 -0
- package/dist/chunk-WN4KX7GE.js +25 -0
- package/dist/chunk-WN4KX7GE.js.map +1 -0
- package/dist/chunk-XIY7P54H.js +84 -0
- package/dist/chunk-XIY7P54H.js.map +1 -0
- package/dist/chunk-XPLTWUMN.js +103 -0
- package/dist/chunk-XPLTWUMN.js.map +1 -0
- package/dist/chunk-Y6T5ZKBK.js +19 -0
- package/dist/chunk-Y6T5ZKBK.js.map +1 -0
- package/dist/chunk-YGGRQXDP.js +382 -0
- package/dist/chunk-YGGRQXDP.js.map +1 -0
- package/dist/chunk-YMBB4JBD.js +1830 -0
- package/dist/chunk-YMBB4JBD.js.map +1 -0
- package/dist/chunk-YNWM426O.js +159 -0
- package/dist/chunk-YNWM426O.js.map +1 -0
- package/dist/chunk-YQSBHWOI.js +41 -0
- package/dist/chunk-YTF3IVMF.js +149 -0
- package/dist/chunk-YTF3IVMF.js.map +1 -0
- package/dist/chunk-Z3ENMCFE.js +94 -0
- package/dist/chunk-Z3ENMCFE.js.map +1 -0
- package/dist/chunk-Z7MWSXLG.js +94 -0
- package/dist/chunk-Z7MWSXLG.js.map +1 -0
- package/dist/chunk-ZIXHS6AM.js +42 -0
- package/dist/chunk-ZIXHS6AM.js.map +1 -0
- package/dist/chunk-ZJ7TQUCU.js +4410 -0
- package/dist/chunk-ZJ7TQUCU.js.map +1 -0
- package/dist/chunk-ZNQRDLSS.js +52 -0
- package/dist/chunk-ZNQRDLSS.js.map +1 -0
- package/dist/chunk-ZPGGSXU3.js +275 -0
- package/dist/chunk-ZPGGSXU3.js.map +1 -0
- package/dist/claim-NXYQZEMC.js +197 -0
- package/dist/claim-NXYQZEMC.js.map +1 -0
- package/dist/cli.js +104 -69952
- package/dist/cli.js.map +1 -1
- package/dist/client-EURRWXPW.js +19 -0
- package/dist/code-FKQW7V7N.js +76 -0
- package/dist/code-FKQW7V7N.js.map +1 -0
- package/dist/companies-5ZH47E4H.js +195 -0
- package/dist/companies-5ZH47E4H.js.map +1 -0
- package/dist/complete-62OQPRHW.js +81 -0
- package/dist/complete-62OQPRHW.js.map +1 -0
- package/dist/config-OZOHIAOJ.js +88 -0
- package/dist/config-OZOHIAOJ.js.map +1 -0
- package/dist/connect-6DQFYKGN.js +42 -0
- package/dist/content-PCGSX2QU.js +85 -0
- package/dist/content-PCGSX2QU.js.map +1 -0
- package/dist/conversation-NS7JHTPK.js +93 -0
- package/dist/conversation-NS7JHTPK.js.map +1 -0
- package/dist/conversion-report-7QSWB2FY.js +125 -0
- package/dist/conversion-report-7QSWB2FY.js.map +1 -0
- package/dist/conversion-upload-command-XESIAQPU.js +438 -0
- package/dist/conversion-upload-command-XESIAQPU.js.map +1 -0
- package/dist/conversion-writes-BGOVLBS5.js +120 -0
- package/dist/conversion-writes-BGOVLBS5.js.map +1 -0
- package/dist/conversions-46MI57VC.js +135 -0
- package/dist/conversions-46MI57VC.js.map +1 -0
- package/dist/conversions-IYIWW4O7.js +76 -0
- package/dist/conversions-IYIWW4O7.js.map +1 -0
- package/dist/countries-5OBUVLLD.js +82 -0
- package/dist/countries-5OBUVLLD.js.map +1 -0
- package/dist/create-BEDPXUB7.js +236 -0
- package/dist/create-BEDPXUB7.js.map +1 -0
- package/dist/create-LLTMBBGV.js +207 -0
- package/dist/create-LLTMBBGV.js.map +1 -0
- package/dist/create-VNJ2VH3A.js +59 -0
- package/dist/create-VNJ2VH3A.js.map +1 -0
- package/dist/create-ZYKG2XOP.js +138 -0
- package/dist/create-ZYKG2XOP.js.map +1 -0
- package/dist/creatives-2LL66X4E.js +51 -0
- package/dist/creatives-2LL66X4E.js.map +1 -0
- package/dist/creatives-3MEMSUKJ.js +182 -0
- package/dist/creatives-3MEMSUKJ.js.map +1 -0
- package/dist/creatives-XI2DGQUZ.js +87 -0
- package/dist/creatives-XI2DGQUZ.js.map +1 -0
- package/dist/credentials-63PRTM3K.js +287 -0
- package/dist/credentials-63PRTM3K.js.map +1 -0
- package/dist/critique-IQI7CCTT.js +213 -0
- package/dist/critique-IQI7CCTT.js.map +1 -0
- package/dist/critique-UV7FPG45.js +1449 -0
- package/dist/critique-UV7FPG45.js.map +1 -0
- package/dist/crm-OERYUOBS.js +224 -0
- package/dist/crm-OERYUOBS.js.map +1 -0
- package/dist/crm-VNO3QTQG.js +318 -0
- package/dist/crm-VNO3QTQG.js.map +1 -0
- package/dist/crop-B52KIQ4O.js +113 -0
- package/dist/crop-B52KIQ4O.js.map +1 -0
- package/dist/currency-GGWF5DMU.js +88 -0
- package/dist/currency-GGWF5DMU.js.map +1 -0
- package/dist/custom-conversions-7WDBTC4X.js +125 -0
- package/dist/custom-conversions-7WDBTC4X.js.map +1 -0
- package/dist/customers-FOPXEGCB.js +56 -0
- package/dist/decide-PK7WNSQ2.js +199 -0
- package/dist/decide-PK7WNSQ2.js.map +1 -0
- package/dist/delete-56LKNEGA.js +71 -0
- package/dist/delete-56LKNEGA.js.map +1 -0
- package/dist/delete-EZ7HHOOD.js +69 -0
- package/dist/delete-EZ7HHOOD.js.map +1 -0
- package/dist/delete-JSYM7QKN.js +54 -0
- package/dist/delete-JSYM7QKN.js.map +1 -0
- package/dist/delete-NOUWBNZM.js +66 -0
- package/dist/delete-NOUWBNZM.js.map +1 -0
- package/dist/delete-T33AWV63.js +63 -0
- package/dist/delete-T33AWV63.js.map +1 -0
- package/dist/delete-YSYVFL6W.js +71 -0
- package/dist/delete-YSYVFL6W.js.map +1 -0
- package/dist/demographics-LQGFUS4F.js +138 -0
- package/dist/demographics-LQGFUS4F.js.map +1 -0
- package/dist/describe-AAVYIFE3.js +97 -0
- package/dist/describe-AAVYIFE3.js.map +1 -0
- package/dist/describe-UQFLWVFR.js +97 -0
- package/dist/describe-UQFLWVFR.js.map +1 -0
- package/dist/dimensions-QDXBG2XC.js +101 -0
- package/dist/dimensions-QDXBG2XC.js.map +1 -0
- package/dist/discard-V4LQ7ZGA.js +66 -0
- package/dist/discard-V4LQ7ZGA.js.map +1 -0
- package/dist/discover-6TEBPVNC.js +93 -0
- package/dist/discover-6TEBPVNC.js.map +1 -0
- package/dist/discover-SBZPB7T2.js +172 -0
- package/dist/discover-SBZPB7T2.js.map +1 -0
- package/dist/domain-65J2DEDB.js +98 -0
- package/dist/domain-65J2DEDB.js.map +1 -0
- package/dist/download-LV3GPOWV.js +299 -0
- package/dist/download-LV3GPOWV.js.map +1 -0
- package/dist/draft-DDFFTZ43.js +233 -0
- package/dist/draft-DDFFTZ43.js.map +1 -0
- package/dist/draft-FIKJXNIQ.js +281 -0
- package/dist/draft-FIKJXNIQ.js.map +1 -0
- package/dist/draft-GYGWTMBU.js +307 -0
- package/dist/draft-GYGWTMBU.js.map +1 -0
- package/dist/draft-KNXVZAZV.js +217 -0
- package/dist/draft-KNXVZAZV.js.map +1 -0
- package/dist/draft-N4LFPKTA.js +100 -0
- package/dist/draft-N4LFPKTA.js.map +1 -0
- package/dist/draft-NG2DPL2X.js +306 -0
- package/dist/draft-NG2DPL2X.js.map +1 -0
- package/dist/draft-QILZ7M7N.js +328 -0
- package/dist/draft-QILZ7M7N.js.map +1 -0
- package/dist/draft-XPO5RWST.js +103 -0
- package/dist/draft-XPO5RWST.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-TQ2XS2KY.js} +12 -2
- package/dist/env-TQ2XS2KY.js.map +1 -0
- package/dist/experiment-FQNKMORZ.js +1397 -0
- package/dist/experiment-FQNKMORZ.js.map +1 -0
- package/dist/export-4IZQZAPF.js +168 -0
- package/dist/export-4IZQZAPF.js.map +1 -0
- package/dist/extract-DZMGVQ7D.js +113 -0
- package/dist/extract-DZMGVQ7D.js.map +1 -0
- package/dist/facets-FAAOFHBF.js +114 -0
- package/dist/facets-FAAOFHBF.js.map +1 -0
- package/dist/favorites-DD2LNSTG.js +178 -0
- package/dist/favorites-DD2LNSTG.js.map +1 -0
- package/dist/feed-TUVFNX2U.js +177 -0
- package/dist/feed-TUVFNX2U.js.map +1 -0
- package/dist/feedback-NWOOZOFW.js +66 -0
- package/dist/feedback-NWOOZOFW.js.map +1 -0
- package/dist/feedback-record-CFPUKLMY.js +175 -0
- package/dist/feedback-record-CFPUKLMY.js.map +1 -0
- package/dist/fetch-LEY77E7V.js +176 -0
- package/dist/fetch-LEY77E7V.js.map +1 -0
- package/dist/fetch-O6UHNXWB.js +139 -0
- package/dist/fetch-O6UHNXWB.js.map +1 -0
- package/dist/find-4XKIBF4D.js +134 -0
- package/dist/find-4XKIBF4D.js.map +1 -0
- package/dist/fit-ODVVXV2Q.js +45 -0
- package/dist/fit-ODVVXV2Q.js.map +1 -0
- package/dist/flows-QKPC63AF.js +247 -0
- package/dist/flows-QKPC63AF.js.map +1 -0
- package/dist/follow-RCOXTZGY.js +94 -0
- package/dist/follow-RCOXTZGY.js.map +1 -0
- package/dist/follow-competitors-SQ5XBFTK.js +112 -0
- package/dist/follow-competitors-SQ5XBFTK.js.map +1 -0
- package/dist/following-VDU3BHC4.js +113 -0
- package/dist/following-VDU3BHC4.js.map +1 -0
- package/dist/fonts-WM2MJDVJ.js +34 -0
- package/dist/fonts-WM2MJDVJ.js.map +1 -0
- package/dist/forecast-2GJKBNBM.js +168 -0
- package/dist/forecast-2GJKBNBM.js.map +1 -0
- package/dist/forecast-7K3TAHDL.js +104 -0
- package/dist/forecast-7K3TAHDL.js.map +1 -0
- package/dist/funding-HTFVZLLG.js +85 -0
- package/dist/funding-HTFVZLLG.js.map +1 -0
- package/dist/funnel-CSPK5SPZ.js +394 -0
- package/dist/funnel-CSPK5SPZ.js.map +1 -0
- package/dist/ga4-2RC4EH7V.js +55 -0
- package/dist/ga4-2RC4EH7V.js.map +1 -0
- package/dist/generate-TPDOBCKQ.js +262 -0
- package/dist/generate-TPDOBCKQ.js.map +1 -0
- package/dist/get-4YZ4PI3B.js +56 -0
- package/dist/get-4YZ4PI3B.js.map +1 -0
- package/dist/get-FH2LIEYL.js +63 -0
- package/dist/get-FH2LIEYL.js.map +1 -0
- package/dist/get-GZLCDXXW.js +61 -0
- package/dist/get-GZLCDXXW.js.map +1 -0
- package/dist/get-HFU6ZJPX.js +78 -0
- package/dist/get-HFU6ZJPX.js.map +1 -0
- package/dist/get-TSPQYEKC.js +59 -0
- package/dist/get-TSPQYEKC.js.map +1 -0
- package/dist/get-TY3RXYNZ.js +63 -0
- package/dist/get-TY3RXYNZ.js.map +1 -0
- package/dist/get-VPW33XTN.js +92 -0
- package/dist/get-VPW33XTN.js.map +1 -0
- package/dist/gif-JFEYPFFI.js +94 -0
- package/dist/gif-JFEYPFFI.js.map +1 -0
- package/dist/google-R6RD4L6Z.js +136 -0
- package/dist/google-R6RD4L6Z.js.map +1 -0
- package/dist/google-VPQNRVIB.js +3190 -0
- package/dist/google-VPQNRVIB.js.map +1 -0
- package/dist/google-ads-WWM5KIRS.js +195 -0
- package/dist/google-ads-WWM5KIRS.js.map +1 -0
- package/dist/group-7AV6UL26.js +43 -0
- package/dist/group-7AV6UL26.js.map +1 -0
- package/dist/group-BVQZEZIC.js +43 -0
- package/dist/group-BVQZEZIC.js.map +1 -0
- package/dist/gsc-SQ42WAQE.js +30 -0
- package/dist/gsc-SQ42WAQE.js.map +1 -0
- package/dist/history-BNNHFURR.js +67 -0
- package/dist/history-BNNHFURR.js.map +1 -0
- package/dist/history-KBK5TP65.js +133 -0
- package/dist/history-KBK5TP65.js.map +1 -0
- package/dist/hubspot-GAAWWVLL.js +779 -0
- package/dist/hubspot-GAAWWVLL.js.map +1 -0
- package/dist/icon-OYTTSNSL.js +137 -0
- package/dist/icon-OYTTSNSL.js.map +1 -0
- package/dist/ideas-CELMD3BL.js +32 -0
- package/dist/ideas-CELMD3BL.js.map +1 -0
- package/dist/images-QHV4ECAP.js +90 -0
- package/dist/images-QHV4ECAP.js.map +1 -0
- package/dist/improve-W6GZNT2A.js +86 -0
- package/dist/improve-W6GZNT2A.js.map +1 -0
- package/dist/ingest-SH35YX6X.js +23 -0
- package/dist/ingest-SH35YX6X.js.map +1 -0
- package/dist/ingest-UWCGJZXV.js +107 -0
- package/dist/ingest-UWCGJZXV.js.map +1 -0
- package/dist/insights-IW7LGAWU.js +423 -0
- package/dist/insights-IW7LGAWU.js.map +1 -0
- package/dist/insights-QH54F56A.js +122 -0
- package/dist/insights-QH54F56A.js.map +1 -0
- package/dist/inspect-6Z6HEMBI.js +189 -0
- package/dist/inspect-6Z6HEMBI.js.map +1 -0
- package/dist/inspiration-RDQ3Y3N3.js +53 -0
- package/dist/inspiration-RDQ3Y3N3.js.map +1 -0
- package/dist/intent-5GSSCFZ2.js +95 -0
- package/dist/intent-5GSSCFZ2.js.map +1 -0
- package/dist/job-URVXJP75.js +202 -0
- package/dist/job-URVXJP75.js.map +1 -0
- package/dist/job-create-S4SECUVF.js +109 -0
- package/dist/job-create-S4SECUVF.js.map +1 -0
- package/dist/job-status-253SUCTJ.js +74 -0
- package/dist/job-status-253SUCTJ.js.map +1 -0
- package/dist/keep-GPSYDIGJ.js +78 -0
- package/dist/keep-GPSYDIGJ.js.map +1 -0
- package/dist/keyword-gap-NTFDX43B.js +130 -0
- package/dist/keyword-gap-NTFDX43B.js.map +1 -0
- package/dist/keyword-metrics-NKZRCF4L.js +197 -0
- package/dist/keyword-metrics-NKZRCF4L.js.map +1 -0
- package/dist/keywords-for-site-NQUPJNUR.js +128 -0
- package/dist/keywords-for-site-NQUPJNUR.js.map +1 -0
- package/dist/landing-AHNZSZHY.js +28 -0
- package/dist/landing-AHNZSZHY.js.map +1 -0
- package/dist/landings-NEF4PQL2.js +151 -0
- package/dist/landings-NEF4PQL2.js.map +1 -0
- package/dist/languages-3RDPPPTE.js +55 -0
- package/dist/languages-3RDPPPTE.js.map +1 -0
- package/dist/languages-CQX3YOIT.js +40 -0
- package/dist/languages-CQX3YOIT.js.map +1 -0
- package/dist/launches-GBHLJH5S.js +19 -0
- package/dist/launches-GBHLJH5S.js.map +1 -0
- package/dist/layerize-Q56C6LFG.js +190 -0
- package/dist/layerize-Q56C6LFG.js.map +1 -0
- package/dist/leads-5MUVPXA2.js +90 -0
- package/dist/leads-5MUVPXA2.js.map +1 -0
- package/dist/leads-JHUM6FYR.js +293 -0
- package/dist/leads-JHUM6FYR.js.map +1 -0
- package/dist/learn-EMV7RWTB.js +203 -0
- package/dist/learn-EMV7RWTB.js.map +1 -0
- package/dist/library-6VUFHTEK.js +109 -0
- package/dist/library-6VUFHTEK.js.map +1 -0
- package/dist/lighthouse-57U2GMPV.js +75 -0
- package/dist/lighthouse-57U2GMPV.js.map +1 -0
- package/dist/line-item-writes-GMIZYHLB.js +208 -0
- package/dist/line-item-writes-GMIZYHLB.js.map +1 -0
- package/dist/line-items-B5HAC47U.js +103 -0
- package/dist/line-items-B5HAC47U.js.map +1 -0
- package/dist/link-B6ZJFGFE.js +64 -0
- package/dist/link-B6ZJFGFE.js.map +1 -0
- package/dist/linkedin-FJ3OUYT2.js +1008 -0
- package/dist/linkedin-FJ3OUYT2.js.map +1 -0
- package/dist/list-2MBSU4ZX.js +63 -0
- package/dist/list-2MBSU4ZX.js.map +1 -0
- package/dist/list-EFUPHLG3.js +303 -0
- package/dist/list-EFUPHLG3.js.map +1 -0
- package/dist/list-G57ZO4PG.js +50 -0
- package/dist/list-G57ZO4PG.js.map +1 -0
- package/dist/list-JCSWZWDI.js +57 -0
- package/dist/list-JCSWZWDI.js.map +1 -0
- package/dist/list-QOSPRCH4.js +151 -0
- package/dist/list-QOSPRCH4.js.map +1 -0
- package/dist/list-RINCJOAC.js +76 -0
- package/dist/list-RINCJOAC.js.map +1 -0
- package/dist/list-SRNXHS6L.js +51 -0
- package/dist/list-SRNXHS6L.js.map +1 -0
- package/dist/list-YJSO4M5Q.js +65 -0
- package/dist/list-YJSO4M5Q.js.map +1 -0
- package/dist/locations-HW2Y5OJO.js +67 -0
- package/dist/locations-HW2Y5OJO.js.map +1 -0
- package/dist/locations-XOHI3VWI.js +40 -0
- package/dist/locations-XOHI3VWI.js.map +1 -0
- package/dist/log-SZDYUMM3.js +92 -0
- package/dist/log-SZDYUMM3.js.map +1 -0
- package/dist/logo-KXTGIYBI.js +18 -0
- package/dist/logo-KXTGIYBI.js.map +1 -0
- package/dist/lookup-X6O5UNJH.js +22 -0
- package/dist/lookup-X6O5UNJH.js.map +1 -0
- package/dist/make-SGCBJTRR.js +633 -0
- package/dist/make-SGCBJTRR.js.map +1 -0
- package/dist/map-ZK46VVL3.js +404 -0
- package/dist/map-ZK46VVL3.js.map +1 -0
- package/dist/mcp-NCM5TQUG.js +463 -0
- package/dist/mcp-NCM5TQUG.js.map +1 -0
- package/dist/media-MI4EE7L4.js +89 -0
- package/dist/media-MI4EE7L4.js.map +1 -0
- package/dist/media-QUTQOBA7.js +15 -0
- package/dist/media-QUTQOBA7.js.map +1 -0
- package/dist/media-sources-MS3RMQ6A.js +32 -0
- package/dist/media-sources-MS3RMQ6A.js.map +1 -0
- package/dist/members-IGHLTQKW.js +44 -0
- package/dist/members-IGHLTQKW.js.map +1 -0
- package/dist/meta-E3JOUOSS.js +69 -0
- package/dist/meta-E3JOUOSS.js.map +1 -0
- package/dist/metrics-HQ7XJAYQ.js +152 -0
- package/dist/metrics-HQ7XJAYQ.js.map +1 -0
- package/dist/models-PGX3FBHU.js +155 -0
- package/dist/models-PGX3FBHU.js.map +1 -0
- package/dist/normalize-FPJ6GSOY.js +806 -0
- package/dist/normalize-FPJ6GSOY.js.map +1 -0
- package/dist/normalize-LHD5LVFK.js +141 -0
- package/dist/normalize-LHD5LVFK.js.map +1 -0
- package/dist/options-CPHN3RMO.js +121 -0
- package/dist/options-CPHN3RMO.js.map +1 -0
- package/dist/output-GQFJ2T5B.js +24 -0
- package/dist/output-GQFJ2T5B.js.map +1 -0
- package/dist/page-VTTSBC6Y.js +105 -0
- package/dist/page-VTTSBC6Y.js.map +1 -0
- package/dist/pages-PMZVNVQM.js +66 -0
- package/dist/pages-PMZVNVQM.js.map +1 -0
- package/dist/performance-ECIJJEFV.js +24 -0
- package/dist/performance-ECIJJEFV.js.map +1 -0
- package/dist/pinterest-UDNGOWDM.js +96 -0
- package/dist/pinterest-UDNGOWDM.js.map +1 -0
- package/dist/pixels-OYZDGCH3.js +108 -0
- package/dist/pixels-OYZDGCH3.js.map +1 -0
- package/dist/pixels-XKGNTCFX.js +60 -0
- package/dist/pixels-XKGNTCFX.js.map +1 -0
- package/dist/plan-DZS3TVIJ.js +207 -0
- package/dist/plan-DZS3TVIJ.js.map +1 -0
- package/dist/preview-DR6MXOGI.js +169 -0
- package/dist/preview-DR6MXOGI.js.map +1 -0
- package/dist/profile-VOVZG44G.js +159 -0
- package/dist/profile-VOVZG44G.js.map +1 -0
- package/dist/promoted-tweet-writes-UJJI5SQL.js +180 -0
- package/dist/promoted-tweet-writes-UJJI5SQL.js.map +1 -0
- package/dist/promoted-tweets-O5RCETPX.js +119 -0
- package/dist/promoted-tweets-O5RCETPX.js.map +1 -0
- package/dist/properties-MKVF7MUK.js +101 -0
- package/dist/properties-MKVF7MUK.js.map +1 -0
- package/dist/publish-RRYU3NNX.js +322 -0
- package/dist/publish-RRYU3NNX.js.map +1 -0
- package/dist/query-CNWQ6STR.js +61 -0
- package/dist/query-CNWQ6STR.js.map +1 -0
- package/dist/query-DBSBZ73C.js +247 -0
- package/dist/query-DBSBZ73C.js.map +1 -0
- package/dist/query-QK4U4TEL.js +236 -0
- package/dist/query-QK4U4TEL.js.map +1 -0
- package/dist/questionnaire-OVJWNUVV.js +93 -0
- package/dist/questionnaire-OVJWNUVV.js.map +1 -0
- package/dist/read-L2QIVJTL.js +141 -0
- package/dist/read-L2QIVJTL.js.map +1 -0
- package/dist/reddit-K6CKJZRF.js +26 -0
- package/dist/reddit-K6CKJZRF.js.map +1 -0
- package/dist/refresh-IF4P57JJ.js +94 -0
- package/dist/refresh-IF4P57JJ.js.map +1 -0
- package/dist/release-H4EL3J6R.js +60 -0
- package/dist/release-H4EL3J6R.js.map +1 -0
- package/dist/relevant-pages-CRI2NLWG.js +99 -0
- package/dist/relevant-pages-CRI2NLWG.js.map +1 -0
- package/dist/remove-DKSHQRNS.js +50 -0
- package/dist/remove-DKSHQRNS.js.map +1 -0
- package/dist/remove-JKSCGKQG.js +48 -0
- package/dist/remove-JKSCGKQG.js.map +1 -0
- package/dist/reopen-B26V2GEJ.js +63 -0
- package/dist/reopen-B26V2GEJ.js.map +1 -0
- package/dist/rerun-6WKE4MPY.js +84 -0
- package/dist/rerun-6WKE4MPY.js.map +1 -0
- package/dist/research-O3IVF3MM.js +62 -0
- package/dist/research-O3IVF3MM.js.map +1 -0
- package/dist/research-SC7S6IPV.js +262 -0
- package/dist/research-SC7S6IPV.js.map +1 -0
- package/dist/reset-7HMOB2KE.js +54 -0
- package/dist/reset-7HMOB2KE.js.map +1 -0
- package/dist/reset-THPEXZDK.js +54 -0
- package/dist/reset-THPEXZDK.js.map +1 -0
- package/dist/resolve-HX5R52A3.js +121 -0
- package/dist/resolve-HX5R52A3.js.map +1 -0
- package/dist/retry-4ENRUJOJ.js +62 -0
- package/dist/retry-4ENRUJOJ.js.map +1 -0
- package/dist/retry-ELIMI7U5.js +60 -0
- package/dist/retry-ELIMI7U5.js.map +1 -0
- package/dist/retry-failed-2OYMCB55.js +45 -0
- package/dist/retry-failed-2OYMCB55.js.map +1 -0
- package/dist/run-CY4BAIQI.js +65 -0
- package/dist/run-CY4BAIQI.js.map +1 -0
- package/dist/run-GXPPPDGI.js +59 -0
- package/dist/run-GXPPPDGI.js.map +1 -0
- package/dist/scaffold-ad-X6VPBVTB.js +1548 -0
- package/dist/scaffold-ad-X6VPBVTB.js.map +1 -0
- package/dist/scaffold-static-ad-LKOOZSDP.js +971 -0
- package/dist/scaffold-static-ad-LKOOZSDP.js.map +1 -0
- package/dist/scaffold-video-NAOIFIM4.js +872 -0
- package/dist/scaffold-video-NAOIFIM4.js.map +1 -0
- package/dist/schedule-TLYT5UXM.js +66 -0
- package/dist/schedule-TLYT5UXM.js.map +1 -0
- package/dist/schedule-V654LLZ2.js +61 -0
- package/dist/schedule-V654LLZ2.js.map +1 -0
- package/dist/scheduled-agents-MJNUZYEK.js +49 -0
- package/dist/scheduled-agents-MJNUZYEK.js.map +1 -0
- package/dist/schema-DN4WKWUM.js +132 -0
- package/dist/schema-DN4WKWUM.js.map +1 -0
- package/dist/schema-MZTVCNP4.js +63 -0
- package/dist/schema-MZTVCNP4.js.map +1 -0
- package/dist/scrape-T3DA7ER7.js +2241 -0
- package/dist/scrape-T3DA7ER7.js.map +1 -0
- package/dist/screenshot-EIGC6SZB.js +102 -0
- package/dist/screenshot-EIGC6SZB.js.map +1 -0
- package/dist/search-2SVUDZIX.js +224 -0
- package/dist/search-2SVUDZIX.js.map +1 -0
- package/dist/search-34NFJ5F6.js +26 -0
- package/dist/search-34NFJ5F6.js.map +1 -0
- package/dist/search-BWE3OPOY.js +91 -0
- package/dist/search-BWE3OPOY.js.map +1 -0
- package/dist/search-EYYAOZND.js +92 -0
- package/dist/search-EYYAOZND.js.map +1 -0
- package/dist/search-EZZMYU4Y.js +174 -0
- package/dist/search-EZZMYU4Y.js.map +1 -0
- package/dist/search-copy-VKQ2OOBM.js +168 -0
- package/dist/search-copy-VKQ2OOBM.js.map +1 -0
- package/dist/seeds-HQYSVFIX.js +101 -0
- package/dist/seeds-HQYSVFIX.js.map +1 -0
- package/dist/select-3SIBANY6.js +94 -0
- package/dist/select-3SIBANY6.js.map +1 -0
- package/dist/sends-I7VQFE4S.js +309 -0
- package/dist/sends-I7VQFE4S.js.map +1 -0
- package/dist/sequences-JHSEJJGN.js +146 -0
- package/dist/sequences-JHSEJJGN.js.map +1 -0
- package/dist/set-prompt-RAG7RJOD.js +185 -0
- package/dist/set-prompt-RAG7RJOD.js.map +1 -0
- package/dist/setup-links-TNRBFS5Z.js +141 -0
- package/dist/setup-links-TNRBFS5Z.js.map +1 -0
- package/dist/{shared-J7DQZ2ED.js → shared-AT3FXPAG.js} +8 -6
- package/dist/shared-AT3FXPAG.js.map +1 -0
- package/dist/shopify-LUETQ5NT.js +3819 -0
- package/dist/shopify-LUETQ5NT.js.map +1 -0
- package/dist/site-SDL6LF6D.js +177 -0
- package/dist/site-SDL6LF6D.js.map +1 -0
- package/dist/sitemaps-FG37N5EB.js +87 -0
- package/dist/sitemaps-FG37N5EB.js.map +1 -0
- package/dist/sites-FIXK4Y3O.js +101 -0
- package/dist/sites-FIXK4Y3O.js.map +1 -0
- package/dist/skills-OKVCVQVD.js +47 -0
- package/dist/skills-OKVCVQVD.js.map +1 -0
- package/dist/sources-ISAUZFRN.js +30 -0
- package/dist/sources-ISAUZFRN.js.map +1 -0
- package/dist/sources-LQTJXAJG.js +421 -0
- package/dist/sources-LQTJXAJG.js.map +1 -0
- package/dist/stale-2L7NTLC6.js +63 -0
- package/dist/stale-2L7NTLC6.js.map +1 -0
- package/dist/stats-ZWZ7BAHV.js +34 -0
- package/dist/stats-ZWZ7BAHV.js.map +1 -0
- package/dist/status-4QBSIHO7.js +62 -0
- package/dist/status-4QBSIHO7.js.map +1 -0
- package/dist/sticker-FLRZM3BI.js +94 -0
- package/dist/sticker-FLRZM3BI.js.map +1 -0
- package/dist/stock-2CSMWRWV.js +179 -0
- package/dist/stock-2CSMWRWV.js.map +1 -0
- package/dist/studio-TTTR6N7D.js +49 -0
- package/dist/studio-TTTR6N7D.js.map +1 -0
- package/dist/sync-DH7FTPGG.js +54 -0
- package/dist/sync-DH7FTPGG.js.map +1 -0
- package/dist/sync-G5CS2RYV.js +54 -0
- package/dist/sync-G5CS2RYV.js.map +1 -0
- package/dist/sync-UADA6M33.js +265 -0
- package/dist/sync-UADA6M33.js.map +1 -0
- package/dist/sync-definition-ATMMOJ37.js +52 -0
- package/dist/sync-definition-ATMMOJ37.js.map +1 -0
- package/dist/tag-manager-NK3ZHSJB.js +43 -0
- package/dist/tag-manager-NK3ZHSJB.js.map +1 -0
- package/dist/tags-4RBZWDHS.js +20 -0
- package/dist/tags-4RBZWDHS.js.map +1 -0
- package/dist/tags-M7ATU2R7.js +26 -0
- package/dist/tags-M7ATU2R7.js.map +1 -0
- package/dist/tags-MXJKIBL4.js +20 -0
- package/dist/tags-MXJKIBL4.js.map +1 -0
- package/dist/tags-YG5EGPBW.js +20 -0
- package/dist/tags-YG5EGPBW.js.map +1 -0
- package/dist/tags-ZP4O3I2F.js +224 -0
- package/dist/tags-ZP4O3I2F.js.map +1 -0
- package/dist/targeting-constants-ZGBX3VWU.js +118 -0
- package/dist/targeting-constants-ZGBX3VWU.js.map +1 -0
- package/dist/targeting-criteria-BTB2RVI4.js +113 -0
- package/dist/targeting-criteria-BTB2RVI4.js.map +1 -0
- package/dist/targets-DEGJD2N6.js +102 -0
- package/dist/targets-DEGJD2N6.js.map +1 -0
- package/dist/templates-FZDWQSTV.js +178 -0
- package/dist/templates-FZDWQSTV.js.map +1 -0
- package/dist/testimonials-TI5EDABS.js +32 -0
- package/dist/testimonials-TI5EDABS.js.map +1 -0
- package/dist/themes-3RV3HNNE.js +94 -0
- package/dist/themes-3RV3HNNE.js.map +1 -0
- package/dist/top-companies-OKH7UNKX.js +108 -0
- package/dist/top-companies-OKH7UNKX.js.map +1 -0
- package/dist/translate-IUQBBVE6.js +598 -0
- package/dist/translate-IUQBBVE6.js.map +1 -0
- package/dist/triggers-2NWMXQ5P.js +141 -0
- package/dist/triggers-2NWMXQ5P.js.map +1 -0
- package/dist/tweets-X64YDEAA.js +123 -0
- package/dist/tweets-X64YDEAA.js.map +1 -0
- package/dist/unfollow-PIONCSBL.js +46 -0
- package/dist/unfollow-PIONCSBL.js.map +1 -0
- package/dist/unlink-UAPLQMK6.js +67 -0
- package/dist/unlink-UAPLQMK6.js.map +1 -0
- package/dist/unstage-BJJ5M7MK.js +95 -0
- package/dist/unstage-BJJ5M7MK.js.map +1 -0
- package/dist/unstage-X2BYGH2S.js +84 -0
- package/dist/unstage-X2BYGH2S.js.map +1 -0
- package/dist/update-7YK3VSOK.js +142 -0
- package/dist/update-7YK3VSOK.js.map +1 -0
- package/dist/update-BHG7BTK3.js +155 -0
- package/dist/update-BHG7BTK3.js.map +1 -0
- package/dist/update-CDJXKEVA.js +63 -0
- package/dist/update-CDJXKEVA.js.map +1 -0
- package/dist/update-RZXDAMAG.js +98 -0
- package/dist/update-RZXDAMAG.js.map +1 -0
- package/dist/upload-DSZEXNHH.js +126 -0
- package/dist/upload-DSZEXNHH.js.map +1 -0
- package/dist/upload-IWFYKD7A.js +150 -0
- package/dist/upload-IWFYKD7A.js.map +1 -0
- package/dist/upscale-EYCEYRWE.js +109 -0
- package/dist/upscale-EYCEYRWE.js.map +1 -0
- package/dist/url-options-RA3XISLN.js +130 -0
- package/dist/url-options-RA3XISLN.js.map +1 -0
- package/dist/url-params-OGZXF6MT.js +98 -0
- package/dist/url-params-OGZXF6MT.js.map +1 -0
- package/dist/use-E2TA2K6J.js +95 -0
- package/dist/use-E2TA2K6J.js.map +1 -0
- package/dist/validate-C6HWDI6K.js +88 -0
- package/dist/validate-C6HWDI6K.js.map +1 -0
- package/dist/variant-ETHB6XUM.js +338 -0
- package/dist/variant-ETHB6XUM.js.map +1 -0
- package/dist/videos-A2X5AARB.js +39 -0
- package/dist/videos-A2X5AARB.js.map +1 -0
- package/dist/view-BVEZRRV2.js +121 -0
- package/dist/view-BVEZRRV2.js.map +1 -0
- package/dist/viewer-check-W4ICSBHO.js +68 -0
- package/dist/viewer-check-W4ICSBHO.js.map +1 -0
- package/dist/web-GJSFDBBE.js +140 -0
- package/dist/web-GJSFDBBE.js.map +1 -0
- package/dist/winners-MJDKCGEZ.js +113 -0
- package/dist/winners-MJDKCGEZ.js.map +1 -0
- package/dist/winning-ads-NNU5MM75.js +84 -0
- package/dist/winning-ads-NNU5MM75.js.map +1 -0
- package/dist/write-commands-5I5KY6ZS.js +1015 -0
- package/dist/write-commands-5I5KY6ZS.js.map +1 -0
- package/dist/write-commands-DA6FIFAO.js +737 -0
- package/dist/write-commands-DA6FIFAO.js.map +1 -0
- package/dist/write-commands-KTPISQRE.js +206 -0
- package/dist/write-commands-KTPISQRE.js.map +1 -0
- package/dist/write-commands-QBGIWU27.js +713 -0
- package/dist/write-commands-QBGIWU27.js.map +1 -0
- package/dist/x-VCL5VRXC.js +47 -0
- package/dist/x-VCL5VRXC.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-VLUGGVJL.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/{client-GR6YL3YX.js.map → chunk-YQSBHWOI.js.map} +0 -0
- /package/dist/{env-4P5HOGNA.js.map → client-EURRWXPW.js.map} +0 -0
- /package/dist/{output-NMQXZF3Z.js.map → connect-6DQFYKGN.js.map} +0 -0
- /package/dist/{shared-J7DQZ2ED.js.map → customers-FOPXEGCB.js.map} +0 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import {
|
|
2
|
+
failApi
|
|
3
|
+
} from "./chunk-NMGELUIA.js";
|
|
4
|
+
import {
|
|
5
|
+
CREATIVE_PERFORMANCE_DEFAULT_DAYS,
|
|
6
|
+
CREATIVE_PERFORMANCE_MAX_DAYS
|
|
7
|
+
} from "./chunk-D46NOXRY.js";
|
|
8
|
+
import {
|
|
9
|
+
apiPost
|
|
10
|
+
} from "./chunk-CUL3VB4L.js";
|
|
11
|
+
import {
|
|
12
|
+
registerSchema,
|
|
13
|
+
writeJson
|
|
14
|
+
} from "./chunk-MYTDK3AL.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-YNWM426O.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":[]}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __glob = (map) => (path) => {
|
|
8
|
+
var fn = map[path];
|
|
9
|
+
if (fn) return fn();
|
|
10
|
+
throw new Error("Module not found in bundle: " + path);
|
|
11
|
+
};
|
|
12
|
+
var __esm = (fn, res) => function __init() {
|
|
13
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
14
|
+
};
|
|
15
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
16
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
17
|
+
};
|
|
18
|
+
var __copyProps = (to, from, except, desc) => {
|
|
19
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
20
|
+
for (let key of __getOwnPropNames(from))
|
|
21
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
22
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
23
|
+
}
|
|
24
|
+
return to;
|
|
25
|
+
};
|
|
26
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
27
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
28
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
29
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
30
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
31
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
32
|
+
mod
|
|
33
|
+
));
|
|
34
|
+
|
|
35
|
+
export {
|
|
36
|
+
__glob,
|
|
37
|
+
__esm,
|
|
38
|
+
__commonJS,
|
|
39
|
+
__toESM
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=chunk-YQSBHWOI.js.map
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import {
|
|
2
|
+
hintLines,
|
|
3
|
+
splitHints
|
|
4
|
+
} from "./chunk-D5FY4FAK.js";
|
|
5
|
+
import {
|
|
6
|
+
isNotConnectedError,
|
|
7
|
+
writeJsonEnvelope
|
|
8
|
+
} from "./chunk-EIGXX6KI.js";
|
|
9
|
+
import {
|
|
10
|
+
ApiError,
|
|
11
|
+
apiPost
|
|
12
|
+
} from "./chunk-CUL3VB4L.js";
|
|
13
|
+
import {
|
|
14
|
+
requireChatId,
|
|
15
|
+
resolveChatId
|
|
16
|
+
} from "./chunk-I4FTS5EE.js";
|
|
17
|
+
|
|
18
|
+
// src/commands/tag-manager/shared.ts
|
|
19
|
+
import { readFileSync } from "fs";
|
|
20
|
+
function failValidation(message) {
|
|
21
|
+
writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
function requireTarget(args, entity) {
|
|
25
|
+
const positional = Array.isArray(args._) ? args._[0] : void 0;
|
|
26
|
+
const target = args.id ?? args.target ?? positional;
|
|
27
|
+
if (typeof target !== "string" || target.length === 0) {
|
|
28
|
+
failValidation(`pass the ${entity} id or path as the positional argument`);
|
|
29
|
+
}
|
|
30
|
+
return target;
|
|
31
|
+
}
|
|
32
|
+
function loadJsonArg(args, flag = "json") {
|
|
33
|
+
const inline = args[flag];
|
|
34
|
+
const file = args.file;
|
|
35
|
+
const raw = typeof file === "string" && file.length > 0 ? readFileSync(file, "utf8") : typeof inline === "string" && inline.length > 0 ? inline : void 0;
|
|
36
|
+
if (raw === void 0) {
|
|
37
|
+
failValidation(`pass --${flag} with inline JSON or --file with a path to a JSON file`);
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
const parsed = JSON.parse(raw);
|
|
41
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
42
|
+
failValidation(`--${flag} must be a JSON object`);
|
|
43
|
+
}
|
|
44
|
+
return parsed;
|
|
45
|
+
} catch {
|
|
46
|
+
return failValidation(`--${flag} is not valid JSON`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
var RETRYABLE_CODES = /* @__PURE__ */ new Set(["RATE_LIMITED", "UNAVAILABLE", "INTERNAL_ERROR", "NETWORK_ERROR", "TIMEOUT"]);
|
|
50
|
+
function handleError(err) {
|
|
51
|
+
if (err instanceof ApiError) {
|
|
52
|
+
writeJsonEnvelope({
|
|
53
|
+
ok: false,
|
|
54
|
+
error: {
|
|
55
|
+
code: err.code,
|
|
56
|
+
message: err.message,
|
|
57
|
+
...err.code === "UNAUTHORIZED" || err.code === "FORBIDDEN" && isNotConnectedError(err.code, err.message) ? {
|
|
58
|
+
fix: {
|
|
59
|
+
action: "request_connection",
|
|
60
|
+
explanation: 'Tag Manager is not connected for this company yet, or no container has been picked. Don\'t send the user to Settings \u2014 call the `request_connection` tool with { platform: "google-tag-manager", reason } and they connect and pick their containers (they can pick more than one) from inside the chat. `request_tag_input` is not the route: that form manages the container snippet on the site, not what runs inside the container, and it cannot pick a container. If the `request_connection` call fails, say so plainly and give the exact route: dashboard \u2192 Brain \u2192 Integrations \u2192 Platforms \u2192 Google Tag Manager, where they also pick the container. Then carry on with the rest of the task.'
|
|
61
|
+
}
|
|
62
|
+
} : {},
|
|
63
|
+
retryable: RETRYABLE_CODES.has(err.code)
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
writeJsonEnvelope({ ok: false, error: { code: "NETWORK_ERROR", message: "Unexpected error", retryable: true } });
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
var TAG_MANAGER_TIMEOUT_MS = 18e4;
|
|
72
|
+
var STAGE_HINTS = [
|
|
73
|
+
"Staged only \u2014 nothing has changed in Tag Manager yet. These apply when the chat completes, in dependency order, and close as a Tag Manager version that is then published, so they do go live on the user's site. Say the changes are ready and go live when they publish \u2014 not that they are live already."
|
|
74
|
+
];
|
|
75
|
+
async function stageOp(op) {
|
|
76
|
+
const chatId = requireChatId();
|
|
77
|
+
try {
|
|
78
|
+
const { data, hints } = splitHints(
|
|
79
|
+
await apiPost(
|
|
80
|
+
"/api/tag-manager/draft/stage",
|
|
81
|
+
{ chatId, op },
|
|
82
|
+
{ timeoutMs: TAG_MANAGER_TIMEOUT_MS }
|
|
83
|
+
)
|
|
84
|
+
);
|
|
85
|
+
writeJsonEnvelope({ ok: true, data, hints: [...hints, ...STAGE_HINTS] });
|
|
86
|
+
} catch (err) {
|
|
87
|
+
handleError(err);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
async function draftAction(path, body, chat) {
|
|
91
|
+
const chatId = resolveChatId(chat);
|
|
92
|
+
try {
|
|
93
|
+
const { data, hints } = splitHints(
|
|
94
|
+
await apiPost(path, { chatId, ...body }, { timeoutMs: TAG_MANAGER_TIMEOUT_MS })
|
|
95
|
+
);
|
|
96
|
+
writeJsonEnvelope({ ok: true, data, ...hints.length > 0 ? { hints } : {} });
|
|
97
|
+
return data;
|
|
98
|
+
} catch (err) {
|
|
99
|
+
handleError(err);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function renderDraft(response) {
|
|
103
|
+
if (response.count === 0) {
|
|
104
|
+
return "No Tag Manager changes staged on this chat.";
|
|
105
|
+
}
|
|
106
|
+
const lines = [
|
|
107
|
+
`${response.count} staged Tag Manager change(s)`,
|
|
108
|
+
...response.ops.flatMap((op) => {
|
|
109
|
+
const status = op.result ? ` [${op.result.status}]` : "";
|
|
110
|
+
return [` ${op.ref} ${op.summary}${status}`, ...(op.warnings ?? []).map((warning) => ` \u26A0 ${warning}`)];
|
|
111
|
+
})
|
|
112
|
+
];
|
|
113
|
+
if (response.versionId) {
|
|
114
|
+
lines.push(
|
|
115
|
+
"",
|
|
116
|
+
response.published ? `Applied and published as Tag Manager version ${response.versionId}. These changes are live on the site.` : `Applied into Tag Manager version ${response.versionId}. It is NOT published \u2014 publish it in Tag Manager to go live.`
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
if (response.compilerError) {
|
|
120
|
+
lines.push("", `Tag Manager reported a problem building the version: ${response.compilerError}`);
|
|
121
|
+
}
|
|
122
|
+
return lines.join("\n");
|
|
123
|
+
}
|
|
124
|
+
async function draftList(json, chat) {
|
|
125
|
+
const chatId = resolveChatId(chat);
|
|
126
|
+
try {
|
|
127
|
+
const response = await apiPost("/api/tag-manager/draft", { chatId });
|
|
128
|
+
const { data, hints } = splitHints(response);
|
|
129
|
+
if (json) {
|
|
130
|
+
writeJsonEnvelope({ ok: true, data, ...hints.length > 0 ? { hints } : {} });
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
process.stdout.write(`${renderDraft(data)}${hintLines(response)}
|
|
134
|
+
`);
|
|
135
|
+
} catch (err) {
|
|
136
|
+
handleError(err);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export {
|
|
141
|
+
requireTarget,
|
|
142
|
+
loadJsonArg,
|
|
143
|
+
handleError,
|
|
144
|
+
TAG_MANAGER_TIMEOUT_MS,
|
|
145
|
+
stageOp,
|
|
146
|
+
draftAction,
|
|
147
|
+
draftList
|
|
148
|
+
};
|
|
149
|
+
//# sourceMappingURL=chunk-YTF3IVMF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/tag-manager/shared.ts"],"sourcesContent":["import { readFileSync } from \"node:fs\";\nimport type {\n TagManagerDraftListResponse,\n TagManagerDraftRemoveResponse,\n TagManagerDraftShowResponse,\n TagManagerDraftStageResponse,\n} from \"@baker/api/tag-manager\";\nimport { ApiError, apiPost } from \"../../client.ts\";\nimport { requireChatId, resolveChatId } from \"../../env.ts\";\nimport { isNotConnectedError } from \"../../error-handler.ts\";\nimport { hintLines, splitHints } from \"../ads/hints.ts\";\nimport { writeJsonEnvelope } from \"../ads/output.ts\";\n\n/**\n * Shared plumbing for the staged Tag Manager commands. Writes NEVER hit the\n * Tag Manager API directly: every command stages an op against this chat's\n * draft, and the whole draft applies when the chat is published — into the\n * container's working workspace, in dependency order, closing with a container\n * version that is published when every change applies cleanly.\n */\n\nexport function failValidation(message: string): never {\n writeJsonEnvelope({ ok: false, error: { code: \"VALIDATION_ERROR\", message } });\n process.exit(1);\n}\n\nexport function requireTarget(args: Record<string, unknown>, entity: string): string {\n const positional = Array.isArray(args._) ? args._[0] : undefined;\n const target = args.id ?? args.target ?? positional;\n if (typeof target !== \"string\" || target.length === 0) {\n failValidation(`pass the ${entity} id or path as the positional argument`);\n }\n return target;\n}\n\n/** `--json '<inline>'` or `--file <path>` → a parsed object. */\nexport function loadJsonArg(args: Record<string, unknown>, flag: \"patch\" | \"json\" = \"json\"): Record<string, unknown> {\n const inline = args[flag];\n const file = args.file;\n const raw =\n typeof file === \"string\" && file.length > 0\n ? readFileSync(file, \"utf8\")\n : typeof inline === \"string\" && inline.length > 0\n ? inline\n : undefined;\n if (raw === undefined) {\n failValidation(`pass --${flag} with inline JSON or --file with a path to a JSON file`);\n }\n try {\n const parsed: unknown = JSON.parse(raw);\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n failValidation(`--${flag} must be a JSON object`);\n }\n return parsed as Record<string, unknown>;\n } catch {\n return failValidation(`--${flag} is not valid JSON`);\n }\n}\n\n/**\n * Transient by nature — worth one more go. Saying so is the difference between\n * the agent retrying a blip and abandoning a multi-step job over one. Every\n * other code is a real answer that a second call returns again.\n */\nconst RETRYABLE_CODES = new Set([\"RATE_LIMITED\", \"UNAVAILABLE\", \"INTERNAL_ERROR\", \"NETWORK_ERROR\", \"TIMEOUT\"]);\n\n/**\n * The one error shape for the whole family.\n *\n * Only the 403s raised while resolving the company's container mean \"not\n * connected\", which is why the fix is keyed to the message and not just the\n * status: other 403s are real permission refusals a reconnect cannot fix.\n * `NOT_FOUND` deliberately does NOT trigger the connect form either — it is also\n * what a missing tag returns, and asking the user to reconnect a working\n * connection because a tag id was wrong wastes their time and fixes nothing.\n */\nexport function handleError(err: unknown): never {\n if (err instanceof ApiError) {\n writeJsonEnvelope({\n ok: false,\n error: {\n code: err.code,\n message: err.message,\n ...(err.code === \"UNAUTHORIZED\" || (err.code === \"FORBIDDEN\" && isNotConnectedError(err.code, err.message))\n ? {\n fix: {\n action: \"request_connection\",\n explanation:\n \"Tag Manager is not connected for this company yet, or no container has been picked. Don't send \" +\n \"the user to Settings — call the `request_connection` tool with \" +\n '{ platform: \"google-tag-manager\", reason } and they connect and pick their containers (they can ' +\n \"pick more than one) from inside the chat. `request_tag_input` is not the route: that form \" +\n \"manages the container snippet on the \" +\n \"site, not what runs inside the container, and it cannot pick a container. If the \" +\n \"`request_connection` call fails, say so plainly and give the exact route: dashboard → Brain → \" +\n \"Integrations → Platforms → Google Tag Manager, where they also pick the container. Then carry on \" +\n \"with the rest of the task.\",\n },\n }\n : {}),\n retryable: RETRYABLE_CODES.has(err.code),\n },\n });\n process.exit(1);\n }\n writeJsonEnvelope({ ok: false, error: { code: \"NETWORK_ERROR\", message: \"Unexpected error\", retryable: true } });\n process.exit(1);\n}\n\n/**\n * Tag Manager allows Baker a few requests a second across every company, so a\n * call that reads the container can queue behind another company's publish. It\n * still finishes on the server, so giving up early only invites a repeat.\n */\nexport const TAG_MANAGER_TIMEOUT_MS = 180_000;\n\n/** Nudges returned after a stage so the agent's next step is obvious. */\nconst STAGE_HINTS = [\n \"Staged only — nothing has changed in Tag Manager yet. These apply when the chat completes, in dependency \" +\n \"order, and close as a Tag Manager version that is then published, so they do go live on the user's site. \" +\n \"Say the changes are ready and go live when they publish — not that they are live already.\",\n];\n\nexport async function stageOp(op: Record<string, unknown>): Promise<void> {\n const chatId = requireChatId();\n try {\n const { data, hints } = splitHints(\n await apiPost<TagManagerDraftStageResponse>(\n \"/api/tag-manager/draft/stage\",\n { chatId, op },\n { timeoutMs: TAG_MANAGER_TIMEOUT_MS },\n ),\n );\n writeJsonEnvelope({ ok: true, data, hints: [...hints, ...STAGE_HINTS] });\n } catch (err) {\n handleError(err);\n }\n}\n\nexport async function draftAction(\n path: string,\n body: Record<string, unknown>,\n chat?: unknown,\n): Promise<TagManagerDraftRemoveResponse | TagManagerDraftShowResponse | Record<string, unknown>> {\n const chatId = resolveChatId(chat);\n try {\n const { data, hints } = splitHints(\n await apiPost<Record<string, unknown>>(path, { chatId, ...body }, { timeoutMs: TAG_MANAGER_TIMEOUT_MS }),\n );\n writeJsonEnvelope({ ok: true, data, ...(hints.length > 0 ? { hints } : {}) });\n return data;\n } catch (err) {\n handleError(err);\n }\n}\n\n/** A compact, readable view of everything staged on this chat. */\nexport function renderDraft(response: TagManagerDraftListResponse): string {\n if (response.count === 0) {\n return \"No Tag Manager changes staged on this chat.\";\n }\n const lines = [\n `${response.count} staged Tag Manager change(s)`,\n ...response.ops.flatMap((op) => {\n const status = op.result ? ` [${op.result.status}]` : \"\";\n return [` ${op.ref} ${op.summary}${status}`, ...(op.warnings ?? []).map((warning) => ` ⚠ ${warning}`)];\n }),\n ];\n if (response.versionId) {\n lines.push(\n \"\",\n response.published\n ? `Applied and published as Tag Manager version ${response.versionId}. These changes are live on the site.`\n : `Applied into Tag Manager version ${response.versionId}. It is NOT published — publish it in Tag Manager to go live.`,\n );\n }\n if (response.compilerError) {\n lines.push(\"\", `Tag Manager reported a problem building the version: ${response.compilerError}`);\n }\n return lines.join(\"\\n\");\n}\n\nexport async function draftList(json: boolean, chat?: unknown): Promise<void> {\n const chatId = resolveChatId(chat);\n try {\n const response = await apiPost<TagManagerDraftListResponse>(\"/api/tag-manager/draft\", { chatId });\n const { data, hints } = splitHints(response);\n if (json) {\n writeJsonEnvelope({ ok: true, data, ...(hints.length > 0 ? { hints } : {}) });\n return;\n }\n process.stdout.write(`${renderDraft(data)}${hintLines(response)}\\n`);\n } catch (err) {\n handleError(err);\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// src/commands/landing/import-graph.ts
|
|
2
|
+
import { readdir, readFile, stat } from "fs/promises";
|
|
3
|
+
import path from "path";
|
|
4
|
+
var SOURCE_EXT = /\.(astro|ts|tsx|js|jsx|mjs|cjs|vue|svelte)$/;
|
|
5
|
+
var RESOLVE_CANDIDATES = [
|
|
6
|
+
"",
|
|
7
|
+
".astro",
|
|
8
|
+
".ts",
|
|
9
|
+
".tsx",
|
|
10
|
+
".js",
|
|
11
|
+
".jsx",
|
|
12
|
+
".mjs",
|
|
13
|
+
".cjs",
|
|
14
|
+
"/index.astro",
|
|
15
|
+
"/index.ts",
|
|
16
|
+
"/index.js"
|
|
17
|
+
];
|
|
18
|
+
var IMPORT_RE = /(?<![A-Za-z0-9_$])(?:import|export)\s*(?:[\s\S]*?\bfrom\s*)?["']([^"']+)["']/g;
|
|
19
|
+
var DYNAMIC_IMPORT_RE = /\bimport\s*\(\s*["']([^"']+)["']\s*\)/g;
|
|
20
|
+
async function isFile(p) {
|
|
21
|
+
try {
|
|
22
|
+
return (await stat(p)).isFile();
|
|
23
|
+
} catch {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
async function walkFiles(dir) {
|
|
28
|
+
let entries;
|
|
29
|
+
try {
|
|
30
|
+
entries = await readdir(dir, { withFileTypes: true });
|
|
31
|
+
} catch {
|
|
32
|
+
return [];
|
|
33
|
+
}
|
|
34
|
+
const out = [];
|
|
35
|
+
for (const entry of entries) {
|
|
36
|
+
const full = path.join(dir, entry.name);
|
|
37
|
+
if (entry.isDirectory()) {
|
|
38
|
+
if (entry.name === "node_modules" || entry.name === "dist") continue;
|
|
39
|
+
out.push(...await walkFiles(full));
|
|
40
|
+
} else if (SOURCE_EXT.test(entry.name)) {
|
|
41
|
+
out.push(full);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return out;
|
|
45
|
+
}
|
|
46
|
+
async function resolveSpecifier(specifier, fromFile, root) {
|
|
47
|
+
const bare = specifier.split("?")[0] ?? "";
|
|
48
|
+
if (bare.includes("*")) return null;
|
|
49
|
+
let base;
|
|
50
|
+
if (bare.startsWith("/")) base = path.join(root, bare.slice(1));
|
|
51
|
+
else if (bare.startsWith(".")) base = path.resolve(path.dirname(fromFile), bare);
|
|
52
|
+
else return null;
|
|
53
|
+
for (const suffix of RESOLVE_CANDIDATES) {
|
|
54
|
+
const candidate = base + suffix;
|
|
55
|
+
if (SOURCE_EXT.test(candidate) && await isFile(candidate)) return candidate;
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
async function importedFiles(text, file, root) {
|
|
60
|
+
const out = [];
|
|
61
|
+
for (const re of [IMPORT_RE, DYNAMIC_IMPORT_RE]) {
|
|
62
|
+
for (const match of text.matchAll(re)) {
|
|
63
|
+
const spec = match[1];
|
|
64
|
+
if (spec === void 0) continue;
|
|
65
|
+
const target = await resolveSpecifier(spec, file, root);
|
|
66
|
+
if (target !== null) out.push(target);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return out;
|
|
70
|
+
}
|
|
71
|
+
async function landingGraphFiles(root, slug) {
|
|
72
|
+
const seen = /* @__PURE__ */ new Set();
|
|
73
|
+
const queue = await walkFiles(path.join(root, "src/pages", slug));
|
|
74
|
+
while (queue.length > 0) {
|
|
75
|
+
const file = queue.pop();
|
|
76
|
+
if (file === void 0 || seen.has(file)) continue;
|
|
77
|
+
let text;
|
|
78
|
+
try {
|
|
79
|
+
text = await readFile(file, "utf8");
|
|
80
|
+
} catch {
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
seen.add(file);
|
|
84
|
+
for (const target of await importedFiles(text, file, root)) {
|
|
85
|
+
if (!seen.has(target)) queue.push(target);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return new Set([...seen].map((abs) => path.relative(root, abs).split(path.sep).join("/")));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export {
|
|
92
|
+
landingGraphFiles
|
|
93
|
+
};
|
|
94
|
+
//# sourceMappingURL=chunk-Z3ENMCFE.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/landing/import-graph.ts"],"sourcesContent":["import type { Dirent } from \"node:fs\";\nimport { readdir, readFile, stat } from \"node:fs/promises\";\nimport path from \"node:path\";\n\n/**\n * Which source files does a landing actually pull in?\n *\n * Pages share components since A/B tests shipped: a variant borrows the\n * control's sections and forks only the one under test. So a landing's source is\n * no longer \"this folder\" — the critic has to read the sections it renders\n * wherever they live, and the freshness fingerprint has to cover them or an edit\n * to a shared section leaves the borrowing page's sha unchanged and the quality\n * gate passes a page it never scored.\n *\n * MIRROR OF `apps/scaffold-template/__tooling__/checks/sdk/landing-import-graph.mjs`.\n * Neither can import the other — the CLI ships as a binary, the scaffold ships as\n * files — so they are two implementations of one rule, and\n * `scripts/__tests__/landing-source-version-parity.test.ts` runs both over one\n * fixture tree and fails when they disagree. Change one, change the other, and\n * let that test say whether you got it right.\n */\n\n/**\n * Files worth opening: source that ends up in the build. Gates both the\n * directory seed and every import target, so a landing that imports\n * `./_images/hero.png` never gets a binary read as UTF-8.\n */\nconst SOURCE_EXT = /\\.(astro|ts|tsx|js|jsx|mjs|cjs|vue|svelte)$/;\n\n/** Extension guesses for an extensionless specifier, in resolution order. */\nconst RESOLVE_CANDIDATES = [\n \"\",\n \".astro\",\n \".ts\",\n \".tsx\",\n \".js\",\n \".jsx\",\n \".mjs\",\n \".cjs\",\n \"/index.astro\",\n \"/index.ts\",\n \"/index.js\",\n];\n\n/**\n * Static and dynamic import specifiers. Both boundaries are lookarounds rather\n * than character classes, because an inlined `<script>import{a}from\"./x\"</script>`\n * has no whitespace anywhere.\n */\nconst IMPORT_RE = /(?<![A-Za-z0-9_$])(?:import|export)\\s*(?:[\\s\\S]*?\\bfrom\\s*)?[\"']([^\"']+)[\"']/g;\nconst DYNAMIC_IMPORT_RE = /\\bimport\\s*\\(\\s*[\"']([^\"']+)[\"']\\s*\\)/g;\n\nasync function isFile(p: string): Promise<boolean> {\n try {\n return (await stat(p)).isFile();\n } catch {\n return false;\n }\n}\n\n/** Every source file under `dir`, recursively. */\nasync function walkFiles(dir: string): Promise<string[]> {\n let entries: Dirent[];\n try {\n entries = await readdir(dir, { withFileTypes: true });\n } catch {\n return [];\n }\n const out: string[] = [];\n for (const entry of entries) {\n const full = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n if (entry.name === \"node_modules\" || entry.name === \"dist\") continue;\n out.push(...(await walkFiles(full)));\n } else if (SOURCE_EXT.test(entry.name)) {\n out.push(full);\n }\n }\n return out;\n}\n\n/** Resolve a relative or root-absolute specifier to a source file, else null. */\nasync function resolveSpecifier(specifier: string, fromFile: string, root: string): Promise<string | null> {\n // Vite resolves a leading `/` from the project root; everything else that is\n // not relative is a bare package specifier. A glob has no single target.\n const bare = specifier.split(\"?\")[0] ?? \"\";\n if (bare.includes(\"*\")) return null;\n\n let base: string;\n if (bare.startsWith(\"/\")) base = path.join(root, bare.slice(1));\n else if (bare.startsWith(\".\")) base = path.resolve(path.dirname(fromFile), bare);\n else return null;\n\n for (const suffix of RESOLVE_CANDIDATES) {\n const candidate = base + suffix;\n if (SOURCE_EXT.test(candidate) && (await isFile(candidate))) return candidate;\n }\n return null;\n}\n\n/**\n * Every source file one landing pulls in, transitively, as repo-relative POSIX\n * paths.\n *\n * Seeded with the whole `src/pages/<slug>` directory rather than just\n * `index.astro`: co-located `_components/**` are imported from markup the\n * regexes do not always see.\n */\n/** Every source file `file`'s own text imports, resolved to absolute paths. */\nasync function importedFiles(text: string, file: string, root: string): Promise<string[]> {\n const out: string[] = [];\n for (const re of [IMPORT_RE, DYNAMIC_IMPORT_RE]) {\n // `matchAll` clones the regex, so a shared global one carries no\n // `lastIndex` between files.\n for (const match of text.matchAll(re)) {\n const spec = match[1];\n if (spec === undefined) continue;\n const target = await resolveSpecifier(spec, file, root);\n if (target !== null) out.push(target);\n }\n }\n return out;\n}\n\nexport async function landingGraphFiles(root: string, slug: string): Promise<Set<string>> {\n const seen = new Set<string>();\n const queue = await walkFiles(path.join(root, \"src/pages\", slug));\n\n while (queue.length > 0) {\n const file = queue.pop();\n if (file === undefined || seen.has(file)) continue;\n\n let text: string;\n try {\n text = await readFile(file, \"utf8\");\n } catch {\n continue;\n }\n seen.add(file);\n\n for (const target of await importedFiles(text, file, root)) {\n if (!seen.has(target)) queue.push(target);\n }\n }\n\n return new Set([...seen].map((abs) => path.relative(root, abs).split(path.sep).join(\"/\")));\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ApiError
|
|
3
|
+
} from "./chunk-CUL3VB4L.js";
|
|
4
|
+
import {
|
|
5
|
+
writeJson
|
|
6
|
+
} from "./chunk-MYTDK3AL.js";
|
|
7
|
+
|
|
8
|
+
// src/commands/landing/inspiration/shared.ts
|
|
9
|
+
var INSPIRATION_HINTS = {
|
|
10
|
+
adapt: "Reference only. Re-express this in the client's BRAND.md palette, type and imagery register. Reusing a headline, subhead or CTA verbatim is a Tier 0 message-match failure (references/gotchas.md).",
|
|
11
|
+
structureNotCopy: "Take the structural decision, not the furniture: what the eye hits first, the grid ratio, what was deliberately left out. Your copy must come from the client's own offer."
|
|
12
|
+
};
|
|
13
|
+
function favoritesScopeHints(health, resultCount) {
|
|
14
|
+
if (!health) return [];
|
|
15
|
+
const hints = [];
|
|
16
|
+
if (health.savedPages === 0) {
|
|
17
|
+
hints.push(
|
|
18
|
+
"This company hasn't saved any reference pages yet, so there is no taste profile to search \u2014 an empty result here says nothing about the library. Search the whole shared library with --scope all, or save a page the client admires with `baker landing inspiration add <url>`."
|
|
19
|
+
);
|
|
20
|
+
return hints;
|
|
21
|
+
}
|
|
22
|
+
if (health.failedPages > 0) {
|
|
23
|
+
const retryable = health.failedExamples.filter((example) => example.retryable).map((example) => example.url);
|
|
24
|
+
const permanent = health.failedExamples.filter((example) => !example.retryable).map((example) => example.url);
|
|
25
|
+
hints.push(
|
|
26
|
+
`${health.failedPages} of this company's ${health.savedPages} saved pages could not be read, so they hold no sections \u2014 only ${health.usablePages} are usable, which is why this result is thin. Search the whole library with --scope all.`
|
|
27
|
+
);
|
|
28
|
+
if (retryable.length > 0) {
|
|
29
|
+
hints.push(
|
|
30
|
+
`Worth another go: ${retryable.join(", ")} \u2014 run \`baker landing inspiration add <url>\` on one of them to study it again.`
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
if (permanent.length > 0) {
|
|
34
|
+
hints.push(`Not worth retrying \u2014 these sites refuse automated readers: ${permanent.join(", ")}.`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if (health.studyingPages > 0) {
|
|
38
|
+
hints.push(
|
|
39
|
+
`${health.studyingPages} saved ${health.studyingPages === 1 ? "page is" : "pages are"} still being studied and will be searchable in a few minutes. Carry on; do not wait on them.`
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
if (resultCount === 0 && health.failedPages === 0 && health.studyingPages === 0) {
|
|
43
|
+
hints.push(
|
|
44
|
+
`Nothing in this company's ${health.usablePages} readable saved pages matches. The saved set is healthy, so this is the query, not the library \u2014 loosen the filters or search everything with --scope all.`
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
return hints;
|
|
48
|
+
}
|
|
49
|
+
function fidelityHint(fidelity) {
|
|
50
|
+
if (fidelity == null) return null;
|
|
51
|
+
if (fidelity >= 0.9) return null;
|
|
52
|
+
if (fidelity >= 0.75) {
|
|
53
|
+
return `Reproduction fidelity ${fidelity.toFixed(2)} \u2014 the markup is close but not exact. Trust the screenshot over the code.`;
|
|
54
|
+
}
|
|
55
|
+
return `Reproduction fidelity ${fidelity.toFixed(2)} \u2014 this section is scroll- or JS-driven and the extracted markup does NOT render like the original. Use the screenshot and the notes; treat the code as a hint only.`;
|
|
56
|
+
}
|
|
57
|
+
var STALE_COPY_AFTER_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
58
|
+
function staleCopyHint(studiedAt, filedUrl, now = Date.now()) {
|
|
59
|
+
if (!studiedAt || now - studiedAt < STALE_COPY_AFTER_MS) return null;
|
|
60
|
+
const date = new Date(studiedAt).toLocaleDateString("en-US", { month: "short", day: "numeric", timeZone: "UTC" });
|
|
61
|
+
return `This copy of the page was read on ${date}. If the user says the live page looks different, run: baker landing inspiration add ${filedUrl} --refresh`;
|
|
62
|
+
}
|
|
63
|
+
function reportError(error) {
|
|
64
|
+
if (error instanceof ApiError) {
|
|
65
|
+
writeJson({ ok: false, error: { code: error.code, message: error.message } });
|
|
66
|
+
} else {
|
|
67
|
+
writeJson({
|
|
68
|
+
ok: false,
|
|
69
|
+
error: { code: "UNKNOWN", message: error instanceof Error ? error.message : String(error) }
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
function splitList(value) {
|
|
75
|
+
if (!value) return void 0;
|
|
76
|
+
const parts = value.split(",").map((part) => part.trim()).filter(Boolean);
|
|
77
|
+
return parts.length > 0 ? parts : void 0;
|
|
78
|
+
}
|
|
79
|
+
function parseNumber(value) {
|
|
80
|
+
if (value === void 0 || value === "") return void 0;
|
|
81
|
+
const parsed = Number(value);
|
|
82
|
+
return Number.isFinite(parsed) ? parsed : void 0;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export {
|
|
86
|
+
INSPIRATION_HINTS,
|
|
87
|
+
favoritesScopeHints,
|
|
88
|
+
fidelityHint,
|
|
89
|
+
staleCopyHint,
|
|
90
|
+
reportError,
|
|
91
|
+
splitList,
|
|
92
|
+
parseNumber
|
|
93
|
+
};
|
|
94
|
+
//# sourceMappingURL=chunk-Z7MWSXLG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/landing/inspiration/shared.ts"],"sourcesContent":["import type { InspirationFavoritesHealth } from \"@baker/api/landing-library\";\nimport { ApiError } from \"../../../client.ts\";\nimport { writeJson } from \"../../../output.ts\";\n\n/**\n * The framing every consumer of the library gets.\n *\n * These are not decoration. The corpus only earns its keep if what comes out of\n * it gets re-expressed rather than pasted, and a hint that fires on every single\n * call is the cheapest place to say so — cheaper than a doc the agent may not\n * re-read, and softer than the critic that will block a clone at publish.\n */\nexport const INSPIRATION_HINTS = {\n adapt:\n \"Reference only. Re-express this in the client's BRAND.md palette, type and imagery register. \" +\n \"Reusing a headline, subhead or CTA verbatim is a Tier 0 message-match failure (references/gotchas.md).\",\n structureNotCopy:\n \"Take the structural decision, not the furniture: what the eye hits first, the grid ratio, \" +\n \"what was deliberately left out. Your copy must come from the client's own offer.\",\n} as const;\n\n/**\n * Say what is actually true about a thin favorites result.\n *\n * `search` defaults to this company's saved sections, and that default is a\n * deliberate choice — those are the client's own taste signals, and quietly\n * widening it would replace their taste with the library's average. But a thin\n * favorites result has three completely different causes that look identical\n * from the outside:\n *\n * 1. the client has no taste profile yet,\n * 2. the client saved plenty and the pages failed to be read,\n * 3. the query simply did not match.\n *\n * They call for opposite next moves, and one production company sat in case 2\n * with **211 of 234 saved pages holding no sections at all** — where the honest\n * answer, \"your library is broken\", was being delivered as \"nothing saved yet\".\n *\n * So: never widen the scope, always name the cause, and always leave the\n * decision with the caller.\n */\nexport function favoritesScopeHints(health: InspirationFavoritesHealth | undefined, resultCount: number): string[] {\n if (!health) return [];\n\n const hints: string[] = [];\n\n if (health.savedPages === 0) {\n hints.push(\n \"This company hasn't saved any reference pages yet, so there is no taste profile to search — an empty result here says nothing about the library. \" +\n \"Search the whole shared library with --scope all, or save a page the client admires with `baker landing inspiration add <url>`.\",\n );\n return hints;\n }\n\n if (health.failedPages > 0) {\n const retryable = health.failedExamples.filter((example) => example.retryable).map((example) => example.url);\n const permanent = health.failedExamples.filter((example) => !example.retryable).map((example) => example.url);\n hints.push(\n `${health.failedPages} of this company's ${health.savedPages} saved pages could not be read, so they hold no sections — ` +\n `only ${health.usablePages} are usable, which is why this result is thin. Search the whole library with --scope all.`,\n );\n if (retryable.length > 0) {\n hints.push(\n `Worth another go: ${retryable.join(\", \")} — run \\`baker landing inspiration add <url>\\` on one of them to study it again.`,\n );\n }\n if (permanent.length > 0) {\n hints.push(`Not worth retrying — these sites refuse automated readers: ${permanent.join(\", \")}.`);\n }\n }\n\n if (health.studyingPages > 0) {\n hints.push(\n `${health.studyingPages} saved ${health.studyingPages === 1 ? \"page is\" : \"pages are\"} still being studied and will be searchable in a few minutes. Carry on; do not wait on them.`,\n );\n }\n\n if (resultCount === 0 && health.failedPages === 0 && health.studyingPages === 0) {\n hints.push(\n `Nothing in this company's ${health.usablePages} readable saved pages matches. The saved set is healthy, so this is the query, not the library — loosen the filters or search everything with --scope all.`,\n );\n }\n\n return hints;\n}\n\n/** Warn when the extracted markup is known not to match what the screenshot shows. */\nexport function fidelityHint(fidelity: number | null | undefined): string | null {\n if (fidelity == null) return null;\n if (fidelity >= 0.9) return null;\n if (fidelity >= 0.75) {\n return `Reproduction fidelity ${fidelity.toFixed(2)} — the markup is close but not exact. Trust the screenshot over the code.`;\n }\n return (\n `Reproduction fidelity ${fidelity.toFixed(2)} — this section is scroll- or JS-driven and the extracted markup ` +\n `does NOT render like the original. Use the screenshot and the notes; treat the code as a hint only.`\n );\n}\n\nconst STALE_COPY_AFTER_MS = 30 * 24 * 60 * 60 * 1000;\n\n/**\n * Tell the agent a page's copy is old, before it builds from it.\n *\n * The library refreshes itself about monthly, but a site can redesign the day\n * after its read, and an agent copying last quarter's hero is building from\n * something the client can see is wrong.\n */\n/** `filedUrl`, never the address the capture landed on: after a redirect, refreshing that one files a second copy. */\nexport function staleCopyHint(studiedAt: number | null | undefined, filedUrl: string, now = Date.now()): string | null {\n if (!studiedAt || now - studiedAt < STALE_COPY_AFTER_MS) return null;\n const date = new Date(studiedAt).toLocaleDateString(\"en-US\", { month: \"short\", day: \"numeric\", timeZone: \"UTC\" });\n return `This copy of the page was read on ${date}. If the user says the live page looks different, run: baker landing inspiration add ${filedUrl} --refresh`;\n}\n\nexport function reportError(error: unknown): never {\n if (error instanceof ApiError) {\n writeJson({ ok: false, error: { code: error.code, message: error.message } });\n } else {\n writeJson({\n ok: false,\n error: { code: \"UNKNOWN\", message: error instanceof Error ? error.message : String(error) },\n });\n }\n process.exit(1);\n}\n\nexport function splitList(value: string | undefined): string[] | undefined {\n if (!value) return undefined;\n const parts = value\n .split(\",\")\n .map((part) => part.trim())\n .filter(Boolean);\n return parts.length > 0 ? parts : undefined;\n}\n\nexport function parseNumber(value: string | undefined): number | undefined {\n if (value === undefined || value === \"\") return undefined;\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : undefined;\n}\n"],"mappings":";;;;;;;;AAYO,IAAM,oBAAoB;AAAA,EAC/B,OACE;AAAA,EAEF,kBACE;AAEJ;AAsBO,SAAS,oBAAoB,QAAgD,aAA+B;AACjH,MAAI,CAAC,OAAQ,QAAO,CAAC;AAErB,QAAM,QAAkB,CAAC;AAEzB,MAAI,OAAO,eAAe,GAAG;AAC3B,UAAM;AAAA,MACJ;AAAA,IAEF;AACA,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,cAAc,GAAG;AAC1B,UAAM,YAAY,OAAO,eAAe,OAAO,CAAC,YAAY,QAAQ,SAAS,EAAE,IAAI,CAAC,YAAY,QAAQ,GAAG;AAC3G,UAAM,YAAY,OAAO,eAAe,OAAO,CAAC,YAAY,CAAC,QAAQ,SAAS,EAAE,IAAI,CAAC,YAAY,QAAQ,GAAG;AAC5G,UAAM;AAAA,MACJ,GAAG,OAAO,WAAW,sBAAsB,OAAO,UAAU,wEAClD,OAAO,WAAW;AAAA,IAC9B;AACA,QAAI,UAAU,SAAS,GAAG;AACxB,YAAM;AAAA,QACJ,qBAAqB,UAAU,KAAK,IAAI,CAAC;AAAA,MAC3C;AAAA,IACF;AACA,QAAI,UAAU,SAAS,GAAG;AACxB,YAAM,KAAK,mEAA8D,UAAU,KAAK,IAAI,CAAC,GAAG;AAAA,IAClG;AAAA,EACF;AAEA,MAAI,OAAO,gBAAgB,GAAG;AAC5B,UAAM;AAAA,MACJ,GAAG,OAAO,aAAa,UAAU,OAAO,kBAAkB,IAAI,YAAY,WAAW;AAAA,IACvF;AAAA,EACF;AAEA,MAAI,gBAAgB,KAAK,OAAO,gBAAgB,KAAK,OAAO,kBAAkB,GAAG;AAC/E,UAAM;AAAA,MACJ,6BAA6B,OAAO,WAAW;AAAA,IACjD;AAAA,EACF;AAEA,SAAO;AACT;AAGO,SAAS,aAAa,UAAoD;AAC/E,MAAI,YAAY,KAAM,QAAO;AAC7B,MAAI,YAAY,IAAK,QAAO;AAC5B,MAAI,YAAY,MAAM;AACpB,WAAO,yBAAyB,SAAS,QAAQ,CAAC,CAAC;AAAA,EACrD;AACA,SACE,yBAAyB,SAAS,QAAQ,CAAC,CAAC;AAGhD;AAEA,IAAM,sBAAsB,KAAK,KAAK,KAAK,KAAK;AAUzC,SAAS,cAAc,WAAsC,UAAkB,MAAM,KAAK,IAAI,GAAkB;AACrH,MAAI,CAAC,aAAa,MAAM,YAAY,oBAAqB,QAAO;AAChE,QAAM,OAAO,IAAI,KAAK,SAAS,EAAE,mBAAmB,SAAS,EAAE,OAAO,SAAS,KAAK,WAAW,UAAU,MAAM,CAAC;AAChH,SAAO,qCAAqC,IAAI,wFAAwF,QAAQ;AAClJ;AAEO,SAAS,YAAY,OAAuB;AACjD,MAAI,iBAAiB,UAAU;AAC7B,cAAU,EAAE,IAAI,OAAO,OAAO,EAAE,MAAM,MAAM,MAAM,SAAS,MAAM,QAAQ,EAAE,CAAC;AAAA,EAC9E,OAAO;AACL,cAAU;AAAA,MACR,IAAI;AAAA,MACJ,OAAO,EAAE,MAAM,WAAW,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE;AAAA,IAC5F,CAAC;AAAA,EACH;AACA,UAAQ,KAAK,CAAC;AAChB;AAEO,SAAS,UAAU,OAAiD;AACzE,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,QAAQ,MACX,MAAM,GAAG,EACT,IAAI,CAAC,SAAS,KAAK,KAAK,CAAC,EACzB,OAAO,OAAO;AACjB,SAAO,MAAM,SAAS,IAAI,QAAQ;AACpC;AAEO,SAAS,YAAY,OAA+C;AACzE,MAAI,UAAU,UAAa,UAAU,GAAI,QAAO;AAChD,QAAM,SAAS,OAAO,KAAK;AAC3B,SAAO,OAAO,SAAS,MAAM,IAAI,SAAS;AAC5C;","names":[]}
|