@koda-sl/baker-cli 0.386.0 → 0.387.0-dev.3bafd569e
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1090 -211
- package/canvas/tiktok-captions-composition/index.html +5 -6
- package/canvas/tiktok-captions-composition/meta.json +5 -0
- package/dist/account-CLOKMTTC.js +49 -0
- package/dist/account-CLOKMTTC.js.map +1 -0
- package/dist/account-V5Y2QHAK.js +79 -0
- package/dist/account-V5Y2QHAK.js.map +1 -0
- package/dist/account-XFK6VX2R.js +80 -0
- package/dist/account-XFK6VX2R.js.map +1 -0
- package/dist/account-reads-S5VXX2QU.js +218 -0
- package/dist/account-reads-S5VXX2QU.js.map +1 -0
- package/dist/account-writes-Y7EQXDXF.js +66 -0
- package/dist/account-writes-Y7EQXDXF.js.map +1 -0
- package/dist/accounts-7YD457YN.js +114 -0
- package/dist/accounts-7YD457YN.js.map +1 -0
- package/dist/accounts-BJ3X5JQT.js +115 -0
- package/dist/accounts-BJ3X5JQT.js.map +1 -0
- package/dist/accounts-LOJ4WLIX.js +77 -0
- package/dist/accounts-LOJ4WLIX.js.map +1 -0
- package/dist/accounts-RYBDLQ6H.js +75 -0
- package/dist/accounts-RYBDLQ6H.js.map +1 -0
- package/dist/accounts-UO4XBWM2.js +611 -0
- package/dist/accounts-UO4XBWM2.js.map +1 -0
- package/dist/actions-3AW3R63U.js +55 -0
- package/dist/actions-3AW3R63U.js.map +1 -0
- package/dist/active-entities-R6GZIO6Z.js +103 -0
- package/dist/active-entities-R6GZIO6Z.js.map +1 -0
- package/dist/activities-ESBF3GFS.js +74 -0
- package/dist/activities-ESBF3GFS.js.map +1 -0
- package/dist/ad-group-writes-I225OYDZ.js +170 -0
- package/dist/ad-group-writes-I225OYDZ.js.map +1 -0
- package/dist/ad-groups-O35MWNF6.js +68 -0
- package/dist/ad-groups-O35MWNF6.js.map +1 -0
- package/dist/ad-writes-SS5YZO5W.js +174 -0
- package/dist/ad-writes-SS5YZO5W.js.map +1 -0
- package/dist/add-43DUOVNR.js +104 -0
- package/dist/add-43DUOVNR.js.map +1 -0
- package/dist/add-IE5WDELB.js +302 -0
- package/dist/add-IE5WDELB.js.map +1 -0
- package/dist/add-QZHAWUBA.js +97 -0
- package/dist/add-QZHAWUBA.js.map +1 -0
- package/dist/add-TGQIVVXH.js +105 -0
- package/dist/add-TGQIVVXH.js.map +1 -0
- package/dist/add-accounts-6QYPOPR2.js +91 -0
- package/dist/add-accounts-6QYPOPR2.js.map +1 -0
- package/dist/ads-AUSRB4GU.js +128 -0
- package/dist/ads-AUSRB4GU.js.map +1 -0
- package/dist/ads-COYOTEKE.js +77 -0
- package/dist/ads-COYOTEKE.js.map +1 -0
- package/dist/ads-DZ4N5INZ.js +40 -0
- package/dist/ads-DZ4N5INZ.js.map +1 -0
- package/dist/ads-XZCMSPM5.js +113 -0
- package/dist/ads-XZCMSPM5.js.map +1 -0
- package/dist/adsets-AKR75THA.js +176 -0
- package/dist/adsets-AKR75THA.js.map +1 -0
- package/dist/advertisers-52FMMBTQ.js +120 -0
- package/dist/advertisers-52FMMBTQ.js.map +1 -0
- package/dist/advertisers-BCGKUMEH.js +125 -0
- package/dist/advertisers-BCGKUMEH.js.map +1 -0
- package/dist/analytics-JPDBKETM.js +1980 -0
- package/dist/analytics-JPDBKETM.js.map +1 -0
- package/dist/analytics-YVQ6H4BG.js +433 -0
- package/dist/analytics-YVQ6H4BG.js.map +1 -0
- package/dist/animate-JXIT77Y5.js +480 -0
- package/dist/animate-JXIT77Y5.js.map +1 -0
- package/dist/assign-66NTWTR2.js +77 -0
- package/dist/assign-66NTWTR2.js.map +1 -0
- package/dist/audience-size-LVQJWQAS.js +94 -0
- package/dist/audience-size-LVQJWQAS.js.map +1 -0
- package/dist/audiences-DC3IOG34.js +85 -0
- package/dist/audiences-DC3IOG34.js.map +1 -0
- package/dist/audiences-NEW3LLQR.js +268 -0
- package/dist/audiences-NEW3LLQR.js.map +1 -0
- package/dist/audiences-NYGMBGQ3.js +79 -0
- package/dist/audiences-NYGMBGQ3.js.map +1 -0
- package/dist/audit-UIPMTI5C.js +88 -0
- package/dist/audit-UIPMTI5C.js.map +1 -0
- package/dist/audit-XGN2OFLN.js +151 -0
- package/dist/audit-XGN2OFLN.js.map +1 -0
- package/dist/autocomplete-LVPDV3JE.js +111 -0
- package/dist/autocomplete-LVPDV3JE.js.map +1 -0
- package/dist/avatars-S6NSLMJK.js +38 -0
- package/dist/avatars-S6NSLMJK.js.map +1 -0
- package/dist/bid-pricing-2LYULXU2.js +99 -0
- package/dist/bid-pricing-2LYULXU2.js.map +1 -0
- package/dist/brand-WWHUZ72R.js +22 -0
- package/dist/brand-WWHUZ72R.js.map +1 -0
- package/dist/brief-K3FILESK.js +492 -0
- package/dist/brief-K3FILESK.js.map +1 -0
- package/dist/businesses-J7OP7MSK.js +53 -0
- package/dist/businesses-J7OP7MSK.js.map +1 -0
- package/dist/campaign-groups-N4TZ2F3L.js +95 -0
- package/dist/campaign-groups-N4TZ2F3L.js.map +1 -0
- package/dist/campaign-writes-5XA727KI.js +170 -0
- package/dist/campaign-writes-5XA727KI.js.map +1 -0
- package/dist/campaign-writes-7YFRQIQT.js +165 -0
- package/dist/campaign-writes-7YFRQIQT.js.map +1 -0
- package/dist/campaigns-JPYNVFQI.js +76 -0
- package/dist/campaigns-JPYNVFQI.js.map +1 -0
- package/dist/campaigns-L43ZUKAI.js +107 -0
- package/dist/campaigns-L43ZUKAI.js.map +1 -0
- package/dist/campaigns-OD7Z332M.js +109 -0
- package/dist/campaigns-OD7Z332M.js.map +1 -0
- package/dist/campaigns-R4DXIR2Q.js +110 -0
- package/dist/campaigns-R4DXIR2Q.js.map +1 -0
- package/dist/canvas-57K7AGAP.js +46 -0
- package/dist/canvas-57K7AGAP.js.map +1 -0
- package/dist/capabilities-FVTZAFPV.js +144 -0
- package/dist/capabilities-FVTZAFPV.js.map +1 -0
- package/dist/cards-7H32TNMO.js +85 -0
- package/dist/cards-7H32TNMO.js.map +1 -0
- package/dist/catalog-OTICZPJA.js +64 -0
- package/dist/catalog-OTICZPJA.js.map +1 -0
- package/dist/catalogs-ABCQLCDU.js +128 -0
- package/dist/catalogs-ABCQLCDU.js.map +1 -0
- package/dist/changes-7ZIGNUW6.js +135 -0
- package/dist/changes-7ZIGNUW6.js.map +1 -0
- package/dist/chatgpt-B3NHRJUE.js +47 -0
- package/dist/chatgpt-B3NHRJUE.js.map +1 -0
- package/dist/chats-E7DBRHBF.js +262 -0
- package/dist/chats-E7DBRHBF.js.map +1 -0
- package/dist/chunk-2CV7LX23.js +474 -0
- package/dist/chunk-2CV7LX23.js.map +1 -0
- package/dist/chunk-2HCI5BXB.js +479 -0
- package/dist/chunk-2HCI5BXB.js.map +1 -0
- package/dist/chunk-2SQJL7ZN.js +56 -0
- package/dist/chunk-2SQJL7ZN.js.map +1 -0
- package/dist/chunk-2Y5V23PU.js +29 -0
- package/dist/chunk-2Y5V23PU.js.map +1 -0
- package/dist/chunk-32CPGJPL.js +149 -0
- package/dist/chunk-32CPGJPL.js.map +1 -0
- package/dist/chunk-3ACMDRSE.js +39 -0
- package/dist/chunk-3ACMDRSE.js.map +1 -0
- package/dist/chunk-3N4PZIIV.js +304 -0
- package/dist/chunk-3N4PZIIV.js.map +1 -0
- package/dist/chunk-3U7TDBIB.js +275 -0
- package/dist/chunk-3U7TDBIB.js.map +1 -0
- package/dist/chunk-3UDSYYND.js +42 -0
- package/dist/chunk-3UDSYYND.js.map +1 -0
- package/dist/chunk-3ZWWXAQZ.js +150 -0
- package/dist/chunk-3ZWWXAQZ.js.map +1 -0
- package/dist/chunk-4MH6LONO.js +274 -0
- package/dist/chunk-4MH6LONO.js.map +1 -0
- package/dist/chunk-4NZ47VXO.js +137 -0
- package/dist/chunk-4NZ47VXO.js.map +1 -0
- package/dist/chunk-564AEU2Q.js +541 -0
- package/dist/chunk-564AEU2Q.js.map +1 -0
- package/dist/chunk-5HYSKH77.js +315 -0
- package/dist/chunk-5HYSKH77.js.map +1 -0
- package/dist/chunk-5MBPIONY.js +29 -0
- package/dist/chunk-5MBPIONY.js.map +1 -0
- package/dist/chunk-5OVOLYY3.js +74 -0
- package/dist/chunk-5OVOLYY3.js.map +1 -0
- package/dist/chunk-5SJ3JNNY.js +6683 -0
- package/dist/chunk-5SJ3JNNY.js.map +1 -0
- package/dist/chunk-66USKCVY.js +4410 -0
- package/dist/chunk-66USKCVY.js.map +1 -0
- package/dist/chunk-6I7SYEYN.js +166 -0
- package/dist/chunk-6I7SYEYN.js.map +1 -0
- package/dist/chunk-6O7ISBC7.js +65 -0
- package/dist/chunk-6O7ISBC7.js.map +1 -0
- package/dist/chunk-752S7JF6.js +35 -0
- package/dist/chunk-752S7JF6.js.map +1 -0
- package/dist/chunk-77DN7R35.js +228 -0
- package/dist/chunk-77DN7R35.js.map +1 -0
- package/dist/chunk-7F7MFMLI.js +175 -0
- package/dist/chunk-7F7MFMLI.js.map +1 -0
- package/dist/chunk-7THBBTJJ.js +183 -0
- package/dist/chunk-7THBBTJJ.js.map +1 -0
- package/dist/chunk-7XU3HKMX.js +1599 -0
- package/dist/chunk-7XU3HKMX.js.map +1 -0
- package/dist/chunk-AEA5JV2X.js +92 -0
- package/dist/chunk-AEA5JV2X.js.map +1 -0
- package/dist/chunk-AFJGYJ7Z.js +45 -0
- package/dist/chunk-AFJGYJ7Z.js.map +1 -0
- package/dist/chunk-AR7PU7BB.js +76 -0
- package/dist/chunk-AR7PU7BB.js.map +1 -0
- package/dist/chunk-ASL7JFBD.js +96 -0
- package/dist/chunk-ASL7JFBD.js.map +1 -0
- package/dist/chunk-AUSKKFVH.js +84 -0
- package/dist/chunk-AUSKKFVH.js.map +1 -0
- package/dist/chunk-B52DCYL2.js +159 -0
- package/dist/chunk-B52DCYL2.js.map +1 -0
- package/dist/{chunk-XHC4LMK4.js → chunk-BVM5IRZW.js} +16 -8
- package/dist/chunk-BVM5IRZW.js.map +1 -0
- package/dist/chunk-CAMX6OHF.js +3182 -0
- package/dist/chunk-CAMX6OHF.js.map +1 -0
- package/dist/chunk-CYBLKMXQ.js +310 -0
- package/dist/chunk-CYBLKMXQ.js.map +1 -0
- package/dist/chunk-CZENWCBS.js +333 -0
- package/dist/chunk-CZENWCBS.js.map +1 -0
- package/dist/chunk-D5FY4FAK.js +24 -0
- package/dist/chunk-D5FY4FAK.js.map +1 -0
- package/dist/chunk-DGCUPJZD.js +39 -0
- package/dist/chunk-DGCUPJZD.js.map +1 -0
- package/dist/chunk-DNCLWSHO.js +41 -0
- package/dist/chunk-DNCLWSHO.js.map +1 -0
- package/dist/chunk-DX4GIDO7.js +296 -0
- package/dist/chunk-DX4GIDO7.js.map +1 -0
- package/dist/chunk-EDLZGTGN.js +216 -0
- package/dist/chunk-EDLZGTGN.js.map +1 -0
- package/dist/chunk-EDNX3AOS.js +76 -0
- package/dist/chunk-EDNX3AOS.js.map +1 -0
- package/dist/chunk-EF5DP6EB.js +52 -0
- package/dist/chunk-EF5DP6EB.js.map +1 -0
- package/dist/chunk-ERSX3MKH.js +34 -0
- package/dist/chunk-ERSX3MKH.js.map +1 -0
- package/dist/chunk-F3IJSR7O.js +346 -0
- package/dist/chunk-F3IJSR7O.js.map +1 -0
- package/dist/chunk-FKOECEVC.js +126 -0
- package/dist/chunk-FKOECEVC.js.map +1 -0
- package/dist/chunk-FYWWTMXP.js +2902 -0
- package/dist/chunk-FYWWTMXP.js.map +1 -0
- package/dist/chunk-G7AFVTUS.js +106 -0
- package/dist/chunk-G7AFVTUS.js.map +1 -0
- package/dist/chunk-GIW7ABMM.js +74 -0
- package/dist/chunk-GIW7ABMM.js.map +1 -0
- package/dist/chunk-GIWHHCD6.js +145 -0
- package/dist/chunk-GIWHHCD6.js.map +1 -0
- package/dist/chunk-GPZH5ASB.js +3151 -0
- package/dist/chunk-GPZH5ASB.js.map +1 -0
- package/dist/chunk-GRQ2AXDX.js +9 -0
- package/dist/chunk-GRQ2AXDX.js.map +1 -0
- package/dist/chunk-GXDLWBOY.js +73 -0
- package/dist/chunk-GXDLWBOY.js.map +1 -0
- package/dist/chunk-GYABNLWW.js +629 -0
- package/dist/chunk-GYABNLWW.js.map +1 -0
- package/dist/chunk-H7MLHG2I.js +94 -0
- package/dist/chunk-H7MLHG2I.js.map +1 -0
- package/dist/chunk-H7XVKLIY.js +206 -0
- package/dist/chunk-H7XVKLIY.js.map +1 -0
- package/dist/chunk-HAE4WWFQ.js +455 -0
- package/dist/chunk-HAE4WWFQ.js.map +1 -0
- package/dist/chunk-HDHWIEJJ.js +136 -0
- package/dist/chunk-HDHWIEJJ.js.map +1 -0
- package/dist/chunk-HJTIBTF7.js +98 -0
- package/dist/chunk-HJTIBTF7.js.map +1 -0
- package/dist/{chunk-VZEDAFAR.js → chunk-HLXWKMTK.js} +47 -8
- package/dist/chunk-HLXWKMTK.js.map +1 -0
- package/dist/{chunk-MF7YA62W.js → chunk-HREWXNTO.js} +10 -5
- package/dist/chunk-HREWXNTO.js.map +1 -0
- package/dist/chunk-HYXKRNRV.js +176 -0
- package/dist/chunk-HYXKRNRV.js.map +1 -0
- package/dist/chunk-I3DIZWN5.js +97 -0
- package/dist/chunk-I3DIZWN5.js.map +1 -0
- package/dist/chunk-IJMWEO4P.js +57 -0
- package/dist/chunk-IJMWEO4P.js.map +1 -0
- package/dist/chunk-IOCSDFF2.js +23992 -0
- package/dist/chunk-IOCSDFF2.js.map +1 -0
- package/dist/chunk-IVIJJXXT.js +62 -0
- package/dist/chunk-IVIJJXXT.js.map +1 -0
- package/dist/chunk-J57GWTPK.js +106 -0
- package/dist/chunk-J57GWTPK.js.map +1 -0
- package/dist/chunk-JPK34QPS.js +134 -0
- package/dist/chunk-JPK34QPS.js.map +1 -0
- package/dist/chunk-JRCFCIE3.js +188 -0
- package/dist/chunk-JRCFCIE3.js.map +1 -0
- package/dist/chunk-JUAIGJ2A.js +76 -0
- package/dist/chunk-JUAIGJ2A.js.map +1 -0
- package/dist/chunk-K5OQES4V.js +58 -0
- package/dist/chunk-K5OQES4V.js.map +1 -0
- package/dist/chunk-KBS5GH4T.js +1626 -0
- package/dist/chunk-KBS5GH4T.js.map +1 -0
- package/dist/chunk-KIGGMKAE.js +66 -0
- package/dist/chunk-KIGGMKAE.js.map +1 -0
- package/dist/chunk-KKJ4KJCW.js +29 -0
- package/dist/chunk-KKJ4KJCW.js.map +1 -0
- package/dist/chunk-KLK6KQLQ.js +55 -0
- package/dist/chunk-KLK6KQLQ.js.map +1 -0
- package/dist/chunk-KUZFWMJN.js +207 -0
- package/dist/chunk-KUZFWMJN.js.map +1 -0
- package/dist/chunk-KXGG6EQM.js +382 -0
- package/dist/chunk-KXGG6EQM.js.map +1 -0
- package/dist/chunk-KXRKPZZY.js +169 -0
- package/dist/chunk-KXRKPZZY.js.map +1 -0
- package/dist/chunk-KZUHRZ2C.js +5187 -0
- package/dist/chunk-KZUHRZ2C.js.map +1 -0
- package/dist/chunk-L45A3IYV.js +1079 -0
- package/dist/chunk-L45A3IYV.js.map +1 -0
- package/dist/chunk-LA6PPSNA.js +65 -0
- package/dist/chunk-LA6PPSNA.js.map +1 -0
- package/dist/chunk-LEIQAHWF.js +25 -0
- package/dist/chunk-LEIQAHWF.js.map +1 -0
- package/dist/chunk-LERWCRY5.js +297 -0
- package/dist/chunk-LERWCRY5.js.map +1 -0
- package/dist/chunk-M6UNISGO.js +66 -0
- package/dist/chunk-M6UNISGO.js.map +1 -0
- package/dist/chunk-MGKHFGLV.js +75 -0
- package/dist/chunk-MGKHFGLV.js.map +1 -0
- package/dist/chunk-MZWC6HHA.js +455 -0
- package/dist/chunk-MZWC6HHA.js.map +1 -0
- package/dist/chunk-N3XJ434P.js +197 -0
- package/dist/chunk-N3XJ434P.js.map +1 -0
- package/dist/chunk-NFSLRRIE.js +77 -0
- package/dist/chunk-NFSLRRIE.js.map +1 -0
- package/dist/chunk-NHU33T2S.js +60 -0
- package/dist/chunk-NHU33T2S.js.map +1 -0
- package/dist/chunk-NJEZM4OB.js +51 -0
- package/dist/chunk-NJEZM4OB.js.map +1 -0
- package/dist/chunk-O6QKCJE4.js +455 -0
- package/dist/chunk-O6QKCJE4.js.map +1 -0
- package/dist/chunk-OFFAMC5H.js +225 -0
- package/dist/chunk-OFFAMC5H.js.map +1 -0
- package/dist/chunk-OHGTCFFE.js +57 -0
- package/dist/chunk-OHGTCFFE.js.map +1 -0
- package/dist/chunk-P4NSJS54.js +20 -0
- package/dist/chunk-P4NSJS54.js.map +1 -0
- package/dist/chunk-P5T7OZKV.js +26 -0
- package/dist/chunk-P5T7OZKV.js.map +1 -0
- package/dist/chunk-PFBQERWX.js +10 -0
- package/dist/chunk-PFBQERWX.js.map +1 -0
- package/dist/chunk-PKTLHYH4.js +509 -0
- package/dist/chunk-PKTLHYH4.js.map +1 -0
- package/dist/chunk-PUPEGICD.js +103 -0
- package/dist/chunk-PUPEGICD.js.map +1 -0
- package/dist/chunk-Q6ULQMWG.js +41 -0
- package/dist/chunk-Q6ULQMWG.js.map +1 -0
- package/dist/chunk-QO23YHLK.js +84 -0
- package/dist/chunk-QO23YHLK.js.map +1 -0
- package/dist/chunk-QSGIWV4P.js +337 -0
- package/dist/chunk-QSGIWV4P.js.map +1 -0
- package/dist/chunk-R5OQM7FF.js +179 -0
- package/dist/chunk-R5OQM7FF.js.map +1 -0
- package/dist/chunk-RFB6RYKA.js +111 -0
- package/dist/chunk-RFB6RYKA.js.map +1 -0
- package/dist/chunk-RGIXQEGJ.js +502 -0
- package/dist/chunk-RGIXQEGJ.js.map +1 -0
- package/dist/chunk-RODLBWIR.js +592 -0
- package/dist/chunk-RODLBWIR.js.map +1 -0
- package/dist/chunk-S4LZ7KTG.js +160 -0
- package/dist/chunk-S4LZ7KTG.js.map +1 -0
- package/dist/chunk-SHTESUB6.js +1442 -0
- package/dist/chunk-SHTESUB6.js.map +1 -0
- package/dist/chunk-SJH4EOZH.js +23 -0
- package/dist/chunk-SJH4EOZH.js.map +1 -0
- package/dist/chunk-SLB46MSS.js +64 -0
- package/dist/chunk-SLB46MSS.js.map +1 -0
- package/dist/chunk-SMIENBNX.js +6212 -0
- package/dist/chunk-SMIENBNX.js.map +1 -0
- package/dist/chunk-T7GT22KA.js +494 -0
- package/dist/chunk-T7GT22KA.js.map +1 -0
- package/dist/chunk-T7M4WFNV.js +172 -0
- package/dist/chunk-T7M4WFNV.js.map +1 -0
- package/dist/chunk-TLQ23DDW.js +19 -0
- package/dist/chunk-TLQ23DDW.js.map +1 -0
- package/dist/chunk-TMIDUSOR.js +665 -0
- package/dist/chunk-TMIDUSOR.js.map +1 -0
- package/dist/{chunk-WLDM2TRF.js → chunk-TPXI2GCW.js} +4 -4
- package/dist/chunk-U6VRBDNQ.js +1830 -0
- package/dist/chunk-U6VRBDNQ.js.map +1 -0
- package/dist/chunk-U7BBXM67.js +1743 -0
- package/dist/chunk-U7BBXM67.js.map +1 -0
- package/dist/chunk-UI6BKYQD.js +225 -0
- package/dist/chunk-UI6BKYQD.js.map +1 -0
- package/dist/chunk-UOI5S62H.js +846 -0
- package/dist/chunk-UOI5S62H.js.map +1 -0
- package/dist/chunk-USL5ARRE.js +26 -0
- package/dist/chunk-USL5ARRE.js.map +1 -0
- package/dist/chunk-UYC45JNS.js +139 -0
- package/dist/chunk-UYC45JNS.js.map +1 -0
- package/dist/chunk-VNKVBY54.js +363 -0
- package/dist/chunk-VNKVBY54.js.map +1 -0
- package/dist/chunk-VS4C7VAR.js +533 -0
- package/dist/chunk-VS4C7VAR.js.map +1 -0
- package/dist/chunk-W4W4ZRBP.js +191 -0
- package/dist/chunk-W4W4ZRBP.js.map +1 -0
- package/dist/chunk-WN4KX7GE.js +25 -0
- package/dist/chunk-WN4KX7GE.js.map +1 -0
- package/dist/chunk-WNFTXSGR.js +111 -0
- package/dist/chunk-WNFTXSGR.js.map +1 -0
- package/dist/chunk-WOTDHRNF.js +2109 -0
- package/dist/chunk-WOTDHRNF.js.map +1 -0
- package/dist/chunk-XGWKTYXQ.js +67 -0
- package/dist/chunk-XGWKTYXQ.js.map +1 -0
- package/dist/chunk-XIGIJJSF.js +66 -0
- package/dist/chunk-XIGIJJSF.js.map +1 -0
- package/dist/chunk-XNUXB63I.js +817 -0
- package/dist/chunk-XNUXB63I.js.map +1 -0
- package/dist/chunk-XQ3CCNJD.js +610 -0
- package/dist/chunk-XQ3CCNJD.js.map +1 -0
- package/dist/chunk-XX6ZMCY5.js +4227 -0
- package/dist/chunk-XX6ZMCY5.js.map +1 -0
- package/dist/chunk-Y362QH54.js +98 -0
- package/dist/chunk-Y362QH54.js.map +1 -0
- package/dist/chunk-Y4T6ATDQ.js +74 -0
- package/dist/chunk-Y4T6ATDQ.js.map +1 -0
- package/dist/chunk-YQSBHWOI.js +41 -0
- package/dist/chunk-YU26SDNT.js +46 -0
- package/dist/chunk-YU26SDNT.js.map +1 -0
- package/dist/chunk-YULENNA7.js +501 -0
- package/dist/chunk-YULENNA7.js.map +1 -0
- package/dist/chunk-YYSZYSAG.js +150 -0
- package/dist/chunk-YYSZYSAG.js.map +1 -0
- package/dist/chunk-Z3ENMCFE.js +94 -0
- package/dist/chunk-Z3ENMCFE.js.map +1 -0
- package/dist/chunk-ZH7ZM3ZM.js +125 -0
- package/dist/chunk-ZH7ZM3ZM.js.map +1 -0
- package/dist/chunk-ZIXHS6AM.js +42 -0
- package/dist/chunk-ZIXHS6AM.js.map +1 -0
- package/dist/chunk-ZLLJKSNS.js +96 -0
- package/dist/chunk-ZLLJKSNS.js.map +1 -0
- package/dist/claim-LF6VQ7OR.js +197 -0
- package/dist/claim-LF6VQ7OR.js.map +1 -0
- package/dist/cli.js +104 -70026
- package/dist/cli.js.map +1 -1
- package/dist/client-26SAJ46D.js +19 -0
- package/dist/code-MOWYJMDH.js +76 -0
- package/dist/code-MOWYJMDH.js.map +1 -0
- package/dist/companies-6HSK5BLK.js +195 -0
- package/dist/companies-6HSK5BLK.js.map +1 -0
- package/dist/complete-2PUAFQEC.js +81 -0
- package/dist/complete-2PUAFQEC.js.map +1 -0
- package/dist/config-X6GKOVQ6.js +88 -0
- package/dist/config-X6GKOVQ6.js.map +1 -0
- package/dist/connect-RXPMAJQI.js +42 -0
- package/dist/content-UYZC4AKN.js +85 -0
- package/dist/content-UYZC4AKN.js.map +1 -0
- package/dist/conversation-Y3NB2VDI.js +93 -0
- package/dist/conversation-Y3NB2VDI.js.map +1 -0
- package/dist/conversion-report-R4GJWWTK.js +125 -0
- package/dist/conversion-report-R4GJWWTK.js.map +1 -0
- package/dist/conversion-upload-command-YP4DGTPP.js +438 -0
- package/dist/conversion-upload-command-YP4DGTPP.js.map +1 -0
- package/dist/conversion-writes-WHFFUWWL.js +120 -0
- package/dist/conversion-writes-WHFFUWWL.js.map +1 -0
- package/dist/conversions-K7C32DPW.js +135 -0
- package/dist/conversions-K7C32DPW.js.map +1 -0
- package/dist/conversions-OXJAX5GB.js +76 -0
- package/dist/conversions-OXJAX5GB.js.map +1 -0
- package/dist/countries-PBXNB3BR.js +82 -0
- package/dist/countries-PBXNB3BR.js.map +1 -0
- package/dist/create-AJ4KPSJ4.js +59 -0
- package/dist/create-AJ4KPSJ4.js.map +1 -0
- package/dist/create-ALKOAD5J.js +138 -0
- package/dist/create-ALKOAD5J.js.map +1 -0
- package/dist/create-HTKZMXKB.js +207 -0
- package/dist/create-HTKZMXKB.js.map +1 -0
- package/dist/create-TZMAOFBR.js +236 -0
- package/dist/create-TZMAOFBR.js.map +1 -0
- package/dist/creatives-BJYJFVXJ.js +51 -0
- package/dist/creatives-BJYJFVXJ.js.map +1 -0
- package/dist/creatives-OZHVU4WB.js +182 -0
- package/dist/creatives-OZHVU4WB.js.map +1 -0
- package/dist/creatives-VMGY5SU4.js +87 -0
- package/dist/creatives-VMGY5SU4.js.map +1 -0
- package/dist/credentials-FY4UH6TF.js +287 -0
- package/dist/credentials-FY4UH6TF.js.map +1 -0
- package/dist/critique-B3H7QFM2.js +1449 -0
- package/dist/critique-B3H7QFM2.js.map +1 -0
- package/dist/critique-YZBOA27H.js +216 -0
- package/dist/critique-YZBOA27H.js.map +1 -0
- package/dist/crm-2IBLUHDB.js +318 -0
- package/dist/crm-2IBLUHDB.js.map +1 -0
- package/dist/crm-YMYO4U53.js +224 -0
- package/dist/crm-YMYO4U53.js.map +1 -0
- package/dist/crop-U3AD4DDR.js +113 -0
- package/dist/crop-U3AD4DDR.js.map +1 -0
- package/dist/currency-S6KWZSZ6.js +88 -0
- package/dist/currency-S6KWZSZ6.js.map +1 -0
- package/dist/custom-conversions-FABS6YVT.js +125 -0
- package/dist/custom-conversions-FABS6YVT.js.map +1 -0
- package/dist/customers-P6LLLJHK.js +56 -0
- package/dist/decide-YTHCBKM6.js +199 -0
- package/dist/decide-YTHCBKM6.js.map +1 -0
- package/dist/delete-B2TDEW7H.js +63 -0
- package/dist/delete-B2TDEW7H.js.map +1 -0
- package/dist/delete-DZUDLYPC.js +69 -0
- package/dist/delete-DZUDLYPC.js.map +1 -0
- package/dist/delete-NZGZP4YP.js +71 -0
- package/dist/delete-NZGZP4YP.js.map +1 -0
- package/dist/delete-SDOZNDWQ.js +54 -0
- package/dist/delete-SDOZNDWQ.js.map +1 -0
- package/dist/delete-VQMU56OH.js +71 -0
- package/dist/delete-VQMU56OH.js.map +1 -0
- package/dist/delete-WKQPMVAM.js +66 -0
- package/dist/delete-WKQPMVAM.js.map +1 -0
- package/dist/demographics-Q3DCXULY.js +138 -0
- package/dist/demographics-Q3DCXULY.js.map +1 -0
- package/dist/describe-JNTCQZNL.js +97 -0
- package/dist/describe-JNTCQZNL.js.map +1 -0
- package/dist/describe-MT4334NG.js +97 -0
- package/dist/describe-MT4334NG.js.map +1 -0
- package/dist/dimensions-FEZUJRAG.js +101 -0
- package/dist/dimensions-FEZUJRAG.js.map +1 -0
- package/dist/discard-NEZM5CHF.js +66 -0
- package/dist/discard-NEZM5CHF.js.map +1 -0
- package/dist/discover-4GD7QSF5.js +93 -0
- package/dist/discover-4GD7QSF5.js.map +1 -0
- package/dist/discover-6K3IOYXR.js +172 -0
- package/dist/discover-6K3IOYXR.js.map +1 -0
- package/dist/domain-7Y256IDR.js +98 -0
- package/dist/domain-7Y256IDR.js.map +1 -0
- package/dist/download-L27HWEOE.js +299 -0
- package/dist/download-L27HWEOE.js.map +1 -0
- package/dist/draft-25G2P2TE.js +281 -0
- package/dist/draft-25G2P2TE.js.map +1 -0
- package/dist/draft-F6TUGXAY.js +307 -0
- package/dist/draft-F6TUGXAY.js.map +1 -0
- package/dist/draft-KLULNBWP.js +233 -0
- package/dist/draft-KLULNBWP.js.map +1 -0
- package/dist/draft-LY5ZPF73.js +217 -0
- package/dist/draft-LY5ZPF73.js.map +1 -0
- package/dist/draft-M4ZHDQ46.js +306 -0
- package/dist/draft-M4ZHDQ46.js.map +1 -0
- package/dist/draft-MI7RWY2K.js +100 -0
- package/dist/draft-MI7RWY2K.js.map +1 -0
- package/dist/draft-P4IVYTY3.js +103 -0
- package/dist/draft-P4IVYTY3.js.map +1 -0
- package/dist/draft-QQMCVDDS.js +328 -0
- package/dist/draft-QQMCVDDS.js.map +1 -0
- package/dist/engine/index.d.ts +213 -127
- package/dist/engine/index.js +18 -4
- package/dist/{env-4P5HOGNA.js → env-FBTHZKGN.js} +12 -2
- package/dist/env-FBTHZKGN.js.map +1 -0
- package/dist/experiment-HDYTJPUY.js +1397 -0
- package/dist/experiment-HDYTJPUY.js.map +1 -0
- package/dist/export-TS5GYEMA.js +168 -0
- package/dist/export-TS5GYEMA.js.map +1 -0
- package/dist/extract-QVQFUOIK.js +113 -0
- package/dist/extract-QVQFUOIK.js.map +1 -0
- package/dist/facets-7MBSM7BP.js +114 -0
- package/dist/facets-7MBSM7BP.js.map +1 -0
- package/dist/favorites-7QP7BY5K.js +178 -0
- package/dist/favorites-7QP7BY5K.js.map +1 -0
- package/dist/feed-EETRO2FG.js +177 -0
- package/dist/feed-EETRO2FG.js.map +1 -0
- package/dist/feedback-ZOUL22TP.js +66 -0
- package/dist/feedback-ZOUL22TP.js.map +1 -0
- package/dist/feedback-record-XFFJRKS6.js +177 -0
- package/dist/feedback-record-XFFJRKS6.js.map +1 -0
- package/dist/fetch-QE3EB756.js +176 -0
- package/dist/fetch-QE3EB756.js.map +1 -0
- package/dist/fetch-Z7O3ZL4D.js +139 -0
- package/dist/fetch-Z7O3ZL4D.js.map +1 -0
- package/dist/find-KAQ6JDMO.js +134 -0
- package/dist/find-KAQ6JDMO.js.map +1 -0
- package/dist/fit-MY5GVZZZ.js +45 -0
- package/dist/fit-MY5GVZZZ.js.map +1 -0
- package/dist/flows-C67KEMDU.js +247 -0
- package/dist/flows-C67KEMDU.js.map +1 -0
- package/dist/follow-IX4XVK5Y.js +94 -0
- package/dist/follow-IX4XVK5Y.js.map +1 -0
- package/dist/follow-competitors-UZBUOYTH.js +112 -0
- package/dist/follow-competitors-UZBUOYTH.js.map +1 -0
- package/dist/following-VGOIUCIZ.js +113 -0
- package/dist/following-VGOIUCIZ.js.map +1 -0
- package/dist/fonts-UR7XZ5XZ.js +34 -0
- package/dist/fonts-UR7XZ5XZ.js.map +1 -0
- package/dist/forecast-3F4SZNAK.js +104 -0
- package/dist/forecast-3F4SZNAK.js.map +1 -0
- package/dist/forecast-K5E7CTKX.js +168 -0
- package/dist/forecast-K5E7CTKX.js.map +1 -0
- package/dist/funding-H5YO37OW.js +85 -0
- package/dist/funding-H5YO37OW.js.map +1 -0
- package/dist/funnel-2PPEPAMY.js +394 -0
- package/dist/funnel-2PPEPAMY.js.map +1 -0
- package/dist/ga4-YHJ2XMLC.js +55 -0
- package/dist/ga4-YHJ2XMLC.js.map +1 -0
- package/dist/generate-M2ZX5DMI.js +262 -0
- package/dist/generate-M2ZX5DMI.js.map +1 -0
- package/dist/get-4EYKCZ6F.js +59 -0
- package/dist/get-4EYKCZ6F.js.map +1 -0
- package/dist/get-637GALM2.js +63 -0
- package/dist/get-637GALM2.js.map +1 -0
- package/dist/get-AZARFR6O.js +61 -0
- package/dist/get-AZARFR6O.js.map +1 -0
- package/dist/get-BPMEHRUG.js +56 -0
- package/dist/get-BPMEHRUG.js.map +1 -0
- package/dist/get-MQ6MMIZ7.js +78 -0
- package/dist/get-MQ6MMIZ7.js.map +1 -0
- package/dist/get-N4BPOQCB.js +63 -0
- package/dist/get-N4BPOQCB.js.map +1 -0
- package/dist/get-RPZHLQ56.js +92 -0
- package/dist/get-RPZHLQ56.js.map +1 -0
- package/dist/gif-6PRTB2VR.js +94 -0
- package/dist/gif-6PRTB2VR.js.map +1 -0
- package/dist/google-4XAYE4OI.js +3190 -0
- package/dist/google-4XAYE4OI.js.map +1 -0
- package/dist/google-52JRH7X3.js +136 -0
- package/dist/google-52JRH7X3.js.map +1 -0
- package/dist/google-ads-PWX7OF5Z.js +195 -0
- package/dist/google-ads-PWX7OF5Z.js.map +1 -0
- package/dist/group-AAZ5QKC3.js +43 -0
- package/dist/group-AAZ5QKC3.js.map +1 -0
- package/dist/group-GSYCZORC.js +43 -0
- package/dist/group-GSYCZORC.js.map +1 -0
- package/dist/gsc-TS5T7ML2.js +30 -0
- package/dist/gsc-TS5T7ML2.js.map +1 -0
- package/dist/history-EW6LFFCX.js +67 -0
- package/dist/history-EW6LFFCX.js.map +1 -0
- package/dist/history-XI5ABCFO.js +133 -0
- package/dist/history-XI5ABCFO.js.map +1 -0
- package/dist/hubspot-AVUOILRE.js +779 -0
- package/dist/hubspot-AVUOILRE.js.map +1 -0
- package/dist/icon-K75KI6BV.js +137 -0
- package/dist/icon-K75KI6BV.js.map +1 -0
- package/dist/ideas-UCPV3KTM.js +35 -0
- package/dist/ideas-UCPV3KTM.js.map +1 -0
- package/dist/images-CD53I2W5.js +90 -0
- package/dist/images-CD53I2W5.js.map +1 -0
- package/dist/improve-L3BW4EQG.js +86 -0
- package/dist/improve-L3BW4EQG.js.map +1 -0
- package/dist/ingest-KRJOYTCQ.js +107 -0
- package/dist/ingest-KRJOYTCQ.js.map +1 -0
- package/dist/ingest-WE3SPPND.js +23 -0
- package/dist/ingest-WE3SPPND.js.map +1 -0
- package/dist/insights-PELVD4RY.js +122 -0
- package/dist/insights-PELVD4RY.js.map +1 -0
- package/dist/insights-XCA4BUJW.js +423 -0
- package/dist/insights-XCA4BUJW.js.map +1 -0
- package/dist/inspect-QKETG5UJ.js +189 -0
- package/dist/inspect-QKETG5UJ.js.map +1 -0
- package/dist/inspiration-Y2J2PUPC.js +53 -0
- package/dist/inspiration-Y2J2PUPC.js.map +1 -0
- package/dist/intent-YJOJGNVJ.js +95 -0
- package/dist/intent-YJOJGNVJ.js.map +1 -0
- package/dist/job-E2U4FS5P.js +202 -0
- package/dist/job-E2U4FS5P.js.map +1 -0
- package/dist/job-create-DFYCHVQ7.js +109 -0
- package/dist/job-create-DFYCHVQ7.js.map +1 -0
- package/dist/job-status-FFPMTSHB.js +74 -0
- package/dist/job-status-FFPMTSHB.js.map +1 -0
- package/dist/keep-GYZS2UTL.js +78 -0
- package/dist/keep-GYZS2UTL.js.map +1 -0
- package/dist/keyword-gap-QU7O7UKC.js +130 -0
- package/dist/keyword-gap-QU7O7UKC.js.map +1 -0
- package/dist/keyword-metrics-HLCM3QU7.js +197 -0
- package/dist/keyword-metrics-HLCM3QU7.js.map +1 -0
- package/dist/keywords-for-site-BDKPQKWB.js +128 -0
- package/dist/keywords-for-site-BDKPQKWB.js.map +1 -0
- package/dist/landing-4K6XYNFM.js +28 -0
- package/dist/landing-4K6XYNFM.js.map +1 -0
- package/dist/landings-F7LOAEJE.js +151 -0
- package/dist/landings-F7LOAEJE.js.map +1 -0
- package/dist/languages-P3ZM6R2A.js +40 -0
- package/dist/languages-P3ZM6R2A.js.map +1 -0
- package/dist/languages-XEJKTIFP.js +55 -0
- package/dist/languages-XEJKTIFP.js.map +1 -0
- package/dist/launches-TCFAYUA5.js +19 -0
- package/dist/launches-TCFAYUA5.js.map +1 -0
- package/dist/layerize-ZSKFIPZA.js +190 -0
- package/dist/layerize-ZSKFIPZA.js.map +1 -0
- package/dist/leads-GDF4S2AM.js +90 -0
- package/dist/leads-GDF4S2AM.js.map +1 -0
- package/dist/leads-TPB5OFSQ.js +293 -0
- package/dist/leads-TPB5OFSQ.js.map +1 -0
- package/dist/learn-NMFEA5H5.js +203 -0
- package/dist/learn-NMFEA5H5.js.map +1 -0
- package/dist/library-IP2UKNRU.js +109 -0
- package/dist/library-IP2UKNRU.js.map +1 -0
- package/dist/lighthouse-57XBJRCO.js +75 -0
- package/dist/lighthouse-57XBJRCO.js.map +1 -0
- package/dist/line-item-writes-O6SSS5NQ.js +208 -0
- package/dist/line-item-writes-O6SSS5NQ.js.map +1 -0
- package/dist/line-items-ZZAKH3YZ.js +103 -0
- package/dist/line-items-ZZAKH3YZ.js.map +1 -0
- package/dist/link-CRY57R3E.js +64 -0
- package/dist/link-CRY57R3E.js.map +1 -0
- package/dist/linkedin-WC7LGYPP.js +1008 -0
- package/dist/linkedin-WC7LGYPP.js.map +1 -0
- package/dist/list-6IKPWQGG.js +57 -0
- package/dist/list-6IKPWQGG.js.map +1 -0
- package/dist/list-CAUH3BMG.js +65 -0
- package/dist/list-CAUH3BMG.js.map +1 -0
- package/dist/list-CWAKX5TH.js +63 -0
- package/dist/list-CWAKX5TH.js.map +1 -0
- package/dist/list-FJ5FSVL6.js +151 -0
- package/dist/list-FJ5FSVL6.js.map +1 -0
- package/dist/list-GTOSN7DP.js +50 -0
- package/dist/list-GTOSN7DP.js.map +1 -0
- package/dist/list-HLJP4NVE.js +51 -0
- package/dist/list-HLJP4NVE.js.map +1 -0
- package/dist/list-LCUPF7EF.js +76 -0
- package/dist/list-LCUPF7EF.js.map +1 -0
- package/dist/list-NH4ZRZTL.js +303 -0
- package/dist/list-NH4ZRZTL.js.map +1 -0
- package/dist/locations-2BYWKIYA.js +67 -0
- package/dist/locations-2BYWKIYA.js.map +1 -0
- package/dist/locations-LVVDOSXO.js +40 -0
- package/dist/locations-LVVDOSXO.js.map +1 -0
- package/dist/log-6JOWOY5G.js +92 -0
- package/dist/log-6JOWOY5G.js.map +1 -0
- package/dist/logo-AJK2TDQU.js +18 -0
- package/dist/logo-AJK2TDQU.js.map +1 -0
- package/dist/lookup-H5GEM77H.js +22 -0
- package/dist/lookup-H5GEM77H.js.map +1 -0
- package/dist/make-Q2AMLCWE.js +640 -0
- package/dist/make-Q2AMLCWE.js.map +1 -0
- package/dist/map-4KOYFHAN.js +404 -0
- package/dist/map-4KOYFHAN.js.map +1 -0
- package/dist/mcp-LSS2DHYL.js +463 -0
- package/dist/mcp-LSS2DHYL.js.map +1 -0
- package/dist/media-JBCN6V4X.js +15 -0
- package/dist/media-JBCN6V4X.js.map +1 -0
- package/dist/media-RAGEJTZX.js +89 -0
- package/dist/media-RAGEJTZX.js.map +1 -0
- package/dist/media-sources-GSPAV7HT.js +32 -0
- package/dist/media-sources-GSPAV7HT.js.map +1 -0
- package/dist/members-GUUVEK2Y.js +44 -0
- package/dist/members-GUUVEK2Y.js.map +1 -0
- package/dist/meta-Z37ZR3PJ.js +69 -0
- package/dist/meta-Z37ZR3PJ.js.map +1 -0
- package/dist/metrics-KW6SDULI.js +152 -0
- package/dist/metrics-KW6SDULI.js.map +1 -0
- package/dist/models-5J4WFUD3.js +155 -0
- package/dist/models-5J4WFUD3.js.map +1 -0
- package/dist/normalize-DSFVTRXN.js +806 -0
- package/dist/normalize-DSFVTRXN.js.map +1 -0
- package/dist/normalize-EUDI5HEM.js +141 -0
- package/dist/normalize-EUDI5HEM.js.map +1 -0
- package/dist/options-P4PPJQH4.js +121 -0
- package/dist/options-P4PPJQH4.js.map +1 -0
- package/dist/output-DTCLVPUF.js +24 -0
- package/dist/output-DTCLVPUF.js.map +1 -0
- package/dist/page-N2ZO3O7F.js +105 -0
- package/dist/page-N2ZO3O7F.js.map +1 -0
- package/dist/pages-FQ4CBAJ2.js +66 -0
- package/dist/pages-FQ4CBAJ2.js.map +1 -0
- package/dist/performance-A66LYIZX.js +24 -0
- package/dist/performance-A66LYIZX.js.map +1 -0
- package/dist/pinterest-NV5XTNJE.js +96 -0
- package/dist/pinterest-NV5XTNJE.js.map +1 -0
- package/dist/pixels-CTJ43FZ4.js +108 -0
- package/dist/pixels-CTJ43FZ4.js.map +1 -0
- package/dist/pixels-HKINGZCH.js +60 -0
- package/dist/pixels-HKINGZCH.js.map +1 -0
- package/dist/plan-ZYTWLGWK.js +207 -0
- package/dist/plan-ZYTWLGWK.js.map +1 -0
- package/dist/preview-5ROBOQG7.js +169 -0
- package/dist/preview-5ROBOQG7.js.map +1 -0
- package/dist/profile-Q3PHR6FU.js +159 -0
- package/dist/profile-Q3PHR6FU.js.map +1 -0
- package/dist/promoted-tweet-writes-AEOUK2LK.js +180 -0
- package/dist/promoted-tweet-writes-AEOUK2LK.js.map +1 -0
- package/dist/promoted-tweets-L2CEC2BJ.js +119 -0
- package/dist/promoted-tweets-L2CEC2BJ.js.map +1 -0
- package/dist/properties-WLL6M2P6.js +101 -0
- package/dist/properties-WLL6M2P6.js.map +1 -0
- package/dist/publish-KHNR5ARF.js +322 -0
- package/dist/publish-KHNR5ARF.js.map +1 -0
- package/dist/query-A34J7BGX.js +61 -0
- package/dist/query-A34J7BGX.js.map +1 -0
- package/dist/query-IYZN5KHO.js +236 -0
- package/dist/query-IYZN5KHO.js.map +1 -0
- package/dist/query-UN2P6DBA.js +247 -0
- package/dist/query-UN2P6DBA.js.map +1 -0
- package/dist/questionnaire-Z2ZIKNBV.js +93 -0
- package/dist/questionnaire-Z2ZIKNBV.js.map +1 -0
- package/dist/read-GM7PQYJA.js +141 -0
- package/dist/read-GM7PQYJA.js.map +1 -0
- package/dist/reddit-5NPFULGD.js +26 -0
- package/dist/reddit-5NPFULGD.js.map +1 -0
- package/dist/refresh-FGXW4Y4X.js +94 -0
- package/dist/refresh-FGXW4Y4X.js.map +1 -0
- package/dist/release-OKZMC73N.js +60 -0
- package/dist/release-OKZMC73N.js.map +1 -0
- package/dist/relevant-pages-J76ZKNKF.js +99 -0
- package/dist/relevant-pages-J76ZKNKF.js.map +1 -0
- package/dist/remove-CA2J6ACH.js +50 -0
- package/dist/remove-CA2J6ACH.js.map +1 -0
- package/dist/remove-GOYW2G4R.js +48 -0
- package/dist/remove-GOYW2G4R.js.map +1 -0
- package/dist/reopen-XPKSOE6O.js +63 -0
- package/dist/reopen-XPKSOE6O.js.map +1 -0
- package/dist/rerun-2ERJV4WC.js +86 -0
- package/dist/rerun-2ERJV4WC.js.map +1 -0
- package/dist/research-FZ63UZTE.js +62 -0
- package/dist/research-FZ63UZTE.js.map +1 -0
- package/dist/research-YGQQ6CNG.js +262 -0
- package/dist/research-YGQQ6CNG.js.map +1 -0
- package/dist/reset-BGPZ4HMA.js +54 -0
- package/dist/reset-BGPZ4HMA.js.map +1 -0
- package/dist/reset-HTD6LCIT.js +54 -0
- package/dist/reset-HTD6LCIT.js.map +1 -0
- package/dist/resolve-NRDZ6N2B.js +121 -0
- package/dist/resolve-NRDZ6N2B.js.map +1 -0
- package/dist/retry-PF4BGKJV.js +60 -0
- package/dist/retry-PF4BGKJV.js.map +1 -0
- package/dist/retry-XL26JDAV.js +62 -0
- package/dist/retry-XL26JDAV.js.map +1 -0
- package/dist/retry-failed-BEFWRV4Z.js +45 -0
- package/dist/retry-failed-BEFWRV4Z.js.map +1 -0
- package/dist/run-EMJLI7LR.js +65 -0
- package/dist/run-EMJLI7LR.js.map +1 -0
- package/dist/run-L5K44UEA.js +61 -0
- package/dist/run-L5K44UEA.js.map +1 -0
- package/dist/scaffold-ad-AY2OL7RI.js +1550 -0
- package/dist/scaffold-ad-AY2OL7RI.js.map +1 -0
- package/dist/scaffold-static-ad-FXYE46MT.js +973 -0
- package/dist/scaffold-static-ad-FXYE46MT.js.map +1 -0
- package/dist/scaffold-video-533BT6RX.js +874 -0
- package/dist/scaffold-video-533BT6RX.js.map +1 -0
- package/dist/schedule-KQ7UIR3N.js +66 -0
- package/dist/schedule-KQ7UIR3N.js.map +1 -0
- package/dist/schedule-PKPNSISL.js +61 -0
- package/dist/schedule-PKPNSISL.js.map +1 -0
- package/dist/scheduled-agents-LP5LITA3.js +49 -0
- package/dist/scheduled-agents-LP5LITA3.js.map +1 -0
- package/dist/schema-B6J6VPTO.js +132 -0
- package/dist/schema-B6J6VPTO.js.map +1 -0
- package/dist/schema-QXTDLZVC.js +63 -0
- package/dist/schema-QXTDLZVC.js.map +1 -0
- package/dist/scrape-7YKJWFZE.js +2241 -0
- package/dist/scrape-7YKJWFZE.js.map +1 -0
- package/dist/screenshot-ZHBSG3SI.js +102 -0
- package/dist/screenshot-ZHBSG3SI.js.map +1 -0
- package/dist/search-332KFYZ6.js +224 -0
- package/dist/search-332KFYZ6.js.map +1 -0
- package/dist/search-4PBMXXUY.js +91 -0
- package/dist/search-4PBMXXUY.js.map +1 -0
- package/dist/search-6WNUKCMP.js +174 -0
- package/dist/search-6WNUKCMP.js.map +1 -0
- package/dist/search-AVNUU6TJ.js +26 -0
- package/dist/search-AVNUU6TJ.js.map +1 -0
- package/dist/search-F5INRFFK.js +92 -0
- package/dist/search-F5INRFFK.js.map +1 -0
- package/dist/search-copy-DZVBYG2B.js +168 -0
- package/dist/search-copy-DZVBYG2B.js.map +1 -0
- package/dist/seeds-5JTQN5WI.js +101 -0
- package/dist/seeds-5JTQN5WI.js.map +1 -0
- package/dist/select-RSGLDQ5Z.js +96 -0
- package/dist/select-RSGLDQ5Z.js.map +1 -0
- package/dist/sends-3L6QBS46.js +309 -0
- package/dist/sends-3L6QBS46.js.map +1 -0
- package/dist/sequences-YKFV7BDH.js +146 -0
- package/dist/sequences-YKFV7BDH.js.map +1 -0
- package/dist/set-prompt-7WWJI6XW.js +188 -0
- package/dist/set-prompt-7WWJI6XW.js.map +1 -0
- package/dist/setup-links-6H5ONDCQ.js +141 -0
- package/dist/setup-links-6H5ONDCQ.js.map +1 -0
- package/dist/{shared-6762QE6R.js → shared-QAMP7FZV.js} +8 -6
- package/dist/shared-QAMP7FZV.js.map +1 -0
- package/dist/shopify-2OY3J3OY.js +3692 -0
- package/dist/shopify-2OY3J3OY.js.map +1 -0
- package/dist/site-TBPERLY3.js +177 -0
- package/dist/site-TBPERLY3.js.map +1 -0
- package/dist/sitemaps-XPGLW24S.js +87 -0
- package/dist/sitemaps-XPGLW24S.js.map +1 -0
- package/dist/sites-WMBY2HJV.js +101 -0
- package/dist/sites-WMBY2HJV.js.map +1 -0
- package/dist/skills-3HEILQCU.js +47 -0
- package/dist/skills-3HEILQCU.js.map +1 -0
- package/dist/sources-JFQKTK2L.js +421 -0
- package/dist/sources-JFQKTK2L.js.map +1 -0
- package/dist/sources-Q3I6DDV7.js +30 -0
- package/dist/sources-Q3I6DDV7.js.map +1 -0
- package/dist/stale-CAXBLZKJ.js +66 -0
- package/dist/stale-CAXBLZKJ.js.map +1 -0
- package/dist/stats-GNILHSKK.js +34 -0
- package/dist/stats-GNILHSKK.js.map +1 -0
- package/dist/status-LIZWJYS4.js +62 -0
- package/dist/status-LIZWJYS4.js.map +1 -0
- package/dist/sticker-KCV3VZHY.js +94 -0
- package/dist/sticker-KCV3VZHY.js.map +1 -0
- package/dist/stock-VTORKR4C.js +179 -0
- package/dist/stock-VTORKR4C.js.map +1 -0
- package/dist/studio-QCRA6BY5.js +49 -0
- package/dist/studio-QCRA6BY5.js.map +1 -0
- package/dist/sync-455DB46Y.js +54 -0
- package/dist/sync-455DB46Y.js.map +1 -0
- package/dist/sync-A4KKQ3B6.js +265 -0
- package/dist/sync-A4KKQ3B6.js.map +1 -0
- package/dist/sync-ULKWDFXM.js +54 -0
- package/dist/sync-ULKWDFXM.js.map +1 -0
- package/dist/sync-definition-P6QTHJJ6.js +55 -0
- package/dist/sync-definition-P6QTHJJ6.js.map +1 -0
- package/dist/tag-manager-E7QTXBWQ.js +43 -0
- package/dist/tag-manager-E7QTXBWQ.js.map +1 -0
- package/dist/tags-4Q4I5GQJ.js +20 -0
- package/dist/tags-4Q4I5GQJ.js.map +1 -0
- package/dist/tags-AMEVAQZ4.js +26 -0
- package/dist/tags-AMEVAQZ4.js.map +1 -0
- package/dist/tags-DPLOLH3E.js +20 -0
- package/dist/tags-DPLOLH3E.js.map +1 -0
- package/dist/tags-LDHXONR3.js +224 -0
- package/dist/tags-LDHXONR3.js.map +1 -0
- package/dist/tags-UW3WJTAQ.js +20 -0
- package/dist/tags-UW3WJTAQ.js.map +1 -0
- package/dist/targeting-constants-D64YO3E7.js +118 -0
- package/dist/targeting-constants-D64YO3E7.js.map +1 -0
- package/dist/targeting-criteria-BP6VJA7X.js +113 -0
- package/dist/targeting-criteria-BP6VJA7X.js.map +1 -0
- package/dist/targets-CQWO2UXD.js +102 -0
- package/dist/targets-CQWO2UXD.js.map +1 -0
- package/dist/templates-WZSTNRNZ.js +178 -0
- package/dist/templates-WZSTNRNZ.js.map +1 -0
- package/dist/testimonials-ETHSNWUH.js +32 -0
- package/dist/testimonials-ETHSNWUH.js.map +1 -0
- package/dist/themes-YU663LQH.js +94 -0
- package/dist/themes-YU663LQH.js.map +1 -0
- package/dist/top-companies-KTXHS472.js +108 -0
- package/dist/top-companies-KTXHS472.js.map +1 -0
- package/dist/translate-A7LYHUW3.js +600 -0
- package/dist/translate-A7LYHUW3.js.map +1 -0
- package/dist/triggers-4EDFLNGH.js +141 -0
- package/dist/triggers-4EDFLNGH.js.map +1 -0
- package/dist/tweets-ZUKQAAUQ.js +123 -0
- package/dist/tweets-ZUKQAAUQ.js.map +1 -0
- package/dist/unfollow-A4JVCJBF.js +46 -0
- package/dist/unfollow-A4JVCJBF.js.map +1 -0
- package/dist/unlink-KY2OEKMD.js +67 -0
- package/dist/unlink-KY2OEKMD.js.map +1 -0
- package/dist/unstage-FHUG67RI.js +84 -0
- package/dist/unstage-FHUG67RI.js.map +1 -0
- package/dist/unstage-ZRLLCSQF.js +95 -0
- package/dist/unstage-ZRLLCSQF.js.map +1 -0
- package/dist/update-27LGM65V.js +63 -0
- package/dist/update-27LGM65V.js.map +1 -0
- package/dist/update-AIY46I2Q.js +155 -0
- package/dist/update-AIY46I2Q.js.map +1 -0
- package/dist/update-QYD2XZFM.js +142 -0
- package/dist/update-QYD2XZFM.js.map +1 -0
- package/dist/update-W2OSRNFO.js +98 -0
- package/dist/update-W2OSRNFO.js.map +1 -0
- package/dist/upload-JGBTSKGH.js +126 -0
- package/dist/upload-JGBTSKGH.js.map +1 -0
- package/dist/upload-XEHWYMJG.js +150 -0
- package/dist/upload-XEHWYMJG.js.map +1 -0
- package/dist/upscale-I5P2OHTN.js +109 -0
- package/dist/upscale-I5P2OHTN.js.map +1 -0
- package/dist/url-options-QHGA42RP.js +130 -0
- package/dist/url-options-QHGA42RP.js.map +1 -0
- package/dist/url-params-NWSUHWRE.js +98 -0
- package/dist/url-params-NWSUHWRE.js.map +1 -0
- package/dist/use-U4HG2NF3.js +95 -0
- package/dist/use-U4HG2NF3.js.map +1 -0
- package/dist/validate-VKL3XKQ2.js +91 -0
- package/dist/validate-VKL3XKQ2.js.map +1 -0
- package/dist/variant-FOVE6URJ.js +338 -0
- package/dist/variant-FOVE6URJ.js.map +1 -0
- package/dist/videos-DP3VCSYG.js +39 -0
- package/dist/videos-DP3VCSYG.js.map +1 -0
- package/dist/view-HRI3FHCH.js +121 -0
- package/dist/view-HRI3FHCH.js.map +1 -0
- package/dist/viewer-check-JYUE24M6.js +68 -0
- package/dist/viewer-check-JYUE24M6.js.map +1 -0
- package/dist/web-AFUIWPFU.js +140 -0
- package/dist/web-AFUIWPFU.js.map +1 -0
- package/dist/winners-SMMDN6LW.js +113 -0
- package/dist/winners-SMMDN6LW.js.map +1 -0
- package/dist/winning-ads-PCIJUYVA.js +84 -0
- package/dist/winning-ads-PCIJUYVA.js.map +1 -0
- package/dist/write-commands-7Z34WG2J.js +206 -0
- package/dist/write-commands-7Z34WG2J.js.map +1 -0
- package/dist/write-commands-BLT2SEC4.js +713 -0
- package/dist/write-commands-BLT2SEC4.js.map +1 -0
- package/dist/write-commands-N4FSGRVQ.js +743 -0
- package/dist/write-commands-N4FSGRVQ.js.map +1 -0
- package/dist/write-commands-Q4MQ3BGM.js +1015 -0
- package/dist/write-commands-Q4MQ3BGM.js.map +1 -0
- package/dist/x-AUOZJNWE.js +47 -0
- package/dist/x-AUOZJNWE.js.map +1 -0
- package/package.json +9 -2
- package/dist/chunk-FGHMWBUD.js +0 -9989
- package/dist/chunk-FGHMWBUD.js.map +0 -1
- package/dist/chunk-HJEMOSPH.js +0 -1292
- package/dist/chunk-HJEMOSPH.js.map +0 -1
- package/dist/chunk-MF7YA62W.js.map +0 -1
- package/dist/chunk-VZEDAFAR.js.map +0 -1
- package/dist/chunk-XHC4LMK4.js.map +0 -1
- package/dist/client-GR6YL3YX.js +0 -17
- package/dist/output-NMQXZF3Z.js +0 -18
- /package/dist/{chunk-WLDM2TRF.js.map → chunk-TPXI2GCW.js.map} +0 -0
- /package/dist/{client-GR6YL3YX.js.map → chunk-YQSBHWOI.js.map} +0 -0
- /package/dist/{env-4P5HOGNA.js.map → client-26SAJ46D.js.map} +0 -0
- /package/dist/{output-NMQXZF3Z.js.map → connect-RXPMAJQI.js.map} +0 -0
- /package/dist/{shared-6762QE6R.js.map → customers-P6LLLJHK.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/flows/value-expression.ts","../src/commands/flows/mapping.ts"],"sourcesContent":["/**\n * What goes on the RIGHT of a `--map`, and how it becomes an AutofillDoc.\n *\n * The first version of this command could only map a plain form field, which\n * left out most of what a real CRM mapping is made of. `lead_source` almost\n * always wants `tracking.utm_source`; a \"full name\" column wants two fields and\n * a space between them; a Pipedrive owner field wants a literal. None of that\n * was expressible, so the command that exists to stop the agent hand-writing\n * ProseMirror sent it straight back to hand-writing ProseMirror for the most\n * common mapping in paid marketing.\n *\n * The grammar is four prefixes, a quoted literal, and `+`:\n *\n * nombre a form field (shorthand for field:nombre)\n * field:nombre …the same, explicit\n * field:Contact Info.nombre …disambiguated when two steps share a name\n * tracking:utm_source a built-in tracking variable\n * global:UserEmail a global variable, by the name it was given\n * code:total_score a codeExecution exposed value\n * \"Paid Search\" literal text\n * field:first + \" \" + field:last concatenation\n * {{<stepId>.customForm.nombre}} a mention as the flow file stores it\n * (also .codeExecution., tracking., global.)\n *\n * A value never runs code: `.split(\" \")[0]` and the like are refused, because\n * the engine substitutes a mention and nothing evaluates what follows it.\n *\n * Every reference is resolved against the flow's own tree — a name that is not\n * there is refused with the names that are. That is the whole point: `attrs.id`\n * is not checked by anything downstream, so a mapping with a subtly wrong id is\n * valid, ships, and sends an empty value forever.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { MappingError } from \"./mapping.ts\";\nimport { flowsDir, walkNodes } from \"./shared.ts\";\n\ntype AnyRecord = Record<string, unknown>;\n\nexport type ValuePart =\n | { kind: \"text\"; text: string }\n | { kind: \"field\"; ref: string }\n | { kind: \"tracking\"; name: string }\n | { kind: \"global\"; name: string }\n | { kind: \"code\"; ref: string };\n\nconst PREFIXES = [\"field\", \"tracking\", \"global\", \"code\"] as const;\n\n/**\n * Split on `+` at the top level, keeping quoted segments intact.\n *\n * Hand-rolled rather than a regex because a literal may contain `+` — a mapping\n * that emits `\"A + B\"` as text is legitimate, and a regex split would tear it in\n * half silently.\n */\nfunction splitParts(raw: string): string[] {\n const parts: string[] = [];\n let current = \"\";\n let inQuotes = false;\n for (let i = 0; i < raw.length; i++) {\n const char = raw[i];\n if (char === '\"') {\n inQuotes = !inQuotes;\n current += char;\n } else if (char === \"+\" && !inQuotes) {\n parts.push(current);\n current = \"\";\n } else {\n current += char;\n }\n }\n parts.push(current);\n if (inQuotes) {\n throw new MappingError(`Unclosed quote in value \\`${raw}\\`.`, 'A literal is written \"like this\".');\n }\n return parts.map((part) => part.trim()).filter((part) => part.length > 0);\n}\n\nconst TRANSFORM_REFUSAL =\n \"A value cannot run code. Map the field as it is (firstname=full_name), or split it in the step with a codeExecution that exposes first_name and last_name and map code:first_name.\";\n\n/** `.split(`, `.slice(`, `.toUpperCase()` — a method call, which no mapping can run. */\nconst METHOD_CALL = /\\.\\s*[A-Za-z_$][\\w$]*\\s*\\(/;\n/** `[0]` on the end of a reference — an index, which no mapping can run either. */\nconst TRAILING_INDEX = /\\[[^\\]]*\\]$/;\n\n/**\n * A reference in the spelling the flow file itself stores it in —\n * `{{<stepId>.customForm.<field>}}` — and the one every refusal's inventory\n * prints the step id for. Refusing it sent the agent back to hand-writing the\n * ProseMirror doc for a field the command had just listed.\n */\nfunction mentionPart(inner: string): ValuePart {\n if (inner.startsWith(\"tracking.\")) return { kind: \"tracking\", name: inner.slice(\"tracking.\".length) };\n if (inner.startsWith(\"global.\")) return { kind: \"global\", name: inner.slice(\"global.\".length) };\n return referencePart(inner);\n}\n\n/** A bare reference: `<stepId>.codeExecution.<name>` is an exposed value, anything else a form field. */\nfunction referencePart(ref: string): ValuePart {\n return /\\.codeExecution\\.[^.]+$/.test(ref) ? { kind: \"code\", ref } : { kind: \"field\", ref };\n}\n\n/** One `+`-separated segment: a quoted literal, a prefixed reference, or a bare field name. */\nfunction parsePart(part: string): ValuePart {\n if (part.startsWith('\"') && part.endsWith('\"') && part.length >= 2) {\n return { kind: \"text\", text: part.slice(1, -1) };\n }\n if (METHOD_CALL.test(part) || TRAILING_INDEX.test(part)) {\n throw new MappingError(TRANSFORM_REFUSAL);\n }\n\n if (part.startsWith(\"{{\")) {\n const close = part.indexOf(\"}}\");\n if (close < 0) {\n throw new MappingError(\n `Unclosed \\`{{\\` in value \\`${part}\\`.`,\n \"A mention is written {{<stepId>.customForm.<field>}}.\",\n );\n }\n if (part.slice(close + 2).trim()) throw new MappingError(TRANSFORM_REFUSAL);\n return mentionPart(part.slice(2, close).trim());\n }\n\n const colon = part.indexOf(\":\");\n if (colon <= 0) return referencePart(part);\n\n const prefix = part.slice(0, colon);\n const rest = part.slice(colon + 1).trim();\n if (!(PREFIXES as readonly string[]).includes(prefix)) {\n throw new MappingError(\n `\\`${prefix}:\\` is not a value kind.`,\n `Use one of ${PREFIXES.map((candidate) => `${candidate}:`).join(\" \")}, a bare form field name, or a \"quoted literal\".`,\n );\n }\n if (!rest) throw new MappingError(`\\`${part}\\` names no ${prefix}.`);\n\n switch (prefix) {\n case \"tracking\":\n return { kind: \"tracking\", name: rest.replace(/^tracking\\./, \"\") };\n case \"global\":\n return { kind: \"global\", name: rest };\n case \"code\":\n return { kind: \"code\", ref: rest };\n default:\n return { kind: \"field\", ref: rest };\n }\n}\n\nexport function parseValueExpression(raw: string): ValuePart[] {\n const parts = splitParts(raw);\n if (parts.length === 0) {\n throw new MappingError(\"A --map needs a value on the right of the `=`.\");\n }\n return parts.map(parsePart);\n}\n\n/**\n * The tracking vocabulary, read out of the workspace the command is running in\n * rather than copied here. `TRACKING_FIELD_IDS` is the engine's own list, so\n * reading it is the only way this cannot drift — and there are already four\n * hand-copies of the flow taxonomy in this repo without adding a fifth.\n *\n * Returns null when the file is not there (the CLI run outside a client repo),\n * which skips validation rather than refusing a mapping that is probably fine.\n */\nexport function trackingFieldIds(): Set<string> | null {\n const path = join(flowsDir(), \"..\", \"tracking.ts\");\n if (!existsSync(path)) return null;\n try {\n const source = readFileSync(path, \"utf-8\");\n const block = source.match(/TRACKING_FIELD_IDS\\s*=\\s*\\[([\\s\\S]*?)\\]\\s*as const/)?.[1];\n if (!block) return null;\n const ids = [...block.matchAll(/\"(tracking\\.[a-z0-9_]+)\"/g)].map((match) => match[1] as string);\n return ids.length > 0 ? new Set(ids) : null;\n } catch {\n return null;\n }\n}\n\n/**\n * A step's `nodeData.form.external` — the one place the engine keeps both a\n * step's fields and its `codeExecution`.\n *\n * Read through here rather than off `nodeData` directly. `codeExecution` is\n * nested one level deeper than it looks (`CustomFormData` in `types.ts`, and\n * both readers — `store.ts` `applyCodeExecution` and `code-normalize.ts`\n * `pushCustomFormExposedNames` — go through `form.external`), and reading it\n * from the wrong level is invisible: the lookup simply finds nothing and every\n * `code:` reference is refused as if the form exposed no values at all.\n */\nfunction externalOf(node: AnyRecord): AnyRecord {\n const nodeData = (node.nodeData ?? {}) as AnyRecord;\n return ((nodeData.form as AnyRecord | undefined)?.external ?? {}) as AnyRecord;\n}\n\ntype FieldOwner = { id: string; name: string; fields: string[] };\n\n/** Steps that collect data, with the fields each one owns. */\nfunction fieldOwners(tree: AnyRecord): FieldOwner[] {\n return walkNodes(tree).flatMap((node) => {\n const external = externalOf(node);\n if (!Array.isArray(external.fields)) return [];\n return [\n {\n id: String(node.id ?? \"\"),\n name: typeof node.name === \"string\" && node.name ? node.name : \"Form\",\n fields: (external.fields as AnyRecord[])\n .map((field) => field?.fieldName)\n .filter((name): name is string => typeof name === \"string\"),\n },\n ];\n });\n}\n\n/**\n * `Contact Info.email` → the step called \"Contact Info\"; `email` → whichever step\n * owns it; `<stepId>.customForm.email` → that step, spelled as the flow file\n * stores the mention (`segment` is `customForm` for a field, `codeExecution`\n * for an exposed value).\n */\nfunction splitRef(ref: string, segment: \"customForm\" | \"codeExecution\"): { step?: string; name: string } {\n const marker = `.${segment}.`;\n const at = ref.lastIndexOf(marker);\n if (at > 0 && !ref.slice(at + marker.length).includes(\".\")) {\n return { step: ref.slice(0, at), name: ref.slice(at + marker.length) };\n }\n const dot = ref.lastIndexOf(\".\");\n if (dot <= 0) return { name: ref };\n return { step: ref.slice(0, dot), name: ref.slice(dot + 1) };\n}\n\nfunction mention(id: string, label: string): AnyRecord {\n return { type: \"VariablesMention\", attrs: { id, label, mentionSuggestionChar: \"{{\" } };\n}\n\n/** \"servicio_deseado\" → \"Servicio Deseado\" — the dashboard's display convention. */\nfunction titleize(value: string): string {\n return value\n .split(/[_-]+/)\n .filter(Boolean)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(\" \");\n}\n\nfunction resolveField(tree: AnyRecord, ref: string): AnyRecord {\n const { step, name } = splitRef(ref, \"customForm\");\n const owners = fieldOwners(tree);\n const inventory = owners\n .map((owner) => ` ${owner.name} (${owner.id}): ${owner.fields.join(\", \") || \"(no fields)\"}`)\n .join(\"\\n\");\n\n const candidates = owners.filter(\n (owner) => owner.fields.includes(name) && (!step || owner.name === step || owner.id === step),\n );\n if (candidates.length === 0) {\n throw new MappingError(`Form field \"${ref}\" does not exist in this form.`, inventory);\n }\n // Two steps can legitimately own a field with the same name. Picking one would\n // wire the mapping to whichever happened to come first in the tree.\n if (candidates.length > 1) {\n throw new MappingError(\n `Form field \"${name}\" exists on ${candidates.length} steps — say which: field:<step>.${name}`,\n candidates.map((owner) => ` field:${owner.name}.${name}`).join(\"\\n\"),\n );\n }\n const owner = candidates[0] as FieldOwner;\n // The engine stores every node type's submission under `.customForm.`\n // (`controller.ts`, `wire.ts`), so this prefix is not the node's type.\n return mention(`${owner.id}.customForm.${name}`, `${owner.name} => ${titleize(name)}`);\n}\n\nfunction resolveTracking(name: string): AnyRecord {\n const id = `tracking.${name}`;\n const known = trackingFieldIds();\n if (known && !known.has(id)) {\n const near = [...known].filter((candidate) => candidate.includes(name.split(\"_\")[0] ?? name)).slice(0, 8);\n throw new MappingError(\n `\\`${id}\\` is not a tracking variable.`,\n near.length > 0\n ? `Close matches: ${near.join(\", \")}`\n : \"See references/autofill-and-variables.md § Built-in Tracking Variables.\",\n );\n }\n // Tracking and global mentions carry the id as their own label — that is what\n // the dashboard editor writes, and what the renderer displays.\n return mention(id, id);\n}\n\nfunction resolveGlobal(tree: AnyRecord, name: string): AnyRecord {\n const globals = (tree.globalVariables as AnyRecord[] | undefined) ?? [];\n const match = globals.find((variable) => variable?.name === name || variable?.id === name);\n if (!match) {\n throw new MappingError(\n `No global variable named \"${name}\" on this form.`,\n globals.length > 0\n ? `Defined: ${globals.map((variable) => String(variable.name)).join(\", \")}`\n : \"This form defines none. Globals live on the first node only — see references/autofill-and-variables.md § Global Variables.\",\n );\n }\n const id = `global.${String(match.id)}`;\n return mention(id, id);\n}\n\nfunction resolveCode(tree: AnyRecord, ref: string): AnyRecord {\n const { step, name } = splitRef(ref, \"codeExecution\");\n const owners = walkNodes(tree).flatMap((node) => {\n const exposed = ((externalOf(node).codeExecution as AnyRecord | undefined)?.exposedValues ?? []) as AnyRecord[];\n const names = exposed.map((value) => value?.name).filter((value): value is string => typeof value === \"string\");\n return names.length > 0 ? [{ id: String(node.id ?? \"\"), name: String(node.name ?? \"step\"), names }] : [];\n });\n\n const candidates = owners.filter(\n (owner) => owner.names.includes(name) && (!step || owner.name === step || owner.id === step),\n );\n if (candidates.length !== 1) {\n throw new MappingError(\n candidates.length === 0\n ? `No codeExecution exposes \"${ref}\" on this form.`\n : `\"${name}\" is exposed by ${candidates.length} steps — say which: code:<step>.${name}`,\n owners.length > 0\n ? owners.map((owner) => ` ${owner.name} (${owner.id}): ${owner.names.join(\", \")}`).join(\"\\n\")\n : \"No step on this form exposes any codeExecution value.\",\n );\n }\n const owner = candidates[0] as { id: string; name: string };\n // Exposed values live under `.codeExecution.`, NOT `.customForm.` — the same\n // id under the wrong segment resolves to empty in every CRM payload.\n return mention(`${owner.id}.codeExecution.${name}`, `${owner.name} => ${titleize(name)}`);\n}\n\n/**\n * Build the AutofillDoc a mapping's `value` holds.\n *\n * A single mention keeps its trailing space: that is byte-for-byte what the\n * dashboard's editor produces, and matching it means a mapping written here and\n * one written there are indistinguishable. A multi-part expression emits exactly\n * the parts given, because an injected space would corrupt `first + last`.\n */\nexport function buildValueDoc(tree: AnyRecord, expression: string): AnyRecord {\n const parts = parseValueExpression(expression);\n const content = parts.map((part) => {\n switch (part.kind) {\n case \"text\":\n return { type: \"text\", text: part.text };\n case \"tracking\":\n return resolveTracking(part.name);\n case \"global\":\n return resolveGlobal(tree, part.name);\n case \"code\":\n return resolveCode(tree, part.ref);\n default:\n return resolveField(tree, part.ref);\n }\n });\n\n const single = content.length === 1 && parts[0]?.kind !== \"text\";\n return {\n type: \"doc\",\n content: [{ type: \"paragraph\", content: single ? [...content, { type: \"text\", text: \" \" }] : content }],\n };\n}\n","/**\n * Build a side effect's `fieldMapping` / `columnMapping` from a short spec.\n *\n * Why this exists. A single mapped field is a ~28-line ProseMirror document:\n *\n * { \"objectTypeId\": \"0-1\", \"fieldType\": \"email\", \"fieldName\": \"email\",\n * \"value\": { \"type\": \"doc\", \"content\": [ { \"type\": \"paragraph\", \"content\": [\n * { \"type\": \"VariablesMention\", \"attrs\": {\n * \"id\": \"<nodeId>.customForm.<formField>\",\n * \"label\": \"<Node Name> => <Form Field>\",\n * \"mentionSuggestionChar\": \"{{\" } },\n * { \"type\": \"text\", \"text\": \" \" } ] } ] } }\n *\n * An eight-field CRM mapping is ~230 lines of hand-emitted JSON per form, in\n * which the only information is eight pairs of names. In one real session two\n * forms cost ~460 lines — written once, lost, and written again by hand.\n *\n * It also removes the failure mode those lines invite. `attrs.id` is\n * `<owning node's id>.customForm.<field>`: get the node wrong, or the field name\n * subtly wrong, and the mapping is structurally valid, ships, and silently sends\n * an empty value forever. This resolves the node id from the tree and refuses a\n * form field that does not exist.\n *\n * What it deliberately does NOT do: choose the destination. The CRM-side names\n * (`firstname`, a sheet column) describe an account only `request_flow_input`\n * can see. Configure the side effect first, read the real names back off that\n * call's own result, then map.\n *\n * This file owns the DESTINATION half — which record shape each side-effect type\n * reads, and what it refuses to guess. What goes in `value` is the other half,\n * and it lives in `value-expression.ts`.\n *\n * ## A mapping accumulates, so a write merges\n *\n * Every slot merges with what is already in it, addressed by destination name:\n * re-mapping a name overwrites it in place, a new name is appended, and a name\n * this call did not mention is left alone. `MapOptions.replace` is the opt-in\n * for the other reading, and it is the only way to remove a mapping.\n *\n * Merging is the default because building a mapping is not one act. The\n * documented order is configure the destination, read the real field names back,\n * then map — and in practice that means several calls, because the names arrive\n * in batches and some of them need a field type the first call did not have.\n * Replacing on every call turned \"add the ninth field\" into \"delete the other\n * eight\", with nothing said. That is this file's own failure mode, one level up:\n * a mapping that is structurally valid, ships, and delivers nothing.\n *\n * ## Destination metadata is derived, never defaulted\n *\n * A CRM mapping carries more than a pair of names: `fieldType`, `objectTypeId`,\n * `entityType`, `isCustomField`. Every one of them is a fact about the connected\n * account, and every one is required by the record the engine reads — so there\n * are exactly two honest ways to fill them, and inventing a plausible value is\n * not one. Either the caller hands over the destination's own field catalog\n * (`MapOptions.destinationFields`, which `map.ts` reads off the account) and\n * they are DERIVED, or the mapping states them and they are declared. Anything\n * else is refused.\n *\n * That order matters for how much work the agent does. Deriving is both less\n * work and more accurate than being told, so a caller that can read the\n * destination should: the agent then writes `firstname=nombre` and the types\n * take care of themselves.\n *\n * Pure — every function here takes a decoded tree and returns data, so the\n * refusals are unit-tested without a filesystem. Reading a destination's\n * catalog is I/O and therefore lives in `map.ts`.\n */\n\nimport { buildValueDoc } from \"./value-expression.ts\";\n\ntype AnyRecord = Record<string, unknown>;\n\n/** A refusal the caller turns into a `{ ok: false }` envelope with a `fix`. */\nexport class MappingError extends Error {\n readonly fix: string | undefined;\n constructor(message: string, fix?: string) {\n super(message);\n this.name = \"MappingError\";\n this.fix = fix;\n }\n}\n\n/**\n * A destination addressed by a list of records: one entry per mapped field.\n *\n * Two families share it. The CRM/sheet family (`fieldMapping`, `columnMapping`)\n * carries destination metadata alongside the value; the `PayloadKey` family\n * (`payloadKeys`, `eventParams`, `eventProperties`, `dataLayerParams`,\n * `goalParams`) is just `{ key, value }`.\n */\ntype ListShape = {\n kind: \"list\";\n key: string;\n /**\n * The object the list hangs off, when it is not the side effect itself.\n *\n * Only `email` needs it — its keys live at `body.fields`, and only while\n * `body.format` is `\"json\"`. That one level of nesting is why this command\n * used to refuse `email` outright, which left the single most common\n * notification side effect as the one place an agent still hand-wrote a\n * ProseMirror document per field.\n */\n under?: string;\n addressedBy: string;\n entities?: readonly string[];\n needsFieldType?: boolean;\n needsIsCustom?: boolean;\n /** Where the per-mapping field types come from, for the refusal that asks for one. */\n fieldTypeSource?: string;\n};\n\n/**\n * A destination addressed by a fixed set of named slots, each an AutofillDoc.\n *\n * Meta advanced matching, Google Ads enhanced conversions, TikTok identify,\n * LinkedIn/X user matching, Pinterest enhanced matching. The key set is closed\n * and defined by the platform, so a name outside it is a typo, not a field.\n */\ntype RecordShape = { kind: \"record\"; key: string; allowed: readonly string[] };\n\n/** A single AutofillDoc sitting directly on the side effect (`value`, `currency`, …). */\ntype ScalarShape = { kind: \"scalar\"; keys: readonly string[] };\n\ntype MappingShape = ListShape | RecordShape | ScalarShape;\n\nconst PAYLOAD = (key: string): ListShape => ({ kind: \"list\", key, addressedBy: \"key\" });\n\nconst META_MATCHING = [\"em\", \"fn\", \"ln\", \"ph\", \"external_id\", \"ge\", \"db\", \"ct\", \"st\", \"zp\", \"country\"] as const;\nconst ADS_MATCHING = [\n \"email\",\n \"phone_number\",\n \"first_name\",\n \"last_name\",\n \"street\",\n \"city\",\n \"region\",\n \"postal_code\",\n \"country\",\n] as const;\n\n/**\n * Every slot each side-effect type can have a value mapped into, in the order\n * `--map` defaults to.\n *\n * This started as five CRM entries, which meant `baker flows map` refused\n * eleven of the sixteen mappable types — including the two most common things\n * in a real workspace: a webhook body and a Meta pixel's parameters. Its\n * refusal also said, in as many words, that `httpWebhook` and `zapier` \"carry\n * the whole submission and do not address individual destination fields\", which\n * is not true of either: both have `payloadKeys`, and a real form was already\n * using fourteen of them.\n *\n * A type with more than one slot takes `--into <key>` to pick; without it the\n * first is used, and the response names the others.\n */\nexport const MAPPING_SLOTS: Record<string, readonly MappingShape[]> = {\n shopifyCustomer: [\n {\n kind: \"record\",\n key: \"customer\",\n allowed: [\"email\", \"phone\", \"firstName\", \"lastName\", \"acceptsEmailMarketing\", \"acceptsSmsMarketing\"],\n },\n ],\n googleSpreadsheet: [{ kind: \"list\", key: \"columnMapping\", addressedBy: \"column\" }],\n hubspotForm: [\n {\n kind: \"list\",\n key: \"fieldMapping\",\n addressedBy: \"fieldName\",\n needsFieldType: true,\n fieldTypeSource:\n \"Pass --hubspot-form <formGuid> and this command reads every property's type off the form itself — the guid is the `formGuid` in the `destination` request_flow_input returned. `baker hubspot forms view <formGuid>` prints the same list if you want to see it.\",\n },\n ],\n pipedrive: [\n {\n kind: \"list\",\n key: \"fieldMapping\",\n addressedBy: \"fieldKey\",\n entities: [\"person\", \"organization\", \"lead\"],\n needsFieldType: true,\n needsIsCustom: true,\n },\n ],\n goHighlevelContact: [\n {\n kind: \"list\",\n key: \"fieldMapping\",\n addressedBy: \"fieldKey\",\n entities: [\"business\", \"contact\", \"opportunity\"],\n needsFieldType: true,\n needsIsCustom: true,\n },\n ],\n crmble: [\n { kind: \"list\", key: \"fieldMapping\", addressedBy: \"fieldId\", entities: [\"contact\", \"lead\"], needsFieldType: true },\n ],\n\n email: [{ ...PAYLOAD(\"fields\"), under: \"body\" }],\n zapier: [PAYLOAD(\"payloadKeys\")],\n httpWebhook: [PAYLOAD(\"payloadKeys\")],\n googleTagManager: [PAYLOAD(\"dataLayerParams\")],\n googleAnalytics: [PAYLOAD(\"eventParams\")],\n posthog: [PAYLOAD(\"eventParams\")],\n amplitude: [PAYLOAD(\"eventProperties\")],\n hubspot: [PAYLOAD(\"eventProperties\")],\n vwo: [PAYLOAD(\"eventProperties\")],\n code: [PAYLOAD(\"eventProperties\")],\n datafast: [PAYLOAD(\"goalParams\")],\n\n meta: [PAYLOAD(\"eventParams\"), { kind: \"record\", key: \"advancedMatching\", allowed: META_MATCHING }],\n chatgptAds: [\n PAYLOAD(\"eventParams\"),\n {\n kind: \"record\",\n key: \"advancedMatching\",\n allowed: [\"em\", \"ph\", \"fn\", \"ln\", \"external_id\", \"ct\", \"st\", \"zp\", \"country\"],\n },\n ],\n tiktok: [\n PAYLOAD(\"eventParams\"),\n { kind: \"record\", key: \"identify\", allowed: [\"email\", \"phone_number\", \"external_id\"] },\n ],\n pinterest: [PAYLOAD(\"eventParams\"), { kind: \"record\", key: \"enhancedMatching\", allowed: [\"em\", \"hashed_maids\"] }],\n googleAds: [\n { kind: \"record\", key: \"enhancedConversions\", allowed: ADS_MATCHING },\n { kind: \"scalar\", keys: [\"value\", \"currency\", \"transactionId\"] },\n ],\n linkedinInsightTag: [\n { kind: \"record\", key: \"userMatching\", allowed: [\"em\", \"fn\", \"ln\", \"title\", \"companyName\", \"country\"] },\n { kind: \"scalar\", keys: [\"value\", \"currency\"] },\n ],\n twitterAds: [\n { kind: \"record\", key: \"userMatching\", allowed: [\"em\", \"ph\"] },\n { kind: \"scalar\", keys: [\"value\", \"currency\"] },\n ],\n};\n\n/**\n * The types that genuinely address nothing, and why — so the refusal can say it.\n *\n * Exported for `flow-catalog-coverage.test.ts`, which asserts that this and\n * `MAPPING_SLOTS` between them classify EVERY side-effect type the catalog\n * defines, exactly once. That gate is the reason a claim about this file can be\n * trusted: `email` used to live here, moved to `MAPPING_SLOTS` when `body.fields`\n * became mappable, and left behind prose elsewhere still describing it as\n * unmappable. A type in neither list refuses with \"not a side-effect type this\n * workspace's flow engine defines\" — which is false, and unanswerable.\n */\nexport const UNMAPPABLE: Record<string, string> = {\n hotjar: \"A Hotjar event carries only its name.\",\n clarity: \"A Clarity custom tag carries only its name.\",\n};\n\n/** How a slot is named everywhere the agent sees it — qualified when it is nested. */\nfunction slotName(shape: MappingShape): string {\n if (shape.kind === \"scalar\") return shape.keys.join(\"/\");\n if (shape.kind === \"list\" && shape.under) return `${shape.under}.${shape.key}`;\n return shape.key;\n}\n\n/**\n * The slot to map into: the one named by `--into`, or the first.\n * Refuses rather than guessing between a real slot and a name that is not one.\n */\nexport function shapeFor(type: string, into?: string): MappingShape {\n const slots = MAPPING_SLOTS[type];\n if (!slots) {\n const why = UNMAPPABLE[type];\n throw new MappingError(\n `Side effect \"${type}\" has no mappable field.`,\n why ?? `\"${type}\" is not a side-effect type this workspace's flow engine defines.`,\n );\n }\n if (!into) return slots[0] as MappingShape;\n const chosen = slots.find((slot) =>\n slot.kind === \"scalar\"\n ? slot.keys.includes(into) || into === \"scalar\"\n : slot.key === into || slotName(slot) === into,\n );\n if (!chosen) {\n throw new MappingError(\n `\"${into}\" is not a mappable slot on a ${type} side effect.`,\n `Slots on ${type}: ${slots.map(slotName).join(\", \")}`,\n );\n }\n return chosen;\n}\n\n/**\n * Whether this slot's names come from the connected account, or from the agent.\n *\n * The distinction decides what an unconfigured destination means. A sheet\n * column, a HubSpot property, a Pipedrive field key — those exist only in an\n * account the agent cannot see, so writing them before `request_flow_input` has\n * run means inventing them, and an invented destination is valid JSON that\n * ships and drops every submission. A webhook's `payloadKeys` and a pixel's\n * `eventParams` are the opposite: the agent picks those names (or the platform\n * fixes them), so they are perfectly authorable before the endpoint is set.\n */\nexport function namesComeFromAccount(shape: MappingShape): boolean {\n return shape.kind === \"list\" && shape.addressedBy !== \"key\";\n}\n\n/**\n * What can be mapped into a side effect, and — the part that is not guessable —\n * where the legal keys on the LEFT of each mapping come from.\n *\n * There are three different answers, and reading the wrong one produces a\n * mapping that is valid JSON and silently delivers nothing:\n *\n * closed the platform fixes the names (`em`, `ph`, `postal_code`). Anything\n * else is a typo, and they are listed here in full.\n * yours the keys are whatever the receiving system expects — a Make\n * scenario's field names, a GA4 parameter. Nobody but the user knows\n * them, but nothing validates them either, so you write what you were told.\n * account a sheet column, a HubSpot property, a Pipedrive field key. These\n * exist only in the connected account, so they come back from\n * `request_flow_input` and cannot be known before it runs.\n *\n * Exposed so the discovery path is a plain read rather than a wrong guess: the\n * agent used to learn a closed set only by naming a key outside it.\n */\nexport type SlotDescription = {\n slot: string;\n addressedBy: string;\n keysFrom: \"closed\" | \"yours\" | \"account\";\n keys?: readonly string[];\n note: string;\n /** How to get the per-mapping field types, for a slot that stores one. */\n fieldTypes?: string;\n};\n\nexport function describeSlots(type: string): SlotDescription[] {\n return (MAPPING_SLOTS[type] ?? []).map((shape) => {\n if (shape.kind === \"record\") {\n return {\n slot: shape.key,\n addressedBy: \"one of a closed set\",\n keysFrom: \"closed\" as const,\n keys: shape.allowed,\n note: `${type} defines these names; any other is refused.`,\n };\n }\n if (shape.kind === \"scalar\") {\n return {\n slot: shape.keys.join(\"/\"),\n addressedBy: \"the field's own name\",\n keysFrom: \"closed\" as const,\n keys: shape.keys,\n note: \"Each is a single value on the side effect, mapped like any other.\",\n };\n }\n if (shape.addressedBy === \"key\") {\n return {\n slot: slotName(shape),\n addressedBy: \"key\",\n keysFrom: \"yours\" as const,\n note: \"You name these — they are what the receiving system expects. Ask the user if you do not know them.\",\n };\n }\n return {\n slot: slotName(shape),\n addressedBy: shape.addressedBy,\n keysFrom: \"account\" as const,\n note: \"These live in the connected account. Read them off the request_flow_input result; they cannot be guessed.\",\n ...(shape.needsFieldType ? { fieldTypes: shape.fieldTypeSource ?? FIELD_TYPE_FROM_INPUT } : {}),\n };\n });\n}\n\n/** Where a per-mapping field type comes from when the shape names no better source. */\nconst FIELD_TYPE_FROM_INPUT =\n \"Each mapping stores a field type. They come back from request_flow_input with the field list — write one on the LEFT: <field>:<fieldType>=<value>.\";\n\n/** Every slot a type offers, for the hint that tells the agent what else it could map. */\nexport function otherSlots(type: string, used: MappingShape): string[] {\n return (MAPPING_SLOTS[type] ?? []).filter((slot) => slot !== used).map(slotName);\n}\n\n/**\n * One destination property as the connected account describes it.\n *\n * The point of carrying this is that `fieldType` stops being something the agent\n * has to know. It is a destination-side fact — HubSpot's own answer for that\n * property — so the only two honest ways to fill it are to read it off the\n * account or to be told it explicitly. Guessing a plausible-looking one is the\n * third option, and it is the one that ships: the key the engine builds is\n * `<objectTypeId>.<fieldType>.<fieldName>`, and a wrong `fieldType` on a date\n * property silently skips the YYYY-MM-DD coercion HubSpot requires.\n */\nexport type DestinationField = { fieldType: string; objectTypeId?: string };\n\nexport type MapOptions = {\n /** Which slot to map into, when the type has more than one. */\n into?: string | undefined;\n entity?: string | undefined;\n isCustomField?: boolean | undefined;\n objectType?: string | undefined;\n /**\n * The destination's own field catalog, keyed by destination field name, when\n * the caller was able to read it. Present ⇒ a per-mapping field type is\n * derived rather than demanded, and a name that is not on the destination is\n * refused with the ones that are.\n */\n destinationFields?: ReadonlyMap<string, DestinationField> | undefined;\n /**\n * Drop the mappings whose destination field is no longer on the account.\n *\n * The repair for a deleted CRM property, and the reason it is not `--replace`:\n * HubSpot refuses the WHOLE submission when it names a field it does not\n * have, so a Form with one dead mapping delivers nothing — and the only tool\n * for removing one was `--replace`, which drops everything the call does not\n * name. Repairing seven dead mappings that way meant first reconstructing the\n * other twenty correctly, from a file the agent had to read and re-emit, or\n * silently deleting them.\n *\n * This removes exactly the entries the destination cannot accept and touches\n * nothing else, so the safe move and the small move are the same move.\n * Requires `destinationFields`: without the account's own catalog \"missing\n * from the destination\" has no answer, and the available wrong answer is\n * \"drop them all\".\n */\n pruneMissing?: boolean | undefined;\n /**\n * Write the slot exactly as given, dropping every mapping already in it.\n *\n * Off by default, because the default has to be the one that cannot lose\n * work. A mapping accumulates — read a destination, map what you can name,\n * come back for the rest — and a call that quietly replaced the slot turned\n * \"add a ninth field\" into \"delete eight\". The reverse mistake is visible\n * the moment you look: an entry you meant to remove is still listed.\n *\n * `--from` is the one place replacing is the natural reading, since a\n * mapping file states the whole mapping — so it can set `\"replace\": true`.\n */\n replace?: boolean | undefined;\n};\n\ntype Spec = { raw: string; destField: string; fieldType?: string | undefined; expression: string };\n\n/**\n * `<destField>[:<fieldType>]=<value expression>`\n *\n * The field type sits with the destination rather than the value, for two\n * reasons: it IS a destination-side property (a HubSpot `single_line_text`, a\n * Pipedrive `varchar`), and on the right it would collide with the value\n * grammar's `field:` / `tracking:` / `global:` / `code:` prefixes.\n */\nexport function parseMapSpec(raw: string): Spec {\n const eq = raw.indexOf(\"=\");\n if (eq <= 0 || eq === raw.length - 1) {\n throw new MappingError(\n `--map \"${raw}\" must be <destField>[:<fieldType>]=<value>`,\n 'Value: a form field (`nombre`), `tracking:utm_source`, `global:Name`, `code:name`, a \"literal\", or those joined with `+`.',\n );\n }\n const left = raw.slice(0, eq).trim();\n const expression = raw.slice(eq + 1).trim();\n const colon = left.indexOf(\":\");\n const destField = (colon > 0 ? left.slice(0, colon) : left).trim();\n const fieldType = colon > 0 ? left.slice(colon + 1).trim() : \"\";\n if (!destField) throw new MappingError(`--map \"${raw}\" names no destination field.`);\n return { raw, destField, fieldType: fieldType || undefined, expression };\n}\n\nfunction sheetEntry(spec: Spec, value: AnyRecord): AnyRecord {\n if (!/^[A-Z]{1,3}$/.test(spec.destField)) {\n throw new MappingError(\n `--map \"${spec.raw}\": a Google Sheet is addressed by COLUMN, so the left side must be a column letter (A, B, … AA), got \"${spec.destField}\".`,\n \"Read the real destination back from the configured side effect first — a column letter is a guess until a spreadsheet is picked.\",\n );\n }\n return { column: spec.destField, value };\n}\n\n/**\n * The destination property this mapping addresses, when the caller read the\n * destination's own catalog.\n *\n * Refusing an unknown name is the whole reason to carry the catalog at all. A\n * destination field nothing validates is the same failure as a wrong `attrs.id`\n * on the value side: structurally valid, ships, delivers nothing forever.\n */\nfunction destinationField(spec: Spec, options: MapOptions): DestinationField | undefined {\n const catalog = options.destinationFields;\n if (!catalog) return undefined;\n const match = catalog.get(spec.destField);\n if (match) return match;\n throw new MappingError(\n `--map \"${spec.raw}\": the destination has no field called \"${spec.destField}\".`,\n `Fields on it: ${[...catalog.keys()].join(\", \") || \"(none)\"}`,\n );\n}\n\n/**\n * The per-mapping field type: taken from the destination when we can read it,\n * from the spec when we were told, and refused when neither.\n *\n * Derived first, on purpose. The type is a destination-side fact, so reading it\n * off the account is both less work for the caller and MORE accurate than being\n * told — an explicit `:type` is kept as the override for a destination this\n * command cannot reach.\n */\nfunction fieldTypeFor(type: string, shape: ListShape, spec: Spec, known: DestinationField | undefined): string {\n const resolved = spec.fieldType ?? known?.fieldType;\n if (resolved) return resolved;\n throw new MappingError(\n `--map \"${spec.raw}\": ${type} stores a field type per mapping, and \"${spec.destField}\" has none — write it on the left: <field>:<fieldType>=<value>.`,\n shape.fieldTypeSource ?? FIELD_TYPE_FROM_INPUT,\n );\n}\n\n/**\n * The two answers a CRM shape needs beyond the field type, and will not default.\n *\n * Each decides whether the write lands or is accepted and dropped: which object\n * it lands on, and whether the key is looked up as a custom field. Both are\n * destination-side facts that come back from `request_flow_input`, so refusing\n * is the only honest response to their absence.\n *\n * The entity check is skipped for a shape that declares no `entities` —\n * `hubspotForm` addresses its object through `objectTypeId`, which rides on each\n * mapping rather than on the call.\n */\nfunction assertCrmOptions(type: string, shape: ListShape, options: MapOptions): void {\n const entities = shape.entities;\n if (entities) {\n if (!options.entity) {\n throw new MappingError(\n `${type} addresses a specific object, so --entity is required (one of: ${entities.join(\", \")}).`,\n \"Which object a value lands on is a destination-side fact — read it back from the configured side effect, do not assume.\",\n );\n }\n if (!entities.includes(options.entity)) {\n throw new MappingError(\n `--entity \"${options.entity}\" is not valid for ${type} — expected one of: ${entities.join(\", \")}.`,\n );\n }\n }\n if (shape.needsIsCustom && options.isCustomField === undefined) {\n throw new MappingError(\n `${type} looks a key up differently for custom and standard fields, so pass --custom or --standard.`,\n \"Mapping a custom field as standard (or the reverse) is accepted and then dropped. The field list from request_flow_input says which each one is.\",\n );\n }\n}\n\nfunction buildEntry(type: string, shape: ListShape, spec: Spec, value: AnyRecord, options: MapOptions): AnyRecord {\n if (shape.key === \"columnMapping\") {\n return sheetEntry(spec, value);\n }\n\n // The PayloadKey family is the plain shape: a name and a value, nothing else\n // to get wrong. Refuse the CRM flags here rather than writing a record with\n // keys the engine does not read.\n if (shape.addressedBy === \"key\") {\n if (spec.fieldType) {\n throw new MappingError(\n `--map \"${spec.raw}\": a ${type} ${shape.key} entry is just a name and a value — it takes no field type.`,\n `Write it as ${spec.destField}=${spec.expression}`,\n );\n }\n return { key: spec.destField, value };\n }\n\n const known = destinationField(spec, options);\n\n if (type === \"hubspotForm\") {\n // `objectTypeId` and `fieldType` are both HubSpot's answer, not ours. The\n // engine concatenates them into `<objectTypeId>.<fieldType>.<fieldName>`,\n // which is the key the dashboard's own picker writes — so a mapping built\n // here and one built there have to be indistinguishable, or HubSpot's\n // \"add the required fields\" list offers a field that is already mapped.\n // `0-1` (contact) is the fallback the engine itself uses for a key it\n // cannot split, so it is the one default that changes no behaviour.\n return {\n objectTypeId: options.objectType ?? known?.objectTypeId ?? \"0-1\",\n fieldType: fieldTypeFor(type, shape, spec, known),\n fieldName: spec.destField,\n value,\n };\n }\n\n // Everything left is the CRM `fieldMapping` family, and every one of those\n // records types `fieldType` as required — so it is resolved, never optional.\n assertCrmOptions(type, shape, options);\n return {\n entityType: options.entity,\n fieldType: fieldTypeFor(type, shape, spec, known),\n ...(shape.needsIsCustom ? { isCustomField: options.isCustomField } : {}),\n [shape.addressedBy]: spec.destField,\n value,\n };\n}\n\n/**\n * What a built mapping is, and where it goes.\n *\n * `patch` is spliced onto the side effect as-is, so a list slot yields\n * `{ payloadKeys: [...] }` and a record slot yields the whole record with the\n * mapped slots filled and the rest left `null`. Merging rather than replacing\n * matters for a record: every key is required by the engine, so writing only\n * the mapped ones would produce a side effect that no longer typechecks.\n *\n * `kept` is how many mappings were already in the slot and survive this call.\n * It exists so the response can say so out loud — a number that moves without\n * being named is the shape of every silent-loss bug this file is about.\n */\nexport type BuiltMapping = {\n key: string;\n count: number;\n kept: number;\n /** Destination names removed by `pruneMissing`, named so the caller can print each. */\n dropped: string[];\n patch: AnyRecord;\n};\n\n/**\n * Splice a list into the object that owns it, keeping that object's other keys.\n *\n * `email` is the one nested case, and the key it must not lose is `body.format`:\n * the engine reads `{ format: \"json\", fields }` as a discriminated union, so a\n * patch that replaced `body` wholesale would drop the discriminator and the\n * side effect would stop typechecking.\n */\nfunction listPatch(shape: ListShape, sideEffect: AnyRecord, entries: AnyRecord[]): AnyRecord {\n if (!shape.under) return { [shape.key]: entries };\n const owner = (sideEffect[shape.under] ?? {}) as AnyRecord;\n return { [shape.under]: { ...owner, [shape.key]: entries } };\n}\n\n/** The list already in a slot, skipping anything that is not a record to merge with. */\nfunction existingEntries(shape: ListShape, sideEffect: AnyRecord): AnyRecord[] {\n const owner = shape.under ? sideEffect[shape.under] : sideEffect;\n if (!owner || typeof owner !== \"object\") return [];\n const list = (owner as AnyRecord)[shape.key];\n if (!Array.isArray(list)) return [];\n return list.filter((entry): entry is AnyRecord => Boolean(entry) && typeof entry === \"object\");\n}\n\n/**\n * Merge new mappings into the ones already in the slot, addressed by name.\n *\n * A mapping is built up over several calls in practice — you configure the\n * destination, map the fields you can name, read the rest back, map those —\n * so replacing the slot on every call deleted the earlier ones with nothing\n * said. That is the same failure the whole command exists to prevent\n * (a mapping that is valid, ships, and delivers nothing), one level up.\n *\n * Address, not position: `shape.addressedBy` is the key that names the\n * destination (`key`, `column`, `fieldName`, `fieldKey`, `fieldId`), so\n * re-mapping the same destination overwrites it IN PLACE and a new one is\n * appended. Order therefore stays stable across calls, which matters for a\n * Google Sheet, where the column order is the row the client reads.\n *\n * An existing entry with no address at all is kept as-is: it is not something\n * this call can be addressing, and dropping it would be the silent loss again.\n *\n * `kept` counts the entries that were already there and this call did not touch,\n * so it is derived from what happened rather than from the spec count — two\n * `--map` flags naming one destination are one written mapping, not two.\n */\nfunction mergeEntries(\n shape: ListShape,\n existing: AnyRecord[],\n incoming: AnyRecord[],\n): { entries: AnyRecord[]; written: number; kept: number } {\n const address = (entry: AnyRecord) => {\n const value = entry[shape.addressedBy];\n return typeof value === \"string\" ? value : null;\n };\n const entries = [...existing];\n const overwritten = new Set<number>();\n for (const entry of incoming) {\n const name = address(entry);\n const at = name === null ? -1 : entries.findIndex((candidate) => address(candidate) === name);\n if (at === -1) {\n entries.push(entry);\n continue;\n }\n entries[at] = entry;\n if (at < existing.length) overwritten.add(at);\n }\n const kept = existing.length - overwritten.size;\n return { entries, written: entries.length - kept, kept };\n}\n\n/**\n * An email's mapped keys exist only in its JSON body shape.\n *\n * `{ format: \"body\", content: <AutofillDoc> }` is one written message, not named\n * keys — mapping into it would produce a `fields` array the engine never reads.\n * Refuse rather than switch the format: which of the two an email sends is the\n * agent's decision about the notification, not this command's to make.\n */\nfunction assertMappableOwner(type: string, shape: ListShape, sideEffect: AnyRecord): void {\n if (shape.under !== \"body\") return;\n const format = ((sideEffect.body ?? {}) as AnyRecord).format;\n if (format !== undefined && format !== \"json\") {\n throw new MappingError(\n `This ${type} side effect sends \\`body.format: \"${String(format)}\"\\`, which is one written message rather than named keys.`,\n 'Set `body` to `{ \"format\": \"json\", \"fields\": [] }` first if you want mapped keys, or write the message in `body.content` and map nothing.',\n );\n }\n}\n\nfunction buildList(\n tree: AnyRecord,\n type: string,\n shape: ListShape,\n sideEffect: AnyRecord,\n specs: string[],\n options: MapOptions,\n): BuiltMapping {\n assertMappableOwner(type, shape, sideEffect);\n const incoming = specs.map((raw) => {\n const spec = parseMapSpec(raw);\n return buildEntry(type, shape, spec, buildValueDoc(tree, spec.expression), options);\n });\n const present = options.replace === true ? [] : existingEntries(shape, sideEffect);\n const { kept: existing, dropped } = pruneAbsent(shape, present, options);\n const { entries, written, kept } = mergeEntries(shape, existing, incoming);\n return { key: slotName(shape), count: written, kept, dropped, patch: listPatch(shape, sideEffect, entries) };\n}\n\n/**\n * Split the mappings already in the slot into the ones the destination still\n * has and the ones it does not.\n *\n * An entry with no address at all is kept, for the same reason `mergeEntries`\n * keeps it: it is not something this call can be addressing, and dropping it\n * would be the silent loss the whole module exists to prevent.\n */\nfunction pruneAbsent(\n shape: ListShape,\n existing: AnyRecord[],\n options: MapOptions,\n): { kept: AnyRecord[]; dropped: string[] } {\n if (options.pruneMissing !== true) return { kept: existing, dropped: [] };\n\n const catalog = options.destinationFields;\n if (!catalog) {\n throw new MappingError(\n \"--prune-missing needs the destination's own field list, and it could not be read.\",\n \"Name the destination so its fields can be read — today that is --hubspot-form <formGuid>, the only destination whose catalog this command can fetch. `baker flows show <slug>` names the side effect and returns the request_flow_input call that carries the guid.\",\n );\n }\n\n const kept: AnyRecord[] = [];\n const dropped: string[] = [];\n for (const entry of existing) {\n const name = entry[shape.addressedBy];\n if (typeof name !== \"string\" || catalog.has(name)) {\n kept.push(entry);\n continue;\n }\n dropped.push(name);\n }\n return { kept, dropped };\n}\n\nfunction buildRecord(\n tree: AnyRecord,\n type: string,\n shape: RecordShape,\n sideEffect: AnyRecord,\n specs: string[],\n options: MapOptions,\n): BuiltMapping {\n const existing = (options.replace === true ? {} : (sideEffect[shape.key] ?? {})) as AnyRecord;\n const record: AnyRecord = Object.fromEntries(shape.allowed.map((slot) => [slot, existing[slot] ?? null]));\n const filledBefore = shape.allowed.filter((slot) => record[slot] != null);\n const written = new Set<string>();\n for (const raw of specs) {\n const spec = parseMapSpec(raw);\n if (!shape.allowed.includes(spec.destField)) {\n throw new MappingError(\n `\"${spec.destField}\" is not a slot in ${shape.key} on a ${type} side effect.`,\n `${shape.key} slots: ${shape.allowed.join(\", \")}`,\n );\n }\n if (spec.fieldType) {\n throw new MappingError(`--map \"${spec.raw}\": a ${shape.key} slot takes no field type.`);\n }\n record[spec.destField] = buildValueDoc(tree, spec.expression);\n written.add(spec.destField);\n }\n return {\n key: shape.key,\n count: written.size,\n kept: filledBefore.filter((slot) => !written.has(slot)).length,\n dropped: [],\n patch: { [shape.key]: record },\n };\n}\n\nfunction buildScalar(\n tree: AnyRecord,\n type: string,\n shape: ScalarShape,\n sideEffect: AnyRecord,\n specs: string[],\n options: MapOptions,\n): BuiltMapping {\n // `--replace` means the same thing here as everywhere else: the slot ends up\n // exactly what was passed. Each key is typed `AutofillDoc | null`, so the\n // ones this call did not name are cleared rather than left standing.\n const patch: AnyRecord = options.replace === true ? Object.fromEntries(shape.keys.map((key) => [key, null])) : {};\n const written = new Set<string>();\n for (const raw of specs) {\n const spec = parseMapSpec(raw);\n if (!shape.keys.includes(spec.destField)) {\n throw new MappingError(\n `\"${spec.destField}\" is not a mappable field on a ${type} side effect.`,\n `Mappable directly: ${shape.keys.join(\", \")}`,\n );\n }\n if (spec.fieldType) {\n throw new MappingError(`--map \"${spec.raw}\": ${spec.destField} takes no field type.`);\n }\n patch[spec.destField] = buildValueDoc(tree, spec.expression);\n written.add(spec.destField);\n }\n const kept =\n options.replace === true ? 0 : shape.keys.filter((key) => !written.has(key) && sideEffect[key] != null).length;\n return { key: shape.keys.join(\"/\"), count: written.size, kept, dropped: [], patch };\n}\n\n/**\n * Build the mapping a side effect reads, from the form's own tree.\n * Throws `MappingError` for every refusal — nothing is guessed.\n */\nexport function buildFieldMapping(\n tree: AnyRecord,\n sideEffect: AnyRecord,\n specs: string[],\n options: MapOptions = {},\n): BuiltMapping {\n const type = String(sideEffect.type ?? \"\");\n const shape = shapeFor(type, options.into);\n if (shape.kind === \"record\") return buildRecord(tree, type, shape, sideEffect, specs, options);\n if (shape.kind === \"scalar\") return buildScalar(tree, type, shape, sideEffect, specs, options);\n return buildList(tree, type, shape, sideEffect, specs, options);\n}\n"],"mappings":"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","names":["owner"]}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ApiError
|
|
3
|
+
} from "./chunk-HREWXNTO.js";
|
|
4
|
+
import {
|
|
5
|
+
writeJson
|
|
6
|
+
} from "./chunk-WOTDHRNF.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-H7MLHG2I.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":[]}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import {
|
|
2
|
+
RESEARCH_GOOGLE_ADS_MAX_COPY
|
|
3
|
+
} from "./chunk-SMIENBNX.js";
|
|
4
|
+
|
|
5
|
+
// src/commands/research/hints.ts
|
|
6
|
+
var AD_COPY_ROUTE = 'This returns competing domains and their SERP economics \u2014 no ad copy, no headlines, no creative. For a competitor\'s Google ads and their copy: `baker research google-ads <competitor.com> --copy` (Google\'s Ads Transparency Center: every ad, how long it has run, and the text ads\' headline and description). For Meta and LinkedIn: `baker winning-ads advertisers "<brand>"` \u2192 `baker winning-ads search "<brief>" --advertiser-id <id>` \u2192 `baker winning-ads content <adId>` (`primary_text` / `headline` / `cta`, plus the spoken transcript and on-screen text for video). Do not keep querying this command for copy.';
|
|
7
|
+
function noSerpRowsHints(rowCount, queryContext) {
|
|
8
|
+
if (rowCount > 0) {
|
|
9
|
+
return [];
|
|
10
|
+
}
|
|
11
|
+
const defaulted = queryContext.location_is_default || queryContext.language_is_default;
|
|
12
|
+
if (defaulted) {
|
|
13
|
+
return [
|
|
14
|
+
`No rows for ${queryContext.location} / ${queryContext.language} \u2014 the market you did not set. Set --location and --language for the client's actual market and re-run once (\`baker research countries\` / \`baker research languages\` for the accepted codes) before you touch the keyword.`
|
|
15
|
+
];
|
|
16
|
+
}
|
|
17
|
+
return [
|
|
18
|
+
`No rows for ${queryContext.location} / ${queryContext.language}, which you set explicitly. This term has no third-party SERP coverage in that market \u2014 move on rather than re-querying it. For demand signal try \`baker research autocomplete\`; for a competitor's actual terms, \`baker research keywords-for-site <domain>\`.`
|
|
19
|
+
];
|
|
20
|
+
}
|
|
21
|
+
function advertisersHints(rowCount, queryContext) {
|
|
22
|
+
return [...noSerpRowsHints(rowCount, queryContext), AD_COPY_ROUTE];
|
|
23
|
+
}
|
|
24
|
+
function keywordsForSiteHints(rowCount, queryContext, typeFilter) {
|
|
25
|
+
if (rowCount > 0) {
|
|
26
|
+
return [];
|
|
27
|
+
}
|
|
28
|
+
if (typeFilter === "paid" || typeFilter === "organic") {
|
|
29
|
+
return [
|
|
30
|
+
`No rows with --type ${typeFilter} in ${queryContext.location} / ${queryContext.language}. A domain with zero ${typeFilter} keywords in a market is itself the finding \u2014 record it and move on. Confirm once with --type all (nothing at all there means the domain has no SERP coverage, not that it has no ads) instead of re-running with a different --sort or --limit.`
|
|
31
|
+
];
|
|
32
|
+
}
|
|
33
|
+
return noSerpRowsHints(rowCount, queryContext);
|
|
34
|
+
}
|
|
35
|
+
var THIN_ANSWER_CHARS = 600;
|
|
36
|
+
var THIN_SOURCE_COUNT = 2;
|
|
37
|
+
var ESCALATION = {
|
|
38
|
+
medium: "`medium` is a quick lookup, not a search. Re-ask the SAME question once with `--depth high` before concluding the web has nothing on it.",
|
|
39
|
+
high: "`high` already thought hard about this. `--depth xhigh` is the only step left and it can run 15 minutes \u2014 take it only if this answer blocks a deliverable; otherwise record the gap and move on."
|
|
40
|
+
};
|
|
41
|
+
function fetchHints({
|
|
42
|
+
truncated,
|
|
43
|
+
contentChars,
|
|
44
|
+
shownChars
|
|
45
|
+
}) {
|
|
46
|
+
const hints = [];
|
|
47
|
+
if (shownChars < contentChars) {
|
|
48
|
+
hints.push(
|
|
49
|
+
`Showing the first ${shownChars.toLocaleString("en-US")} of ${contentChars.toLocaleString("en-US")} characters. Re-run the same command with \`--full\` for the whole page \u2014 the read is cached for 24h, so it costs no extra time and no extra credit.`
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
if (truncated) {
|
|
53
|
+
hints.push(
|
|
54
|
+
"This page is longer than one read returns, so the end of it is missing. Don't present this as the complete page; if the part you need is further down, fetch the deeper URL directly."
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
return hints;
|
|
58
|
+
}
|
|
59
|
+
function webDepthHints({
|
|
60
|
+
answer,
|
|
61
|
+
sourceCount,
|
|
62
|
+
depth
|
|
63
|
+
}) {
|
|
64
|
+
const thin = answer.length < THIN_ANSWER_CHARS || sourceCount <= THIN_SOURCE_COUNT;
|
|
65
|
+
const escalation = ESCALATION[depth];
|
|
66
|
+
if (!thin || !escalation) {
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
return [`Thin answer (${answer.length} chars, ${sourceCount} source(s)). ${escalation}`];
|
|
70
|
+
}
|
|
71
|
+
function keywordMetricsHints({
|
|
72
|
+
rows,
|
|
73
|
+
asked,
|
|
74
|
+
clickstream,
|
|
75
|
+
queryContext
|
|
76
|
+
}) {
|
|
77
|
+
if (rows.length === 0) {
|
|
78
|
+
return noSerpRowsHints(0, queryContext);
|
|
79
|
+
}
|
|
80
|
+
const provenance = "DataForSEO resells Google's Keyword Planner volume \u2014 planner_search_volume here is the SAME number `baker ads google keywords metrics` returns, not an independent reading of it. Quoting the two as agreeing sources is not corroboration." + (clickstream ? " clickstream_search_volume IS independent (DataForSEO's own panels); when the two disagree, say which one you are quoting." : " For a genuinely independent estimate of demand, re-run with --clickstream (costs 2x), or use first-party data: `baker gsc query` for what already reaches the site, or the account's own search terms.");
|
|
81
|
+
const hints = [provenance];
|
|
82
|
+
const empty = rows.filter((row) => row.search_volume === null).map((row) => row.keyword);
|
|
83
|
+
if (empty.length > 0) {
|
|
84
|
+
hints.push(
|
|
85
|
+
`${empty.length} of ${asked.length} keywords came back with no data in ${queryContext.location} / ${queryContext.language}: ${empty.join(", ")}. That is missing coverage, NOT zero demand \u2014 do not report them as unsearched, and do not re-query them reworded. \`baker research autocomplete\` on the head term is the way to find the phrasing that market uses.`
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
return hints;
|
|
89
|
+
}
|
|
90
|
+
var ARCHIVE_NOTE = "Read from the Reddit archive: the words are as posted, but points and comment counts on anything under ~36h old are as first captured \u2014 don't quote those numbers as current.";
|
|
91
|
+
function redditSearchHints({
|
|
92
|
+
resultCount,
|
|
93
|
+
kind,
|
|
94
|
+
source
|
|
95
|
+
}) {
|
|
96
|
+
const hints = [];
|
|
97
|
+
if (resultCount === 0) {
|
|
98
|
+
hints.push(
|
|
99
|
+
'Nothing matched. Reddit search matches words, not meaning: try the audience\'s own phrasing (one distinctive word, or a seed from `baker research autocomplete`), a longer --since window, or other subreddits \u2014 `baker research reddit subreddits "<topic>"` finds where the audience actually talks' + (kind === "posts" ? ", and try --kind comments \u2014 most of the voice is in the replies." : ".")
|
|
100
|
+
);
|
|
101
|
+
} else if (kind === "posts") {
|
|
102
|
+
hints.push(
|
|
103
|
+
"Titles rarely carry the voice. Read the promising threads with `baker research reddit thread <permalink>` for the replies, or search the replies directly with --kind comments."
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
if (source === "archive" && resultCount > 0) hints.push(ARCHIVE_NOTE);
|
|
107
|
+
return hints;
|
|
108
|
+
}
|
|
109
|
+
function redditThreadHints({
|
|
110
|
+
commentsShown,
|
|
111
|
+
commentsAsked,
|
|
112
|
+
commentCount,
|
|
113
|
+
source
|
|
114
|
+
}) {
|
|
115
|
+
const hints = [];
|
|
116
|
+
if (commentsAsked > 0 && commentsShown === 0 && (commentCount ?? 0) > 0) {
|
|
117
|
+
hints.push(
|
|
118
|
+
`This thread has ${commentCount} comments but none could be read just now. Quote the post only, and don't describe the replies.`
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
if (source === "archive") hints.push(ARCHIVE_NOTE);
|
|
122
|
+
return hints;
|
|
123
|
+
}
|
|
124
|
+
var REDDIT_HOST = /(^|\.)reddit\.com$|^redd\.it$/i;
|
|
125
|
+
function redditSubredditsHints({ resultCount }) {
|
|
126
|
+
if (resultCount === 0) {
|
|
127
|
+
return [
|
|
128
|
+
'No subreddits matched. Try the audience\'s role or the platform they work on ("amazon flex", "deliveroo", "nurses"), one word at a time, or a web search for `site:reddit.com <topic>`.'
|
|
129
|
+
];
|
|
130
|
+
}
|
|
131
|
+
return [
|
|
132
|
+
'Members say how big a subreddit is, not how active it is. Before mining one, run `baker research reddit search "<word>" --subreddit <name> --since <a recent date>`: nothing back means it is quiet, so pick another. `restricted` can still be read; `private` cannot.'
|
|
133
|
+
];
|
|
134
|
+
}
|
|
135
|
+
var REDDIT_LINK_REJECTED = {
|
|
136
|
+
action: "reject",
|
|
137
|
+
explanation: "Do not quote anything attributed to this link \u2014 it does not lead to those words. Find the real thread with `baker research reddit search`, and if you already wrote a quote from it, remove it."
|
|
138
|
+
};
|
|
139
|
+
function redditPageFix(url, code) {
|
|
140
|
+
let host;
|
|
141
|
+
try {
|
|
142
|
+
host = new URL(url).hostname;
|
|
143
|
+
} catch {
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
if (!REDDIT_HOST.test(host)) return null;
|
|
147
|
+
if (code === "NOT_FOUND") return REDDIT_LINK_REJECTED;
|
|
148
|
+
if (code !== "FORBIDDEN") return null;
|
|
149
|
+
return {
|
|
150
|
+
action: "retry_with_changes",
|
|
151
|
+
explanation: 'Read Reddit with its own commands: `baker research reddit search "<words>" --subreddit <name>` to find what people said, `baker research reddit thread <url>` for one thread.'
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
function googleAdsHints({
|
|
155
|
+
target,
|
|
156
|
+
adCount,
|
|
157
|
+
located,
|
|
158
|
+
textWithoutCopy,
|
|
159
|
+
copyAsked,
|
|
160
|
+
copyUnread,
|
|
161
|
+
visual
|
|
162
|
+
}) {
|
|
163
|
+
if (adCount === 0) {
|
|
164
|
+
return [
|
|
165
|
+
`No Google ads point to ${target}${located ? " in that region" : ""} \u2014 that is the answer, not a failed call: this competitor is not advertising on Google there, or its ads point to another domain. ` + (located ? "Re-run once without --location to see every region; then move on. " : "Move on. ") + `Its paid search terms, if any: \`baker research keywords-for-site ${target} --type paid\`.`
|
|
166
|
+
];
|
|
167
|
+
}
|
|
168
|
+
const hints = [];
|
|
169
|
+
if (!copyAsked && textWithoutCopy > 0) {
|
|
170
|
+
hints.push(
|
|
171
|
+
`${textWithoutCopy} text ads came back without their words. Re-run with --copy to read the headline and description of up to ${RESEARCH_GOOGLE_ADS_MAX_COPY} (cached, so only the reading is new).`
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
const pastCap = copyAsked ? textWithoutCopy - copyUnread : 0;
|
|
175
|
+
if (pastCap > 0) {
|
|
176
|
+
hints.push(
|
|
177
|
+
`${pastCap} text ads past the first ${RESEARCH_GOOGLE_ADS_MAX_COPY} were not read \u2014 one request reads at most ${RESEARCH_GOOGLE_ADS_MAX_COPY}. Narrow with --since, --location or --platform google_search and re-run for their words.`
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
if (visual > 0 || copyUnread > 0) {
|
|
181
|
+
const without = [
|
|
182
|
+
visual > 0 ? `${visual} image or video ads (Google gives no text for those)` : "",
|
|
183
|
+
copyUnread > 0 ? `${copyUnread} text ads whose image could not be read` : ""
|
|
184
|
+
].filter(Boolean);
|
|
185
|
+
hints.push(
|
|
186
|
+
`No copy for ${without.join(" and ")}: show those by their \`transparency_url\`. Do not open the Transparency Center in agent-browser to read them \u2014 it is the browser load this command exists to avoid.`
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
return hints;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export {
|
|
193
|
+
noSerpRowsHints,
|
|
194
|
+
advertisersHints,
|
|
195
|
+
keywordsForSiteHints,
|
|
196
|
+
fetchHints,
|
|
197
|
+
webDepthHints,
|
|
198
|
+
keywordMetricsHints,
|
|
199
|
+
redditSearchHints,
|
|
200
|
+
redditThreadHints,
|
|
201
|
+
redditSubredditsHints,
|
|
202
|
+
REDDIT_LINK_REJECTED,
|
|
203
|
+
redditPageFix,
|
|
204
|
+
googleAdsHints
|
|
205
|
+
};
|
|
206
|
+
//# sourceMappingURL=chunk-H7XVKLIY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/research/hints.ts"],"sourcesContent":["/**\n * The `research` family shipped with no `hints[]` on any command. Everything\n * here is one nudge for one dead end that an audited run actually hit — not a\n * running commentary on healthy results.\n */\n\nimport { RESEARCH_GOOGLE_ADS_MAX_COPY, type ResearchRedditSource } from \"@baker/api\";\nimport type { QueryContext } from \"../../geo-context.ts\";\nimport type { ResearchFix } from \"./output.ts\";\n\ntype Depth = \"medium\" | \"high\" | \"xhigh\";\n\n/**\n * `advertisers` is named after advertisers and returns none of their advertising.\n * A run read the name as \"SERP ad creative\", got domain economics, and wrote \"no\n * live paid ad copy captured\" into the client's vault without ever trying the\n * command that does return copy. So this fires on every call, not just empty ones.\n */\nexport const AD_COPY_ROUTE =\n \"This returns competing domains and their SERP economics — no ad copy, no headlines, no creative. \" +\n \"For a competitor's Google ads and their copy: `baker research google-ads <competitor.com> --copy` \" +\n \"(Google's Ads Transparency Center: every ad, how long it has run, and the text ads' headline and description). \" +\n 'For Meta and LinkedIn: `baker winning-ads advertisers \"<brand>\"` → ' +\n '`baker winning-ads search \"<brief>\" --advertiser-id <id>` → `baker winning-ads content <adId>` ' +\n \"(`primary_text` / `headline` / `cta`, plus the spoken transcript and on-screen text for video). \" +\n \"Do not keep querying this command for copy.\";\n\n/**\n * Empty SERP data has two causes and only one is worth a second call: the wrong\n * market. Once the market was explicit, a re-query is waste — say so, because\n * \"no rows\" otherwise reads as \"reword the keyword\".\n */\nexport function noSerpRowsHints(rowCount: number, queryContext: QueryContext): string[] {\n if (rowCount > 0) {\n return [];\n }\n const defaulted = queryContext.location_is_default || queryContext.language_is_default;\n if (defaulted) {\n return [\n `No rows for ${queryContext.location} / ${queryContext.language} — the market you did not set. ` +\n \"Set --location and --language for the client's actual market and re-run once \" +\n \"(`baker research countries` / `baker research languages` for the accepted codes) \" +\n \"before you touch the keyword.\",\n ];\n }\n return [\n `No rows for ${queryContext.location} / ${queryContext.language}, which you set explicitly. ` +\n \"This term has no third-party SERP coverage in that market — move on rather than re-querying it. \" +\n \"For demand signal try `baker research autocomplete`; for a competitor's actual terms, \" +\n \"`baker research keywords-for-site <domain>`.\",\n ];\n}\n\nexport function advertisersHints(rowCount: number, queryContext: QueryContext): string[] {\n return [...noSerpRowsHints(rowCount, queryContext), AD_COPY_ROUTE];\n}\n\n/**\n * \"This competitor buys no paid search\" is a real competitive answer, but it\n * arrives as an empty array that looks like a broken call — so say which it is\n * before the agent re-runs the same query with a different sort.\n */\nexport function keywordsForSiteHints(\n rowCount: number,\n queryContext: QueryContext,\n typeFilter: string | undefined,\n): string[] {\n if (rowCount > 0) {\n return [];\n }\n if (typeFilter === \"paid\" || typeFilter === \"organic\") {\n return [\n `No rows with --type ${typeFilter} in ${queryContext.location} / ${queryContext.language}. ` +\n `A domain with zero ${typeFilter} keywords in a market is itself the finding — record it and move on. ` +\n \"Confirm once with --type all (nothing at all there means the domain has no SERP coverage, \" +\n \"not that it has no ads) instead of re-running with a different --sort or --limit.\",\n ];\n }\n return noSerpRowsHints(rowCount, queryContext);\n}\n\nconst THIN_ANSWER_CHARS = 600;\nconst THIN_SOURCE_COUNT = 2;\n\n// Only `medium` and `high` have somewhere to escalate to; `xhigh` is the ceiling,\n// so a thin answer there is a fact about the web, not a flag the agent forgot.\nconst ESCALATION: Partial<Record<Depth, string>> = {\n medium:\n \"`medium` is a quick lookup, not a search. Re-ask the SAME question once with `--depth high` before \" +\n \"concluding the web has nothing on it.\",\n high:\n \"`high` already thought hard about this. `--depth xhigh` is the only step left and it can run 15 minutes — \" +\n \"take it only if this answer blocks a deliverable; otherwise record the gap and move on.\",\n};\n\n/**\n * The one thing worth saying about a page that came back fine is that you are\n * not looking at all of it — which the content itself cannot tell you.\n */\nexport function fetchHints({\n truncated,\n contentChars,\n shownChars,\n}: {\n truncated: boolean;\n contentChars: number;\n shownChars: number;\n}): string[] {\n const hints: string[] = [];\n\n if (shownChars < contentChars) {\n hints.push(\n `Showing the first ${shownChars.toLocaleString(\"en-US\")} of ${contentChars.toLocaleString(\"en-US\")} characters. ` +\n \"Re-run the same command with `--full` for the whole page — the read is cached for 24h, so it costs no extra time and no extra credit.\",\n );\n }\n\n if (truncated) {\n hints.push(\n \"This page is longer than one read returns, so the end of it is missing. \" +\n \"Don't present this as the complete page; if the part you need is further down, fetch the deeper URL directly.\",\n );\n }\n\n return hints;\n}\n\nexport function webDepthHints({\n answer,\n sourceCount,\n depth,\n}: {\n answer: string;\n sourceCount: number;\n depth: Depth;\n}): string[] {\n const thin = answer.length < THIN_ANSWER_CHARS || sourceCount <= THIN_SOURCE_COUNT;\n const escalation = ESCALATION[depth];\n if (!thin || !escalation) {\n return [];\n }\n return [`Thin answer (${answer.length} chars, ${sourceCount} source(s)). ${escalation}`];\n}\n\n/**\n * The volume DataForSEO returns is Google's own Keyword Planner figure resold,\n * so putting the two side by side validates nothing — a run did exactly that,\n * found all seven rows agreeing to the digit, and reported the agreement as\n * corroboration. This fires on every call rather than on a suspicious one,\n * because by the time the numbers are in a table the provenance is already gone.\n */\nexport function keywordMetricsHints({\n rows,\n asked,\n clickstream,\n queryContext,\n}: {\n rows: Array<{ keyword: string; search_volume: number | null }>;\n asked: string[];\n clickstream: boolean;\n queryContext: QueryContext;\n}): string[] {\n if (rows.length === 0) {\n return noSerpRowsHints(0, queryContext);\n }\n\n const provenance =\n \"DataForSEO resells Google's Keyword Planner volume — planner_search_volume here is the SAME number \" +\n \"`baker ads google keywords metrics` returns, not an independent reading of it. Quoting the two as agreeing \" +\n \"sources is not corroboration.\" +\n (clickstream\n ? \" clickstream_search_volume IS independent (DataForSEO's own panels); when the two disagree, say which one you are quoting.\"\n : \" For a genuinely independent estimate of demand, re-run with --clickstream (costs 2x), or use first-party data: \" +\n \"`baker gsc query` for what already reaches the site, or the account's own search terms.\");\n\n const hints = [provenance];\n\n const empty = rows.filter((row) => row.search_volume === null).map((row) => row.keyword);\n if (empty.length > 0) {\n hints.push(\n `${empty.length} of ${asked.length} keywords came back with no data in ${queryContext.location} / ${queryContext.language}: ` +\n `${empty.join(\", \")}. That is missing coverage, NOT zero demand — do not report them as unsearched, and do not ` +\n \"re-query them reworded. `baker research autocomplete` on the head term is the way to find the phrasing that market uses.\",\n );\n }\n\n return hints;\n}\n\n/**\n * The archive keeps a post's words the moment it is written and its points\n * only once it has settled, so a number on something young is not the number\n * Reddit shows. Said once, when it applies, so a count is never quoted as live.\n */\nconst ARCHIVE_NOTE =\n \"Read from the Reddit archive: the words are as posted, but points and comment counts on anything under ~36h old are as first captured — don't quote those numbers as current.\";\n\n/**\n * An empty Reddit search is almost always a phrasing miss, not a silent\n * audience: Reddit matches words, and people write in their own. A run that\n * came back empty on a posts search also never looked at the replies, which is\n * where most of the verbatim voice is.\n */\nexport function redditSearchHints({\n resultCount,\n kind,\n source,\n}: {\n resultCount: number;\n kind: \"posts\" | \"comments\";\n source: ResearchRedditSource;\n}): string[] {\n const hints: string[] = [];\n if (resultCount === 0) {\n hints.push(\n \"Nothing matched. Reddit search matches words, not meaning: try the audience's own phrasing (one distinctive word, \" +\n \"or a seed from `baker research autocomplete`), a longer --since window, or other subreddits — \" +\n '`baker research reddit subreddits \"<topic>\"` finds where the audience actually talks' +\n (kind === \"posts\" ? \", and try --kind comments — most of the voice is in the replies.\" : \".\"),\n );\n } else if (kind === \"posts\") {\n hints.push(\n \"Titles rarely carry the voice. Read the promising threads with `baker research reddit thread <permalink>` \" +\n \"for the replies, or search the replies directly with --kind comments.\",\n );\n }\n if (source === \"archive\" && resultCount > 0) hints.push(ARCHIVE_NOTE);\n return hints;\n}\n\n/** A thread whose replies no source would serve is still the post — but it must not read as a thread nobody answered. */\nexport function redditThreadHints({\n commentsShown,\n commentsAsked,\n commentCount,\n source,\n}: {\n commentsShown: number;\n commentsAsked: number;\n commentCount: number | null;\n source: ResearchRedditSource;\n}): string[] {\n const hints: string[] = [];\n if (commentsAsked > 0 && commentsShown === 0 && (commentCount ?? 0) > 0) {\n hints.push(\n `This thread has ${commentCount} comments but none could be read just now. Quote the post only, and don't describe the replies.`,\n );\n }\n if (source === \"archive\") hints.push(ARCHIVE_NOTE);\n return hints;\n}\n\nconst REDDIT_HOST = /(^|\\.)reddit\\.com$|^redd\\.it$/i;\n\n/**\n * A subreddit's member count is its size, not its pulse. The run that prompted\n * this command mined r/CouriersUK — a real subreddit, with one post in its whole\n * history — and found nothing. One dated search tells a living subreddit from a\n * dead one before it is relied on.\n */\nexport function redditSubredditsHints({ resultCount }: { resultCount: number }): string[] {\n if (resultCount === 0) {\n return [\n 'No subreddits matched. Try the audience\\'s role or the platform they work on (\"amazon flex\", \"deliveroo\", \"nurses\"), one word at a time, or a web search for `site:reddit.com <topic>`.',\n ];\n }\n return [\n 'Members say how big a subreddit is, not how active it is. Before mining one, run `baker research reddit search \"<word>\" --subreddit <name> --since <a recent date>`: nothing back means it is quiet, so pick another. `restricted` can still be read; `private` cannot.',\n ];\n}\n\n/** A Reddit link that does not lead to the words attributed to it. Shared by `reddit thread` and `fetch`. */\nexport const REDDIT_LINK_REJECTED: ResearchFix = {\n action: \"reject\",\n explanation:\n \"Do not quote anything attributed to this link — it does not lead to those words. Find the real thread with `baker research reddit search`, and if you already wrote a quote from it, remove it.\",\n};\n\n/**\n * `research fetch` hands a Reddit URL to the Reddit reader, but its generic\n * remediation was written for ordinary pages: FORBIDDEN reads \"this will not\n * open, carry on without it\" and NOT_FOUND \"carry on\". For Reddit both are the\n * wrong advice. A page the reader will not turn into a thread is one `reddit`\n * command away, and a link that leads nowhere real must not be quoted at all.\n */\nexport function redditPageFix(url: string, code: string): ResearchFix | null {\n let host: string;\n try {\n host = new URL(url).hostname;\n } catch {\n return null;\n }\n if (!REDDIT_HOST.test(host)) return null;\n if (code === \"NOT_FOUND\") return REDDIT_LINK_REJECTED;\n if (code !== \"FORBIDDEN\") return null;\n return {\n action: \"retry_with_changes\",\n explanation:\n 'Read Reddit with its own commands: `baker research reddit search \"<words>\" --subreddit <name>` to find what people said, `baker research reddit thread <url>` for one thread.',\n };\n}\n\n/**\n * `google-ads` replaces a browser trip through Google's Ads Transparency\n * Center, so its hints keep the agent out of one: no ads is an answer, and an\n * ad whose copy Google does not give is shown by its link, never opened.\n */\nexport function googleAdsHints({\n target,\n adCount,\n located,\n textWithoutCopy,\n copyAsked,\n copyUnread,\n visual,\n}: {\n target: string;\n adCount: number;\n located: boolean;\n textWithoutCopy: number;\n copyAsked: boolean;\n copyUnread: number;\n visual: number;\n}): string[] {\n if (adCount === 0) {\n return [\n `No Google ads point to ${target}${located ? \" in that region\" : \"\"} — that is the answer, not a failed call: ` +\n \"this competitor is not advertising on Google there, or its ads point to another domain. \" +\n (located ? \"Re-run once without --location to see every region; then move on. \" : \"Move on. \") +\n `Its paid search terms, if any: \\`baker research keywords-for-site ${target} --type paid\\`.`,\n ];\n }\n const hints: string[] = [];\n if (!copyAsked && textWithoutCopy > 0) {\n hints.push(\n `${textWithoutCopy} text ads came back without their words. Re-run with --copy to read the headline and description of up to ${RESEARCH_GOOGLE_ADS_MAX_COPY} (cached, so only the reading is new).`,\n );\n }\n const pastCap = copyAsked ? textWithoutCopy - copyUnread : 0;\n if (pastCap > 0) {\n hints.push(\n `${pastCap} text ads past the first ${RESEARCH_GOOGLE_ADS_MAX_COPY} were not read — one request reads at most ${RESEARCH_GOOGLE_ADS_MAX_COPY}. ` +\n \"Narrow with --since, --location or --platform google_search and re-run for their words.\",\n );\n }\n if (visual > 0 || copyUnread > 0) {\n const without = [\n visual > 0 ? `${visual} image or video ads (Google gives no text for those)` : \"\",\n copyUnread > 0 ? `${copyUnread} text ads whose image could not be read` : \"\",\n ].filter(Boolean);\n hints.push(\n `No copy for ${without.join(\" and \")}: show those by their \\`transparency_url\\`. ` +\n \"Do not open the Transparency Center in agent-browser to read them — it is the browser load this command exists to avoid.\",\n );\n }\n return hints;\n}\n"],"mappings":"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","names":[]}
|