@koda-sl/baker-cli 0.450.0-dev.b454c3dd2 → 0.450.0-dev.d6701597d
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 +10 -11
- package/dist/{account-XQXC7BR6.js → account-AL2ZDSR7.js} +4 -5
- package/dist/{account-XQXC7BR6.js.map → account-AL2ZDSR7.js.map} +1 -1
- package/dist/{accounts-722UY53A.js → accounts-HAFCLSR5.js} +3 -4
- package/dist/{accounts-722UY53A.js.map → accounts-HAFCLSR5.js.map} +1 -1
- package/dist/{accounts-E67BMK7T.js → accounts-O5MFO3QQ.js} +5 -6
- package/dist/{accounts-E67BMK7T.js.map → accounts-O5MFO3QQ.js.map} +1 -1
- package/dist/{actions-6TQMSVWD.js → actions-P35MEMGN.js} +18 -18
- package/dist/{add-2BEGRHUX.js → add-5GAN6CVO.js} +5 -28
- package/dist/add-5GAN6CVO.js.map +1 -0
- package/dist/{add-LEMKEOPO.js → add-6DTC6X5G.js} +2 -3
- package/dist/{add-LEMKEOPO.js.map → add-6DTC6X5G.js.map} +1 -1
- package/dist/{ads-AGYCVD62.js → ads-73PGA4YC.js} +4 -4
- package/dist/{advertisers-2VQKAYKG.js → advertisers-AE75CGVE.js} +3 -4
- package/dist/{advertisers-2VQKAYKG.js.map → advertisers-AE75CGVE.js.map} +1 -1
- package/dist/{analytics-IFELDWLL.js → analytics-FKCXIMPO.js} +20 -24
- package/dist/analytics-FKCXIMPO.js.map +1 -0
- package/dist/{analytics-OH5QEH7F.js → analytics-FPWQQGRM.js} +3 -4
- package/dist/{analytics-OH5QEH7F.js.map → analytics-FPWQQGRM.js.map} +1 -1
- package/dist/{assign-PTUJUCEL.js → assign-ABN2AQ4J.js} +3 -4
- package/dist/{assign-PTUJUCEL.js.map → assign-ABN2AQ4J.js.map} +1 -1
- package/dist/{audience-size-LRI6GJRT.js → audience-size-GNBJY35X.js} +3 -4
- package/dist/{audience-size-LRI6GJRT.js.map → audience-size-GNBJY35X.js.map} +1 -1
- package/dist/{audit-HWP7OPB7.js → audit-3VS63TBW.js} +3 -4
- package/dist/{audit-HWP7OPB7.js.map → audit-3VS63TBW.js.map} +1 -1
- package/dist/{autocomplete-J6DHU6MR.js → autocomplete-VS3XG3B7.js} +3 -4
- package/dist/{autocomplete-J6DHU6MR.js.map → autocomplete-VS3XG3B7.js.map} +1 -1
- package/dist/{avatars-467OSBD6.js → avatars-EKCKHCC3.js} +4 -4
- package/dist/{bid-pricing-EO5WLHGV.js → bid-pricing-Q72B65AY.js} +3 -4
- package/dist/{bid-pricing-EO5WLHGV.js.map → bid-pricing-Q72B65AY.js.map} +1 -1
- package/dist/{brand-YRTEPGBK.js → brand-C6PFGGQN.js} +2 -2
- package/dist/{brief-OSFJ2V7F.js → brief-YFJHQ5VQ.js} +7 -8
- package/dist/{brief-OSFJ2V7F.js.map → brief-YFJHQ5VQ.js.map} +1 -1
- package/dist/{campaign-groups-PQ6KSQJR.js → campaign-groups-KFFYQPU3.js} +8 -9
- package/dist/{campaign-groups-PQ6KSQJR.js.map → campaign-groups-KFFYQPU3.js.map} +1 -1
- package/dist/{campaign-writes-5OVLUD5E.js → campaign-writes-FHOS5XZY.js} +3 -4
- package/dist/{campaign-writes-5OVLUD5E.js.map → campaign-writes-FHOS5XZY.js.map} +1 -1
- package/dist/{campaigns-6T3NSUT2.js → campaigns-2NHWBF5C.js} +11 -12
- package/dist/{campaigns-6T3NSUT2.js.map → campaigns-2NHWBF5C.js.map} +1 -1
- package/dist/{campaigns-OYMXDGWX.js → campaigns-KZYZTXDS.js} +5 -5
- package/dist/{canvas-YQFG52IG.js → canvas-5NB27FX2.js} +13 -13
- package/dist/{capabilities-PXBKUN2G.js → capabilities-DJFTRJKS.js} +3 -4
- package/dist/{capabilities-PXBKUN2G.js.map → capabilities-DJFTRJKS.js.map} +1 -1
- package/dist/{catalog-XLXIM7IW.js → catalog-VSSY6FGI.js} +4 -4
- package/dist/{chats-UK47UE7C.js → chats-D2CSDX5Q.js} +3 -4
- package/dist/{chats-UK47UE7C.js.map → chats-D2CSDX5Q.js.map} +1 -1
- package/dist/{chunk-5ZNTADVR.js → chunk-3G3ZDLMI.js} +2 -2
- package/dist/{chunk-SJYEY5MV.js → chunk-3HJLHTWP.js} +3 -12
- package/dist/{chunk-SJYEY5MV.js.map → chunk-3HJLHTWP.js.map} +1 -1
- package/dist/{chunk-ZDMTXQ2Q.js → chunk-3IBYKLXR.js} +2 -2
- package/dist/{chunk-CWYAELVG.js → chunk-464O4MT2.js} +2 -2
- package/dist/{chunk-NA63BH7V.js → chunk-4AUMTNVB.js} +3 -3
- package/dist/{chunk-NDEE6G2J.js → chunk-4BQXAE7Z.js} +2 -2
- package/dist/{chunk-2AOE2MZQ.js → chunk-5ZDLTE5T.js} +3 -3
- package/dist/{chunk-ULG4QRTV.js → chunk-6NB47MRW.js} +2 -2
- package/dist/{chunk-24EB7EDR.js → chunk-7YCRFMXF.js} +3 -3
- package/dist/{chunk-WGUQHAJY.js → chunk-A4LOJ2VD.js} +2 -2
- package/dist/{chunk-6F7DVPOS.js → chunk-AEOSAVVL.js} +3 -3
- package/dist/{chunk-MACCF4JZ.js → chunk-CMPEUZOR.js} +22 -16
- package/dist/{chunk-MACCF4JZ.js.map → chunk-CMPEUZOR.js.map} +1 -1
- package/dist/{chunk-N4LAYIIN.js → chunk-CSYSX4D2.js} +2 -2
- package/dist/{chunk-RX2DKU3W.js → chunk-DGUNI37S.js} +2 -2
- package/dist/{chunk-QE7W555R.js → chunk-DWHIOO7E.js} +12 -163
- package/dist/chunk-DWHIOO7E.js.map +1 -0
- package/dist/{chunk-FPOGPFAG.js → chunk-EBWBG6YV.js} +51 -24
- package/dist/chunk-EBWBG6YV.js.map +1 -0
- package/dist/{chunk-NYIGXDUG.js → chunk-EDLZGTGN.js} +39 -1
- package/dist/chunk-EDLZGTGN.js.map +1 -0
- package/dist/{chunk-I3ZR655O.js → chunk-IR6D7K4H.js} +2 -2
- package/dist/{chunk-FUHN4MFY.js → chunk-JQJDXPCO.js} +2 -2
- package/dist/{chunk-7CTMH5AK.js → chunk-KAUOHQTF.js} +3 -3
- package/dist/{chunk-VYQ3QJ3C.js → chunk-KHRXPQID.js} +2 -2
- package/dist/{chunk-6Y7ZBENQ.js → chunk-LECGCWT5.js} +6 -6
- package/dist/{chunk-5WCSKQ7Z.js → chunk-LZ73CZGP.js} +6 -6
- package/dist/{chunk-R25YLW6H.js → chunk-MELOSESI.js} +2 -2
- package/dist/{chunk-DCRPXOJJ.js → chunk-MXYBTMKB.js} +2 -2
- package/dist/{chunk-54C6YDGJ.js → chunk-NPY4QUMQ.js} +2 -2
- package/dist/{chunk-LYQJ4PZW.js → chunk-OQ6663F4.js} +5 -5
- package/dist/{chunk-H3427GPU.js → chunk-OZRUJVIQ.js} +2 -2
- package/dist/{chunk-KMKEYI37.js → chunk-Q2V6E6SL.js} +3 -3
- package/dist/{chunk-VL43TNIP.js → chunk-QRP3PXWN.js} +2 -2
- package/dist/{chunk-HDLYPC6K.js → chunk-RPUSTYHL.js} +3 -5
- package/dist/{chunk-HDLYPC6K.js.map → chunk-RPUSTYHL.js.map} +1 -1
- package/dist/{chunk-C46GUI2S.js → chunk-RZBEK2VE.js} +2 -2
- package/dist/{chunk-2VPBIT65.js → chunk-S3A3YOKO.js} +8 -8
- package/dist/{chunk-FYGR3I2A.js → chunk-S77PZVYM.js} +3 -3
- package/dist/{chunk-VLMBTPXU.js → chunk-SHL7LOC3.js} +3 -3
- package/dist/{chunk-HR6IWNKE.js → chunk-SSJK7FEV.js} +1140 -1196
- package/dist/chunk-SSJK7FEV.js.map +1 -0
- package/dist/{chunk-KS2QY6MK.js → chunk-W3ZHJJVT.js} +4 -4
- package/dist/{chunk-7EPXVICM.js → chunk-XF4JUKVF.js} +5 -38
- package/dist/chunk-XF4JUKVF.js.map +1 -0
- package/dist/{chunk-RL5CP7N6.js → chunk-Y6O7EWYY.js} +5 -5
- package/dist/{chunk-6NY2GPR4.js → chunk-Y6ZQXUZ7.js} +3 -3
- package/dist/{chunk-HROZYQ5H.js → chunk-YRQYA2LR.js} +5 -63
- package/dist/chunk-YRQYA2LR.js.map +1 -0
- package/dist/{chunk-ASI4P6X2.js → chunk-YUCLMOEG.js} +6 -6
- package/dist/chunk-YUCLMOEG.js.map +1 -0
- package/dist/{chunk-WKQG6TER.js → chunk-ZEYEWPK6.js} +2 -2
- package/dist/{claim-W6G6VEG5.js → claim-FZ5OQLMU.js} +3 -4
- package/dist/{claim-W6G6VEG5.js.map → claim-FZ5OQLMU.js.map} +1 -1
- package/dist/cli.js +30 -30
- package/dist/{companies-TS6KBATJ.js → companies-DNI634RC.js} +3 -4
- package/dist/{companies-TS6KBATJ.js.map → companies-DNI634RC.js.map} +1 -1
- package/dist/{complete-LYR2HMQU.js → complete-2FZMGJV5.js} +3 -4
- package/dist/{complete-LYR2HMQU.js.map → complete-2FZMGJV5.js.map} +1 -1
- package/dist/{connect-FCXNVTXG.js → connect-QCOGEPP4.js} +6 -13
- package/dist/{conversation-6ZJGPCXM.js → conversation-6IOGV7B7.js} +3 -4
- package/dist/{conversation-6ZJGPCXM.js.map → conversation-6IOGV7B7.js.map} +1 -1
- package/dist/{conversions-UHB55MMQ.js → conversions-4SRZPBBX.js} +7 -8
- package/dist/{conversions-UHB55MMQ.js.map → conversions-4SRZPBBX.js.map} +1 -1
- package/dist/{create-EX6OWLNM.js → create-BJNMO6HT.js} +2 -3
- package/dist/{create-EX6OWLNM.js.map → create-BJNMO6HT.js.map} +1 -1
- package/dist/{create-JFSK4BOP.js → create-FX4OJ2XF.js} +3 -4
- package/dist/{create-JFSK4BOP.js.map → create-FX4OJ2XF.js.map} +1 -1
- package/dist/{create-JCA7JPLP.js → create-RM7HV77Y.js} +3 -4
- package/dist/{create-JCA7JPLP.js.map → create-RM7HV77Y.js.map} +1 -1
- package/dist/{create-WU22YYU2.js → create-VXM34ZWH.js} +3 -4
- package/dist/{create-WU22YYU2.js.map → create-VXM34ZWH.js.map} +1 -1
- package/dist/{creatives-FXUQ5WSD.js → creatives-B5NTXPUB.js} +10 -10
- package/dist/{creatives-KGXUOYPE.js → creatives-JSWBFQ5R.js} +8 -9
- package/dist/{creatives-KGXUOYPE.js.map → creatives-JSWBFQ5R.js.map} +1 -1
- package/dist/{credentials-MJC7PGKR.js → credentials-C33K6XCJ.js} +3 -4
- package/dist/{credentials-MJC7PGKR.js.map → credentials-C33K6XCJ.js.map} +1 -1
- package/dist/{critique-GS5VV5ZC.js → critique-4V5SKH7C.js} +6 -7
- package/dist/{critique-GS5VV5ZC.js.map → critique-4V5SKH7C.js.map} +1 -1
- package/dist/{critique-TPHR27KH.js → critique-ZS4ON3SU.js} +3 -4
- package/dist/{critique-TPHR27KH.js.map → critique-ZS4ON3SU.js.map} +1 -1
- package/dist/{crm-VK44O3ED.js → crm-52ROSWH5.js} +4 -5
- package/dist/{crm-VK44O3ED.js.map → crm-52ROSWH5.js.map} +1 -1
- package/dist/{crm-AVCM5D4G.js → crm-R5IXIFIV.js} +4 -5
- package/dist/{crm-AVCM5D4G.js.map → crm-R5IXIFIV.js.map} +1 -1
- package/dist/{customers-XH2DMTFH.js → customers-A36LOZOB.js} +5 -6
- package/dist/{delete-WI5E3DR3.js → delete-AIGE4Y4H.js} +3 -4
- package/dist/{delete-WI5E3DR3.js.map → delete-AIGE4Y4H.js.map} +1 -1
- package/dist/{delete-KRH2YMSZ.js → delete-HGHXY24R.js} +3 -4
- package/dist/{delete-KRH2YMSZ.js.map → delete-HGHXY24R.js.map} +1 -1
- package/dist/{delete-E3R3TKIL.js → delete-M2GDLPYN.js} +2 -3
- package/dist/{delete-E3R3TKIL.js.map → delete-M2GDLPYN.js.map} +1 -1
- package/dist/{demographics-XV5PBA77.js → demographics-NTWB2IMG.js} +3 -4
- package/dist/{demographics-XV5PBA77.js.map → demographics-NTWB2IMG.js.map} +1 -1
- package/dist/{discard-HTQUUHJR.js → discard-2WWQG6OU.js} +3 -4
- package/dist/{discard-HTQUUHJR.js.map → discard-2WWQG6OU.js.map} +1 -1
- package/dist/{domain-RECGZXJB.js → domain-Y2LT6JLT.js} +3 -4
- package/dist/{domain-RECGZXJB.js.map → domain-Y2LT6JLT.js.map} +1 -1
- package/dist/{draft-Q546QPPU.js → draft-EJXNNJ3Y.js} +4 -5
- package/dist/{draft-Q546QPPU.js.map → draft-EJXNNJ3Y.js.map} +1 -1
- package/dist/{draft-PVTX6QT6.js → draft-FJ7WHIXW.js} +3 -4
- package/dist/{draft-PVTX6QT6.js.map → draft-FJ7WHIXW.js.map} +1 -1
- package/dist/{draft-2IBSJEKC.js → draft-SLHAKJ2A.js} +3 -4
- package/dist/{draft-2IBSJEKC.js.map → draft-SLHAKJ2A.js.map} +1 -1
- package/dist/engine/index.js +3 -3
- package/dist/{facets-7EVPJMKS.js → facets-U7AQC4H6.js} +3 -4
- package/dist/{facets-7EVPJMKS.js.map → facets-U7AQC4H6.js.map} +1 -1
- package/dist/{feedback-EIZKS4JU.js → feedback-OLTCHE6C.js} +2 -2
- package/dist/{feedback-record-TKO54BOE.js → feedback-record-7WZ4H7EP.js} +8 -9
- package/dist/{feedback-record-TKO54BOE.js.map → feedback-record-7WZ4H7EP.js.map} +1 -1
- package/dist/{fetch-4BY6HYUM.js → fetch-W7NULDEO.js} +3 -4
- package/dist/{fetch-4BY6HYUM.js.map → fetch-W7NULDEO.js.map} +1 -1
- package/dist/{find-FRRHAPWX.js → find-OTDIX6V4.js} +4 -4
- package/dist/{flows-KTFAML22.js → flows-KABCBS3S.js} +17 -21
- package/dist/flows-KABCBS3S.js.map +1 -0
- package/dist/{fonts-MXR3ZKDX.js → fonts-EMMX3KII.js} +5 -6
- package/dist/{forecast-3QTJYVND.js → forecast-GNODEIIC.js} +3 -4
- package/dist/{forecast-3QTJYVND.js.map → forecast-GNODEIIC.js.map} +1 -1
- package/dist/{funnel-I6XIAEHG.js → funnel-AAX27NH4.js} +455 -11
- package/dist/funnel-AAX27NH4.js.map +1 -0
- package/dist/{ga4-DV2AXCSL.js → ga4-UDQ2HA2J.js} +1 -1
- package/dist/{get-5PKNKJ5S.js → get-QEYJRLV3.js} +4 -7
- package/dist/get-QEYJRLV3.js.map +1 -0
- package/dist/{get-72YPHJGV.js → get-RTVUZM6E.js} +3 -4
- package/dist/{get-72YPHJGV.js.map → get-RTVUZM6E.js.map} +1 -1
- package/dist/{google-QYYYSSXI.js → google-KTO3PLEU.js} +5 -5
- package/dist/{google-6OGZX47I.js → google-M7KEXVK5.js} +2 -2
- package/dist/{google-ads-QGMQKZQD.js → google-ads-OK6IG3UV.js} +3 -4
- package/dist/{google-ads-QGMQKZQD.js.map → google-ads-OK6IG3UV.js.map} +1 -1
- package/dist/{gsc-TAKOF7J5.js → gsc-P3QYGDV2.js} +1 -1
- package/dist/{history-6AVQX2OQ.js → history-PQUJKK26.js} +3 -4
- package/dist/{history-6AVQX2OQ.js.map → history-PQUJKK26.js.map} +1 -1
- package/dist/{hubspot-SVEMFK5S.js → hubspot-Y77VLY6Y.js} +8 -9
- package/dist/{hubspot-SVEMFK5S.js.map → hubspot-Y77VLY6Y.js.map} +1 -1
- package/dist/{icon-L4RSS6PZ.js → icon-I43F77FV.js} +4 -4
- package/dist/{ideas-NFOW3HKJ.js → ideas-MIDU7YOA.js} +2 -3
- package/dist/{images-2EFFUNNV.js → images-S254MS6O.js} +9 -9
- package/dist/{ingest-2SO62RRI.js → ingest-J4I3HKM3.js} +2 -3
- package/dist/{ingest-2SO62RRI.js.map → ingest-J4I3HKM3.js.map} +1 -1
- package/dist/{ingest-2EIKN4QC.js → ingest-YV2NLDBE.js} +3 -4
- package/dist/{inspect-4OOS4APT.js → inspect-Q5NHBBHX.js} +3 -4
- package/dist/{inspect-4OOS4APT.js.map → inspect-Q5NHBBHX.js.map} +1 -1
- package/dist/{inspiration-S3DU4CMQ.js → inspiration-P265QJ2H.js} +1 -1
- package/dist/{keyword-metrics-SF4CSNZ2.js → keyword-metrics-PDY4ZXSP.js} +3 -4
- package/dist/{keyword-metrics-SF4CSNZ2.js.map → keyword-metrics-PDY4ZXSP.js.map} +1 -1
- package/dist/{keywords-for-site-WDAOPNKC.js → keywords-for-site-GALSCV77.js} +3 -4
- package/dist/{keywords-for-site-WDAOPNKC.js.map → keywords-for-site-GALSCV77.js.map} +1 -1
- package/dist/{landing-2ZB46LXH.js → landing-CJYGWCK4.js} +3 -3
- package/dist/{leads-A4W5KTWB.js → leads-PHKG6CP3.js} +3 -4
- package/dist/{leads-A4W5KTWB.js.map → leads-PHKG6CP3.js.map} +1 -1
- package/dist/{learn-IPULBCOD.js → learn-FUQSY7DN.js} +4 -5
- package/dist/{learn-IPULBCOD.js.map → learn-FUQSY7DN.js.map} +1 -1
- package/dist/{line-item-writes-EMYSOJKM.js → line-item-writes-E6MZPIZZ.js} +3 -4
- package/dist/{line-item-writes-EMYSOJKM.js.map → line-item-writes-E6MZPIZZ.js.map} +1 -1
- package/dist/{line-items-5NECXUZT.js → line-items-7ZGIKEF2.js} +5 -5
- package/dist/{link-CI45HWFN.js → link-QYAW6A2W.js} +3 -4
- package/dist/{link-CI45HWFN.js.map → link-QYAW6A2W.js.map} +1 -1
- package/dist/{linkedin-B7SYR75X.js → linkedin-FFSDSGGS.js} +26 -27
- package/dist/{linkedin-B7SYR75X.js.map → linkedin-FFSDSGGS.js.map} +1 -1
- package/dist/{list-ZBT3EBVZ.js → list-5IC6KIKO.js} +3 -4
- package/dist/{list-ZBT3EBVZ.js.map → list-5IC6KIKO.js.map} +1 -1
- package/dist/{list-2BARXOT5.js → list-NVQC5SNY.js} +2 -3
- package/dist/{list-2BARXOT5.js.map → list-NVQC5SNY.js.map} +1 -1
- package/dist/{list-BIEVLEHS.js → list-SAV3LQHY.js} +3 -4
- package/dist/{list-BIEVLEHS.js.map → list-SAV3LQHY.js.map} +1 -1
- package/dist/{log-C23OOAJZ.js → log-XZPVOALD.js} +3 -4
- package/dist/{log-C23OOAJZ.js.map → log-XZPVOALD.js.map} +1 -1
- package/dist/{logo-Q5D7PZY6.js → logo-2IP663QO.js} +3 -3
- package/dist/{lookup-ETWY47F7.js → lookup-XK45W2SH.js} +5 -6
- package/dist/{make-TPKKJXGL.js → make-BMWRKIIY.js} +20 -18
- package/dist/{make-TPKKJXGL.js.map → make-BMWRKIIY.js.map} +1 -1
- package/dist/{map-SYZMPHLL.js → map-4J5WIWIG.js} +4 -5
- package/dist/{map-SYZMPHLL.js.map → map-4J5WIWIG.js.map} +1 -1
- package/dist/{mcp-6FQBVJ6F.js → mcp-XXD7ZQCP.js} +2 -3
- package/dist/{mcp-6FQBVJ6F.js.map → mcp-XXD7ZQCP.js.map} +1 -1
- package/dist/{media-sources-ZXHEEP6T.js → media-sources-O6ZRUA3N.js} +2 -2
- package/dist/{members-UDY4OOJW.js → members-D5ZYLS4Y.js} +3 -4
- package/dist/{members-UDY4OOJW.js.map → members-D5ZYLS4Y.js.map} +1 -1
- package/dist/{normalize-DAKHYS3V.js → normalize-PCNC6E2N.js} +3 -7
- package/dist/{normalize-DAKHYS3V.js.map → normalize-PCNC6E2N.js.map} +1 -1
- package/dist/{options-QL3ULED5.js → options-MQ65VEVD.js} +6 -7
- package/dist/{options-QL3ULED5.js.map → options-MQ65VEVD.js.map} +1 -1
- package/dist/{performance-UF5VTY2U.js → performance-6QW2KEEQ.js} +4 -5
- package/dist/{promoted-tweet-writes-7HGESJ46.js → promoted-tweet-writes-JPLHY3GM.js} +3 -4
- package/dist/{promoted-tweet-writes-7HGESJ46.js.map → promoted-tweet-writes-JPLHY3GM.js.map} +1 -1
- package/dist/{promoted-tweets-LZKS5JIF.js → promoted-tweets-SURKMHFI.js} +3 -3
- package/dist/{publish-NPD3SMZL.js → publish-HCQ6MXLB.js} +3 -4
- package/dist/{publish-NPD3SMZL.js.map → publish-HCQ6MXLB.js.map} +1 -1
- package/dist/{reddit-NU2N3LZD.js → reddit-GIP3ADMS.js} +4 -5
- package/dist/{refresh-EBVJ2C6L.js → refresh-UXQSLCR3.js} +2 -3
- package/dist/{refresh-EBVJ2C6L.js.map → refresh-UXQSLCR3.js.map} +1 -1
- package/dist/{release-V43YB2PY.js → release-5KVLXNP6.js} +3 -4
- package/dist/{release-V43YB2PY.js.map → release-5KVLXNP6.js.map} +1 -1
- package/dist/{remove-QPSWLFI4.js → remove-6FIVKCJI.js} +2 -3
- package/dist/{remove-QPSWLFI4.js.map → remove-6FIVKCJI.js.map} +1 -1
- package/dist/{reopen-GQ66NMWF.js → reopen-YM5LNOLB.js} +3 -4
- package/dist/{reopen-GQ66NMWF.js.map → reopen-YM5LNOLB.js.map} +1 -1
- package/dist/{rerun-PZK275DY.js → rerun-6XZG7BGK.js} +17 -18
- package/dist/{rerun-PZK275DY.js.map → rerun-6XZG7BGK.js.map} +1 -1
- package/dist/{research-FMM6AWZC.js → research-2BLEISBG.js} +10 -10
- package/dist/{research-GEOCUBXB.js → research-YOGE7GT2.js} +2 -3
- package/dist/{research-GEOCUBXB.js.map → research-YOGE7GT2.js.map} +1 -1
- package/dist/{reset-REXJ6AUK.js → reset-C4UHQ3EU.js} +2 -3
- package/dist/{reset-REXJ6AUK.js.map → reset-C4UHQ3EU.js.map} +1 -1
- package/dist/{reset-Y72IVESB.js → reset-OLVB6AE6.js} +2 -3
- package/dist/{reset-Y72IVESB.js.map → reset-OLVB6AE6.js.map} +1 -1
- package/dist/{resolve-OGX7C4TV.js → resolve-XYH2GDAE.js} +3 -4
- package/dist/{resolve-OGX7C4TV.js.map → resolve-XYH2GDAE.js.map} +1 -1
- package/dist/{retry-TCUBBFR5.js → retry-726GKI6V.js} +2 -3
- package/dist/{retry-TCUBBFR5.js.map → retry-726GKI6V.js.map} +1 -1
- package/dist/{retry-CD6JAQ3F.js → retry-7EELDEQP.js} +2 -3
- package/dist/{retry-CD6JAQ3F.js.map → retry-7EELDEQP.js.map} +1 -1
- package/dist/{run-EUO34T2J.js → run-MMEDKJDB.js} +17 -18
- package/dist/{run-A5ZDXTOI.js → run-P4KR2MXC.js} +3 -4
- package/dist/{run-A5ZDXTOI.js.map → run-P4KR2MXC.js.map} +1 -1
- package/dist/{scaffold-ad-SW2HEWM3.js → scaffold-ad-PBTEWDAC.js} +12 -13
- package/dist/{scaffold-ad-SW2HEWM3.js.map → scaffold-ad-PBTEWDAC.js.map} +1 -1
- package/dist/{scaffold-static-ad-ECTJL54Y.js → scaffold-static-ad-RM4M4X5U.js} +36 -37
- package/dist/scaffold-static-ad-RM4M4X5U.js.map +1 -0
- package/dist/{scaffold-video-EI7U7RBK.js → scaffold-video-O2TTKZIE.js} +11 -12
- package/dist/{scaffold-video-EI7U7RBK.js.map → scaffold-video-O2TTKZIE.js.map} +1 -1
- package/dist/{schedule-S5YZJZ5U.js → schedule-RDK4GEPI.js} +2 -3
- package/dist/{schedule-S5YZJZ5U.js.map → schedule-RDK4GEPI.js.map} +1 -1
- package/dist/{scheduled-agents-N4LJRM4C.js → scheduled-agents-6U44QE76.js} +11 -11
- package/dist/{schema-R7JWWOF4.js → schema-CHJDC7GQ.js} +4 -8
- package/dist/{schema-R7JWWOF4.js.map → schema-CHJDC7GQ.js.map} +1 -1
- package/dist/{search-KHMQH3AT.js → search-PMJRU3C4.js} +2 -3
- package/dist/{search-KHMQH3AT.js.map → search-PMJRU3C4.js.map} +1 -1
- package/dist/{select-O2FN2JEQ.js → select-OEUKOVZ5.js} +8 -9
- package/dist/{select-O2FN2JEQ.js.map → select-OEUKOVZ5.js.map} +1 -1
- package/dist/{sends-BQZM5PLS.js → sends-WGJVQUMF.js} +4 -5
- package/dist/{sends-BQZM5PLS.js.map → sends-WGJVQUMF.js.map} +1 -1
- package/dist/{set-prompt-2HASHGWC.js → set-prompt-5E5I7QAZ.js} +8 -9
- package/dist/{set-prompt-2HASHGWC.js.map → set-prompt-5E5I7QAZ.js.map} +1 -1
- package/dist/{setup-links-GYSE56GX.js → setup-links-REPREN3C.js} +3 -4
- package/dist/{setup-links-GYSE56GX.js.map → setup-links-REPREN3C.js.map} +1 -1
- package/dist/{site-4SKM7RKG.js → site-WFSWIA3S.js} +4 -5
- package/dist/{site-4SKM7RKG.js.map → site-WFSWIA3S.js.map} +1 -1
- package/dist/{sources-R2NKNC6J.js → sources-AMI2AWKZ.js} +9 -10
- package/dist/{sources-R2NKNC6J.js.map → sources-AMI2AWKZ.js.map} +1 -1
- package/dist/{sources-FQ2UZTHL.js → sources-YBQ6KPFM.js} +6 -6
- package/dist/{stale-W756ACKC.js → stale-IGFUKEN2.js} +7 -8
- package/dist/{stale-W756ACKC.js.map → stale-IGFUKEN2.js.map} +1 -1
- package/dist/{status-SE2VZJJB.js → status-7F2KHFGA.js} +3 -4
- package/dist/{status-SE2VZJJB.js.map → status-7F2KHFGA.js.map} +1 -1
- package/dist/{stock-KXJ26BY4.js → stock-2YCDN3N6.js} +5 -5
- package/dist/{studio-SYKOSNDB.js → studio-RA7QQH4O.js} +1 -1
- package/dist/{sync-LJGSODK3.js → sync-GWTLKZTU.js} +2 -3
- package/dist/{sync-LJGSODK3.js.map → sync-GWTLKZTU.js.map} +1 -1
- package/dist/{sync-definition-QR2N233R.js → sync-definition-UGSDX2SZ.js} +11 -12
- package/dist/{tags-PYWFSBTR.js → tags-3WPW6PTV.js} +4 -4
- package/dist/{tags-QQU3OKMZ.js → tags-6342FQEB.js} +3 -4
- package/dist/{tags-QQU3OKMZ.js.map → tags-6342FQEB.js.map} +1 -1
- package/dist/{tags-5SBMRC2A.js → tags-ABHSX6M5.js} +3 -4
- package/dist/{tags-5SBMRC2A.js.map → tags-ABHSX6M5.js.map} +1 -1
- package/dist/{tags-YYLNF3PK.js → tags-FJIBBBRG.js} +3 -4
- package/dist/{tags-YYLNF3PK.js.map → tags-FJIBBBRG.js.map} +1 -1
- package/dist/{tags-4BAVFH4S.js → tags-KFYLZLB3.js} +2 -3
- package/dist/{tags-4BAVFH4S.js.map → tags-KFYLZLB3.js.map} +1 -1
- package/dist/{targeting-criteria-RJFLFICN.js → targeting-criteria-NR47AF5C.js} +3 -3
- package/dist/{targets-S2MT2PNB.js → targets-L56KOVQE.js} +3 -4
- package/dist/{targets-S2MT2PNB.js.map → targets-L56KOVQE.js.map} +1 -1
- package/dist/{templates-ZE5TOGRT.js → templates-B6XGDYUF.js} +3 -4
- package/dist/{templates-ZE5TOGRT.js.map → templates-B6XGDYUF.js.map} +1 -1
- package/dist/{testimonials-DII5DYLR.js → testimonials-CVC4YIXO.js} +6 -6
- package/dist/{top-companies-PGIAEHDF.js → top-companies-45X3DT7Z.js} +3 -4
- package/dist/{top-companies-PGIAEHDF.js.map → top-companies-45X3DT7Z.js.map} +1 -1
- package/dist/{translate-GXTS633J.js → translate-VP5R67PL.js} +11 -12
- package/dist/{translate-GXTS633J.js.map → translate-VP5R67PL.js.map} +1 -1
- package/dist/{triggers-2PTONXRU.js → triggers-22EMIVFD.js} +3 -4
- package/dist/{triggers-2PTONXRU.js.map → triggers-22EMIVFD.js.map} +1 -1
- package/dist/{unlink-XRMYJ6DB.js → unlink-65KUN6ID.js} +3 -4
- package/dist/{unlink-XRMYJ6DB.js.map → unlink-65KUN6ID.js.map} +1 -1
- package/dist/{unstage-FY7A3YFF.js → unstage-2E3I5SWF.js} +3 -4
- package/dist/{unstage-FY7A3YFF.js.map → unstage-2E3I5SWF.js.map} +1 -1
- package/dist/{unstage-RM2RLXKD.js → unstage-4ZEULXEQ.js} +4 -5
- package/dist/{unstage-RM2RLXKD.js.map → unstage-4ZEULXEQ.js.map} +1 -1
- package/dist/{update-S4562V3O.js → update-2S7CSEAW.js} +3 -4
- package/dist/{update-S4562V3O.js.map → update-2S7CSEAW.js.map} +1 -1
- package/dist/{update-V6YVEUI2.js → update-7NCOTAQZ.js} +3 -4
- package/dist/{update-V6YVEUI2.js.map → update-7NCOTAQZ.js.map} +1 -1
- package/dist/{update-PJ67D2OG.js → update-D6DJC6T7.js} +2 -3
- package/dist/{update-PJ67D2OG.js.map → update-D6DJC6T7.js.map} +1 -1
- package/dist/{update-E5SRBXQR.js → update-KREBPGBH.js} +3 -4
- package/dist/{update-E5SRBXQR.js.map → update-KREBPGBH.js.map} +1 -1
- package/dist/{upload-R6CQVLKF.js → upload-O6NHRPS7.js} +3 -4
- package/dist/{upload-R6CQVLKF.js.map → upload-O6NHRPS7.js.map} +1 -1
- package/dist/{url-options-JOKU46F2.js → url-options-GGXAL3J4.js} +3 -4
- package/dist/{url-options-JOKU46F2.js.map → url-options-GGXAL3J4.js.map} +1 -1
- package/dist/{url-params-7U2XMOWF.js → url-params-3EFGVTZZ.js} +3 -4
- package/dist/{url-params-7U2XMOWF.js.map → url-params-3EFGVTZZ.js.map} +1 -1
- package/dist/{validate-7YPOUKPB.js → validate-CSJM7XZM.js} +9 -10
- package/dist/{validate-7YPOUKPB.js.map → validate-CSJM7XZM.js.map} +1 -1
- package/dist/{videos-LICG6ACJ.js → videos-YSXYGTBM.js} +5 -5
- package/dist/{web-BA2PGTWU.js → web-IGIGVEKS.js} +3 -4
- package/dist/{web-BA2PGTWU.js.map → web-IGIGVEKS.js.map} +1 -1
- package/dist/{winning-ads-C6S2C5VP.js → winning-ads-2WS7FI4E.js} +2 -2
- package/dist/{write-commands-7SJ3BOW5.js → write-commands-5C7FUOVN.js} +4 -5
- package/dist/{write-commands-7SJ3BOW5.js.map → write-commands-5C7FUOVN.js.map} +1 -1
- package/dist/{x-CZHRC6U7.js → x-BFSKFCZD.js} +6 -6
- package/package.json +1 -1
- package/dist/add-2BEGRHUX.js.map +0 -1
- package/dist/analytics-IFELDWLL.js.map +0 -1
- package/dist/chunk-4PDHHHUJ.js +0 -537
- package/dist/chunk-4PDHHHUJ.js.map +0 -1
- package/dist/chunk-7EPXVICM.js.map +0 -1
- package/dist/chunk-ASI4P6X2.js.map +0 -1
- package/dist/chunk-FPOGPFAG.js.map +0 -1
- package/dist/chunk-HR6IWNKE.js.map +0 -1
- package/dist/chunk-HROZYQ5H.js.map +0 -1
- package/dist/chunk-NYIGXDUG.js.map +0 -1
- package/dist/chunk-QE7W555R.js.map +0 -1
- package/dist/flows-KTFAML22.js.map +0 -1
- package/dist/funnel-I6XIAEHG.js.map +0 -1
- package/dist/get-5PKNKJ5S.js.map +0 -1
- package/dist/plan-FT632COT.js +0 -51
- package/dist/plan-FT632COT.js.map +0 -1
- package/dist/questionnaire-JNGYJTAY.js +0 -37
- package/dist/questionnaire-JNGYJTAY.js.map +0 -1
- package/dist/scaffold-static-ad-ECTJL54Y.js.map +0 -1
- /package/dist/{actions-6TQMSVWD.js.map → actions-P35MEMGN.js.map} +0 -0
- /package/dist/{ads-AGYCVD62.js.map → ads-73PGA4YC.js.map} +0 -0
- /package/dist/{avatars-467OSBD6.js.map → avatars-EKCKHCC3.js.map} +0 -0
- /package/dist/{brand-YRTEPGBK.js.map → brand-C6PFGGQN.js.map} +0 -0
- /package/dist/{campaigns-OYMXDGWX.js.map → campaigns-KZYZTXDS.js.map} +0 -0
- /package/dist/{canvas-YQFG52IG.js.map → canvas-5NB27FX2.js.map} +0 -0
- /package/dist/{catalog-XLXIM7IW.js.map → catalog-VSSY6FGI.js.map} +0 -0
- /package/dist/{chunk-5ZNTADVR.js.map → chunk-3G3ZDLMI.js.map} +0 -0
- /package/dist/{chunk-ZDMTXQ2Q.js.map → chunk-3IBYKLXR.js.map} +0 -0
- /package/dist/{chunk-CWYAELVG.js.map → chunk-464O4MT2.js.map} +0 -0
- /package/dist/{chunk-NA63BH7V.js.map → chunk-4AUMTNVB.js.map} +0 -0
- /package/dist/{chunk-NDEE6G2J.js.map → chunk-4BQXAE7Z.js.map} +0 -0
- /package/dist/{chunk-2AOE2MZQ.js.map → chunk-5ZDLTE5T.js.map} +0 -0
- /package/dist/{chunk-ULG4QRTV.js.map → chunk-6NB47MRW.js.map} +0 -0
- /package/dist/{chunk-24EB7EDR.js.map → chunk-7YCRFMXF.js.map} +0 -0
- /package/dist/{chunk-WGUQHAJY.js.map → chunk-A4LOJ2VD.js.map} +0 -0
- /package/dist/{chunk-6F7DVPOS.js.map → chunk-AEOSAVVL.js.map} +0 -0
- /package/dist/{chunk-N4LAYIIN.js.map → chunk-CSYSX4D2.js.map} +0 -0
- /package/dist/{chunk-RX2DKU3W.js.map → chunk-DGUNI37S.js.map} +0 -0
- /package/dist/{chunk-I3ZR655O.js.map → chunk-IR6D7K4H.js.map} +0 -0
- /package/dist/{chunk-FUHN4MFY.js.map → chunk-JQJDXPCO.js.map} +0 -0
- /package/dist/{chunk-7CTMH5AK.js.map → chunk-KAUOHQTF.js.map} +0 -0
- /package/dist/{chunk-VYQ3QJ3C.js.map → chunk-KHRXPQID.js.map} +0 -0
- /package/dist/{chunk-6Y7ZBENQ.js.map → chunk-LECGCWT5.js.map} +0 -0
- /package/dist/{chunk-5WCSKQ7Z.js.map → chunk-LZ73CZGP.js.map} +0 -0
- /package/dist/{chunk-R25YLW6H.js.map → chunk-MELOSESI.js.map} +0 -0
- /package/dist/{chunk-DCRPXOJJ.js.map → chunk-MXYBTMKB.js.map} +0 -0
- /package/dist/{chunk-54C6YDGJ.js.map → chunk-NPY4QUMQ.js.map} +0 -0
- /package/dist/{chunk-LYQJ4PZW.js.map → chunk-OQ6663F4.js.map} +0 -0
- /package/dist/{chunk-H3427GPU.js.map → chunk-OZRUJVIQ.js.map} +0 -0
- /package/dist/{chunk-KMKEYI37.js.map → chunk-Q2V6E6SL.js.map} +0 -0
- /package/dist/{chunk-VL43TNIP.js.map → chunk-QRP3PXWN.js.map} +0 -0
- /package/dist/{chunk-C46GUI2S.js.map → chunk-RZBEK2VE.js.map} +0 -0
- /package/dist/{chunk-2VPBIT65.js.map → chunk-S3A3YOKO.js.map} +0 -0
- /package/dist/{chunk-FYGR3I2A.js.map → chunk-S77PZVYM.js.map} +0 -0
- /package/dist/{chunk-VLMBTPXU.js.map → chunk-SHL7LOC3.js.map} +0 -0
- /package/dist/{chunk-KS2QY6MK.js.map → chunk-W3ZHJJVT.js.map} +0 -0
- /package/dist/{chunk-RL5CP7N6.js.map → chunk-Y6O7EWYY.js.map} +0 -0
- /package/dist/{chunk-6NY2GPR4.js.map → chunk-Y6ZQXUZ7.js.map} +0 -0
- /package/dist/{chunk-WKQG6TER.js.map → chunk-ZEYEWPK6.js.map} +0 -0
- /package/dist/{connect-FCXNVTXG.js.map → connect-QCOGEPP4.js.map} +0 -0
- /package/dist/{creatives-FXUQ5WSD.js.map → creatives-B5NTXPUB.js.map} +0 -0
- /package/dist/{customers-XH2DMTFH.js.map → customers-A36LOZOB.js.map} +0 -0
- /package/dist/{feedback-EIZKS4JU.js.map → feedback-OLTCHE6C.js.map} +0 -0
- /package/dist/{find-FRRHAPWX.js.map → find-OTDIX6V4.js.map} +0 -0
- /package/dist/{fonts-MXR3ZKDX.js.map → fonts-EMMX3KII.js.map} +0 -0
- /package/dist/{ga4-DV2AXCSL.js.map → ga4-UDQ2HA2J.js.map} +0 -0
- /package/dist/{google-QYYYSSXI.js.map → google-KTO3PLEU.js.map} +0 -0
- /package/dist/{google-6OGZX47I.js.map → google-M7KEXVK5.js.map} +0 -0
- /package/dist/{gsc-TAKOF7J5.js.map → gsc-P3QYGDV2.js.map} +0 -0
- /package/dist/{icon-L4RSS6PZ.js.map → icon-I43F77FV.js.map} +0 -0
- /package/dist/{ideas-NFOW3HKJ.js.map → ideas-MIDU7YOA.js.map} +0 -0
- /package/dist/{images-2EFFUNNV.js.map → images-S254MS6O.js.map} +0 -0
- /package/dist/{ingest-2EIKN4QC.js.map → ingest-YV2NLDBE.js.map} +0 -0
- /package/dist/{inspiration-S3DU4CMQ.js.map → inspiration-P265QJ2H.js.map} +0 -0
- /package/dist/{landing-2ZB46LXH.js.map → landing-CJYGWCK4.js.map} +0 -0
- /package/dist/{line-items-5NECXUZT.js.map → line-items-7ZGIKEF2.js.map} +0 -0
- /package/dist/{logo-Q5D7PZY6.js.map → logo-2IP663QO.js.map} +0 -0
- /package/dist/{lookup-ETWY47F7.js.map → lookup-XK45W2SH.js.map} +0 -0
- /package/dist/{media-sources-ZXHEEP6T.js.map → media-sources-O6ZRUA3N.js.map} +0 -0
- /package/dist/{performance-UF5VTY2U.js.map → performance-6QW2KEEQ.js.map} +0 -0
- /package/dist/{promoted-tweets-LZKS5JIF.js.map → promoted-tweets-SURKMHFI.js.map} +0 -0
- /package/dist/{reddit-NU2N3LZD.js.map → reddit-GIP3ADMS.js.map} +0 -0
- /package/dist/{research-FMM6AWZC.js.map → research-2BLEISBG.js.map} +0 -0
- /package/dist/{run-EUO34T2J.js.map → run-MMEDKJDB.js.map} +0 -0
- /package/dist/{scheduled-agents-N4LJRM4C.js.map → scheduled-agents-6U44QE76.js.map} +0 -0
- /package/dist/{sources-FQ2UZTHL.js.map → sources-YBQ6KPFM.js.map} +0 -0
- /package/dist/{stock-KXJ26BY4.js.map → stock-2YCDN3N6.js.map} +0 -0
- /package/dist/{studio-SYKOSNDB.js.map → studio-RA7QQH4O.js.map} +0 -0
- /package/dist/{sync-definition-QR2N233R.js.map → sync-definition-UGSDX2SZ.js.map} +0 -0
- /package/dist/{tags-PYWFSBTR.js.map → tags-3WPW6PTV.js.map} +0 -0
- /package/dist/{targeting-criteria-RJFLFICN.js.map → targeting-criteria-NR47AF5C.js.map} +0 -0
- /package/dist/{testimonials-DII5DYLR.js.map → testimonials-CVC4YIXO.js.map} +0 -0
- /package/dist/{videos-LICG6ACJ.js.map → videos-YSXYGTBM.js.map} +0 -0
- /package/dist/{winning-ads-C6S2C5VP.js.map → winning-ads-2WS7FI4E.js.map} +0 -0
- /package/dist/{x-CZHRC6U7.js.map → x-BFSKFCZD.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/flows/map.ts"],"sourcesContent":["import { readFileSync } from \"node:fs\";\nimport type { HubspotFormsViewResponse } from \"@baker/api\";\nimport { defineCommand } from \"citty\";\nimport { apiPost } from \"../../client.ts\";\nimport { repeatedFlagValues } from \"../../lib/repeatedFlags.ts\";\nimport { writeJson } from \"../../output.ts\";\nimport { registerSchema } from \"../../schemas.ts\";\nimport {\n type BuiltMapping,\n buildFieldMapping,\n type DestinationField,\n describeSlots,\n type MapOptions,\n MappingError,\n namesComeFromAccount,\n otherSlots,\n shapeFor,\n} from \"./mapping.ts\";\nimport {\n collectConfigStatus,\n collectSideEffects,\n flowDataPath,\n readFlowTree,\n requestFlowInputCall,\n sideEffectNeedsInput,\n writeFlowTree,\n} from \"./shared.ts\";\n\nregisterSchema({\n command: \"flows.map\",\n description:\n \"Map form fields onto any named value a side effect sends: a CRM fieldMapping, a sheet columnMapping, a webhook payloadKeys, a pixel eventParams, or a platform matching block. Emits the mapping and splices it in with --write. Configure the destination through request_flow_input FIRST — the destination-side names come from the connected account, not from you.\",\n args: {\n slug: { type: \"positional\", description: \"Form slug (folder under flows/)\", required: true },\n map: {\n type: \"string\",\n description:\n \"<destField>[:<fieldType>]=<value>, repeatable. Omit both this and --from to be told what the side effect accepts instead. Sheet: A=name. HubSpot with --hubspot-form: firstname=nombre (the type is read off the form). Where a destination cannot be read, state the type on the LEFT — c0ffee:varchar=email — because `:` on the right belongs to the value grammar.\",\n required: false,\n },\n from: {\n type: \"string\",\n description:\n 'The whole mapping as a JSON file, or `-` for stdin: { \"sideEffect\": \"…\", \"map\": { \"<destField>\": \"<value>\", … } }. Past ~3 fields prefer this over repeated --map.',\n required: false,\n },\n \"side-effect\": { type: \"string\", description: \"Side-effect id, when the form has more than one\", required: false },\n \"hubspot-form\": {\n type: \"string\",\n description:\n \"HubSpot formGuid of the configured destination. Fills every mapping's fieldType and objectTypeId from the form itself, so you write no types at all. The guid is the `formGuid` in the `destination` request_flow_input returned.\",\n required: false,\n },\n into: {\n type: \"string\",\n description:\n \"Slot to map into when the type has more than one: meta/tiktok/pinterest take eventParams (default) or their matching record; googleAds takes enhancedConversions or value/currency/transactionId.\",\n required: false,\n },\n entity: {\n type: \"string\",\n description: \"Destination object (pipedrive: person|organization|lead, …)\",\n required: false,\n },\n custom: { type: \"boolean\", description: \"The destination fields are custom fields\", required: false },\n standard: { type: \"boolean\", description: \"The destination fields are standard fields\", required: false },\n \"object-type\": { type: \"string\", description: \"HubSpot objectTypeId (default 0-1, contact)\", required: false },\n \"prune-missing\": {\n type: \"boolean\",\n description:\n \"Drop the mappings whose destination field no longer exists on the account, and nothing else. The repair for a deleted HubSpot property: HubSpot refuses the WHOLE submission when it names a field it does not have, so one dead mapping loses every lead. Needs --hubspot-form so the live field list can be read. Runs on its own — no --map required. Prefer this to --replace, which drops everything this call does not name.\",\n required: false,\n },\n replace: {\n type: \"boolean\",\n description:\n \"Make the slot exactly what this call passes, dropping every mapping already in it. Without it, mappings MERGE by destination name — re-mapping a name overwrites it, a new name is appended, and the rest are left alone. To REMOVE a dead mapping, reach for --prune-missing instead: this one also deletes every mapping you did not re-state.\",\n required: false,\n },\n write: {\n type: \"boolean\",\n description: \"Splice the mapping into the form. Without it, prints and changes nothing\",\n required: false,\n },\n },\n});\n\n/**\n * Every `--map` on the command line.\n *\n * Read from `rawArgs`, not `args.map`: citty collapses a repeated flag to its\n * LAST value, so `--map A=name --map B=email` arrives as the single string\n * `\"B=email\"`. Taken from `args`, this command would map one field, report\n * success, and leave the other silently unmapped — which is the exact\n * failure mode it exists to prevent, one level up.\n */\nexport function mapSpecsFrom(rawArgs: readonly string[]): string[] {\n return repeatedFlagValues(rawArgs, \"map\");\n}\n\n/**\n * A whole mapping in one file, which is what a real one looks like.\n *\n * A CRM mapping is eight to fifteen fields. As repeated `--map` flags that is a\n * fifteen-flag command line whose shell quoting is its own hazard — an\n * improvement on hand-writing 230 lines of ProseMirror, but not much of one.\n * The JSON form is what the agent is actually holding in its head, and it is one\n * Write plus one command however many fields there are.\n *\n * {\n * \"sideEffect\": \"se-hubspotForm-1\",\n * \"hubspotForm\": \"8b1f…\",\n * \"map\": {\n * \"email\": \"email\",\n * \"firstname\": \"nombre\",\n * \"hs_lead_source\": \"tracking:utm_source\",\n * \"full_name\": \"nombre + \\\" \\\" + apellido\"\n * }\n * }\n *\n * `\"firstname\": { \"type\": \"…\", \"value\": \"…\" }` is still accepted for a\n * destination this command cannot read, but naming the destination once\n * (`hubspotForm` here, `--hubspot-form` on the command line) is strictly better:\n * the types then come from the account instead of from memory.\n */\ntype MapSpecFile = {\n sideEffect?: string;\n into?: string;\n entity?: string;\n custom?: boolean;\n objectType?: string;\n /**\n * Treat this file as the WHOLE mapping: anything in the slot it does not name\n * is dropped. Off by default so a file that lists three fields cannot delete\n * the five that were mapped before it.\n */\n replace?: boolean;\n /** Drop the mappings the destination no longer has. See `MapOptions.pruneMissing`. */\n pruneMissing?: boolean;\n /** HubSpot formGuid of the configured destination, so its field types can be read. */\n hubspotForm?: string;\n map?: Record<string, string | { type?: string; value?: string }>;\n};\n\n/** Flatten the JSON form into the same `<dest>[:<type>]=<value>` specs the flags produce. */\nexport function specsFromFile(parsed: MapSpecFile): string[] {\n return Object.entries(parsed.map ?? {}).map(([destField, entry]) => {\n if (typeof entry === \"string\") return `${destField}=${entry}`;\n const type = entry?.type ? `:${entry.type}` : \"\";\n return `${destField}${type}=${entry?.value ?? \"\"}`;\n });\n}\n\nfunction readSpecFile(path: string): MapSpecFile {\n let raw: string;\n try {\n raw = path === \"-\" ? readFileSync(0, \"utf-8\") : readFileSync(path, \"utf-8\");\n } catch (error) {\n refuse(\n `Could not read ${path === \"-\" ? \"the mapping from stdin\" : `\"${path}\"`}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (error) {\n refuse(\n `${path === \"-\" ? \"stdin\" : `\"${path}\"`} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`,\n 'Expected { \"map\": { \"<destField>\": \"<value>\", … } }',\n );\n }\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n refuse(\"A mapping file must be a JSON object.\", 'Expected { \"map\": { \"<destField>\": \"<value>\", … } }');\n }\n const spec = parsed as MapSpecFile;\n if (!spec.map || typeof spec.map !== \"object\" || Object.keys(spec.map).length === 0) {\n refuse(\"A mapping file needs a non-empty `map` object.\", 'Expected { \"map\": { \"firstname\": \"nombre\", … } }');\n }\n return spec;\n}\n\n/** Refuse with the same envelope shape everywhere, so the agent parses one thing. */\nfunction refuse(message: string, fix?: string): never {\n writeJson({ ok: false, error: { code: \"VALIDATION_ERROR\", message, ...(fix ? { fix } : {}) } });\n process.exit(1);\n}\n\n/**\n * The destination's own field catalog, read off the connected account.\n *\n * This is the whole reason a HubSpot mapping no longer needs a type per field.\n * `fieldType` and `objectTypeId` are HubSpot's answers about its own properties,\n * not the agent's — the engine concatenates them into\n * `<objectTypeId>.<fieldType>.<fieldName>`, which is byte-for-byte the key the\n * dashboard's picker writes. Asking the agent to remember them is both more work\n * and less accurate than asking HubSpot, and a plausible-but-wrong one is the\n * silent kind: on a date property the engine skips the YYYY-MM-DD coercion and\n * HubSpot drops the value.\n *\n * One call for the whole mapping, and only when a destination was named. A\n * failure refuses rather than falling back to writing types nobody verified.\n */\nasync function hubspotFieldCatalog(\n formId: string,\n): Promise<{ fields: Map<string, DestinationField>; captchaEnabled: boolean }> {\n let response: HubspotFormsViewResponse;\n try {\n response = await apiPost<HubspotFormsViewResponse>(\"/api/hubspot/forms/view\", { formId });\n } catch (error) {\n refuse(\n `Could not read HubSpot form \"${formId}\": ${error instanceof Error ? error.message : String(error)}`,\n \"Check the guid against the `destination` request_flow_input returned, or `baker hubspot forms list`. Drop --hubspot-form and write `<field>:<fieldType>=<value>` per mapping only if HubSpot is unreachable.\",\n );\n }\n const fields = response.data.form?.fields ?? [];\n if (fields.length === 0) {\n refuse(\n `HubSpot form \"${formId}\" reports no fields, so nothing can be mapped against it.`,\n \"Confirm the guid names the form this side effect submits to: baker hubspot forms list\",\n );\n }\n return {\n fields: new Map(\n fields.map((field) => [\n field.name,\n { fieldType: field.fieldType, ...(field.objectTypeId ? { objectTypeId: field.objectTypeId } : {}) },\n ]),\n ),\n // Read while the form is already open, because this is the moment a\n // delivery is being wired: HubSpot refuses every submission sent to a form\n // with spam prevention on, so a mapping written against one is correct and\n // will still never arrive. Reported, not refused — the mapping is not the\n // mistake, and the client can switch it off without the work being redone.\n captchaEnabled: response.data.form?.captchaEnabled === true,\n };\n}\n\n/**\n * Answer the bare `baker flows map <slug> --side-effect <id>` probe.\n *\n * The left of a mapping is a different question per slot — a closed platform\n * set, a name the agent picks, or a name that only exists in the connected\n * account — and none of it was readable without guessing wrong first.\n */\nfunction describeDestination(chosen: Located): void {\n const type = String(chosen.sideEffect.type ?? \"\");\n const slots = describeSlots(type);\n if (slots.length === 0) {\n refuse(\n `A ${type} side effect has no mappable field.`,\n `Nothing on it addresses named values. \\`baker flows schema side-effect ${type}\\` shows what it does take.`,\n );\n }\n writeJson({\n ok: true,\n data: { sideEffectId: chosen.sideEffect.id, type, mappable: slots },\n hints: [\n `Nothing mapped — this is what a ${type} side effect accepts. Add --map <key>=<value> to build one.`,\n ...slots.map((slot) =>\n slot.keys\n ? `${slot.slot}: ${slot.keys.join(\", \")}`\n : `${slot.slot}: ${slot.keysFrom === \"account\" ? \"keys come from the connected account (request_flow_input returns them)\" : \"keys are yours to choose — whatever the receiving system expects\"}`,\n ),\n // Named separately from the key hint above: the key and its field type are\n // two different questions with two different answers, and the type is the\n // one an agent does not know it is being asked until a mapping is refused.\n ...slots.flatMap((slot) => (slot.fieldTypes ? [`${slot.slot} field types — ${slot.fieldTypes}`] : [])),\n 'Values (right of the `=`) are the same for every slot: a form field, tracking:<var>, global:<name>, code:<name>, a \"literal\", or those joined with +. A field may also be written as the file stores it, {{<stepId>.customForm.<field>}}. A value cannot run code (no .split(), .slice(), [0]).',\n ],\n });\n}\n\n/**\n * `shapeFor` as a refusal rather than a throw.\n *\n * `assertDestinationReady` is the one place `shapeFor` is reached BEFORE the\n * try/catch around `buildFieldMapping`, so an uncaught error here would escape\n * the `{ ok: false }` envelope every other path emits and reach the agent as a\n * stack trace.\n *\n * In practice the live case is an unrecognised `--into`, because only a type in\n * `FLOW_SECRET_SIDE_EFFECT_TYPES` gets this far (everything else returns at the\n * `sideEffectNeedsInput` check above) and every one of those has a slot. So\n * `--into eventParams` on an unconfigured `googleSpreadsheet` is enough to hit\n * it, and the message it would lose — the list of slots that type does have —\n * is exactly the one that answers it.\n */\nfunction shapeOrRefuse(type: string, into: string | undefined): ReturnType<typeof shapeFor> {\n try {\n return shapeFor(type, into);\n } catch (error) {\n if (error instanceof MappingError) refuse(error.message, error.fix);\n throw error;\n }\n}\n\n/**\n * Stop a mapping written against a destination nobody has picked yet.\n *\n * This is the failure the whole command exists to prevent, one level up: the\n * column letters and field keys live in an account only `request_flow_input`\n * can see, so before that call has run they can only be guesses — and a guessed\n * destination is structurally valid, passes every check here, ships, and sends\n * nothing forever. `verify` does catch it later (`flow-schema-unconfigured-oauth`),\n * but by then the mapping is written and the agent has moved on.\n *\n * Only for slots whose names come from the account. A webhook body or a pixel\n * parameter is the agent's to name, so an unset endpoint is a note, not a block.\n */\nfunction assertDestinationReady(\n slug: string,\n tree: Record<string, unknown>,\n chosen: Located,\n into: string | undefined,\n): void {\n if (!sideEffectNeedsInput(chosen.sideEffect)) return;\n\n const type = String(chosen.sideEffect.type ?? \"\");\n const status = collectConfigStatusFor(tree, slug, String(chosen.sideEffect.id ?? \"\"));\n const call = status ? requestFlowInputCall(slug, status) : `request_flow_input for the ${type} side effect`;\n\n if (!namesComeFromAccount(shapeOrRefuse(type, into))) return;\n\n refuse(\n `The ${type} destination is not configured yet, so its field names cannot be anything but a guess.`,\n `Configure it first, then map against the names that call returns: ${call}`,\n );\n}\n\n/** The config row for one side effect, so the refusal can carry a ready-to-issue call. */\nfunction collectConfigStatusFor(tree: Record<string, unknown>, _slug: string, sideEffectId: string) {\n const rows: Parameters<typeof requestFlowInputCall>[1][] = [];\n collectConfigStatus(tree, rows);\n return rows.find((row) => row.sideEffectId === sideEffectId);\n}\n\n/**\n * Name the slots this side effect has and this call did not use.\n *\n * A `meta` side effect has both `eventParams` and `advancedMatching`, and the\n * one an agent most often needs — advanced matching, which decides whether Meta\n * can attribute the conversion at all — is not the default. Saying so on every\n * response is cheaper than the agent finding out from a reference file it may\n * not open.\n */\nfunction slotHintFor(type: string, into: string | undefined): string[] {\n const others = otherSlots(type, shapeFor(type, into));\n if (others.length === 0) return [];\n return [`This side effect also takes ${others.join(\" and \")} — pass --into <slot> to map into one of those instead.`];\n}\n\n/**\n * What happened to the mappings this call did NOT name.\n *\n * Said out loud in both directions, because a slot whose size moved without\n * being mentioned is exactly how the loss stays silent: \"kept\" answers the\n * question a merge raises (\"did it drop the others?\"), and `--replace` has to\n * state its drop or it is the same bug with a flag on it.\n */\nfunction survivorHint(built: BuiltMapping, replacing: boolean): string[] {\n if (built.kept > 0) {\n return [`${built.kept} mapping${built.kept === 1 ? \"\" : \"s\"} already in ${built.key} kept — this merged by name.`];\n }\n if (!replacing) return [];\n return [`--replace: ${built.key} is now exactly these ${built.count}; anything else it held is gone.`];\n}\n\n/**\n * Every mapping `--prune-missing` removed, named one by one.\n *\n * A count would be the same mistake this whole repair exists to undo: the drift\n * Task that nobody could act on said \"an answer HubSpot no longer accepts\" and\n * named none of them, and six Forms were closed as false positives off that\n * sentence. A removal the agent cannot repeat back to the user is a removal\n * nobody can check.\n */\nfunction droppedHint(built: BuiltMapping): string[] {\n if (built.dropped.length === 0) return [];\n return [\n `--prune-missing dropped ${built.dropped.length} mapping${built.dropped.length === 1 ? \"\" : \"s\"} the destination no longer has: ${built.dropped.join(\", \")}. Every other mapping in ${built.key} was left alone.`,\n ];\n}\n\n/**\n * A note, not a block: these keys are the agent's to choose, but the endpoint\n * they are posted to is still the user's to supply, and nothing later in this\n * command will mention it.\n */\nfunction pendingEndpointHint(slug: string, tree: Record<string, unknown>, chosen: Located): string[] {\n if (!sideEffectNeedsInput(chosen.sideEffect)) return [];\n const status = collectConfigStatusFor(tree, slug, String(chosen.sideEffect.id ?? \"\"));\n if (!status) return [];\n return [`The mapping is written, but this destination still needs the user: ${requestFlowInputCall(slug, status)}`];\n}\n\ntype Located = { node: Record<string, unknown>; sideEffect: Record<string, unknown> };\n\n/** The side effect to map into: the named one, or the only one. Never a guess between several. */\nfunction pickSideEffect(slug: string, found: Located[], named: string | undefined): Located {\n if (found.length === 0) {\n refuse(\n `\"${slug}\" has no side effects — author the side effect first, then map into it.`,\n `baker flows add-side-effect ${slug} --node <nodeId> --type <type>`,\n );\n }\n const chosen = named\n ? found.find((entry) => entry.sideEffect.id === named)\n : found.length === 1\n ? found[0]\n : undefined;\n if (chosen) return chosen;\n\n const inventory = found.map((entry) => `${entry.sideEffect.id} (${entry.sideEffect.type})`).join(\", \");\n refuse(\n named\n ? `No side effect with id \"${named}\" in \"${slug}\".`\n : `\"${slug}\" has ${found.length} side effects — name one with --side-effect <id>.`,\n `Side effects in this form: ${inventory}`,\n );\n}\n\n/**\n * `--custom` and `--standard` answer the same question, and the answer decides\n * whether the write lands or is silently dropped. Taking the last flag would\n * pick one of two contradictory instructions at random.\n */\nfunction customFlag(custom: unknown, standard: unknown): boolean | undefined {\n if (custom === true && standard === true) {\n refuse(\"--custom and --standard contradict each other. Pass one.\");\n }\n if (custom === true) return true;\n if (standard === true) return false;\n return undefined;\n}\n\n/**\n * The destination-side options, from the flags and the mapping file together.\n *\n * A flag beats the file, so a saved mapping can be retargeted without editing\n * it. The destination catalog is read HERE, before anything is built, so every\n * mapping's field type is derived from the account rather than remembered —\n * and only when a destination was actually named: without one the build still\n * runs, and refuses per mapping if it turns out a type was needed.\n */\nasync function mapOptions(\n args: Record<string, unknown>,\n fromFile: MapSpecFile | undefined,\n into: string | undefined,\n): Promise<{ options: MapOptions; hints: string[] }> {\n const hubspotForm = args[\"hubspot-form\"] ? String(args[\"hubspot-form\"]) : fromFile?.hubspotForm;\n const catalog = hubspotForm ? await hubspotFieldCatalog(hubspotForm) : undefined;\n return {\n options: {\n into,\n entity: args.entity ? String(args.entity) : fromFile?.entity,\n isCustomField: customFlag(args.custom, args.standard) ?? fromFile?.custom,\n objectType: args[\"object-type\"] ? String(args[\"object-type\"]) : fromFile?.objectType,\n replace: args.replace === true || fromFile?.replace === true,\n pruneMissing: args[\"prune-missing\"] === true || fromFile?.pruneMissing === true,\n destinationFields: catalog?.fields,\n },\n hints: catalog?.captchaEnabled\n ? [\n \"WARNING: this HubSpot form has spam prevention (captcha) on. HubSpot refuses every submission sent to a form with it on, so nothing mapped here will arrive — the mapping is fine, the destination is not. Only the user can switch it off, on the form in HubSpot. Tell them that, and do not swap the destination yourself.\",\n ]\n : [],\n };\n}\n\nexport const mapCommand = defineCommand({\n meta: {\n name: \"map\",\n description:\n \"Map form fields onto any value a side effect sends — never hand-write a mapping. Start here: baker flows map contact --from map.json --write\",\n },\n args: {\n slug: { type: \"positional\", description: \"Form slug\", required: true },\n map: { type: \"string\", description: \"<destField>[:<fieldType>]=<value> (repeatable)\" },\n from: { type: \"string\", description: \"Read the whole mapping from a JSON file, or `-` for stdin\" },\n \"side-effect\": { type: \"string\", description: \"Side-effect id, when the form has more than one\" },\n \"hubspot-form\": {\n type: \"string\",\n description: \"HubSpot formGuid — reads every field's type off the form so you write none\",\n },\n into: {\n type: \"string\",\n description: \"Which slot to map into, for a type with more than one (e.g. meta: eventParams | advancedMatching)\",\n },\n entity: { type: \"string\", description: \"Destination object (person, contact, lead, …)\" },\n custom: { type: \"boolean\", description: \"Destination fields are custom fields\" },\n standard: { type: \"boolean\", description: \"Destination fields are standard fields\" },\n \"object-type\": { type: \"string\", description: \"HubSpot objectTypeId (default 0-1)\" },\n \"prune-missing\": {\n type: \"boolean\",\n description: \"Drop only the mappings the destination no longer has — the repair for a deleted HubSpot field\",\n },\n replace: {\n type: \"boolean\",\n description: \"Drop every mapping already in the slot. Default merges by destination name\",\n },\n write: { type: \"boolean\", description: \"Splice the mapping into the form\" },\n },\n run: async ({ args, rawArgs }) => {\n const slug = String(args.slug);\n const fromFile = args.from ? readSpecFile(String(args.from)) : undefined;\n const specs = fromFile ? specsFromFile(fromFile) : mapSpecsFrom(rawArgs);\n const into = args.into ? String(args.into) : fromFile?.into;\n const replacing = args.replace === true || fromFile?.replace === true;\n const pruning = args[\"prune-missing\"] === true || fromFile?.pruneMissing === true;\n\n const tree = readFlowTree(slug);\n // A flag beats the file, so a saved mapping can be retargeted without editing it.\n const chosen = pickSideEffect(\n slug,\n collectSideEffects(tree),\n args[\"side-effect\"] ? String(args[\"side-effect\"]) : fromFile?.sideEffect,\n );\n\n // No mappings given: answer \"what can I map here, and where do the key names\n // come from\" rather than printing usage. The command already holds the side\n // effect, so refusing threw the answer away and left the only discovery path\n // a wrong guess — name a key outside a closed set and read it off the refusal.\n // `--prune-missing` is a whole call on its own: the repair for a deleted\n // destination field is a removal, and requiring a `--map` alongside it would\n // mean inventing a mapping to make a deletion legal.\n if (specs.length === 0 && !pruning) {\n describeDestination(chosen);\n return;\n }\n\n assertDestinationReady(slug, tree, chosen, into);\n\n const { options, hints: destinationHints } = await mapOptions(args, fromFile, into);\n\n let built: ReturnType<typeof buildFieldMapping>;\n try {\n built = buildFieldMapping(tree, chosen.sideEffect, specs, options);\n } catch (error) {\n if (error instanceof MappingError) {\n refuse(error.message, error.fix);\n }\n throw error;\n }\n\n const slotHint = [\n ...destinationHints,\n ...droppedHint(built),\n ...survivorHint(built, replacing),\n ...slotHintFor(String(chosen.sideEffect.type ?? \"\"), into),\n ...pendingEndpointHint(slug, tree, chosen),\n ];\n\n if (args.write !== true) {\n emitDryRun(slug, chosen, built, slotHint);\n return;\n }\n\n Object.assign(chosen.sideEffect, built.patch);\n writeFlowTree(slug, tree);\n emitWritten(slug, chosen, built, slotHint);\n },\n});\n\n/**\n * The first line of the answer: what this call did, or would do.\n *\n * It has to survive a call that only REMOVES. `--prune-missing` on its own\n * writes nothing and drops something, and \"Wrote 0 fieldMapping mappings\"\n * describes the opposite of what happened — it reads as a no-op, which is the\n * one reading that sends an agent looking for a different command after the\n * repair has already landed. The drops are named by `droppedHint` two lines\n * further down, and that is not where anybody looks to find out whether a\n * command worked.\n *\n * Exported for its own test, because this sentence is the whole report.\n */\nexport function mapHeadline(built: BuiltMapping, phase: \"written\" | \"dry-run\", slug = \"\"): string {\n const wrote = `${built.count} ${built.key} mapping${built.count === 1 ? \"\" : \"s\"}`;\n const drops = `${built.dropped.length} dead mapping${built.dropped.length === 1 ? \"\" : \"s\"}`;\n\n if (phase === \"dry-run\") {\n if (built.count === 0 && built.dropped.length > 0) {\n return `Nothing written. Re-run with --write to drop ${drops} from ${slug}.`;\n }\n return `Nothing written. Re-run with --write to splice ${wrote} into ${slug}.`;\n }\n\n if (built.dropped.length === 0) return `Wrote ${wrote}.`;\n if (built.count === 0) return `Dropped ${drops} from ${built.key}; nothing else changed.`;\n return `Wrote ${wrote} and dropped ${drops}.`;\n}\n\n/** What the call WOULD do, plus the one sentence saying how to make it happen. */\nfunction emitDryRun(slug: string, chosen: Located, built: BuiltMapping, slotHint: string[]): void {\n writeJson({\n ok: true,\n data: {\n sideEffectId: chosen.sideEffect.id,\n type: chosen.sideEffect.type,\n key: built.key,\n patch: built.patch,\n },\n hints: [mapHeadline(built, \"dry-run\", slug), ...slotHint],\n });\n}\n\nfunction emitWritten(slug: string, chosen: Located, built: BuiltMapping, slotHint: string[]): void {\n writeJson({\n ok: true,\n data: {\n sideEffectId: chosen.sideEffect.id,\n type: chosen.sideEffect.type,\n key: built.key,\n written: built.count,\n kept: built.kept,\n dropped: built.dropped,\n path: flowDataPath(slug),\n },\n hints: [\n mapHeadline(built, \"written\"),\n `A mapping is only real once the destination is set — check with: baker flows show ${slug}`,\n ...slotHint,\n ],\n });\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/commands/flows/map.ts"],"sourcesContent":["import { readFileSync } from \"node:fs\";\nimport type { HubspotFormsViewResponse } from \"@baker/api\";\nimport { defineCommand } from \"citty\";\nimport { apiPost } from \"../../client.ts\";\nimport { repeatedFlagValues } from \"../../lib/repeatedFlags.ts\";\nimport { writeJson } from \"../../output.ts\";\nimport { registerSchema } from \"../../schemas.ts\";\nimport {\n type BuiltMapping,\n buildFieldMapping,\n type DestinationField,\n describeSlots,\n type MapOptions,\n MappingError,\n namesComeFromAccount,\n otherSlots,\n shapeFor,\n} from \"./mapping.ts\";\nimport {\n collectConfigStatus,\n collectSideEffects,\n flowDataPath,\n readFlowTree,\n requestFlowInputCall,\n sideEffectNeedsInput,\n writeFlowTree,\n} from \"./shared.ts\";\n\nregisterSchema({\n command: \"flows.map\",\n description:\n \"Map form fields onto any named value a side effect sends: a CRM fieldMapping, a sheet columnMapping, a webhook payloadKeys, a pixel eventParams, or a platform matching block. Emits the mapping and splices it in with --write. Configure the destination through request_flow_input FIRST — the destination-side names come from the connected account, not from you.\",\n args: {\n slug: { type: \"positional\", description: \"Form slug (folder under flows/)\", required: true },\n map: {\n type: \"string\",\n description:\n \"<destField>[:<fieldType>]=<value>, repeatable. Omit both this and --from to be told what the side effect accepts instead. Sheet: A=name. HubSpot with --hubspot-form: firstname=nombre (the type is read off the form). Where a destination cannot be read, state the type on the LEFT — c0ffee:varchar=email — because `:` on the right belongs to the value grammar.\",\n required: false,\n },\n from: {\n type: \"string\",\n description:\n 'The whole mapping as a JSON file, or `-` for stdin: { \"sideEffect\": \"…\", \"map\": { \"<destField>\": \"<value>\", … } }. Past ~3 fields prefer this over repeated --map.',\n required: false,\n },\n \"side-effect\": { type: \"string\", description: \"Side-effect id, when the form has more than one\", required: false },\n \"hubspot-form\": {\n type: \"string\",\n description:\n \"HubSpot formGuid of the configured destination. Fills every mapping's fieldType and objectTypeId from the form itself, so you write no types at all. The guid is the `formGuid` in the `destination` request_flow_input returned.\",\n required: false,\n },\n into: {\n type: \"string\",\n description:\n \"Slot to map into when the type has more than one: meta/tiktok/pinterest take eventParams (default) or their matching record; googleAds takes enhancedConversions or value/currency/transactionId.\",\n required: false,\n },\n entity: {\n type: \"string\",\n description: \"Destination object (pipedrive: person|organization|lead, …)\",\n required: false,\n },\n custom: { type: \"boolean\", description: \"The destination fields are custom fields\", required: false },\n standard: { type: \"boolean\", description: \"The destination fields are standard fields\", required: false },\n \"object-type\": { type: \"string\", description: \"HubSpot objectTypeId (default 0-1, contact)\", required: false },\n \"prune-missing\": {\n type: \"boolean\",\n description:\n \"Drop the mappings whose destination field no longer exists on the account, and nothing else. The repair for a deleted HubSpot property: HubSpot refuses the WHOLE submission when it names a field it does not have, so one dead mapping loses every lead. Needs --hubspot-form so the live field list can be read. Runs on its own — no --map required. Prefer this to --replace, which drops everything this call does not name.\",\n required: false,\n },\n replace: {\n type: \"boolean\",\n description:\n \"Make the slot exactly what this call passes, dropping every mapping already in it. Without it, mappings MERGE by destination name — re-mapping a name overwrites it, a new name is appended, and the rest are left alone. To REMOVE a dead mapping, reach for --prune-missing instead: this one also deletes every mapping you did not re-state.\",\n required: false,\n },\n write: {\n type: \"boolean\",\n description: \"Splice the mapping into the form. Without it, prints and changes nothing\",\n required: false,\n },\n },\n});\n\n/**\n * Every `--map` on the command line.\n *\n * Read from `rawArgs`, not `args.map`: citty collapses a repeated flag to its\n * LAST value, so `--map A=name --map B=email` arrives as the single string\n * `\"B=email\"`. Taken from `args`, this command would map one field, report\n * success, and leave the other silently unmapped — which is the exact\n * failure mode it exists to prevent, one level up.\n */\nexport function mapSpecsFrom(rawArgs: readonly string[]): string[] {\n return repeatedFlagValues(rawArgs, \"map\");\n}\n\n/**\n * A whole mapping in one file, which is what a real one looks like.\n *\n * A CRM mapping is eight to fifteen fields. As repeated `--map` flags that is a\n * fifteen-flag command line whose shell quoting is its own hazard — an\n * improvement on hand-writing 230 lines of ProseMirror, but not much of one.\n * The JSON form is what the agent is actually holding in its head, and it is one\n * Write plus one command however many fields there are.\n *\n * {\n * \"sideEffect\": \"se-hubspotForm-1\",\n * \"hubspotForm\": \"8b1f…\",\n * \"map\": {\n * \"email\": \"email\",\n * \"firstname\": \"nombre\",\n * \"hs_lead_source\": \"tracking:utm_source\",\n * \"full_name\": \"nombre + \\\" \\\" + apellido\"\n * }\n * }\n *\n * `\"firstname\": { \"type\": \"…\", \"value\": \"…\" }` is still accepted for a\n * destination this command cannot read, but naming the destination once\n * (`hubspotForm` here, `--hubspot-form` on the command line) is strictly better:\n * the types then come from the account instead of from memory.\n */\ntype MapSpecFile = {\n sideEffect?: string;\n into?: string;\n entity?: string;\n custom?: boolean;\n objectType?: string;\n /**\n * Treat this file as the WHOLE mapping: anything in the slot it does not name\n * is dropped. Off by default so a file that lists three fields cannot delete\n * the five that were mapped before it.\n */\n replace?: boolean;\n /** Drop the mappings the destination no longer has. See `MapOptions.pruneMissing`. */\n pruneMissing?: boolean;\n /** HubSpot formGuid of the configured destination, so its field types can be read. */\n hubspotForm?: string;\n map?: Record<string, string | { type?: string; value?: string }>;\n};\n\n/** Flatten the JSON form into the same `<dest>[:<type>]=<value>` specs the flags produce. */\nexport function specsFromFile(parsed: MapSpecFile): string[] {\n return Object.entries(parsed.map ?? {}).map(([destField, entry]) => {\n if (typeof entry === \"string\") return `${destField}=${entry}`;\n const type = entry?.type ? `:${entry.type}` : \"\";\n return `${destField}${type}=${entry?.value ?? \"\"}`;\n });\n}\n\nfunction readSpecFile(path: string): MapSpecFile {\n let raw: string;\n try {\n raw = path === \"-\" ? readFileSync(0, \"utf-8\") : readFileSync(path, \"utf-8\");\n } catch (error) {\n refuse(\n `Could not read ${path === \"-\" ? \"the mapping from stdin\" : `\"${path}\"`}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (error) {\n refuse(\n `${path === \"-\" ? \"stdin\" : `\"${path}\"`} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`,\n 'Expected { \"map\": { \"<destField>\": \"<value>\", … } }',\n );\n }\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n refuse(\"A mapping file must be a JSON object.\", 'Expected { \"map\": { \"<destField>\": \"<value>\", … } }');\n }\n const spec = parsed as MapSpecFile;\n if (!spec.map || typeof spec.map !== \"object\" || Object.keys(spec.map).length === 0) {\n refuse(\"A mapping file needs a non-empty `map` object.\", 'Expected { \"map\": { \"firstname\": \"nombre\", … } }');\n }\n return spec;\n}\n\n/** Refuse with the same envelope shape everywhere, so the agent parses one thing. */\nfunction refuse(message: string, fix?: string): never {\n writeJson({ ok: false, error: { code: \"VALIDATION_ERROR\", message, ...(fix ? { fix } : {}) } });\n process.exit(1);\n}\n\n/**\n * The destination's own field catalog, read off the connected account.\n *\n * This is the whole reason a HubSpot mapping no longer needs a type per field.\n * `fieldType` and `objectTypeId` are HubSpot's answers about its own properties,\n * not the agent's — the engine concatenates them into\n * `<objectTypeId>.<fieldType>.<fieldName>`, which is byte-for-byte the key the\n * dashboard's picker writes. Asking the agent to remember them is both more work\n * and less accurate than asking HubSpot, and a plausible-but-wrong one is the\n * silent kind: on a date property the engine skips the YYYY-MM-DD coercion and\n * HubSpot drops the value.\n *\n * One call for the whole mapping, and only when a destination was named. A\n * failure refuses rather than falling back to writing types nobody verified.\n */\nasync function hubspotFieldCatalog(\n formId: string,\n): Promise<{ fields: Map<string, DestinationField>; captchaEnabled: boolean }> {\n let response: HubspotFormsViewResponse;\n try {\n response = await apiPost<HubspotFormsViewResponse>(\"/api/hubspot/forms/view\", { formId });\n } catch (error) {\n refuse(\n `Could not read HubSpot form \"${formId}\": ${error instanceof Error ? error.message : String(error)}`,\n \"Check the guid against the `destination` request_flow_input returned, or `baker hubspot forms list`. Drop --hubspot-form and write `<field>:<fieldType>=<value>` per mapping only if HubSpot is unreachable.\",\n );\n }\n const fields = response.data.form?.fields ?? [];\n if (fields.length === 0) {\n refuse(\n `HubSpot form \"${formId}\" reports no fields, so nothing can be mapped against it.`,\n \"Confirm the guid names the form this side effect submits to: baker hubspot forms list\",\n );\n }\n return {\n fields: new Map(\n fields.map((field) => [\n field.name,\n { fieldType: field.fieldType, ...(field.objectTypeId ? { objectTypeId: field.objectTypeId } : {}) },\n ]),\n ),\n // Read while the form is already open, because this is the moment a\n // delivery is being wired: HubSpot refuses every submission sent to a form\n // with spam prevention on, so a mapping written against one is correct and\n // will still never arrive. Reported, not refused — the mapping is not the\n // mistake, and the client can switch it off without the work being redone.\n captchaEnabled: response.data.form?.captchaEnabled === true,\n };\n}\n\n/**\n * Answer the bare `baker flows map <slug> --side-effect <id>` probe.\n *\n * The left of a mapping is a different question per slot — a closed platform\n * set, a name the agent picks, or a name that only exists in the connected\n * account — and none of it was readable without guessing wrong first.\n */\nfunction describeDestination(chosen: Located): void {\n const type = String(chosen.sideEffect.type ?? \"\");\n const slots = describeSlots(type);\n if (slots.length === 0) {\n refuse(\n `A ${type} side effect has no mappable field.`,\n `Nothing on it addresses named values. \\`baker flows schema side-effect ${type}\\` shows what it does take.`,\n );\n }\n writeJson({\n ok: true,\n data: { sideEffectId: chosen.sideEffect.id, type, mappable: slots },\n hints: [\n `Nothing mapped — this is what a ${type} side effect accepts. Add --map <key>=<value> to build one.`,\n ...slots.map((slot) =>\n slot.keys\n ? `${slot.slot}: ${slot.keys.join(\", \")}`\n : `${slot.slot}: ${slot.keysFrom === \"account\" ? \"keys come from the connected account (request_flow_input returns them)\" : \"keys are yours to choose — whatever the receiving system expects\"}`,\n ),\n // Named separately from the key hint above: the key and its field type are\n // two different questions with two different answers, and the type is the\n // one an agent does not know it is being asked until a mapping is refused.\n ...slots.flatMap((slot) => (slot.fieldTypes ? [`${slot.slot} field types — ${slot.fieldTypes}`] : [])),\n 'Values (right of the `=`) are the same for every slot: a form field, tracking:<var>, global:<name>, code:<name>, a \"literal\", or those joined with +. A field may also be written as the file stores it, {{<stepId>.customForm.<field>}}. A value cannot run code (no .split(), .slice(), [0]).',\n ],\n });\n}\n\n/**\n * `shapeFor` as a refusal rather than a throw.\n *\n * `assertDestinationReady` is the one place `shapeFor` is reached BEFORE the\n * try/catch around `buildFieldMapping`, so an uncaught error here would escape\n * the `{ ok: false }` envelope every other path emits and reach the agent as a\n * stack trace.\n *\n * In practice the live case is an unrecognised `--into`, because only a type in\n * `FLOW_SECRET_SIDE_EFFECT_TYPES` gets this far (everything else returns at the\n * `sideEffectNeedsInput` check above) and every one of those has a slot. So\n * `--into eventParams` on an unconfigured `googleSpreadsheet` is enough to hit\n * it, and the message it would lose — the list of slots that type does have —\n * is exactly the one that answers it.\n */\nfunction shapeOrRefuse(type: string, into: string | undefined): ReturnType<typeof shapeFor> {\n try {\n return shapeFor(type, into);\n } catch (error) {\n if (error instanceof MappingError) refuse(error.message, error.fix);\n throw error;\n }\n}\n\n/**\n * Stop a mapping written against a destination nobody has picked yet.\n *\n * This is the failure the whole command exists to prevent, one level up: the\n * column letters and field keys live in an account only `request_flow_input`\n * can see, so before that call has run they can only be guesses — and a guessed\n * destination is structurally valid, passes every check here, ships, and sends\n * nothing forever. `verify` does catch it later (`flow-schema-unconfigured-oauth`),\n * but by then the mapping is written and the agent has moved on.\n *\n * Only for slots whose names come from the account. A webhook body or a pixel\n * parameter is the agent's to name, so an unset endpoint is a note, not a block.\n */\nfunction assertDestinationReady(\n slug: string,\n tree: Record<string, unknown>,\n chosen: Located,\n into: string | undefined,\n): void {\n if (!sideEffectNeedsInput(chosen.sideEffect)) return;\n\n const type = String(chosen.sideEffect.type ?? \"\");\n const status = collectConfigStatusFor(tree, slug, String(chosen.sideEffect.id ?? \"\"));\n const call = status ? requestFlowInputCall(slug, status) : `request_flow_input for the ${type} side effect`;\n\n if (!namesComeFromAccount(shapeOrRefuse(type, into))) return;\n\n refuse(\n `The ${type} destination is not configured yet, so its field names cannot be anything but a guess.`,\n `Configure it first, then map against the names that call returns: ${call}`,\n );\n}\n\n/** The config row for one side effect, so the refusal can carry a ready-to-issue call. */\nfunction collectConfigStatusFor(tree: Record<string, unknown>, _slug: string, sideEffectId: string) {\n const rows: Parameters<typeof requestFlowInputCall>[1][] = [];\n collectConfigStatus(tree, rows);\n return rows.find((row) => row.sideEffectId === sideEffectId);\n}\n\n/**\n * Name the slots this side effect has and this call did not use.\n *\n * A `meta` side effect has both `eventParams` and `advancedMatching`, and the\n * one an agent most often needs — advanced matching, which decides whether Meta\n * can attribute the conversion at all — is not the default. Saying so on every\n * response is cheaper than the agent finding out from a reference file it may\n * not open.\n */\nfunction slotHintFor(type: string, into: string | undefined): string[] {\n const others = otherSlots(type, shapeFor(type, into));\n if (others.length === 0) return [];\n return [`This side effect also takes ${others.join(\" and \")} — pass --into <slot> to map into one of those instead.`];\n}\n\n/**\n * What happened to the mappings this call did NOT name.\n *\n * Said out loud in both directions, because a slot whose size moved without\n * being mentioned is exactly how the loss stays silent: \"kept\" answers the\n * question a merge raises (\"did it drop the others?\"), and `--replace` has to\n * state its drop or it is the same bug with a flag on it.\n */\nfunction survivorHint(built: BuiltMapping, replacing: boolean): string[] {\n if (built.kept > 0) {\n return [`${built.kept} mapping${built.kept === 1 ? \"\" : \"s\"} already in ${built.key} kept — this merged by name.`];\n }\n if (!replacing) return [];\n return [`--replace: ${built.key} is now exactly these ${built.count}; anything else it held is gone.`];\n}\n\n/**\n * Every mapping `--prune-missing` removed, named one by one.\n *\n * A count would be the same mistake this whole repair exists to undo: the drift\n * Task that nobody could act on said \"an answer HubSpot no longer accepts\" and\n * named none of them, and six Forms were closed as false positives off that\n * sentence. A removal the agent cannot repeat back to the user is a removal\n * nobody can check.\n */\nfunction droppedHint(built: BuiltMapping): string[] {\n if (built.dropped.length === 0) return [];\n return [\n `--prune-missing dropped ${built.dropped.length} mapping${built.dropped.length === 1 ? \"\" : \"s\"} the destination no longer has: ${built.dropped.join(\", \")}. Every other mapping in ${built.key} was left alone.`,\n ];\n}\n\n/**\n * A note, not a block: these keys are the agent's to choose, but the endpoint\n * they are posted to is still the user's to supply, and nothing later in this\n * command will mention it.\n */\nfunction pendingEndpointHint(slug: string, tree: Record<string, unknown>, chosen: Located): string[] {\n if (!sideEffectNeedsInput(chosen.sideEffect)) return [];\n const status = collectConfigStatusFor(tree, slug, String(chosen.sideEffect.id ?? \"\"));\n if (!status) return [];\n return [`The mapping is written, but this destination still needs the user: ${requestFlowInputCall(slug, status)}`];\n}\n\ntype Located = { node: Record<string, unknown>; sideEffect: Record<string, unknown> };\n\n/** The side effect to map into: the named one, or the only one. Never a guess between several. */\nfunction pickSideEffect(slug: string, found: Located[], named: string | undefined): Located {\n if (found.length === 0) {\n refuse(\n `\"${slug}\" has no side effects — author the side effect first, then map into it.`,\n `baker flows add-side-effect ${slug} --node <nodeId> --type <type>`,\n );\n }\n const chosen = named\n ? found.find((entry) => entry.sideEffect.id === named)\n : found.length === 1\n ? found[0]\n : undefined;\n if (chosen) return chosen;\n\n const inventory = found.map((entry) => `${entry.sideEffect.id} (${entry.sideEffect.type})`).join(\", \");\n refuse(\n named\n ? `No side effect with id \"${named}\" in \"${slug}\".`\n : `\"${slug}\" has ${found.length} side effects — name one with --side-effect <id>.`,\n `Side effects in this form: ${inventory}`,\n );\n}\n\n/**\n * `--custom` and `--standard` answer the same question, and the answer decides\n * whether the write lands or is silently dropped. Taking the last flag would\n * pick one of two contradictory instructions at random.\n */\nfunction customFlag(custom: unknown, standard: unknown): boolean | undefined {\n if (custom === true && standard === true) {\n refuse(\"--custom and --standard contradict each other. Pass one.\");\n }\n if (custom === true) return true;\n if (standard === true) return false;\n return undefined;\n}\n\n/**\n * The destination-side options, from the flags and the mapping file together.\n *\n * A flag beats the file, so a saved mapping can be retargeted without editing\n * it. The destination catalog is read HERE, before anything is built, so every\n * mapping's field type is derived from the account rather than remembered —\n * and only when a destination was actually named: without one the build still\n * runs, and refuses per mapping if it turns out a type was needed.\n */\nasync function mapOptions(\n args: Record<string, unknown>,\n fromFile: MapSpecFile | undefined,\n into: string | undefined,\n): Promise<{ options: MapOptions; hints: string[] }> {\n const hubspotForm = args[\"hubspot-form\"] ? String(args[\"hubspot-form\"]) : fromFile?.hubspotForm;\n const catalog = hubspotForm ? await hubspotFieldCatalog(hubspotForm) : undefined;\n return {\n options: {\n into,\n entity: args.entity ? String(args.entity) : fromFile?.entity,\n isCustomField: customFlag(args.custom, args.standard) ?? fromFile?.custom,\n objectType: args[\"object-type\"] ? String(args[\"object-type\"]) : fromFile?.objectType,\n replace: args.replace === true || fromFile?.replace === true,\n pruneMissing: args[\"prune-missing\"] === true || fromFile?.pruneMissing === true,\n destinationFields: catalog?.fields,\n },\n hints: catalog?.captchaEnabled\n ? [\n \"WARNING: this HubSpot form has spam prevention (captcha) on. HubSpot refuses every submission sent to a form with it on, so nothing mapped here will arrive — the mapping is fine, the destination is not. Only the user can switch it off, on the form in HubSpot. Tell them that, and do not swap the destination yourself.\",\n ]\n : [],\n };\n}\n\nexport const mapCommand = defineCommand({\n meta: {\n name: \"map\",\n description:\n \"Map form fields onto any value a side effect sends — never hand-write a mapping. Start here: baker flows map contact --from map.json --write\",\n },\n args: {\n slug: { type: \"positional\", description: \"Form slug\", required: true },\n map: { type: \"string\", description: \"<destField>[:<fieldType>]=<value> (repeatable)\" },\n from: { type: \"string\", description: \"Read the whole mapping from a JSON file, or `-` for stdin\" },\n \"side-effect\": { type: \"string\", description: \"Side-effect id, when the form has more than one\" },\n \"hubspot-form\": {\n type: \"string\",\n description: \"HubSpot formGuid — reads every field's type off the form so you write none\",\n },\n into: {\n type: \"string\",\n description: \"Which slot to map into, for a type with more than one (e.g. meta: eventParams | advancedMatching)\",\n },\n entity: { type: \"string\", description: \"Destination object (person, contact, lead, …)\" },\n custom: { type: \"boolean\", description: \"Destination fields are custom fields\" },\n standard: { type: \"boolean\", description: \"Destination fields are standard fields\" },\n \"object-type\": { type: \"string\", description: \"HubSpot objectTypeId (default 0-1)\" },\n \"prune-missing\": {\n type: \"boolean\",\n description: \"Drop only the mappings the destination no longer has — the repair for a deleted HubSpot field\",\n },\n replace: {\n type: \"boolean\",\n description: \"Drop every mapping already in the slot. Default merges by destination name\",\n },\n write: { type: \"boolean\", description: \"Splice the mapping into the form\" },\n },\n run: async ({ args, rawArgs }) => {\n const slug = String(args.slug);\n const fromFile = args.from ? readSpecFile(String(args.from)) : undefined;\n const specs = fromFile ? specsFromFile(fromFile) : mapSpecsFrom(rawArgs);\n const into = args.into ? String(args.into) : fromFile?.into;\n const replacing = args.replace === true || fromFile?.replace === true;\n const pruning = args[\"prune-missing\"] === true || fromFile?.pruneMissing === true;\n\n const tree = readFlowTree(slug);\n // A flag beats the file, so a saved mapping can be retargeted without editing it.\n const chosen = pickSideEffect(\n slug,\n collectSideEffects(tree),\n args[\"side-effect\"] ? String(args[\"side-effect\"]) : fromFile?.sideEffect,\n );\n\n // No mappings given: answer \"what can I map here, and where do the key names\n // come from\" rather than printing usage. The command already holds the side\n // effect, so refusing threw the answer away and left the only discovery path\n // a wrong guess — name a key outside a closed set and read it off the refusal.\n // `--prune-missing` is a whole call on its own: the repair for a deleted\n // destination field is a removal, and requiring a `--map` alongside it would\n // mean inventing a mapping to make a deletion legal.\n if (specs.length === 0 && !pruning) {\n describeDestination(chosen);\n return;\n }\n\n assertDestinationReady(slug, tree, chosen, into);\n\n const { options, hints: destinationHints } = await mapOptions(args, fromFile, into);\n\n let built: ReturnType<typeof buildFieldMapping>;\n try {\n built = buildFieldMapping(tree, chosen.sideEffect, specs, options);\n } catch (error) {\n if (error instanceof MappingError) {\n refuse(error.message, error.fix);\n }\n throw error;\n }\n\n const slotHint = [\n ...destinationHints,\n ...droppedHint(built),\n ...survivorHint(built, replacing),\n ...slotHintFor(String(chosen.sideEffect.type ?? \"\"), into),\n ...pendingEndpointHint(slug, tree, chosen),\n ];\n\n if (args.write !== true) {\n emitDryRun(slug, chosen, built, slotHint);\n return;\n }\n\n Object.assign(chosen.sideEffect, built.patch);\n writeFlowTree(slug, tree);\n emitWritten(slug, chosen, built, slotHint);\n },\n});\n\n/**\n * The first line of the answer: what this call did, or would do.\n *\n * It has to survive a call that only REMOVES. `--prune-missing` on its own\n * writes nothing and drops something, and \"Wrote 0 fieldMapping mappings\"\n * describes the opposite of what happened — it reads as a no-op, which is the\n * one reading that sends an agent looking for a different command after the\n * repair has already landed. The drops are named by `droppedHint` two lines\n * further down, and that is not where anybody looks to find out whether a\n * command worked.\n *\n * Exported for its own test, because this sentence is the whole report.\n */\nexport function mapHeadline(built: BuiltMapping, phase: \"written\" | \"dry-run\", slug = \"\"): string {\n const wrote = `${built.count} ${built.key} mapping${built.count === 1 ? \"\" : \"s\"}`;\n const drops = `${built.dropped.length} dead mapping${built.dropped.length === 1 ? \"\" : \"s\"}`;\n\n if (phase === \"dry-run\") {\n if (built.count === 0 && built.dropped.length > 0) {\n return `Nothing written. Re-run with --write to drop ${drops} from ${slug}.`;\n }\n return `Nothing written. Re-run with --write to splice ${wrote} into ${slug}.`;\n }\n\n if (built.dropped.length === 0) return `Wrote ${wrote}.`;\n if (built.count === 0) return `Dropped ${drops} from ${built.key}; nothing else changed.`;\n return `Wrote ${wrote} and dropped ${drops}.`;\n}\n\n/** What the call WOULD do, plus the one sentence saying how to make it happen. */\nfunction emitDryRun(slug: string, chosen: Located, built: BuiltMapping, slotHint: string[]): void {\n writeJson({\n ok: true,\n data: {\n sideEffectId: chosen.sideEffect.id,\n type: chosen.sideEffect.type,\n key: built.key,\n patch: built.patch,\n },\n hints: [mapHeadline(built, \"dry-run\", slug), ...slotHint],\n });\n}\n\nfunction emitWritten(slug: string, chosen: Located, built: BuiltMapping, slotHint: string[]): void {\n writeJson({\n ok: true,\n data: {\n sideEffectId: chosen.sideEffect.id,\n type: chosen.sideEffect.type,\n key: built.key,\n written: built.count,\n kept: built.kept,\n dropped: built.dropped,\n path: flowDataPath(slug),\n },\n hints: [\n mapHeadline(built, \"written\"),\n `A mapping is only real once the destination is set — check with: baker flows show ${slug}`,\n ...slotHint,\n ],\n });\n}\n"],"mappings":"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","names":[]}
|
|
@@ -3,11 +3,10 @@ import {
|
|
|
3
3
|
} from "./chunk-ERSX3MKH.js";
|
|
4
4
|
import {
|
|
5
5
|
customMcpServerNameRequestSchema
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-XF4JUKVF.js";
|
|
7
7
|
import "./chunk-GXDLWBOY.js";
|
|
8
8
|
import "./chunk-TEINLN64.js";
|
|
9
9
|
import "./chunk-ZJWUBJYQ.js";
|
|
10
|
-
import "./chunk-HR6IWNKE.js";
|
|
11
10
|
import "./chunk-NE4F3FHN.js";
|
|
12
11
|
import {
|
|
13
12
|
ApiError,
|
|
@@ -474,4 +473,4 @@ Full guide: __tooling__/docs/tools/baker/mcp.md`
|
|
|
474
473
|
export {
|
|
475
474
|
mcpCommand
|
|
476
475
|
};
|
|
477
|
-
//# sourceMappingURL=mcp-
|
|
476
|
+
//# sourceMappingURL=mcp-XXD7ZQCP.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../api/src/mcp-catalog.ts","../src/commands/mcp/index.ts","../src/commands/mcp/catalog.ts","../src/commands/mcp/platforms.ts"],"sourcesContent":["/**\n * Contract for `GET /api/mcp/catalog` — searching the managed-app catalog the\n * sandbox agent can ask the user to connect when a vendor publishes no MCP\n * server of its own.\n *\n * `connect` mirrors `ToolkitConnectMode` in `convex/composio/types.ts`, folded\n * to what the user will be asked for: a sign-in or a key. Apps that need no\n * sign-in are left out — Composio refuses to connect them.\n */\nimport { z } from \"zod\";\n\nexport const MCP_CATALOG_DEFAULT_LIMIT = 8;\nexport const MCP_CATALOG_DESCRIPTION_MAX = 160;\n\nexport const mcpCatalogRequestSchema = z.object({\n search: z.string().trim().min(1, \"Provide --search\").max(100),\n limit: z.coerce.number().int().min(1).max(20).default(MCP_CATALOG_DEFAULT_LIMIT),\n});\nexport type McpCatalogRequest = z.infer<typeof mcpCatalogRequestSchema>;\n\nexport const mcpCatalogConnectSchema = z.enum([\"sign-in\", \"key\"]);\nexport type McpCatalogConnect = z.infer<typeof mcpCatalogConnectSchema>;\n\nexport const mcpCatalogEntrySchema = z.object({\n /** The toolkit slug — what request_connection `{ app }` takes. */\n app: z.string(),\n name: z.string(),\n description: z.string().max(MCP_CATALOG_DESCRIPTION_MAX),\n connect: mcpCatalogConnectSchema,\n connected: z.boolean(),\n});\nexport type McpCatalogEntry = z.infer<typeof mcpCatalogEntrySchema>;\n\nexport const mcpCatalogResponseSchema = z.object({\n apps: z.array(mcpCatalogEntrySchema),\n /** The company has managed apps switched off: nothing here can be connected, so `apps` is empty. */\n managedDisabled: z.boolean().optional(),\n /** Baker's own connections this search matched — ask for these with `{ platform }`, never a managed copy. */\n platforms: z.array(z.string()).optional(),\n});\nexport type McpCatalogResponse = z.infer<typeof mcpCatalogResponseSchema>;\n","import {\n type CustomMcpDisableResponse,\n type CustomMcpVerifyResponse,\n customMcpServerNameRequestSchema,\n} from \"@baker/api\";\nimport { type McpCatalogResponse, mcpCatalogRequestSchema } from \"@baker/api/mcp-catalog\";\nimport { defineCommand } from \"citty\";\nimport { ApiError, apiGet, apiPost } from \"../../client.ts\";\nimport { getEnv } from \"../../env.ts\";\nimport { repeatedValues } from \"../../lib/repeatedFlags.ts\";\nimport { writeJson } from \"../../output.ts\";\nimport { registerSchema } from \"../../schemas.ts\";\nimport { catalogHints } from \"./catalog.ts\";\nimport { type ConnectedPlatform, platformEntry } from \"./platforms.ts\";\n\nconst SCOPES = [\"user\", \"user_org\", \"company\", \"org\"] as const;\ntype Scope = (typeof SCOPES)[number];\n\nfunction parseScope(raw: unknown): Scope {\n const scope = raw === undefined ? \"company\" : String(raw);\n if (!(SCOPES as readonly string[]).includes(scope)) {\n throw new ApiError(\"VALIDATION_ERROR\", `Invalid --scope \"${scope}\". Use user | user_org | company | org.`);\n }\n return scope as Scope;\n}\n\n/** The turn's message sender, injected by the bridge — required only for user scope. */\nfunction actingUserId(): string | undefined {\n return getEnv().BAKER_ACTING_USER_ID;\n}\n\ntype CustomMcpServer = {\n _id: string;\n scope: \"user\" | \"user_org\" | \"company\" | \"org\";\n name: string;\n url: string;\n headerKeys: string[];\n enabled: boolean;\n /** Absent until the address has been checked; `ok: false` means it serves no tools. */\n health?: { ok: boolean; message?: string; suggestedUrl?: string; transient?: boolean; checkedAt: number };\n createdAt: number;\n};\n\n/**\n * What to report for one custom server. `problem` is the whole point: a server can\n * be signed in, enabled and still serve nothing (wrong address), and reporting it\n * as plain \"connected\" is how an agent ends up promising tools it does not have.\n * A `transient` failure is reported separately — the tool may well answer, so\n * declaring it broken would be its own kind of lie.\n */\nfunction customEntry(server: CustomMcpServer): Record<string, unknown> {\n const failed = server.health && !server.health.ok;\n const problem = server.health?.message ?? \"This server's address is not serving tools.\";\n return {\n name: server.name,\n scope: server.scope,\n enabled: server.enabled,\n ...(failed && !server.health?.transient ? { usable: false, problem } : {}),\n ...(failed && server.health?.transient ? { lastCheck: \"failed\", problem } : {}),\n ...(failed && server.health?.suggestedUrl ? { suggestedAddress: server.health.suggestedUrl } : {}),\n };\n}\n\n/** The hint an unusable server earns — the agent must not offer its tools or invent a reason. */\nconst BROKEN_SERVER_HINT =\n \"A server marked usable=false will NOT answer: its tools are absent from this turn. Say plainly that the tool is not working and relay `problem`; never claim its tools are loading, coming next message, or temporarily unavailable. `problem` names what a person has to fix — the address, the sign-in, or the key the server was added with — so pass on that fix and no other: never tell the user to reconnect a server whose `problem` is its address or its key. The user makes the fix in the dashboard (Brain → Integrations → More apps). If `suggestedAddress` is present, that is the address to use.\";\n\n/** The hint for a server whose last check failed for a reason that may already have passed. */\nconst LAST_CHECK_FAILED_HINT =\n \"A server with lastCheck=failed was unreachable or erroring when it was last checked — that may already have passed, and its tools ARE loaded this turn. Try the tool; if it works, say nothing about the check. If it fails, report `problem` as what happened rather than guessing.\";\n\n/** Turn repeated `--header \"K: V\"` (or `K=V`) flags into a headers record. */\n/** `--header` is repeatable, so its values come off the command line — citty keeps only the last. */\nfunction parseHeaders(raw: unknown, rawArgs?: readonly string[]): Record<string, string> | undefined {\n const list = repeatedValues(rawArgs, \"header\", raw);\n const headers: Record<string, string> = {};\n for (const entry of list) {\n const text = String(entry);\n const sep = text.indexOf(\":\") >= 0 && (text.indexOf(\":\") < text.indexOf(\"=\") || text.indexOf(\"=\") < 0) ? \":\" : \"=\";\n const at = text.indexOf(sep);\n if (at <= 0) {\n throw new ApiError(\"VALIDATION_ERROR\", `Invalid header \"${text}\". Use \"Key: Value\".`);\n }\n headers[text.slice(0, at).trim()] = text.slice(at + 1).trim();\n }\n return Object.keys(headers).length > 0 ? headers : undefined;\n}\n\nfunction fail(err: unknown): never {\n if (err instanceof ApiError) {\n writeJson({ ok: false, error: { code: err.code, message: err.message } });\n process.exit(1);\n }\n writeJson({ ok: false, error: { code: \"NETWORK_ERROR\", message: \"Unexpected error\" } });\n process.exit(1);\n}\n\ntype ManagedConnection = {\n toolkitSlug: string;\n scope: \"user\" | \"user_org\" | \"company\" | \"org\";\n status: string;\n accountLabel: string | null;\n readOnly: boolean;\n};\n\ntype ConnectedResponse = {\n managedDisabled: boolean;\n managed: ManagedConnection[];\n custom: CustomMcpServer[];\n platforms: ConnectedPlatform[];\n};\n\n/** The one thing an agent must not do with this list: infer a platform's state from the MCP half. */\nconst PLATFORMS_HINT =\n \"`platforms` are connected accounts you reach through `baker` commands (HubSpot, Google Ads, GA4, Search Console, Tag Manager, …), NOT mcp__* tools — there is no tool to call for them. A platform listed here IS connected: never tell the user to connect it, and never conclude it is missing because it has no mcp__* entry. Read what it holds with its own command family (`baker hubspot …`, `baker ads google …`, `baker ga4 …`, and so on).\";\n\nregisterSchema({\n command: \"mcp.connected\",\n description:\n \"List everything this chat can reach: managed integrations (Attio, Slack, Gmail, Google Sheets, …), custom MCP servers, and the platforms the company signed in to (HubSpot, Google Ads, GA4, Search Console, Tag Manager) which you read through their own `baker` commands. Start here when the user mentions an external tool or platform.\",\n args: {},\n});\n\nconst connectedCommand = defineCommand({\n meta: {\n name: \"connected\",\n description: `Everything this chat can reach — managed integrations, custom MCP servers, and connected platforms.\n\nManaged tools ride the composio servers (mcp__composio_<scope>__*); custom servers expose mcp__<name>__*.\nPlatforms (HubSpot, Google Ads, GA4, …) have no mcp__* tools at all — you read them with their own\n\\`baker\\` command family, and one listed here is connected and ready to use.\nA tool or platform the user names that is NOT listed anywhere here is simply not connected yet.`,\n },\n run: async () => {\n try {\n const user = actingUserId();\n const data = await apiGet<ConnectedResponse>(\"/api/mcp/connected\", user ? { actingUserId: user } : undefined);\n const managed = data.managed.map((c) => ({\n toolkit: c.toolkitSlug,\n scope: c.scope,\n ...(c.status !== \"ACTIVE\" ? { status: c.status } : {}),\n ...(c.accountLabel ? { account: c.accountLabel } : {}),\n ...(c.readOnly ? { readOnly: true } : {}),\n }));\n const custom = data.custom.map(customEntry);\n const platforms = (data.platforms ?? []).map(platformEntry);\n const hints: string[] = [];\n if (platforms.length > 0) {\n hints.push(PLATFORMS_HINT);\n }\n if (data.custom.some((s) => s.health && !s.health.ok && !s.health.transient)) {\n hints.push(BROKEN_SERVER_HINT);\n }\n if (data.custom.some((s) => s.health && !s.health.ok && s.health.transient)) {\n hints.push(LAST_CHECK_FAILED_HINT);\n }\n if (data.managedDisabled) {\n hints.push(\"Managed integrations are disabled for this company — only custom MCP servers load.\");\n }\n if ([...data.managed, ...data.custom].some((e) => e.scope === \"user\" || e.scope === \"user_org\")) {\n hints.push(\n \"user/user_org entries are personal: they belong to the current message sender and load only in their turns — other users in this chat won't have them.\",\n );\n }\n hints.push(\n \"Not listed anywhere = not connected — connect it from the chat with request_connection, never by sending the user to the dashboard: a Baker platform (HubSpot, Google Ads, GA4, …) → { platform }; anything else → the vendor's own MCP server FIRST: use the address the user gave you, or WebSearch '<vendor> MCP server' and WebFetch its official docs for the remote https address and how it signs in, then { server: { name, url, auth, keyHeader } }; only when the vendor has none → `baker mcp catalog --search <name>`, then { app }. Research before you ask the user anything. What they connect loads into this same turn.\",\n );\n writeJson({\n ok: true,\n data: { ...(data.managedDisabled ? { managedDisabled: true } : {}), managed, custom, platforms },\n hints,\n });\n } catch (err) {\n fail(err);\n }\n },\n});\n\nconst catalogArgs = {\n search: { type: \"string\", description: \"App or vendor name, e.g. notion, clarity, pipedrive\", required: true },\n limit: { type: \"string\", description: \"Max apps to return, 1-20 (default 8)\", required: false },\n} as const;\n\nregisterSchema({\n command: \"mcp.catalog\",\n description:\n \"Search the managed apps you can ask the user to connect when a vendor has no MCP server of its own. Each app says how the user connects it (sign-in | key) and whether this chat already reaches it. Example: baker mcp catalog --search notion\",\n args: catalogArgs,\n});\n\nconst catalogCommand = defineCommand({\n meta: {\n name: \"catalog\",\n description: `Managed apps you can ask the user to connect when a vendor has no MCP server of its own.\n\nFor a tool \\`baker mcp connected\\` does not list whose vendor has no official remote MCP server:\n baker mcp catalog --search notion\n baker mcp catalog --search \"microsoft clarity\" --limit 3\n\nEach app: app (slug for request_connection), name, description, connect (sign-in | key), connected.\nPrefer the vendor's own MCP server when it publishes one; a catalog app is the fallback.`,\n },\n args: catalogArgs,\n run: async ({ args }) => {\n const parsed = mcpCatalogRequestSchema.safeParse({ search: args.search, limit: args.limit });\n if (!parsed.success) {\n writeJson({\n ok: false,\n error: { code: \"VALIDATION_ERROR\", message: parsed.error.issues[0]?.message ?? \"Invalid arguments\" },\n });\n process.exit(1);\n }\n try {\n const user = actingUserId();\n const data = await apiGet<McpCatalogResponse>(\"/api/mcp/catalog\", {\n search: parsed.data.search,\n limit: String(parsed.data.limit),\n ...(user ? { actingUserId: user } : {}),\n });\n writeJson({\n ok: true,\n data: {\n apps: data.apps,\n ...(data.platforms?.length ? { platforms: data.platforms } : {}),\n ...(data.managedDisabled ? { managedDisabled: true } : {}),\n },\n hints: catalogHints(data.apps, {\n managedDisabled: data.managedDisabled === true,\n platforms: data.platforms ?? [],\n }),\n });\n } catch (err) {\n fail(err);\n }\n },\n});\n\nregisterSchema({\n command: \"mcp.list\",\n description: \"List the custom MCP servers this company's chats see (org + company + your own user scope).\",\n args: {},\n});\n\nconst listCommand = defineCommand({\n meta: { name: \"list\", description: \"List custom MCP servers visible to this company's chats.\" },\n run: async () => {\n try {\n const user = actingUserId();\n const data = await apiGet<{ servers: CustomMcpServer[] }>(\n \"/api/mcp/custom\",\n user ? { actingUserId: user } : undefined,\n );\n writeJson({\n ok: true,\n // Detail view: the full row (address included) plus the usability verdict.\n // `health` itself is folded into `usable`/`problem` by `customEntry`.\n data: data.servers.map((server) => ({ ...server, health: undefined, ...customEntry(server) })),\n ...(data.servers.some((s) => s.health && !s.health.ok)\n ? {\n hints: data.servers.some((s) => s.health && !s.health.ok && !s.health.transient)\n ? [BROKEN_SERVER_HINT]\n : [LAST_CHECK_FAILED_HINT],\n }\n : {}),\n });\n } catch (err) {\n fail(err);\n }\n },\n});\n\nregisterSchema({\n command: \"mcp.add\",\n description:\n \"Register a custom MCP server. Tools appear as mcp__<name>__* on the next message. URL must be HTTPS. Scope: company (default, all chats) | org (org admin key) | user (only the current sender).\",\n args: {\n name: { type: \"string\", description: \"Server name → tools appear as mcp__<name>__*\", required: true },\n url: {\n type: \"string\",\n description: \"Full HTTPS MCP endpoint (commonly ends in /mcp, not just the domain)\",\n required: true,\n },\n scope: { type: \"string\", description: \"user | user_org | company | org (default company)\", required: false },\n header: { type: \"string\", description: 'Auth header \"Key: Value\" (repeatable)', required: false },\n },\n});\n\nconst addCommand = defineCommand({\n meta: {\n name: \"add\",\n description: `Register a custom MCP server. Tools appear as mcp__<name>__* on the NEXT message.\nFor a server the USER asks for, use request_connection { server } instead: they confirm who can use it,\ntype any key into the card (never the chat), and its tools load in this same turn.\n\nScope: company (default — every chat in the company) | org (all companies in the org; needs an admin key) | user (only the current message sender).\n\nExamples:\n baker mcp add --name weather --url https://mcp.example.com/mcp\n baker mcp add --name acme --url https://acme.dev/mcp --header \"Authorization: Bearer sk-…\"\n baker mcp add --name mine --url https://my.dev/mcp --scope user`,\n },\n args: {\n name: { type: \"string\", description: \"Server name (mcp__<name>__*)\", required: true },\n url: {\n type: \"string\",\n description: \"Full HTTPS MCP endpoint (commonly ends in /mcp, not just the domain)\",\n required: true,\n },\n scope: { type: \"string\", description: \"user | user_org | company | org (default company)\", required: false },\n header: { type: \"string\", description: 'Auth header \"Key: Value\" (repeatable)', required: false },\n },\n run: async ({ args, rawArgs }) => {\n try {\n const scope = parseScope(args.scope);\n const user = actingUserId();\n const headers = parseHeaders(args.header, rawArgs);\n const data = await apiPost<{ name: string }>(\"/api/mcp/custom\", {\n name: args.name as string,\n url: args.url as string,\n scope,\n ...(user ? { actingUserId: user } : {}),\n ...(headers ? { headers } : {}),\n });\n writeJson({\n ok: true,\n data,\n hints: [\n \"The address must be the full MCP endpoint (commonly ending in /mcp), not just the domain — a domain on its own usually answers sign-in and then serves no tools.\",\n \"The address is checked in the background. Run `baker mcp connected` on the next message to confirm it serves tools before promising the user anything.\",\n ],\n });\n } catch (err) {\n fail(err);\n }\n },\n});\n\nregisterSchema({\n command: \"mcp.remove\",\n description: \"Remove a company custom MCP server by name.\",\n args: { name: { type: \"string\", description: \"Server name to remove\", required: true } },\n});\n\nconst removeCommand = defineCommand({\n meta: {\n name: \"remove\",\n description: `Remove a company custom MCP server by name.\n\nExample:\n baker mcp remove --name weather`,\n },\n args: { name: { type: \"string\", description: \"Server name to remove\", required: true } },\n run: async ({ args }) => {\n try {\n const user = actingUserId();\n const data = await apiPost<{ removed: boolean }>(\"/api/mcp/custom/remove\", {\n name: args.name as string,\n ...(user ? { actingUserId: user } : {}),\n });\n writeJson({ ok: true, data });\n } catch (err) {\n fail(err);\n }\n },\n});\n\nconst serverNameArgs = {\n name: { type: \"string\", description: \"Custom server name, as `baker mcp list` shows it\", required: true },\n} as const;\n\nregisterSchema({\n command: \"mcp.verify\",\n description:\n \"Check a custom MCP server now (the dashboard's 'Check now') and store the result. Use after the user fixed its address or sign-in, or when its tools failed this turn.\",\n args: serverNameArgs,\n});\n\nconst verifyCommand = defineCommand({\n meta: {\n name: \"verify\",\n description: `Check a custom MCP server now and store the result.\n\nExample:\n baker mcp verify --name weather`,\n },\n args: serverNameArgs,\n run: async ({ args }) => {\n const parsed = customMcpServerNameRequestSchema.safeParse({ name: args.name, actingUserId: actingUserId() });\n if (!parsed.success) {\n fail(new ApiError(\"VALIDATION_ERROR\", parsed.error.issues[0]?.message ?? \"Invalid arguments\"));\n }\n try {\n const data = await apiPost<CustomMcpVerifyResponse>(\"/api/mcp/custom/verify\", parsed.data);\n writeJson({\n ok: true,\n data,\n hints: [\n data.ok\n ? \"The server answers and serves tools. Its tools load on the next message.\"\n : data.transient\n ? LAST_CHECK_FAILED_HINT\n : BROKEN_SERVER_HINT,\n ],\n });\n } catch (err) {\n fail(err);\n }\n },\n});\n\nregisterSchema({\n command: \"mcp.disable\",\n description:\n \"Switch a custom MCP server off so its tools stop loading; its address and sign-in are kept. Turning it back on is done by a person in the dashboard, never by the agent.\",\n args: serverNameArgs,\n});\n\nconst disableCommand = defineCommand({\n meta: {\n name: \"disable\",\n description: `Switch a custom MCP server off (its tools stop loading). Only a person can turn it back on, in the dashboard.\n\nExample:\n baker mcp disable --name weather`,\n },\n args: serverNameArgs,\n run: async ({ args }) => {\n const parsed = customMcpServerNameRequestSchema.safeParse({ name: args.name, actingUserId: actingUserId() });\n if (!parsed.success) {\n fail(new ApiError(\"VALIDATION_ERROR\", parsed.error.issues[0]?.message ?? \"Invalid arguments\"));\n }\n try {\n const data = await apiPost<CustomMcpDisableResponse>(\"/api/mcp/custom/disable\", parsed.data);\n writeJson({\n ok: true,\n data,\n hints: [\n \"Its tools stop loading from the next message, and this applies right away — publishing or discarding this chat does not undo it. Tell the user they can turn it back on in Brain → Integrations → More apps.\",\n ],\n });\n } catch (err) {\n fail(err);\n }\n },\n});\n\nexport const mcpCommand = defineCommand({\n meta: {\n name: \"mcp\",\n description: `Third-party tools for this company — see what's connected, register custom HTTPS MCP endpoints.\n\nTools from a registered server appear as mcp__<name>__* on the next message.\nManaged here are **company-scoped** servers; user- and org-scoped servers are managed in the dashboard.\n\nStart here:\n baker mcp connected # everything this chat can reach: managed integrations, custom servers, connected platforms\n baker mcp catalog --search notion # managed apps you can connect when a vendor has no MCP server of its own\n\nExamples:\n baker mcp add --name weather --url https://mcp.example.com/mcp\n baker mcp add --name acme --url https://acme.dev/mcp --header \"Authorization: Bearer sk-…\"\n baker mcp remove --name weather\n baker mcp verify --name weather # check it now after the user fixed it\n baker mcp disable --name weather # stop its tools loading (only a person turns it back on)\nFull guide: __tooling__/docs/tools/baker/mcp.md`,\n },\n subCommands: {\n connected: connectedCommand,\n catalog: catalogCommand,\n list: listCommand,\n add: addCommand,\n remove: removeCommand,\n verify: verifyCommand,\n disable: disableCommand,\n },\n});\n","/**\n * What `baker mcp catalog` tells the agent to do next with the managed apps it\n * found — the fallback when a vendor publishes no MCP server of its own.\n */\nimport type { McpCatalogEntry } from \"@baker/api/mcp-catalog\";\n\nconst PREFER_VENDOR_HINT =\n 'The vendor\\'s own MCP server comes before any app here. If you have not yet, WebSearch \"<vendor> MCP server\" and WebFetch its official docs for the remote https address and how it signs in, then ask for it with request_connection `{ server: { name, url, auth, keyHeader } }`. Only when the vendor has none, ask for an app from this catalog with request_connection `{ app: \"<slug>\", reason }` — the user connects it in the chat and its tools load right after, in this same turn.';\n\nconst ALREADY_CONNECTED_HINT =\n \"An app marked connected is already reachable — use its mcp__composio_* tools; do not ask again.\";\n\nconst NO_MATCH_HINT =\n \"Nothing in the catalog matches. WebSearch for the vendor's official remote MCP server (its docs, its developer site) before telling the user it can't be connected — if one exists, ask for it with request_connection `{ server }`. Only when the web shows no official remote server either, say plainly this tool can't be connected yet and offer a Task.\";\n\nconst MANAGED_DISABLED_HINT =\n \"Managed apps are switched off for this company, so none can be connected here. Use the vendor's own MCP server — WebSearch \\\"<vendor> MCP server\\\" and WebFetch its official docs, then request_connection `{ server }`; when it has none, say plainly this tool can't be connected yet and offer a Task.\";\n\n/** Baker's own connection always wins over a catalog app or anyone's MCP server for the same tool. */\nfunction firstPartyHint(platforms: readonly string[]): string {\n const asks = platforms.map((p) => `request_connection \\`{ platform: \"${p}\" }\\``).join(\" or \");\n return `This is one of Baker's own connections — ask for it with ${asks}. It is the one Baker's commands, staging and publish work with, so never connect it as a catalog app or as an MCP server, even one the vendor publishes or the user names. If it is already connected, read it with its own baker command family instead.`;\n}\n\n/** What the agent should do next with a catalog answer. */\nexport function catalogHints(\n apps: readonly McpCatalogEntry[],\n { managedDisabled = false, platforms = [] }: { managedDisabled?: boolean; platforms?: readonly string[] } = {},\n): string[] {\n if (platforms.length > 0) {\n return [firstPartyHint(platforms)];\n }\n if (managedDisabled) {\n return [MANAGED_DISABLED_HINT];\n }\n const hints = [PREFER_VENDOR_HINT];\n if (apps.some((a) => a.connected)) {\n hints.push(ALREADY_CONNECTED_HINT);\n }\n if (apps.length === 0) {\n hints.push(NO_MATCH_HINT);\n }\n return hints;\n}\n","/**\n * How a connected platform reads back to the agent.\n *\n * A platform (HubSpot, Google Ads, GA4, …) is an account the company signed in\n * to, reached through its own `baker` command family rather than an `mcp__*`\n * tool. It rides `mcp connected` because that is the one answer to \"what can\n * this chat reach\" — and because an agent that only saw the tool half had no\n * way to tell a working HubSpot connection from a missing one.\n */\n\nexport interface ConnectedPlatform {\n type: string;\n label: string;\n account: string | null;\n reads: string[];\n readsLabel: string | null;\n}\n\n/** \"Ad Accounts\" -> `adAccounts`, \"Properties\" -> `properties`. */\nfunction readsKey(label: string): string {\n const [first = \"\", ...rest] = label.split(\" \");\n return [first.toLowerCase(), ...rest].join(\"\");\n}\n\n/**\n * One platform as the agent sees it. The resources are keyed by the platform's\n * own word for them — `properties` for GA4, `containers` for Tag Manager,\n * `adAccounts` for the ad platforms — so what the agent reads back matches what\n * the user sees in the dashboard.\n */\nexport function platformEntry(platform: ConnectedPlatform): Record<string, unknown> {\n return {\n platform: platform.label,\n ...(platform.account ? { account: platform.account } : {}),\n ...(platform.readsLabel && platform.reads.length > 0 ? { [readsKey(platform.readsLabel)]: platform.reads } : {}),\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../api/src/mcp-catalog.ts","../src/commands/mcp/index.ts","../src/commands/mcp/catalog.ts","../src/commands/mcp/platforms.ts"],"sourcesContent":["/**\n * Contract for `GET /api/mcp/catalog` — searching the managed-app catalog the\n * sandbox agent can ask the user to connect when a vendor publishes no MCP\n * server of its own.\n *\n * `connect` mirrors `ToolkitConnectMode` in `convex/composio/types.ts`, folded\n * to what the user will be asked for: a sign-in or a key. Apps that need no\n * sign-in are left out — Composio refuses to connect them.\n */\nimport { z } from \"zod\";\n\nexport const MCP_CATALOG_DEFAULT_LIMIT = 8;\nexport const MCP_CATALOG_DESCRIPTION_MAX = 160;\n\nexport const mcpCatalogRequestSchema = z.object({\n search: z.string().trim().min(1, \"Provide --search\").max(100),\n limit: z.coerce.number().int().min(1).max(20).default(MCP_CATALOG_DEFAULT_LIMIT),\n});\nexport type McpCatalogRequest = z.infer<typeof mcpCatalogRequestSchema>;\n\nexport const mcpCatalogConnectSchema = z.enum([\"sign-in\", \"key\"]);\nexport type McpCatalogConnect = z.infer<typeof mcpCatalogConnectSchema>;\n\nexport const mcpCatalogEntrySchema = z.object({\n /** The toolkit slug — what request_connection `{ app }` takes. */\n app: z.string(),\n name: z.string(),\n description: z.string().max(MCP_CATALOG_DESCRIPTION_MAX),\n connect: mcpCatalogConnectSchema,\n connected: z.boolean(),\n});\nexport type McpCatalogEntry = z.infer<typeof mcpCatalogEntrySchema>;\n\nexport const mcpCatalogResponseSchema = z.object({\n apps: z.array(mcpCatalogEntrySchema),\n /** The company has managed apps switched off: nothing here can be connected, so `apps` is empty. */\n managedDisabled: z.boolean().optional(),\n /** Baker's own connections this search matched — ask for these with `{ platform }`, never a managed copy. */\n platforms: z.array(z.string()).optional(),\n});\nexport type McpCatalogResponse = z.infer<typeof mcpCatalogResponseSchema>;\n","import {\n type CustomMcpDisableResponse,\n type CustomMcpVerifyResponse,\n customMcpServerNameRequestSchema,\n} from \"@baker/api\";\nimport { type McpCatalogResponse, mcpCatalogRequestSchema } from \"@baker/api/mcp-catalog\";\nimport { defineCommand } from \"citty\";\nimport { ApiError, apiGet, apiPost } from \"../../client.ts\";\nimport { getEnv } from \"../../env.ts\";\nimport { repeatedValues } from \"../../lib/repeatedFlags.ts\";\nimport { writeJson } from \"../../output.ts\";\nimport { registerSchema } from \"../../schemas.ts\";\nimport { catalogHints } from \"./catalog.ts\";\nimport { type ConnectedPlatform, platformEntry } from \"./platforms.ts\";\n\nconst SCOPES = [\"user\", \"user_org\", \"company\", \"org\"] as const;\ntype Scope = (typeof SCOPES)[number];\n\nfunction parseScope(raw: unknown): Scope {\n const scope = raw === undefined ? \"company\" : String(raw);\n if (!(SCOPES as readonly string[]).includes(scope)) {\n throw new ApiError(\"VALIDATION_ERROR\", `Invalid --scope \"${scope}\". Use user | user_org | company | org.`);\n }\n return scope as Scope;\n}\n\n/** The turn's message sender, injected by the bridge — required only for user scope. */\nfunction actingUserId(): string | undefined {\n return getEnv().BAKER_ACTING_USER_ID;\n}\n\ntype CustomMcpServer = {\n _id: string;\n scope: \"user\" | \"user_org\" | \"company\" | \"org\";\n name: string;\n url: string;\n headerKeys: string[];\n enabled: boolean;\n /** Absent until the address has been checked; `ok: false` means it serves no tools. */\n health?: { ok: boolean; message?: string; suggestedUrl?: string; transient?: boolean; checkedAt: number };\n createdAt: number;\n};\n\n/**\n * What to report for one custom server. `problem` is the whole point: a server can\n * be signed in, enabled and still serve nothing (wrong address), and reporting it\n * as plain \"connected\" is how an agent ends up promising tools it does not have.\n * A `transient` failure is reported separately — the tool may well answer, so\n * declaring it broken would be its own kind of lie.\n */\nfunction customEntry(server: CustomMcpServer): Record<string, unknown> {\n const failed = server.health && !server.health.ok;\n const problem = server.health?.message ?? \"This server's address is not serving tools.\";\n return {\n name: server.name,\n scope: server.scope,\n enabled: server.enabled,\n ...(failed && !server.health?.transient ? { usable: false, problem } : {}),\n ...(failed && server.health?.transient ? { lastCheck: \"failed\", problem } : {}),\n ...(failed && server.health?.suggestedUrl ? { suggestedAddress: server.health.suggestedUrl } : {}),\n };\n}\n\n/** The hint an unusable server earns — the agent must not offer its tools or invent a reason. */\nconst BROKEN_SERVER_HINT =\n \"A server marked usable=false will NOT answer: its tools are absent from this turn. Say plainly that the tool is not working and relay `problem`; never claim its tools are loading, coming next message, or temporarily unavailable. `problem` names what a person has to fix — the address, the sign-in, or the key the server was added with — so pass on that fix and no other: never tell the user to reconnect a server whose `problem` is its address or its key. The user makes the fix in the dashboard (Brain → Integrations → More apps). If `suggestedAddress` is present, that is the address to use.\";\n\n/** The hint for a server whose last check failed for a reason that may already have passed. */\nconst LAST_CHECK_FAILED_HINT =\n \"A server with lastCheck=failed was unreachable or erroring when it was last checked — that may already have passed, and its tools ARE loaded this turn. Try the tool; if it works, say nothing about the check. If it fails, report `problem` as what happened rather than guessing.\";\n\n/** Turn repeated `--header \"K: V\"` (or `K=V`) flags into a headers record. */\n/** `--header` is repeatable, so its values come off the command line — citty keeps only the last. */\nfunction parseHeaders(raw: unknown, rawArgs?: readonly string[]): Record<string, string> | undefined {\n const list = repeatedValues(rawArgs, \"header\", raw);\n const headers: Record<string, string> = {};\n for (const entry of list) {\n const text = String(entry);\n const sep = text.indexOf(\":\") >= 0 && (text.indexOf(\":\") < text.indexOf(\"=\") || text.indexOf(\"=\") < 0) ? \":\" : \"=\";\n const at = text.indexOf(sep);\n if (at <= 0) {\n throw new ApiError(\"VALIDATION_ERROR\", `Invalid header \"${text}\". Use \"Key: Value\".`);\n }\n headers[text.slice(0, at).trim()] = text.slice(at + 1).trim();\n }\n return Object.keys(headers).length > 0 ? headers : undefined;\n}\n\nfunction fail(err: unknown): never {\n if (err instanceof ApiError) {\n writeJson({ ok: false, error: { code: err.code, message: err.message } });\n process.exit(1);\n }\n writeJson({ ok: false, error: { code: \"NETWORK_ERROR\", message: \"Unexpected error\" } });\n process.exit(1);\n}\n\ntype ManagedConnection = {\n toolkitSlug: string;\n scope: \"user\" | \"user_org\" | \"company\" | \"org\";\n status: string;\n accountLabel: string | null;\n readOnly: boolean;\n};\n\ntype ConnectedResponse = {\n managedDisabled: boolean;\n managed: ManagedConnection[];\n custom: CustomMcpServer[];\n platforms: ConnectedPlatform[];\n};\n\n/** The one thing an agent must not do with this list: infer a platform's state from the MCP half. */\nconst PLATFORMS_HINT =\n \"`platforms` are connected accounts you reach through `baker` commands (HubSpot, Google Ads, GA4, Search Console, Tag Manager, …), NOT mcp__* tools — there is no tool to call for them. A platform listed here IS connected: never tell the user to connect it, and never conclude it is missing because it has no mcp__* entry. Read what it holds with its own command family (`baker hubspot …`, `baker ads google …`, `baker ga4 …`, and so on).\";\n\nregisterSchema({\n command: \"mcp.connected\",\n description:\n \"List everything this chat can reach: managed integrations (Attio, Slack, Gmail, Google Sheets, …), custom MCP servers, and the platforms the company signed in to (HubSpot, Google Ads, GA4, Search Console, Tag Manager) which you read through their own `baker` commands. Start here when the user mentions an external tool or platform.\",\n args: {},\n});\n\nconst connectedCommand = defineCommand({\n meta: {\n name: \"connected\",\n description: `Everything this chat can reach — managed integrations, custom MCP servers, and connected platforms.\n\nManaged tools ride the composio servers (mcp__composio_<scope>__*); custom servers expose mcp__<name>__*.\nPlatforms (HubSpot, Google Ads, GA4, …) have no mcp__* tools at all — you read them with their own\n\\`baker\\` command family, and one listed here is connected and ready to use.\nA tool or platform the user names that is NOT listed anywhere here is simply not connected yet.`,\n },\n run: async () => {\n try {\n const user = actingUserId();\n const data = await apiGet<ConnectedResponse>(\"/api/mcp/connected\", user ? { actingUserId: user } : undefined);\n const managed = data.managed.map((c) => ({\n toolkit: c.toolkitSlug,\n scope: c.scope,\n ...(c.status !== \"ACTIVE\" ? { status: c.status } : {}),\n ...(c.accountLabel ? { account: c.accountLabel } : {}),\n ...(c.readOnly ? { readOnly: true } : {}),\n }));\n const custom = data.custom.map(customEntry);\n const platforms = (data.platforms ?? []).map(platformEntry);\n const hints: string[] = [];\n if (platforms.length > 0) {\n hints.push(PLATFORMS_HINT);\n }\n if (data.custom.some((s) => s.health && !s.health.ok && !s.health.transient)) {\n hints.push(BROKEN_SERVER_HINT);\n }\n if (data.custom.some((s) => s.health && !s.health.ok && s.health.transient)) {\n hints.push(LAST_CHECK_FAILED_HINT);\n }\n if (data.managedDisabled) {\n hints.push(\"Managed integrations are disabled for this company — only custom MCP servers load.\");\n }\n if ([...data.managed, ...data.custom].some((e) => e.scope === \"user\" || e.scope === \"user_org\")) {\n hints.push(\n \"user/user_org entries are personal: they belong to the current message sender and load only in their turns — other users in this chat won't have them.\",\n );\n }\n hints.push(\n \"Not listed anywhere = not connected — connect it from the chat with request_connection, never by sending the user to the dashboard: a Baker platform (HubSpot, Google Ads, GA4, …) → { platform }; anything else → the vendor's own MCP server FIRST: use the address the user gave you, or WebSearch '<vendor> MCP server' and WebFetch its official docs for the remote https address and how it signs in, then { server: { name, url, auth, keyHeader } }; only when the vendor has none → `baker mcp catalog --search <name>`, then { app }. Research before you ask the user anything. What they connect loads into this same turn.\",\n );\n writeJson({\n ok: true,\n data: { ...(data.managedDisabled ? { managedDisabled: true } : {}), managed, custom, platforms },\n hints,\n });\n } catch (err) {\n fail(err);\n }\n },\n});\n\nconst catalogArgs = {\n search: { type: \"string\", description: \"App or vendor name, e.g. notion, clarity, pipedrive\", required: true },\n limit: { type: \"string\", description: \"Max apps to return, 1-20 (default 8)\", required: false },\n} as const;\n\nregisterSchema({\n command: \"mcp.catalog\",\n description:\n \"Search the managed apps you can ask the user to connect when a vendor has no MCP server of its own. Each app says how the user connects it (sign-in | key) and whether this chat already reaches it. Example: baker mcp catalog --search notion\",\n args: catalogArgs,\n});\n\nconst catalogCommand = defineCommand({\n meta: {\n name: \"catalog\",\n description: `Managed apps you can ask the user to connect when a vendor has no MCP server of its own.\n\nFor a tool \\`baker mcp connected\\` does not list whose vendor has no official remote MCP server:\n baker mcp catalog --search notion\n baker mcp catalog --search \"microsoft clarity\" --limit 3\n\nEach app: app (slug for request_connection), name, description, connect (sign-in | key), connected.\nPrefer the vendor's own MCP server when it publishes one; a catalog app is the fallback.`,\n },\n args: catalogArgs,\n run: async ({ args }) => {\n const parsed = mcpCatalogRequestSchema.safeParse({ search: args.search, limit: args.limit });\n if (!parsed.success) {\n writeJson({\n ok: false,\n error: { code: \"VALIDATION_ERROR\", message: parsed.error.issues[0]?.message ?? \"Invalid arguments\" },\n });\n process.exit(1);\n }\n try {\n const user = actingUserId();\n const data = await apiGet<McpCatalogResponse>(\"/api/mcp/catalog\", {\n search: parsed.data.search,\n limit: String(parsed.data.limit),\n ...(user ? { actingUserId: user } : {}),\n });\n writeJson({\n ok: true,\n data: {\n apps: data.apps,\n ...(data.platforms?.length ? { platforms: data.platforms } : {}),\n ...(data.managedDisabled ? { managedDisabled: true } : {}),\n },\n hints: catalogHints(data.apps, {\n managedDisabled: data.managedDisabled === true,\n platforms: data.platforms ?? [],\n }),\n });\n } catch (err) {\n fail(err);\n }\n },\n});\n\nregisterSchema({\n command: \"mcp.list\",\n description: \"List the custom MCP servers this company's chats see (org + company + your own user scope).\",\n args: {},\n});\n\nconst listCommand = defineCommand({\n meta: { name: \"list\", description: \"List custom MCP servers visible to this company's chats.\" },\n run: async () => {\n try {\n const user = actingUserId();\n const data = await apiGet<{ servers: CustomMcpServer[] }>(\n \"/api/mcp/custom\",\n user ? { actingUserId: user } : undefined,\n );\n writeJson({\n ok: true,\n // Detail view: the full row (address included) plus the usability verdict.\n // `health` itself is folded into `usable`/`problem` by `customEntry`.\n data: data.servers.map((server) => ({ ...server, health: undefined, ...customEntry(server) })),\n ...(data.servers.some((s) => s.health && !s.health.ok)\n ? {\n hints: data.servers.some((s) => s.health && !s.health.ok && !s.health.transient)\n ? [BROKEN_SERVER_HINT]\n : [LAST_CHECK_FAILED_HINT],\n }\n : {}),\n });\n } catch (err) {\n fail(err);\n }\n },\n});\n\nregisterSchema({\n command: \"mcp.add\",\n description:\n \"Register a custom MCP server. Tools appear as mcp__<name>__* on the next message. URL must be HTTPS. Scope: company (default, all chats) | org (org admin key) | user (only the current sender).\",\n args: {\n name: { type: \"string\", description: \"Server name → tools appear as mcp__<name>__*\", required: true },\n url: {\n type: \"string\",\n description: \"Full HTTPS MCP endpoint (commonly ends in /mcp, not just the domain)\",\n required: true,\n },\n scope: { type: \"string\", description: \"user | user_org | company | org (default company)\", required: false },\n header: { type: \"string\", description: 'Auth header \"Key: Value\" (repeatable)', required: false },\n },\n});\n\nconst addCommand = defineCommand({\n meta: {\n name: \"add\",\n description: `Register a custom MCP server. Tools appear as mcp__<name>__* on the NEXT message.\nFor a server the USER asks for, use request_connection { server } instead: they confirm who can use it,\ntype any key into the card (never the chat), and its tools load in this same turn.\n\nScope: company (default — every chat in the company) | org (all companies in the org; needs an admin key) | user (only the current message sender).\n\nExamples:\n baker mcp add --name weather --url https://mcp.example.com/mcp\n baker mcp add --name acme --url https://acme.dev/mcp --header \"Authorization: Bearer sk-…\"\n baker mcp add --name mine --url https://my.dev/mcp --scope user`,\n },\n args: {\n name: { type: \"string\", description: \"Server name (mcp__<name>__*)\", required: true },\n url: {\n type: \"string\",\n description: \"Full HTTPS MCP endpoint (commonly ends in /mcp, not just the domain)\",\n required: true,\n },\n scope: { type: \"string\", description: \"user | user_org | company | org (default company)\", required: false },\n header: { type: \"string\", description: 'Auth header \"Key: Value\" (repeatable)', required: false },\n },\n run: async ({ args, rawArgs }) => {\n try {\n const scope = parseScope(args.scope);\n const user = actingUserId();\n const headers = parseHeaders(args.header, rawArgs);\n const data = await apiPost<{ name: string }>(\"/api/mcp/custom\", {\n name: args.name as string,\n url: args.url as string,\n scope,\n ...(user ? { actingUserId: user } : {}),\n ...(headers ? { headers } : {}),\n });\n writeJson({\n ok: true,\n data,\n hints: [\n \"The address must be the full MCP endpoint (commonly ending in /mcp), not just the domain — a domain on its own usually answers sign-in and then serves no tools.\",\n \"The address is checked in the background. Run `baker mcp connected` on the next message to confirm it serves tools before promising the user anything.\",\n ],\n });\n } catch (err) {\n fail(err);\n }\n },\n});\n\nregisterSchema({\n command: \"mcp.remove\",\n description: \"Remove a company custom MCP server by name.\",\n args: { name: { type: \"string\", description: \"Server name to remove\", required: true } },\n});\n\nconst removeCommand = defineCommand({\n meta: {\n name: \"remove\",\n description: `Remove a company custom MCP server by name.\n\nExample:\n baker mcp remove --name weather`,\n },\n args: { name: { type: \"string\", description: \"Server name to remove\", required: true } },\n run: async ({ args }) => {\n try {\n const user = actingUserId();\n const data = await apiPost<{ removed: boolean }>(\"/api/mcp/custom/remove\", {\n name: args.name as string,\n ...(user ? { actingUserId: user } : {}),\n });\n writeJson({ ok: true, data });\n } catch (err) {\n fail(err);\n }\n },\n});\n\nconst serverNameArgs = {\n name: { type: \"string\", description: \"Custom server name, as `baker mcp list` shows it\", required: true },\n} as const;\n\nregisterSchema({\n command: \"mcp.verify\",\n description:\n \"Check a custom MCP server now (the dashboard's 'Check now') and store the result. Use after the user fixed its address or sign-in, or when its tools failed this turn.\",\n args: serverNameArgs,\n});\n\nconst verifyCommand = defineCommand({\n meta: {\n name: \"verify\",\n description: `Check a custom MCP server now and store the result.\n\nExample:\n baker mcp verify --name weather`,\n },\n args: serverNameArgs,\n run: async ({ args }) => {\n const parsed = customMcpServerNameRequestSchema.safeParse({ name: args.name, actingUserId: actingUserId() });\n if (!parsed.success) {\n fail(new ApiError(\"VALIDATION_ERROR\", parsed.error.issues[0]?.message ?? \"Invalid arguments\"));\n }\n try {\n const data = await apiPost<CustomMcpVerifyResponse>(\"/api/mcp/custom/verify\", parsed.data);\n writeJson({\n ok: true,\n data,\n hints: [\n data.ok\n ? \"The server answers and serves tools. Its tools load on the next message.\"\n : data.transient\n ? LAST_CHECK_FAILED_HINT\n : BROKEN_SERVER_HINT,\n ],\n });\n } catch (err) {\n fail(err);\n }\n },\n});\n\nregisterSchema({\n command: \"mcp.disable\",\n description:\n \"Switch a custom MCP server off so its tools stop loading; its address and sign-in are kept. Turning it back on is done by a person in the dashboard, never by the agent.\",\n args: serverNameArgs,\n});\n\nconst disableCommand = defineCommand({\n meta: {\n name: \"disable\",\n description: `Switch a custom MCP server off (its tools stop loading). Only a person can turn it back on, in the dashboard.\n\nExample:\n baker mcp disable --name weather`,\n },\n args: serverNameArgs,\n run: async ({ args }) => {\n const parsed = customMcpServerNameRequestSchema.safeParse({ name: args.name, actingUserId: actingUserId() });\n if (!parsed.success) {\n fail(new ApiError(\"VALIDATION_ERROR\", parsed.error.issues[0]?.message ?? \"Invalid arguments\"));\n }\n try {\n const data = await apiPost<CustomMcpDisableResponse>(\"/api/mcp/custom/disable\", parsed.data);\n writeJson({\n ok: true,\n data,\n hints: [\n \"Its tools stop loading from the next message, and this applies right away — publishing or discarding this chat does not undo it. Tell the user they can turn it back on in Brain → Integrations → More apps.\",\n ],\n });\n } catch (err) {\n fail(err);\n }\n },\n});\n\nexport const mcpCommand = defineCommand({\n meta: {\n name: \"mcp\",\n description: `Third-party tools for this company — see what's connected, register custom HTTPS MCP endpoints.\n\nTools from a registered server appear as mcp__<name>__* on the next message.\nManaged here are **company-scoped** servers; user- and org-scoped servers are managed in the dashboard.\n\nStart here:\n baker mcp connected # everything this chat can reach: managed integrations, custom servers, connected platforms\n baker mcp catalog --search notion # managed apps you can connect when a vendor has no MCP server of its own\n\nExamples:\n baker mcp add --name weather --url https://mcp.example.com/mcp\n baker mcp add --name acme --url https://acme.dev/mcp --header \"Authorization: Bearer sk-…\"\n baker mcp remove --name weather\n baker mcp verify --name weather # check it now after the user fixed it\n baker mcp disable --name weather # stop its tools loading (only a person turns it back on)\nFull guide: __tooling__/docs/tools/baker/mcp.md`,\n },\n subCommands: {\n connected: connectedCommand,\n catalog: catalogCommand,\n list: listCommand,\n add: addCommand,\n remove: removeCommand,\n verify: verifyCommand,\n disable: disableCommand,\n },\n});\n","/**\n * What `baker mcp catalog` tells the agent to do next with the managed apps it\n * found — the fallback when a vendor publishes no MCP server of its own.\n */\nimport type { McpCatalogEntry } from \"@baker/api/mcp-catalog\";\n\nconst PREFER_VENDOR_HINT =\n 'The vendor\\'s own MCP server comes before any app here. If you have not yet, WebSearch \"<vendor> MCP server\" and WebFetch its official docs for the remote https address and how it signs in, then ask for it with request_connection `{ server: { name, url, auth, keyHeader } }`. Only when the vendor has none, ask for an app from this catalog with request_connection `{ app: \"<slug>\", reason }` — the user connects it in the chat and its tools load right after, in this same turn.';\n\nconst ALREADY_CONNECTED_HINT =\n \"An app marked connected is already reachable — use its mcp__composio_* tools; do not ask again.\";\n\nconst NO_MATCH_HINT =\n \"Nothing in the catalog matches. WebSearch for the vendor's official remote MCP server (its docs, its developer site) before telling the user it can't be connected — if one exists, ask for it with request_connection `{ server }`. Only when the web shows no official remote server either, say plainly this tool can't be connected yet and offer a Task.\";\n\nconst MANAGED_DISABLED_HINT =\n \"Managed apps are switched off for this company, so none can be connected here. Use the vendor's own MCP server — WebSearch \\\"<vendor> MCP server\\\" and WebFetch its official docs, then request_connection `{ server }`; when it has none, say plainly this tool can't be connected yet and offer a Task.\";\n\n/** Baker's own connection always wins over a catalog app or anyone's MCP server for the same tool. */\nfunction firstPartyHint(platforms: readonly string[]): string {\n const asks = platforms.map((p) => `request_connection \\`{ platform: \"${p}\" }\\``).join(\" or \");\n return `This is one of Baker's own connections — ask for it with ${asks}. It is the one Baker's commands, staging and publish work with, so never connect it as a catalog app or as an MCP server, even one the vendor publishes or the user names. If it is already connected, read it with its own baker command family instead.`;\n}\n\n/** What the agent should do next with a catalog answer. */\nexport function catalogHints(\n apps: readonly McpCatalogEntry[],\n { managedDisabled = false, platforms = [] }: { managedDisabled?: boolean; platforms?: readonly string[] } = {},\n): string[] {\n if (platforms.length > 0) {\n return [firstPartyHint(platforms)];\n }\n if (managedDisabled) {\n return [MANAGED_DISABLED_HINT];\n }\n const hints = [PREFER_VENDOR_HINT];\n if (apps.some((a) => a.connected)) {\n hints.push(ALREADY_CONNECTED_HINT);\n }\n if (apps.length === 0) {\n hints.push(NO_MATCH_HINT);\n }\n return hints;\n}\n","/**\n * How a connected platform reads back to the agent.\n *\n * A platform (HubSpot, Google Ads, GA4, …) is an account the company signed in\n * to, reached through its own `baker` command family rather than an `mcp__*`\n * tool. It rides `mcp connected` because that is the one answer to \"what can\n * this chat reach\" — and because an agent that only saw the tool half had no\n * way to tell a working HubSpot connection from a missing one.\n */\n\nexport interface ConnectedPlatform {\n type: string;\n label: string;\n account: string | null;\n reads: string[];\n readsLabel: string | null;\n}\n\n/** \"Ad Accounts\" -> `adAccounts`, \"Properties\" -> `properties`. */\nfunction readsKey(label: string): string {\n const [first = \"\", ...rest] = label.split(\" \");\n return [first.toLowerCase(), ...rest].join(\"\");\n}\n\n/**\n * One platform as the agent sees it. The resources are keyed by the platform's\n * own word for them — `properties` for GA4, `containers` for Tag Manager,\n * `adAccounts` for the ad platforms — so what the agent reads back matches what\n * the user sees in the dashboard.\n */\nexport function platformEntry(platform: ConnectedPlatform): Record<string, unknown> {\n return {\n platform: platform.label,\n ...(platform.account ? { account: platform.account } : {}),\n ...(platform.readsLabel && platform.reads.length > 0 ? { [readsKey(platform.readsLabel)]: platform.reads } : {}),\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -22,11 +22,11 @@ Full guide: __tooling__/docs/tools/baker/media-sources.md`
|
|
|
22
22
|
list: () => import("./list-AL7N6X2P.js").then((m) => m.listCommand),
|
|
23
23
|
sync: () => import("./sync-CF7FVUQJ.js").then((m) => m.syncCommand),
|
|
24
24
|
schedule: () => import("./schedule-O2K6M43V.js").then((m) => m.scheduleCommand),
|
|
25
|
-
reset: () => import("./reset-
|
|
25
|
+
reset: () => import("./reset-C4UHQ3EU.js").then((m) => m.resetCommand),
|
|
26
26
|
remove: () => import("./remove-6LGGKMLJ.js").then((m) => m.removeCommand)
|
|
27
27
|
}
|
|
28
28
|
});
|
|
29
29
|
export {
|
|
30
30
|
mediaSourcesCommand
|
|
31
31
|
};
|
|
32
|
-
//# sourceMappingURL=media-sources-
|
|
32
|
+
//# sourceMappingURL=media-sources-O6ZRUA3N.js.map
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
failApi
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-3HJLHTWP.js";
|
|
4
|
+
import "./chunk-XF4JUKVF.js";
|
|
5
5
|
import "./chunk-GXDLWBOY.js";
|
|
6
6
|
import "./chunk-TEINLN64.js";
|
|
7
7
|
import "./chunk-ZJWUBJYQ.js";
|
|
8
|
-
import "./chunk-HR6IWNKE.js";
|
|
9
8
|
import "./chunk-NE4F3FHN.js";
|
|
10
9
|
import {
|
|
11
10
|
apiPost
|
|
@@ -42,4 +41,4 @@ var membersCommand = defineCommand({
|
|
|
42
41
|
export {
|
|
43
42
|
membersCommand
|
|
44
43
|
};
|
|
45
|
-
//# sourceMappingURL=members-
|
|
44
|
+
//# sourceMappingURL=members-D5ZYLS4Y.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/actions/members.ts"],"sourcesContent":["import type { ActionsMembersResponse } from \"@baker/api\";\nimport { defineCommand } from \"citty\";\nimport { apiPost } from \"../../client.ts\";\nimport { writeJson } from \"../../output.ts\";\nimport { registerSchema } from \"../../schemas.ts\";\nimport { failApi } from \"./shared.ts\";\n\nregisterSchema({\n command: \"actions.members\",\n description:\n \"The teammates a Task can be assigned to — everyone with access to this company that the person behind this chat can see, as { userId, name, email, role }. Pass a userId or email from here to `baker actions assign --to`. Read-only.\",\n args: {},\n});\n\nexport const membersCommand = defineCommand({\n meta: {\n name: \"members\",\n description: \"Teammates a Task can be assigned to. Example: baker actions members\",\n },\n run: async () => {\n try {\n const response = await apiPost<ActionsMembersResponse>(\"/api/actions/members\", {});\n writeJson(response);\n } catch (err) {\n failApi(err);\n }\n },\n});\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/commands/actions/members.ts"],"sourcesContent":["import type { ActionsMembersResponse } from \"@baker/api\";\nimport { defineCommand } from \"citty\";\nimport { apiPost } from \"../../client.ts\";\nimport { writeJson } from \"../../output.ts\";\nimport { registerSchema } from \"../../schemas.ts\";\nimport { failApi } from \"./shared.ts\";\n\nregisterSchema({\n command: \"actions.members\",\n description:\n \"The teammates a Task can be assigned to — everyone with access to this company that the person behind this chat can see, as { userId, name, email, role }. Pass a userId or email from here to `baker actions assign --to`. Read-only.\",\n args: {},\n});\n\nexport const membersCommand = defineCommand({\n meta: {\n name: \"members\",\n description: \"Teammates a Task can be assigned to. Example: baker actions members\",\n },\n run: async () => {\n try {\n const response = await apiPost<ActionsMembersResponse>(\"/api/actions/members\", {});\n writeJson(response);\n } catch (err) {\n failApi(err);\n }\n },\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AACA,SAAS,qBAAqB;AAM9B,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aACE;AAAA,EACF,MAAM,CAAC;AACT,CAAC;AAEM,IAAM,iBAAiB,cAAc;AAAA,EAC1C,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AAAA,EACA,KAAK,YAAY;AACf,QAAI;AACF,YAAM,WAAW,MAAM,QAAgC,wBAAwB,CAAC,CAAC;AACjF,gBAAU,QAAQ;AAAA,IACpB,SAAS,KAAK;AACZ,cAAQ,GAAG;AAAA,IACb;AAAA,EACF;AACF,CAAC;","names":[]}
|
|
@@ -4,19 +4,15 @@ import {
|
|
|
4
4
|
readFlowTree,
|
|
5
5
|
walkNodes,
|
|
6
6
|
writeFlowTree
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-YRQYA2LR.js";
|
|
8
8
|
import {
|
|
9
9
|
looksLikeUnresolvedVariable,
|
|
10
10
|
parseEmailRecipients
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-XF4JUKVF.js";
|
|
12
12
|
import "./chunk-GXDLWBOY.js";
|
|
13
13
|
import "./chunk-TEINLN64.js";
|
|
14
14
|
import "./chunk-ZJWUBJYQ.js";
|
|
15
|
-
import "./chunk-HR6IWNKE.js";
|
|
16
15
|
import "./chunk-NE4F3FHN.js";
|
|
17
|
-
import "./chunk-XBOK23HI.js";
|
|
18
|
-
import "./chunk-IFWP3ZDO.js";
|
|
19
|
-
import "./chunk-NAWWC5I3.js";
|
|
20
16
|
import {
|
|
21
17
|
registerSchema,
|
|
22
18
|
writeJson
|
|
@@ -139,4 +135,4 @@ export {
|
|
|
139
135
|
normalizeCommand,
|
|
140
136
|
normalizeFlowTree
|
|
141
137
|
};
|
|
142
|
-
//# sourceMappingURL=normalize-
|
|
138
|
+
//# sourceMappingURL=normalize-PCNC6E2N.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/flows/normalize.ts"],"sourcesContent":["/**\n * Make a form file valid without making the agent memorise a rule.\n *\n * `oauthProviderId` is typed `oauthProviderId?: string`. Writing `null` there is\n * the natural thing to do — every sibling confidential field is authored as\n * `null` — and it is a type error at the next build. Three separate passages in\n * the flow-builder skill existed only to teach that one exception, and the agent\n * paid for them on every turn that touched a form.\n *\n * So the system absorbs it instead: an unset optional is dropped, a nulled array\n * becomes an empty one, a missing `condition` becomes the explicit `null` the\n * schema wants. This runs as a pre-commit fixer, so writing `null` is simply not\n * a mistake any more, and the prose that taught the rule is gone.\n *\n * Pure — `normalizeFlowTree` mutates a decoded tree and reports what it changed,\n * so the command and the tests share one implementation.\n */\n\nimport { looksLikeUnresolvedVariable, parseEmailRecipients } from \"@baker/api\";\nimport { defineCommand } from \"citty\";\nimport { writeJson } from \"../../output.ts\";\nimport { registerSchema } from \"../../schemas.ts\";\nimport { flowDataPath, listFlowSlugs, readFlowTree, walkNodes, writeFlowTree } from \"./shared.ts\";\n\ntype AnyRecord = Record<string, unknown>;\n\n/** Optional string fields where \"unset\" must be an absent key, never `null` or `\"\"`. */\nconst OPTIONAL_STRINGS = [\"oauthProviderId\"] as const;\n/**\n * Fields typed as arrays, where `null` means \"none yet\".\n *\n * Every `PayloadKey[]` slot the engine defines is here, not just the common\n * ones: this list is what makes \"a nulled array is not a mistake\" true, so a\n * slot missing from it is a rule the agent is told it no longer has to\n * remember, and then fails a build for forgetting. `flows-normalize-coverage`\n * in `normalize.test.ts` pins it against `MAPPING_SLOTS`.\n */\nconst ARRAY_FIELDS = [\n \"fieldMapping\",\n \"columnMapping\",\n \"payloadKeys\",\n \"eventParams\",\n \"eventProperties\",\n \"dataLayerParams\",\n \"goalParams\",\n \"fields\",\n \"tagIds\",\n] as const;\n\nexport type Normalization = { path: string; change: string };\n\n/**\n * Objects that can carry a mappable array, relative to the side effect.\n *\n * An email's keys live at `body.fields`, one level down, and `null` there is the\n * same type error as `payloadKeys: null` is at the top. Repairing only the top\n * level would leave the one nested slot as a rule the agent still has to know.\n */\nconst ARRAY_OWNERS = [\"\", \"body\"] as const;\n\n/** Drop an optional string that was authored as `null` or `\"\"`. */\nfunction dropUnsetOptionals(sideEffect: AnyRecord, path: string): Normalization[] {\n return OPTIONAL_STRINGS.flatMap((key) => {\n if (!(key in sideEffect) || (sideEffect[key] !== null && sideEffect[key] !== \"\")) return [];\n delete sideEffect[key];\n return [{ path, change: `dropped \\`${key}\\` (an optional string is absent, never null)` }];\n });\n}\n\n/** Turn every nulled array on one object into an empty one. */\nfunction fillNulledArrays(target: AnyRecord, prefix: string, path: string): Normalization[] {\n return ARRAY_FIELDS.flatMap((key) => {\n if (!(key in target) || target[key] !== null) return [];\n target[key] = [];\n return [{ path, change: `\\`${prefix}${key}: null\\` → \\`[]\\`` }];\n });\n}\n\n/**\n * Tidy an email destination's recipient list, or null when there is nothing to\n * tidy — and, just as importantly, when tidying would hide something.\n *\n * The field is one string holding a list, so it collects the marks of having\n * been typed: a leading space, a trailing comma, a semicolon where a comma was\n * meant, the same address twice. None changes who receives the mail —\n * `parseEmailRecipients` reads all of them the same way at send time — so this\n * is a shape repair rather than a judgement call, which is what keeps it here.\n *\n * It refuses where a rewrite would be one. A `{{…}}` that was never substituted\n * and a fragment that is not an address both belong to\n * `validate-flow-email-recipients`, which quotes them back verbatim; a tidied\n * copy would put words in the author's mouth on the screen where they are\n * trying to recognise their own mistake.\n */\nfunction tidyEmailRecipients(sideEffect: AnyRecord, path: string): Normalization[] {\n if (sideEffect.type !== \"email\") return [];\n const config = sideEffect.encryptedConfig;\n // A string is the dashboard-configured half, encrypted; an object is the\n // agent-authored half, which is the only one anybody can read.\n if (!config || typeof config !== \"object\" || Array.isArray(config)) return [];\n const raw = (config as AnyRecord).email;\n if (typeof raw !== \"string\" || looksLikeUnresolvedVariable(raw)) return [];\n const { to, invalid } = parseEmailRecipients(raw);\n if (invalid.length > 0 || to.length === 0) return [];\n const tidied = to.join(\", \");\n if (tidied === raw) return [];\n (config as AnyRecord).email = tidied;\n return [{ path, change: \"tidied the recipient list's spacing and separators\" }];\n}\n\n/** Side effects of one node, skipping anything that is not an object to patch. */\nfunction sideEffectsOf(node: AnyRecord): AnyRecord[] {\n if (!Array.isArray(node.sideEffects)) return [];\n return (node.sideEffects as unknown[]).filter(\n (sideEffect): sideEffect is AnyRecord => Boolean(sideEffect) && typeof sideEffect === \"object\",\n );\n}\n\n/** Repairs to one side effect, reported against the step that owns it. */\nfunction normalizeSideEffect(sideEffect: AnyRecord, where: string): Normalization[] {\n const path = `${where} → ${String(sideEffect.id ?? \"side effect\")}`;\n const arrays = ARRAY_OWNERS.flatMap((owner) => {\n const target = owner ? (sideEffect[owner] as AnyRecord | undefined) : sideEffect;\n if (!target || typeof target !== \"object\") return [];\n return fillNulledArrays(target, owner ? `${owner}.` : \"\", path);\n });\n return [...dropUnsetOptionals(sideEffect, path), ...arrays, ...tidyEmailRecipients(sideEffect, path)];\n}\n\n/** Fix a decoded tree in place. Returns one line per change, empty when already clean. */\nexport function normalizeFlowTree(tree: AnyRecord): Normalization[] {\n const changes: Normalization[] = [];\n\n for (const node of walkNodes(tree)) {\n const where = typeof node.name === \"string\" && node.name ? String(node.name) : String(node.id ?? \"node\");\n\n // The root node has no condition by definition; every other node needs the\n // key present so a reader can tell \"always runs\" from \"nobody set this\".\n if (!(\"condition\" in node)) {\n node.condition = null;\n changes.push({ path: where, change: \"added the missing `condition: null`\" });\n }\n\n // Filtered, not `?? []`: a hand-authored `sideEffects` can hold a null or a\n // string, and reading `.id` off one throws inside the command that exists to\n // repair a form file that is already slightly wrong.\n for (const sideEffect of sideEffectsOf(node)) {\n changes.push(...normalizeSideEffect(sideEffect, where));\n }\n }\n\n return changes;\n}\n\nregisterSchema({\n command: \"flows.normalize\",\n description:\n \"Fix the shapes a form file is allowed to get slightly wrong: a nulled optional string, a nulled array, a missing condition. Runs automatically before a commit; you rarely need to call it.\",\n args: {\n slug: { type: \"positional\", description: \"Form slug. Omit to check every form.\", required: false },\n write: {\n type: \"boolean\",\n description: \"Apply the fixes. Without it, reports and changes nothing\",\n required: false,\n },\n },\n});\n\nexport const normalizeCommand = defineCommand({\n meta: {\n name: \"normalize\",\n description:\n \"Repair the shapes a form file is allowed to get slightly wrong. Example: baker flows normalize contact --write\",\n },\n args: {\n // `required: false` matters: citty makes a positional required by default,\n // so without it the documented bare `baker flows normalize` printed a wall\n // of usage text and exited 1 instead of checking every form.\n slug: { type: \"positional\", description: \"Form slug (omit for every form)\", required: false },\n write: { type: \"boolean\", description: \"Apply the fixes\" },\n },\n run: ({ args }) => {\n const slugs = args.slug ? [String(args.slug)] : listFlowSlugs();\n const forms = slugs.flatMap((slug) => {\n const tree = readFlowTree(slug);\n const changes = normalizeFlowTree(tree);\n if (changes.length === 0) return [];\n if (args.write === true) writeFlowTree(slug, tree);\n return [{ slug, path: flowDataPath(slug), changes }];\n });\n\n const total = forms.reduce((sum, form) => sum + form.changes.length, 0);\n writeJson({\n ok: true,\n data: { forms, changed: total, written: args.write === true },\n hints:\n total === 0\n ? [\"Nothing to fix.\"]\n : args.write === true\n ? [`Fixed ${total} field(s).`]\n : [`${total} field(s) can be fixed. Re-run with --write.`],\n });\n },\n});\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/commands/flows/normalize.ts"],"sourcesContent":["/**\n * Make a form file valid without making the agent memorise a rule.\n *\n * `oauthProviderId` is typed `oauthProviderId?: string`. Writing `null` there is\n * the natural thing to do — every sibling confidential field is authored as\n * `null` — and it is a type error at the next build. Three separate passages in\n * the flow-builder skill existed only to teach that one exception, and the agent\n * paid for them on every turn that touched a form.\n *\n * So the system absorbs it instead: an unset optional is dropped, a nulled array\n * becomes an empty one, a missing `condition` becomes the explicit `null` the\n * schema wants. This runs as a pre-commit fixer, so writing `null` is simply not\n * a mistake any more, and the prose that taught the rule is gone.\n *\n * Pure — `normalizeFlowTree` mutates a decoded tree and reports what it changed,\n * so the command and the tests share one implementation.\n */\n\nimport { looksLikeUnresolvedVariable, parseEmailRecipients } from \"@baker/api\";\nimport { defineCommand } from \"citty\";\nimport { writeJson } from \"../../output.ts\";\nimport { registerSchema } from \"../../schemas.ts\";\nimport { flowDataPath, listFlowSlugs, readFlowTree, walkNodes, writeFlowTree } from \"./shared.ts\";\n\ntype AnyRecord = Record<string, unknown>;\n\n/** Optional string fields where \"unset\" must be an absent key, never `null` or `\"\"`. */\nconst OPTIONAL_STRINGS = [\"oauthProviderId\"] as const;\n/**\n * Fields typed as arrays, where `null` means \"none yet\".\n *\n * Every `PayloadKey[]` slot the engine defines is here, not just the common\n * ones: this list is what makes \"a nulled array is not a mistake\" true, so a\n * slot missing from it is a rule the agent is told it no longer has to\n * remember, and then fails a build for forgetting. `flows-normalize-coverage`\n * in `normalize.test.ts` pins it against `MAPPING_SLOTS`.\n */\nconst ARRAY_FIELDS = [\n \"fieldMapping\",\n \"columnMapping\",\n \"payloadKeys\",\n \"eventParams\",\n \"eventProperties\",\n \"dataLayerParams\",\n \"goalParams\",\n \"fields\",\n \"tagIds\",\n] as const;\n\nexport type Normalization = { path: string; change: string };\n\n/**\n * Objects that can carry a mappable array, relative to the side effect.\n *\n * An email's keys live at `body.fields`, one level down, and `null` there is the\n * same type error as `payloadKeys: null` is at the top. Repairing only the top\n * level would leave the one nested slot as a rule the agent still has to know.\n */\nconst ARRAY_OWNERS = [\"\", \"body\"] as const;\n\n/** Drop an optional string that was authored as `null` or `\"\"`. */\nfunction dropUnsetOptionals(sideEffect: AnyRecord, path: string): Normalization[] {\n return OPTIONAL_STRINGS.flatMap((key) => {\n if (!(key in sideEffect) || (sideEffect[key] !== null && sideEffect[key] !== \"\")) return [];\n delete sideEffect[key];\n return [{ path, change: `dropped \\`${key}\\` (an optional string is absent, never null)` }];\n });\n}\n\n/** Turn every nulled array on one object into an empty one. */\nfunction fillNulledArrays(target: AnyRecord, prefix: string, path: string): Normalization[] {\n return ARRAY_FIELDS.flatMap((key) => {\n if (!(key in target) || target[key] !== null) return [];\n target[key] = [];\n return [{ path, change: `\\`${prefix}${key}: null\\` → \\`[]\\`` }];\n });\n}\n\n/**\n * Tidy an email destination's recipient list, or null when there is nothing to\n * tidy — and, just as importantly, when tidying would hide something.\n *\n * The field is one string holding a list, so it collects the marks of having\n * been typed: a leading space, a trailing comma, a semicolon where a comma was\n * meant, the same address twice. None changes who receives the mail —\n * `parseEmailRecipients` reads all of them the same way at send time — so this\n * is a shape repair rather than a judgement call, which is what keeps it here.\n *\n * It refuses where a rewrite would be one. A `{{…}}` that was never substituted\n * and a fragment that is not an address both belong to\n * `validate-flow-email-recipients`, which quotes them back verbatim; a tidied\n * copy would put words in the author's mouth on the screen where they are\n * trying to recognise their own mistake.\n */\nfunction tidyEmailRecipients(sideEffect: AnyRecord, path: string): Normalization[] {\n if (sideEffect.type !== \"email\") return [];\n const config = sideEffect.encryptedConfig;\n // A string is the dashboard-configured half, encrypted; an object is the\n // agent-authored half, which is the only one anybody can read.\n if (!config || typeof config !== \"object\" || Array.isArray(config)) return [];\n const raw = (config as AnyRecord).email;\n if (typeof raw !== \"string\" || looksLikeUnresolvedVariable(raw)) return [];\n const { to, invalid } = parseEmailRecipients(raw);\n if (invalid.length > 0 || to.length === 0) return [];\n const tidied = to.join(\", \");\n if (tidied === raw) return [];\n (config as AnyRecord).email = tidied;\n return [{ path, change: \"tidied the recipient list's spacing and separators\" }];\n}\n\n/** Side effects of one node, skipping anything that is not an object to patch. */\nfunction sideEffectsOf(node: AnyRecord): AnyRecord[] {\n if (!Array.isArray(node.sideEffects)) return [];\n return (node.sideEffects as unknown[]).filter(\n (sideEffect): sideEffect is AnyRecord => Boolean(sideEffect) && typeof sideEffect === \"object\",\n );\n}\n\n/** Repairs to one side effect, reported against the step that owns it. */\nfunction normalizeSideEffect(sideEffect: AnyRecord, where: string): Normalization[] {\n const path = `${where} → ${String(sideEffect.id ?? \"side effect\")}`;\n const arrays = ARRAY_OWNERS.flatMap((owner) => {\n const target = owner ? (sideEffect[owner] as AnyRecord | undefined) : sideEffect;\n if (!target || typeof target !== \"object\") return [];\n return fillNulledArrays(target, owner ? `${owner}.` : \"\", path);\n });\n return [...dropUnsetOptionals(sideEffect, path), ...arrays, ...tidyEmailRecipients(sideEffect, path)];\n}\n\n/** Fix a decoded tree in place. Returns one line per change, empty when already clean. */\nexport function normalizeFlowTree(tree: AnyRecord): Normalization[] {\n const changes: Normalization[] = [];\n\n for (const node of walkNodes(tree)) {\n const where = typeof node.name === \"string\" && node.name ? String(node.name) : String(node.id ?? \"node\");\n\n // The root node has no condition by definition; every other node needs the\n // key present so a reader can tell \"always runs\" from \"nobody set this\".\n if (!(\"condition\" in node)) {\n node.condition = null;\n changes.push({ path: where, change: \"added the missing `condition: null`\" });\n }\n\n // Filtered, not `?? []`: a hand-authored `sideEffects` can hold a null or a\n // string, and reading `.id` off one throws inside the command that exists to\n // repair a form file that is already slightly wrong.\n for (const sideEffect of sideEffectsOf(node)) {\n changes.push(...normalizeSideEffect(sideEffect, where));\n }\n }\n\n return changes;\n}\n\nregisterSchema({\n command: \"flows.normalize\",\n description:\n \"Fix the shapes a form file is allowed to get slightly wrong: a nulled optional string, a nulled array, a missing condition. Runs automatically before a commit; you rarely need to call it.\",\n args: {\n slug: { type: \"positional\", description: \"Form slug. Omit to check every form.\", required: false },\n write: {\n type: \"boolean\",\n description: \"Apply the fixes. Without it, reports and changes nothing\",\n required: false,\n },\n },\n});\n\nexport const normalizeCommand = defineCommand({\n meta: {\n name: \"normalize\",\n description:\n \"Repair the shapes a form file is allowed to get slightly wrong. Example: baker flows normalize contact --write\",\n },\n args: {\n // `required: false` matters: citty makes a positional required by default,\n // so without it the documented bare `baker flows normalize` printed a wall\n // of usage text and exited 1 instead of checking every form.\n slug: { type: \"positional\", description: \"Form slug (omit for every form)\", required: false },\n write: { type: \"boolean\", description: \"Apply the fixes\" },\n },\n run: ({ args }) => {\n const slugs = args.slug ? [String(args.slug)] : listFlowSlugs();\n const forms = slugs.flatMap((slug) => {\n const tree = readFlowTree(slug);\n const changes = normalizeFlowTree(tree);\n if (changes.length === 0) return [];\n if (args.write === true) writeFlowTree(slug, tree);\n return [{ slug, path: flowDataPath(slug), changes }];\n });\n\n const total = forms.reduce((sum, form) => sum + form.changes.length, 0);\n writeJson({\n ok: true,\n data: { forms, changed: total, written: args.write === true },\n hints:\n total === 0\n ? [\"Nothing to fix.\"]\n : args.write === true\n ? [`Fixed ${total} field(s).`]\n : [`${total} field(s) can be fixed. Re-run with --write.`],\n });\n },\n});\n"],"mappings":"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","names":[]}
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
destinationRefusal
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
5
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-DWHIOO7E.js";
|
|
4
|
+
import "./chunk-SHL7LOC3.js";
|
|
5
|
+
import "./chunk-YRQYA2LR.js";
|
|
6
6
|
import {
|
|
7
7
|
failApi
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-3HJLHTWP.js";
|
|
9
9
|
import {
|
|
10
10
|
FLOW_AGENT_DESTINATION_KINDS
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-XF4JUKVF.js";
|
|
12
12
|
import "./chunk-GXDLWBOY.js";
|
|
13
13
|
import "./chunk-TEINLN64.js";
|
|
14
14
|
import "./chunk-ZJWUBJYQ.js";
|
|
15
|
-
import "./chunk-HR6IWNKE.js";
|
|
16
15
|
import "./chunk-NE4F3FHN.js";
|
|
17
16
|
import {
|
|
18
17
|
ApiError,
|
|
@@ -119,4 +118,4 @@ export {
|
|
|
119
118
|
optionsCommand,
|
|
120
119
|
optionsHints
|
|
121
120
|
};
|
|
122
|
-
//# sourceMappingURL=options-
|
|
121
|
+
//# sourceMappingURL=options-MQ65VEVD.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/flows/options.ts"],"sourcesContent":["/**\n * `options`: what a Form's step or destination could be filled with, read\n * through the company's connected account — the same list the card shows the\n * user, so the agent can choose instead of asking.\n */\n\nimport { FLOW_AGENT_DESTINATION_KINDS, type FlowAgentDestinationKind, type FlowsOptionsResponse } from \"@baker/api\";\nimport { defineCommand } from \"citty\";\nimport { ApiError, apiPost } from \"../../client.ts\";\nimport { writeJson } from \"../../output.ts\";\nimport { registerSchema } from \"../../schemas.ts\";\nimport { failApi } from \"../actions/shared.ts\";\nimport { destinationRefusal } from \"./connect.ts\";\n\nconst HUBSPOT_KINDS: Record<string, string> = {\n hubspot: \"baker hubspot forms list\",\n hubspotForm: \"baker hubspot forms list\",\n hubspotMeeting: \"baker hubspot meetings list\",\n};\n\n/** The next call for each kind, spelled out — the target flag differs between a step and a destination. */\nexport function optionsHints(data: FlowsOptionsResponse[\"data\"]): string[] {\n const { kind, options } = data;\n if (kind === \"pipedrive\" || kind === \"goHighlevelContact\") {\n return [\n `Nothing to choose: the connected account is the destination. Wire it: baker flows connect <slug> --side-effect <id> (or --all --type ${kind}).`,\n ];\n }\n if (kind === \"googleSpreadsheet\") {\n return [\n \"These are the only spreadsheets Baker can reach: ones someone chose for a Form before, and ones Baker created. Pick one: baker flows connect <slug> --side-effect <id> --resource <id> [--tab <name>].\",\n 'None fits? Create one yourself: baker flows connect <slug> --side-effect <id> --new-sheet \"<Form name> leads\" --columns \"Name,Email,…\". Only when the user wants their own existing sheet: request_flow_input.',\n ];\n }\n const empty =\n options.length === 0\n ? [\"The account has none. Tell the user what to create there, or skip this step — do not invent one.\"]\n : [];\n return [\n ...empty,\n `Fill the step: baker flows connect <slug> --node <stepId> --resource <id> (or --all --type ${kind}). One clear match → use it; several plausible → ask the user which.`,\n ];\n}\n\nregisterSchema({\n command: \"flows.options\",\n description:\n \"What a Form step or destination can be filled with, read from the connected account: Calendly events, SavvyCal links, GoHighLevel calendars and forms, the Google spreadsheets Baker can reach. Pipedrive and GoHighLevel contact have nothing to choose — the account is the destination. Next: `baker flows connect <slug> --node|--side-effect <id> --resource <id>`. HubSpot has its own: `baker hubspot forms list` / `meetings list`.\",\n args: {\n kind: {\n type: \"positional\",\n description: `One of: ${FLOW_AGENT_DESTINATION_KINDS.join(\", \")}`,\n required: true,\n },\n account: {\n type: \"string\",\n description: \"Connection id, when more than one account of the platform is connected\",\n required: false,\n },\n },\n});\n\nexport const optionsCommand = defineCommand({\n meta: {\n name: \"options\",\n description:\n \"What a step or destination can be filled with, from the connected account. Start here: baker flows options calendly\",\n },\n args: {\n kind: { type: \"positional\", description: FLOW_AGENT_DESTINATION_KINDS.join(\" | \"), required: true },\n account: { type: \"string\", description: \"Connection id when several are connected\" },\n },\n run: async ({ args }) => {\n const kind = String(args.kind);\n const hubspot = HUBSPOT_KINDS[kind];\n if (hubspot) {\n writeJson({ ok: false, error: { code: \"VALIDATION_ERROR\", message: `HubSpot has its own list: ${hubspot}.` } });\n process.exit(1);\n }\n if (!(FLOW_AGENT_DESTINATION_KINDS as readonly string[]).includes(kind)) {\n writeJson({\n ok: false,\n error: {\n code: \"VALIDATION_ERROR\",\n message: `\"${kind}\" is not filled from a platform account.`,\n fix: `Kinds: ${FLOW_AGENT_DESTINATION_KINDS.join(\", \")}. Typed credentials (webhooks, Zapier, Crmble) go through request_flow_input.`,\n },\n });\n process.exit(1);\n }\n try {\n const { data } = await apiPost<FlowsOptionsResponse>(\"/api/flows/destinations/options\", {\n kind,\n ...(args.account ? { account: String(args.account) } : {}),\n });\n writeJson({\n ok: true,\n data: { ...data, accounts: data.accounts.length > 1 ? data.accounts : undefined },\n hints: optionsHints(data),\n });\n } catch (err) {\n const refusal = err instanceof ApiError ? destinationRefusal(kind as FlowAgentDestinationKind, err) : null;\n if (err instanceof ApiError && refusal !== null) {\n writeJson({ ok: false, error: { code: refusal.code, message: err.message, fix: refusal.fix } });\n process.exit(1);\n }\n failApi(err);\n }\n },\n});\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/commands/flows/options.ts"],"sourcesContent":["/**\n * `options`: what a Form's step or destination could be filled with, read\n * through the company's connected account — the same list the card shows the\n * user, so the agent can choose instead of asking.\n */\n\nimport { FLOW_AGENT_DESTINATION_KINDS, type FlowAgentDestinationKind, type FlowsOptionsResponse } from \"@baker/api\";\nimport { defineCommand } from \"citty\";\nimport { ApiError, apiPost } from \"../../client.ts\";\nimport { writeJson } from \"../../output.ts\";\nimport { registerSchema } from \"../../schemas.ts\";\nimport { failApi } from \"../actions/shared.ts\";\nimport { destinationRefusal } from \"./connect.ts\";\n\nconst HUBSPOT_KINDS: Record<string, string> = {\n hubspot: \"baker hubspot forms list\",\n hubspotForm: \"baker hubspot forms list\",\n hubspotMeeting: \"baker hubspot meetings list\",\n};\n\n/** The next call for each kind, spelled out — the target flag differs between a step and a destination. */\nexport function optionsHints(data: FlowsOptionsResponse[\"data\"]): string[] {\n const { kind, options } = data;\n if (kind === \"pipedrive\" || kind === \"goHighlevelContact\") {\n return [\n `Nothing to choose: the connected account is the destination. Wire it: baker flows connect <slug> --side-effect <id> (or --all --type ${kind}).`,\n ];\n }\n if (kind === \"googleSpreadsheet\") {\n return [\n \"These are the only spreadsheets Baker can reach: ones someone chose for a Form before, and ones Baker created. Pick one: baker flows connect <slug> --side-effect <id> --resource <id> [--tab <name>].\",\n 'None fits? Create one yourself: baker flows connect <slug> --side-effect <id> --new-sheet \"<Form name> leads\" --columns \"Name,Email,…\". Only when the user wants their own existing sheet: request_flow_input.',\n ];\n }\n const empty =\n options.length === 0\n ? [\"The account has none. Tell the user what to create there, or skip this step — do not invent one.\"]\n : [];\n return [\n ...empty,\n `Fill the step: baker flows connect <slug> --node <stepId> --resource <id> (or --all --type ${kind}). One clear match → use it; several plausible → ask the user which.`,\n ];\n}\n\nregisterSchema({\n command: \"flows.options\",\n description:\n \"What a Form step or destination can be filled with, read from the connected account: Calendly events, SavvyCal links, GoHighLevel calendars and forms, the Google spreadsheets Baker can reach. Pipedrive and GoHighLevel contact have nothing to choose — the account is the destination. Next: `baker flows connect <slug> --node|--side-effect <id> --resource <id>`. HubSpot has its own: `baker hubspot forms list` / `meetings list`.\",\n args: {\n kind: {\n type: \"positional\",\n description: `One of: ${FLOW_AGENT_DESTINATION_KINDS.join(\", \")}`,\n required: true,\n },\n account: {\n type: \"string\",\n description: \"Connection id, when more than one account of the platform is connected\",\n required: false,\n },\n },\n});\n\nexport const optionsCommand = defineCommand({\n meta: {\n name: \"options\",\n description:\n \"What a step or destination can be filled with, from the connected account. Start here: baker flows options calendly\",\n },\n args: {\n kind: { type: \"positional\", description: FLOW_AGENT_DESTINATION_KINDS.join(\" | \"), required: true },\n account: { type: \"string\", description: \"Connection id when several are connected\" },\n },\n run: async ({ args }) => {\n const kind = String(args.kind);\n const hubspot = HUBSPOT_KINDS[kind];\n if (hubspot) {\n writeJson({ ok: false, error: { code: \"VALIDATION_ERROR\", message: `HubSpot has its own list: ${hubspot}.` } });\n process.exit(1);\n }\n if (!(FLOW_AGENT_DESTINATION_KINDS as readonly string[]).includes(kind)) {\n writeJson({\n ok: false,\n error: {\n code: \"VALIDATION_ERROR\",\n message: `\"${kind}\" is not filled from a platform account.`,\n fix: `Kinds: ${FLOW_AGENT_DESTINATION_KINDS.join(\", \")}. Typed credentials (webhooks, Zapier, Crmble) go through request_flow_input.`,\n },\n });\n process.exit(1);\n }\n try {\n const { data } = await apiPost<FlowsOptionsResponse>(\"/api/flows/destinations/options\", {\n kind,\n ...(args.account ? { account: String(args.account) } : {}),\n });\n writeJson({\n ok: true,\n data: { ...data, accounts: data.accounts.length > 1 ? data.accounts : undefined },\n hints: optionsHints(data),\n });\n } catch (err) {\n const refusal = err instanceof ApiError ? destinationRefusal(kind as FlowAgentDestinationKind, err) : null;\n if (err instanceof ApiError && refusal !== null) {\n writeJson({ ok: false, error: { code: refusal.code, message: err.message, fix: refusal.fix } });\n process.exit(1);\n }\n failApi(err);\n }\n },\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOA,SAAS,qBAAqB;AAO9B,IAAM,gBAAwC;AAAA,EAC5C,SAAS;AAAA,EACT,aAAa;AAAA,EACb,gBAAgB;AAClB;AAGO,SAAS,aAAa,MAA8C;AACzE,QAAM,EAAE,MAAM,QAAQ,IAAI;AAC1B,MAAI,SAAS,eAAe,SAAS,sBAAsB;AACzD,WAAO;AAAA,MACL,wIAAwI,IAAI;AAAA,IAC9I;AAAA,EACF;AACA,MAAI,SAAS,qBAAqB;AAChC,WAAO;AAAA,MACL;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,QAAM,QACJ,QAAQ,WAAW,IACf,CAAC,uGAAkG,IACnG,CAAC;AACP,SAAO;AAAA,IACL,GAAG;AAAA,IACH,8FAA8F,IAAI;AAAA,EACpG;AACF;AAEA,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aACE;AAAA,EACF,MAAM;AAAA,IACJ,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,aAAa,WAAW,6BAA6B,KAAK,IAAI,CAAC;AAAA,MAC/D,UAAU;AAAA,IACZ;AAAA,IACA,SAAS;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,IACZ;AAAA,EACF;AACF,CAAC;AAEM,IAAM,iBAAiB,cAAc;AAAA,EAC1C,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aACE;AAAA,EACJ;AAAA,EACA,MAAM;AAAA,IACJ,MAAM,EAAE,MAAM,cAAc,aAAa,6BAA6B,KAAK,KAAK,GAAG,UAAU,KAAK;AAAA,IAClG,SAAS,EAAE,MAAM,UAAU,aAAa,2CAA2C;AAAA,EACrF;AAAA,EACA,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,UAAM,OAAO,OAAO,KAAK,IAAI;AAC7B,UAAM,UAAU,cAAc,IAAI;AAClC,QAAI,SAAS;AACX,gBAAU,EAAE,IAAI,OAAO,OAAO,EAAE,MAAM,oBAAoB,SAAS,6BAA6B,OAAO,IAAI,EAAE,CAAC;AAC9G,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,QAAI,CAAE,6BAAmD,SAAS,IAAI,GAAG;AACvE,gBAAU;AAAA,QACR,IAAI;AAAA,QACJ,OAAO;AAAA,UACL,MAAM;AAAA,UACN,SAAS,IAAI,IAAI;AAAA,UACjB,KAAK,UAAU,6BAA6B,KAAK,IAAI,CAAC;AAAA,QACxD;AAAA,MACF,CAAC;AACD,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,QAAI;AACF,YAAM,EAAE,KAAK,IAAI,MAAM,QAA8B,mCAAmC;AAAA,QACtF;AAAA,QACA,GAAI,KAAK,UAAU,EAAE,SAAS,OAAO,KAAK,OAAO,EAAE,IAAI,CAAC;AAAA,MAC1D,CAAC;AACD,gBAAU;AAAA,QACR,IAAI;AAAA,QACJ,MAAM,EAAE,GAAG,MAAM,UAAU,KAAK,SAAS,SAAS,IAAI,KAAK,WAAW,OAAU;AAAA,QAChF,OAAO,aAAa,IAAI;AAAA,MAC1B,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,YAAM,UAAU,eAAe,WAAW,mBAAmB,MAAkC,GAAG,IAAI;AACtG,UAAI,eAAe,YAAY,YAAY,MAAM;AAC/C,kBAAU,EAAE,IAAI,OAAO,OAAO,EAAE,MAAM,QAAQ,MAAM,SAAS,IAAI,SAAS,KAAK,QAAQ,IAAI,EAAE,CAAC;AAC9F,gBAAQ,KAAK,CAAC;AAAA,MAChB;AACA,cAAQ,GAAG;AAAA,IACb;AAAA,EACF;AACF,CAAC;","names":[]}
|