@koda-sl/baker-cli 0.449.0-dev.bd86e5817 → 0.450.0-dev.b454c3dd2
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 +11 -6
- package/dist/{account-AL2ZDSR7.js → account-XQXC7BR6.js} +5 -4
- package/dist/{account-AL2ZDSR7.js.map → account-XQXC7BR6.js.map} +1 -1
- package/dist/{accounts-HAFCLSR5.js → accounts-722UY53A.js} +4 -3
- package/dist/{accounts-HAFCLSR5.js.map → accounts-722UY53A.js.map} +1 -1
- package/dist/{accounts-O5MFO3QQ.js → accounts-E67BMK7T.js} +6 -5
- package/dist/{accounts-O5MFO3QQ.js.map → accounts-E67BMK7T.js.map} +1 -1
- package/dist/{actions-P35MEMGN.js → actions-6TQMSVWD.js} +18 -18
- package/dist/{add-5GAN6CVO.js → add-2BEGRHUX.js} +28 -5
- package/dist/add-2BEGRHUX.js.map +1 -0
- package/dist/{add-6DTC6X5G.js → add-LEMKEOPO.js} +3 -2
- package/dist/{add-6DTC6X5G.js.map → add-LEMKEOPO.js.map} +1 -1
- package/dist/{ads-73PGA4YC.js → ads-AGYCVD62.js} +4 -4
- package/dist/{advertisers-AE75CGVE.js → advertisers-2VQKAYKG.js} +4 -3
- package/dist/{advertisers-AE75CGVE.js.map → advertisers-2VQKAYKG.js.map} +1 -1
- package/dist/{analytics-FKCXIMPO.js → analytics-IFELDWLL.js} +24 -20
- package/dist/analytics-IFELDWLL.js.map +1 -0
- package/dist/{analytics-FPWQQGRM.js → analytics-OH5QEH7F.js} +4 -3
- package/dist/{analytics-FPWQQGRM.js.map → analytics-OH5QEH7F.js.map} +1 -1
- package/dist/{assign-ABN2AQ4J.js → assign-PTUJUCEL.js} +4 -3
- package/dist/{assign-ABN2AQ4J.js.map → assign-PTUJUCEL.js.map} +1 -1
- package/dist/{audience-size-GNBJY35X.js → audience-size-LRI6GJRT.js} +4 -3
- package/dist/{audience-size-GNBJY35X.js.map → audience-size-LRI6GJRT.js.map} +1 -1
- package/dist/{audit-3VS63TBW.js → audit-HWP7OPB7.js} +4 -3
- package/dist/{audit-3VS63TBW.js.map → audit-HWP7OPB7.js.map} +1 -1
- package/dist/{autocomplete-VS3XG3B7.js → autocomplete-J6DHU6MR.js} +4 -3
- package/dist/{autocomplete-VS3XG3B7.js.map → autocomplete-J6DHU6MR.js.map} +1 -1
- package/dist/{avatars-EKCKHCC3.js → avatars-467OSBD6.js} +4 -4
- package/dist/{bid-pricing-Q72B65AY.js → bid-pricing-EO5WLHGV.js} +4 -3
- package/dist/{bid-pricing-Q72B65AY.js.map → bid-pricing-EO5WLHGV.js.map} +1 -1
- package/dist/{brand-C6PFGGQN.js → brand-YRTEPGBK.js} +2 -2
- package/dist/{brief-YFJHQ5VQ.js → brief-OSFJ2V7F.js} +8 -7
- package/dist/{brief-YFJHQ5VQ.js.map → brief-OSFJ2V7F.js.map} +1 -1
- package/dist/{campaign-groups-KFFYQPU3.js → campaign-groups-PQ6KSQJR.js} +9 -8
- package/dist/{campaign-groups-KFFYQPU3.js.map → campaign-groups-PQ6KSQJR.js.map} +1 -1
- package/dist/{campaign-writes-FHOS5XZY.js → campaign-writes-5OVLUD5E.js} +4 -3
- package/dist/{campaign-writes-FHOS5XZY.js.map → campaign-writes-5OVLUD5E.js.map} +1 -1
- package/dist/{campaigns-2NHWBF5C.js → campaigns-6T3NSUT2.js} +12 -11
- package/dist/{campaigns-2NHWBF5C.js.map → campaigns-6T3NSUT2.js.map} +1 -1
- package/dist/{campaigns-KZYZTXDS.js → campaigns-OYMXDGWX.js} +5 -5
- package/dist/{canvas-UJNSHD3B.js → canvas-YQFG52IG.js} +13 -13
- package/dist/{capabilities-DJFTRJKS.js → capabilities-PXBKUN2G.js} +4 -3
- package/dist/{capabilities-DJFTRJKS.js.map → capabilities-PXBKUN2G.js.map} +1 -1
- package/dist/{catalog-ZQX6BGXS.js → catalog-XLXIM7IW.js} +4 -4
- package/dist/{chats-D2CSDX5Q.js → chats-UK47UE7C.js} +4 -3
- package/dist/{chats-D2CSDX5Q.js.map → chats-UK47UE7C.js.map} +1 -1
- package/dist/{chunk-7YCRFMXF.js → chunk-24EB7EDR.js} +3 -3
- package/dist/{chunk-5ZDLTE5T.js → chunk-2AOE2MZQ.js} +3 -3
- package/dist/{chunk-4SG4RW2P.js → chunk-2VPBIT65.js} +8 -8
- package/dist/chunk-4PDHHHUJ.js +537 -0
- package/dist/chunk-4PDHHHUJ.js.map +1 -0
- package/dist/{chunk-NPY4QUMQ.js → chunk-54C6YDGJ.js} +2 -2
- package/dist/{chunk-LZ73CZGP.js → chunk-5WCSKQ7Z.js} +6 -6
- package/dist/{chunk-3G3ZDLMI.js → chunk-5ZNTADVR.js} +2 -2
- package/dist/{chunk-AEOSAVVL.js → chunk-6F7DVPOS.js} +3 -3
- package/dist/{chunk-CJCVIEJ5.js → chunk-6NY2GPR4.js} +3 -3
- package/dist/{chunk-CXWFX2AM.js → chunk-6Y7ZBENQ.js} +6 -6
- package/dist/{chunk-M242LHLX.js → chunk-7CTMH5AK.js} +3 -3
- package/dist/{chunk-XF4JUKVF.js → chunk-7EPXVICM.js} +38 -5
- package/dist/chunk-7EPXVICM.js.map +1 -0
- package/dist/{chunk-T2PC5AVH.js → chunk-ASI4P6X2.js} +6 -6
- package/dist/chunk-ASI4P6X2.js.map +1 -0
- package/dist/{chunk-QD7ESRLN.js → chunk-C46GUI2S.js} +2 -2
- package/dist/{chunk-6N6WKAJM.js → chunk-CWYAELVG.js} +2 -2
- package/dist/{chunk-MXYBTMKB.js → chunk-DCRPXOJJ.js} +2 -2
- package/dist/{chunk-GKZ2WU75.js → chunk-FPOGPFAG.js} +3 -14
- package/dist/chunk-FPOGPFAG.js.map +1 -0
- package/dist/{chunk-JQJDXPCO.js → chunk-FUHN4MFY.js} +2 -2
- package/dist/{chunk-S77PZVYM.js → chunk-FYGR3I2A.js} +3 -3
- package/dist/{chunk-OZRUJVIQ.js → chunk-H3427GPU.js} +2 -2
- package/dist/{chunk-RPUSTYHL.js → chunk-HDLYPC6K.js} +5 -3
- package/dist/{chunk-RPUSTYHL.js.map → chunk-HDLYPC6K.js.map} +1 -1
- package/dist/{chunk-SSJK7FEV.js → chunk-HR6IWNKE.js} +1196 -1140
- package/dist/chunk-HR6IWNKE.js.map +1 -0
- package/dist/{chunk-YRQYA2LR.js → chunk-HROZYQ5H.js} +63 -5
- package/dist/chunk-HROZYQ5H.js.map +1 -0
- package/dist/{chunk-IR6D7K4H.js → chunk-I3ZR655O.js} +2 -2
- package/dist/{chunk-YK32GUBN.js → chunk-KMKEYI37.js} +3 -3
- package/dist/{chunk-W3ZHJJVT.js → chunk-KS2QY6MK.js} +4 -4
- package/dist/{chunk-WNRV4QH7.js → chunk-LYQJ4PZW.js} +5 -5
- package/dist/{chunk-B5SCU7MJ.js → chunk-MACCF4JZ.js} +16 -22
- package/dist/{chunk-B5SCU7MJ.js.map → chunk-MACCF4JZ.js.map} +1 -1
- package/dist/{chunk-CSYSX4D2.js → chunk-N4LAYIIN.js} +2 -2
- package/dist/{chunk-4AUMTNVB.js → chunk-NA63BH7V.js} +3 -3
- package/dist/{chunk-4BQXAE7Z.js → chunk-NDEE6G2J.js} +2 -2
- package/dist/{chunk-EDLZGTGN.js → chunk-NYIGXDUG.js} +1 -39
- package/dist/chunk-NYIGXDUG.js.map +1 -0
- package/dist/{chunk-DWHIOO7E.js → chunk-QE7W555R.js} +163 -12
- package/dist/chunk-QE7W555R.js.map +1 -0
- package/dist/{chunk-MELOSESI.js → chunk-R25YLW6H.js} +2 -2
- package/dist/{chunk-Y6O7EWYY.js → chunk-RL5CP7N6.js} +5 -5
- package/dist/{chunk-DGUNI37S.js → chunk-RX2DKU3W.js} +2 -2
- package/dist/{chunk-3HJLHTWP.js → chunk-SJYEY5MV.js} +12 -3
- package/dist/{chunk-3HJLHTWP.js.map → chunk-SJYEY5MV.js.map} +1 -1
- package/dist/{chunk-VTDMKARH.js → chunk-ULG4QRTV.js} +2 -2
- package/dist/{chunk-QRP3PXWN.js → chunk-VL43TNIP.js} +2 -2
- package/dist/{chunk-SHL7LOC3.js → chunk-VLMBTPXU.js} +3 -3
- package/dist/{chunk-KHRXPQID.js → chunk-VYQ3QJ3C.js} +2 -2
- package/dist/{chunk-A4LOJ2VD.js → chunk-WGUQHAJY.js} +2 -2
- package/dist/{chunk-ZEYEWPK6.js → chunk-WKQG6TER.js} +2 -2
- package/dist/{chunk-3IBYKLXR.js → chunk-ZDMTXQ2Q.js} +2 -2
- package/dist/{claim-FZ5OQLMU.js → claim-W6G6VEG5.js} +4 -3
- package/dist/{claim-FZ5OQLMU.js.map → claim-W6G6VEG5.js.map} +1 -1
- package/dist/cli.js +30 -30
- package/dist/{companies-DNI634RC.js → companies-TS6KBATJ.js} +4 -3
- package/dist/{companies-DNI634RC.js.map → companies-TS6KBATJ.js.map} +1 -1
- package/dist/{complete-2FZMGJV5.js → complete-LYR2HMQU.js} +4 -3
- package/dist/{complete-2FZMGJV5.js.map → complete-LYR2HMQU.js.map} +1 -1
- package/dist/{connect-QCOGEPP4.js → connect-FCXNVTXG.js} +13 -6
- package/dist/{conversation-6IOGV7B7.js → conversation-6ZJGPCXM.js} +4 -3
- package/dist/{conversation-6IOGV7B7.js.map → conversation-6ZJGPCXM.js.map} +1 -1
- package/dist/{conversions-4SRZPBBX.js → conversions-UHB55MMQ.js} +8 -7
- package/dist/{conversions-4SRZPBBX.js.map → conversions-UHB55MMQ.js.map} +1 -1
- package/dist/{create-BJNMO6HT.js → create-EX6OWLNM.js} +3 -2
- package/dist/{create-BJNMO6HT.js.map → create-EX6OWLNM.js.map} +1 -1
- package/dist/{create-RM7HV77Y.js → create-JCA7JPLP.js} +4 -3
- package/dist/{create-RM7HV77Y.js.map → create-JCA7JPLP.js.map} +1 -1
- package/dist/{create-FX4OJ2XF.js → create-JFSK4BOP.js} +4 -3
- package/dist/{create-FX4OJ2XF.js.map → create-JFSK4BOP.js.map} +1 -1
- package/dist/{create-VXM34ZWH.js → create-WU22YYU2.js} +4 -3
- package/dist/{create-VXM34ZWH.js.map → create-WU22YYU2.js.map} +1 -1
- package/dist/{creatives-NJF2U763.js → creatives-FXUQ5WSD.js} +10 -10
- package/dist/{creatives-JSWBFQ5R.js → creatives-KGXUOYPE.js} +9 -8
- package/dist/{creatives-JSWBFQ5R.js.map → creatives-KGXUOYPE.js.map} +1 -1
- package/dist/{credentials-C33K6XCJ.js → credentials-MJC7PGKR.js} +4 -3
- package/dist/{credentials-C33K6XCJ.js.map → credentials-MJC7PGKR.js.map} +1 -1
- package/dist/{critique-YDKPYZLD.js → critique-GS5VV5ZC.js} +7 -6
- package/dist/{critique-YDKPYZLD.js.map → critique-GS5VV5ZC.js.map} +1 -1
- package/dist/{critique-ZS4ON3SU.js → critique-TPHR27KH.js} +4 -3
- package/dist/{critique-ZS4ON3SU.js.map → critique-TPHR27KH.js.map} +1 -1
- package/dist/{crm-R5IXIFIV.js → crm-AVCM5D4G.js} +5 -4
- package/dist/{crm-R5IXIFIV.js.map → crm-AVCM5D4G.js.map} +1 -1
- package/dist/{crm-52ROSWH5.js → crm-VK44O3ED.js} +5 -4
- package/dist/{crm-52ROSWH5.js.map → crm-VK44O3ED.js.map} +1 -1
- package/dist/{customers-A36LOZOB.js → customers-XH2DMTFH.js} +6 -5
- package/dist/{delete-M2GDLPYN.js → delete-E3R3TKIL.js} +3 -2
- package/dist/{delete-M2GDLPYN.js.map → delete-E3R3TKIL.js.map} +1 -1
- package/dist/{delete-HGHXY24R.js → delete-KRH2YMSZ.js} +4 -3
- package/dist/{delete-HGHXY24R.js.map → delete-KRH2YMSZ.js.map} +1 -1
- package/dist/{delete-AIGE4Y4H.js → delete-WI5E3DR3.js} +4 -3
- package/dist/{delete-AIGE4Y4H.js.map → delete-WI5E3DR3.js.map} +1 -1
- package/dist/{demographics-NTWB2IMG.js → demographics-XV5PBA77.js} +4 -3
- package/dist/{demographics-NTWB2IMG.js.map → demographics-XV5PBA77.js.map} +1 -1
- package/dist/{discard-2WWQG6OU.js → discard-HTQUUHJR.js} +4 -3
- package/dist/{discard-2WWQG6OU.js.map → discard-HTQUUHJR.js.map} +1 -1
- package/dist/{domain-Y2LT6JLT.js → domain-RECGZXJB.js} +4 -3
- package/dist/{domain-Y2LT6JLT.js.map → domain-RECGZXJB.js.map} +1 -1
- package/dist/{draft-SLHAKJ2A.js → draft-2IBSJEKC.js} +4 -3
- package/dist/{draft-SLHAKJ2A.js.map → draft-2IBSJEKC.js.map} +1 -1
- package/dist/{draft-FJ7WHIXW.js → draft-PVTX6QT6.js} +4 -3
- package/dist/{draft-FJ7WHIXW.js.map → draft-PVTX6QT6.js.map} +1 -1
- package/dist/{draft-EJXNNJ3Y.js → draft-Q546QPPU.js} +5 -4
- package/dist/{draft-EJXNNJ3Y.js.map → draft-Q546QPPU.js.map} +1 -1
- package/dist/engine/index.js +3 -3
- package/dist/{facets-U7AQC4H6.js → facets-7EVPJMKS.js} +4 -3
- package/dist/{facets-U7AQC4H6.js.map → facets-7EVPJMKS.js.map} +1 -1
- package/dist/{feedback-PPQMOQ46.js → feedback-EIZKS4JU.js} +2 -2
- package/dist/{feedback-record-V66HWVRR.js → feedback-record-TKO54BOE.js} +9 -8
- package/dist/{feedback-record-V66HWVRR.js.map → feedback-record-TKO54BOE.js.map} +1 -1
- package/dist/{fetch-W7NULDEO.js → fetch-4BY6HYUM.js} +4 -3
- package/dist/{fetch-W7NULDEO.js.map → fetch-4BY6HYUM.js.map} +1 -1
- package/dist/{find-OTDIX6V4.js → find-FRRHAPWX.js} +4 -4
- package/dist/{flows-KABCBS3S.js → flows-KTFAML22.js} +21 -17
- package/dist/flows-KTFAML22.js.map +1 -0
- package/dist/{fonts-EMMX3KII.js → fonts-MXR3ZKDX.js} +6 -5
- package/dist/{forecast-GNODEIIC.js → forecast-3QTJYVND.js} +4 -3
- package/dist/{forecast-GNODEIIC.js.map → forecast-3QTJYVND.js.map} +1 -1
- package/dist/{funnel-AAX27NH4.js → funnel-I6XIAEHG.js} +11 -455
- package/dist/funnel-I6XIAEHG.js.map +1 -0
- package/dist/{ga4-UDQ2HA2J.js → ga4-DV2AXCSL.js} +1 -1
- package/dist/{get-QEYJRLV3.js → get-5PKNKJ5S.js} +7 -4
- package/dist/get-5PKNKJ5S.js.map +1 -0
- package/dist/{get-RTVUZM6E.js → get-72YPHJGV.js} +4 -3
- package/dist/{get-RTVUZM6E.js.map → get-72YPHJGV.js.map} +1 -1
- package/dist/{google-M7KEXVK5.js → google-6OGZX47I.js} +2 -2
- package/dist/{google-KTO3PLEU.js → google-QYYYSSXI.js} +5 -5
- package/dist/{google-ads-OK6IG3UV.js → google-ads-QGMQKZQD.js} +4 -3
- package/dist/{google-ads-OK6IG3UV.js.map → google-ads-QGMQKZQD.js.map} +1 -1
- package/dist/{gsc-P3QYGDV2.js → gsc-TAKOF7J5.js} +1 -1
- package/dist/{history-PQUJKK26.js → history-6AVQX2OQ.js} +4 -3
- package/dist/{history-PQUJKK26.js.map → history-6AVQX2OQ.js.map} +1 -1
- package/dist/{hubspot-Y77VLY6Y.js → hubspot-SVEMFK5S.js} +9 -8
- package/dist/{hubspot-Y77VLY6Y.js.map → hubspot-SVEMFK5S.js.map} +1 -1
- package/dist/{icon-I43F77FV.js → icon-L4RSS6PZ.js} +4 -4
- package/dist/{ideas-MIDU7YOA.js → ideas-NFOW3HKJ.js} +3 -2
- package/dist/{images-S254MS6O.js → images-2EFFUNNV.js} +9 -9
- package/dist/{ingest-YV2NLDBE.js → ingest-2EIKN4QC.js} +4 -3
- package/dist/{ingest-J4I3HKM3.js → ingest-2SO62RRI.js} +3 -2
- package/dist/{ingest-J4I3HKM3.js.map → ingest-2SO62RRI.js.map} +1 -1
- package/dist/{inspect-Q5NHBBHX.js → inspect-4OOS4APT.js} +4 -3
- package/dist/{inspect-Q5NHBBHX.js.map → inspect-4OOS4APT.js.map} +1 -1
- package/dist/{inspiration-P265QJ2H.js → inspiration-S3DU4CMQ.js} +1 -1
- package/dist/{keyword-metrics-PDY4ZXSP.js → keyword-metrics-SF4CSNZ2.js} +4 -3
- package/dist/{keyword-metrics-PDY4ZXSP.js.map → keyword-metrics-SF4CSNZ2.js.map} +1 -1
- package/dist/{keywords-for-site-GALSCV77.js → keywords-for-site-WDAOPNKC.js} +4 -3
- package/dist/{keywords-for-site-GALSCV77.js.map → keywords-for-site-WDAOPNKC.js.map} +1 -1
- package/dist/{landing-CJYGWCK4.js → landing-2ZB46LXH.js} +3 -3
- package/dist/{leads-PHKG6CP3.js → leads-A4W5KTWB.js} +4 -3
- package/dist/{leads-PHKG6CP3.js.map → leads-A4W5KTWB.js.map} +1 -1
- package/dist/{learn-FUQSY7DN.js → learn-IPULBCOD.js} +5 -4
- package/dist/{learn-FUQSY7DN.js.map → learn-IPULBCOD.js.map} +1 -1
- package/dist/{line-item-writes-E6MZPIZZ.js → line-item-writes-EMYSOJKM.js} +4 -3
- package/dist/{line-item-writes-E6MZPIZZ.js.map → line-item-writes-EMYSOJKM.js.map} +1 -1
- package/dist/{line-items-7ZGIKEF2.js → line-items-5NECXUZT.js} +5 -5
- package/dist/{link-QYAW6A2W.js → link-CI45HWFN.js} +4 -3
- package/dist/{link-QYAW6A2W.js.map → link-CI45HWFN.js.map} +1 -1
- package/dist/{linkedin-FFSDSGGS.js → linkedin-B7SYR75X.js} +27 -26
- package/dist/{linkedin-FFSDSGGS.js.map → linkedin-B7SYR75X.js.map} +1 -1
- package/dist/{list-NVQC5SNY.js → list-2BARXOT5.js} +3 -2
- package/dist/{list-NVQC5SNY.js.map → list-2BARXOT5.js.map} +1 -1
- package/dist/{list-SAV3LQHY.js → list-BIEVLEHS.js} +4 -3
- package/dist/{list-SAV3LQHY.js.map → list-BIEVLEHS.js.map} +1 -1
- package/dist/{list-5IC6KIKO.js → list-ZBT3EBVZ.js} +4 -3
- package/dist/{list-5IC6KIKO.js.map → list-ZBT3EBVZ.js.map} +1 -1
- package/dist/{log-XZPVOALD.js → log-C23OOAJZ.js} +4 -3
- package/dist/{log-XZPVOALD.js.map → log-C23OOAJZ.js.map} +1 -1
- package/dist/{logo-2IP663QO.js → logo-Q5D7PZY6.js} +3 -3
- package/dist/{lookup-XK45W2SH.js → lookup-ETWY47F7.js} +6 -5
- package/dist/{make-J3WBO62B.js → make-TPKKJXGL.js} +18 -17
- package/dist/{make-J3WBO62B.js.map → make-TPKKJXGL.js.map} +1 -1
- package/dist/{map-4J5WIWIG.js → map-SYZMPHLL.js} +5 -4
- package/dist/{map-4J5WIWIG.js.map → map-SYZMPHLL.js.map} +1 -1
- package/dist/{mcp-XXD7ZQCP.js → mcp-6FQBVJ6F.js} +3 -2
- package/dist/{mcp-XXD7ZQCP.js.map → mcp-6FQBVJ6F.js.map} +1 -1
- package/dist/{media-sources-O6ZRUA3N.js → media-sources-ZXHEEP6T.js} +2 -2
- package/dist/{members-D5ZYLS4Y.js → members-UDY4OOJW.js} +4 -3
- package/dist/{members-D5ZYLS4Y.js.map → members-UDY4OOJW.js.map} +1 -1
- package/dist/{normalize-PCNC6E2N.js → normalize-DAKHYS3V.js} +7 -3
- package/dist/{normalize-PCNC6E2N.js.map → normalize-DAKHYS3V.js.map} +1 -1
- package/dist/{options-MQ65VEVD.js → options-QL3ULED5.js} +7 -6
- package/dist/{options-MQ65VEVD.js.map → options-QL3ULED5.js.map} +1 -1
- package/dist/{performance-6QW2KEEQ.js → performance-UF5VTY2U.js} +5 -4
- package/dist/plan-FT632COT.js +51 -0
- package/dist/plan-FT632COT.js.map +1 -0
- package/dist/{promoted-tweet-writes-JPLHY3GM.js → promoted-tweet-writes-7HGESJ46.js} +4 -3
- package/dist/{promoted-tweet-writes-JPLHY3GM.js.map → promoted-tweet-writes-7HGESJ46.js.map} +1 -1
- package/dist/{promoted-tweets-SURKMHFI.js → promoted-tweets-LZKS5JIF.js} +3 -3
- package/dist/{publish-HCQ6MXLB.js → publish-NPD3SMZL.js} +4 -3
- package/dist/{publish-HCQ6MXLB.js.map → publish-NPD3SMZL.js.map} +1 -1
- package/dist/questionnaire-JNGYJTAY.js +37 -0
- package/dist/questionnaire-JNGYJTAY.js.map +1 -0
- package/dist/{reddit-GIP3ADMS.js → reddit-NU2N3LZD.js} +5 -4
- package/dist/{refresh-UXQSLCR3.js → refresh-EBVJ2C6L.js} +3 -2
- package/dist/{refresh-UXQSLCR3.js.map → refresh-EBVJ2C6L.js.map} +1 -1
- package/dist/{release-5KVLXNP6.js → release-V43YB2PY.js} +4 -3
- package/dist/{release-5KVLXNP6.js.map → release-V43YB2PY.js.map} +1 -1
- package/dist/{remove-6FIVKCJI.js → remove-QPSWLFI4.js} +3 -2
- package/dist/{remove-6FIVKCJI.js.map → remove-QPSWLFI4.js.map} +1 -1
- package/dist/{reopen-YM5LNOLB.js → reopen-GQ66NMWF.js} +4 -3
- package/dist/{reopen-YM5LNOLB.js.map → reopen-GQ66NMWF.js.map} +1 -1
- package/dist/{rerun-WYDRHIUJ.js → rerun-PZK275DY.js} +18 -17
- package/dist/{rerun-WYDRHIUJ.js.map → rerun-PZK275DY.js.map} +1 -1
- package/dist/{research-2BLEISBG.js → research-FMM6AWZC.js} +10 -10
- package/dist/{research-YOGE7GT2.js → research-GEOCUBXB.js} +3 -2
- package/dist/{research-YOGE7GT2.js.map → research-GEOCUBXB.js.map} +1 -1
- package/dist/{reset-C4UHQ3EU.js → reset-REXJ6AUK.js} +3 -2
- package/dist/{reset-C4UHQ3EU.js.map → reset-REXJ6AUK.js.map} +1 -1
- package/dist/{reset-OLVB6AE6.js → reset-Y72IVESB.js} +3 -2
- package/dist/{reset-OLVB6AE6.js.map → reset-Y72IVESB.js.map} +1 -1
- package/dist/{resolve-XYH2GDAE.js → resolve-OGX7C4TV.js} +4 -3
- package/dist/{resolve-XYH2GDAE.js.map → resolve-OGX7C4TV.js.map} +1 -1
- package/dist/{retry-7EELDEQP.js → retry-CD6JAQ3F.js} +3 -2
- package/dist/{retry-7EELDEQP.js.map → retry-CD6JAQ3F.js.map} +1 -1
- package/dist/{retry-726GKI6V.js → retry-TCUBBFR5.js} +3 -2
- package/dist/{retry-726GKI6V.js.map → retry-TCUBBFR5.js.map} +1 -1
- package/dist/{run-P4KR2MXC.js → run-A5ZDXTOI.js} +4 -3
- package/dist/{run-P4KR2MXC.js.map → run-A5ZDXTOI.js.map} +1 -1
- package/dist/{run-MODGUNGT.js → run-EUO34T2J.js} +18 -17
- package/dist/{scaffold-ad-5ZE7KE62.js → scaffold-ad-SW2HEWM3.js} +13 -12
- package/dist/{scaffold-ad-5ZE7KE62.js.map → scaffold-ad-SW2HEWM3.js.map} +1 -1
- package/dist/{scaffold-static-ad-HJY5HFDL.js → scaffold-static-ad-ECTJL54Y.js} +37 -36
- package/dist/scaffold-static-ad-ECTJL54Y.js.map +1 -0
- package/dist/{scaffold-video-P2PYPWG2.js → scaffold-video-EI7U7RBK.js} +12 -11
- package/dist/{scaffold-video-P2PYPWG2.js.map → scaffold-video-EI7U7RBK.js.map} +1 -1
- package/dist/{schedule-RDK4GEPI.js → schedule-S5YZJZ5U.js} +3 -2
- package/dist/{schedule-RDK4GEPI.js.map → schedule-S5YZJZ5U.js.map} +1 -1
- package/dist/{scheduled-agents-6U44QE76.js → scheduled-agents-N4LJRM4C.js} +11 -11
- package/dist/{schema-CHJDC7GQ.js → schema-R7JWWOF4.js} +8 -4
- package/dist/{schema-CHJDC7GQ.js.map → schema-R7JWWOF4.js.map} +1 -1
- package/dist/{search-PMJRU3C4.js → search-KHMQH3AT.js} +3 -2
- package/dist/{search-PMJRU3C4.js.map → search-KHMQH3AT.js.map} +1 -1
- package/dist/{select-AB2L4GAA.js → select-O2FN2JEQ.js} +9 -8
- package/dist/{select-AB2L4GAA.js.map → select-O2FN2JEQ.js.map} +1 -1
- package/dist/{sends-WGJVQUMF.js → sends-BQZM5PLS.js} +5 -4
- package/dist/{sends-WGJVQUMF.js.map → sends-BQZM5PLS.js.map} +1 -1
- package/dist/{set-prompt-DU2G2WTB.js → set-prompt-2HASHGWC.js} +9 -8
- package/dist/{set-prompt-DU2G2WTB.js.map → set-prompt-2HASHGWC.js.map} +1 -1
- package/dist/{setup-links-REPREN3C.js → setup-links-GYSE56GX.js} +4 -3
- package/dist/{setup-links-REPREN3C.js.map → setup-links-GYSE56GX.js.map} +1 -1
- package/dist/{site-WFSWIA3S.js → site-4SKM7RKG.js} +5 -4
- package/dist/{site-WFSWIA3S.js.map → site-4SKM7RKG.js.map} +1 -1
- package/dist/{sources-YBQ6KPFM.js → sources-FQ2UZTHL.js} +6 -6
- package/dist/{sources-AMI2AWKZ.js → sources-R2NKNC6J.js} +10 -9
- package/dist/{sources-AMI2AWKZ.js.map → sources-R2NKNC6J.js.map} +1 -1
- package/dist/{stale-6MJHVEG4.js → stale-W756ACKC.js} +8 -7
- package/dist/{stale-6MJHVEG4.js.map → stale-W756ACKC.js.map} +1 -1
- package/dist/{status-7F2KHFGA.js → status-SE2VZJJB.js} +4 -3
- package/dist/{status-7F2KHFGA.js.map → status-SE2VZJJB.js.map} +1 -1
- package/dist/{stock-2YCDN3N6.js → stock-KXJ26BY4.js} +5 -5
- package/dist/{studio-RA7QQH4O.js → studio-SYKOSNDB.js} +1 -1
- package/dist/{sync-GWTLKZTU.js → sync-LJGSODK3.js} +3 -2
- package/dist/{sync-GWTLKZTU.js.map → sync-LJGSODK3.js.map} +1 -1
- package/dist/{sync-definition-IPUFS5XS.js → sync-definition-QR2N233R.js} +12 -11
- package/dist/{tags-KFYLZLB3.js → tags-4BAVFH4S.js} +3 -2
- package/dist/{tags-KFYLZLB3.js.map → tags-4BAVFH4S.js.map} +1 -1
- package/dist/{tags-ABHSX6M5.js → tags-5SBMRC2A.js} +4 -3
- package/dist/{tags-ABHSX6M5.js.map → tags-5SBMRC2A.js.map} +1 -1
- package/dist/{tags-3WPW6PTV.js → tags-PYWFSBTR.js} +4 -4
- package/dist/{tags-6342FQEB.js → tags-QQU3OKMZ.js} +4 -3
- package/dist/{tags-6342FQEB.js.map → tags-QQU3OKMZ.js.map} +1 -1
- package/dist/{tags-FJIBBBRG.js → tags-YYLNF3PK.js} +4 -3
- package/dist/{tags-FJIBBBRG.js.map → tags-YYLNF3PK.js.map} +1 -1
- package/dist/{targeting-criteria-NR47AF5C.js → targeting-criteria-RJFLFICN.js} +3 -3
- package/dist/{targets-L56KOVQE.js → targets-S2MT2PNB.js} +4 -3
- package/dist/{targets-L56KOVQE.js.map → targets-S2MT2PNB.js.map} +1 -1
- package/dist/{templates-B6XGDYUF.js → templates-ZE5TOGRT.js} +4 -3
- package/dist/{templates-B6XGDYUF.js.map → templates-ZE5TOGRT.js.map} +1 -1
- package/dist/{testimonials-CVC4YIXO.js → testimonials-DII5DYLR.js} +6 -6
- package/dist/{top-companies-45X3DT7Z.js → top-companies-PGIAEHDF.js} +4 -3
- package/dist/{top-companies-45X3DT7Z.js.map → top-companies-PGIAEHDF.js.map} +1 -1
- package/dist/{translate-Z66FDB4K.js → translate-GXTS633J.js} +12 -11
- package/dist/{translate-Z66FDB4K.js.map → translate-GXTS633J.js.map} +1 -1
- package/dist/{triggers-22EMIVFD.js → triggers-2PTONXRU.js} +4 -3
- package/dist/{triggers-22EMIVFD.js.map → triggers-2PTONXRU.js.map} +1 -1
- package/dist/{unlink-65KUN6ID.js → unlink-XRMYJ6DB.js} +4 -3
- package/dist/{unlink-65KUN6ID.js.map → unlink-XRMYJ6DB.js.map} +1 -1
- package/dist/{unstage-2E3I5SWF.js → unstage-FY7A3YFF.js} +4 -3
- package/dist/{unstage-2E3I5SWF.js.map → unstage-FY7A3YFF.js.map} +1 -1
- package/dist/{unstage-4ZEULXEQ.js → unstage-RM2RLXKD.js} +5 -4
- package/dist/{unstage-4ZEULXEQ.js.map → unstage-RM2RLXKD.js.map} +1 -1
- package/dist/{update-KREBPGBH.js → update-E5SRBXQR.js} +4 -3
- package/dist/{update-KREBPGBH.js.map → update-E5SRBXQR.js.map} +1 -1
- package/dist/{update-D6DJC6T7.js → update-PJ67D2OG.js} +3 -2
- package/dist/{update-D6DJC6T7.js.map → update-PJ67D2OG.js.map} +1 -1
- package/dist/{update-2S7CSEAW.js → update-S4562V3O.js} +4 -3
- package/dist/{update-2S7CSEAW.js.map → update-S4562V3O.js.map} +1 -1
- package/dist/{update-7NCOTAQZ.js → update-V6YVEUI2.js} +4 -3
- package/dist/{update-7NCOTAQZ.js.map → update-V6YVEUI2.js.map} +1 -1
- package/dist/{upload-O6NHRPS7.js → upload-R6CQVLKF.js} +4 -3
- package/dist/{upload-O6NHRPS7.js.map → upload-R6CQVLKF.js.map} +1 -1
- package/dist/{url-options-GGXAL3J4.js → url-options-JOKU46F2.js} +4 -3
- package/dist/{url-options-GGXAL3J4.js.map → url-options-JOKU46F2.js.map} +1 -1
- package/dist/{url-params-3EFGVTZZ.js → url-params-7U2XMOWF.js} +4 -3
- package/dist/{url-params-3EFGVTZZ.js.map → url-params-7U2XMOWF.js.map} +1 -1
- package/dist/{validate-UMHHNTVU.js → validate-7YPOUKPB.js} +10 -9
- package/dist/{validate-UMHHNTVU.js.map → validate-7YPOUKPB.js.map} +1 -1
- package/dist/{videos-YSXYGTBM.js → videos-LICG6ACJ.js} +5 -5
- package/dist/{web-IGIGVEKS.js → web-BA2PGTWU.js} +4 -3
- package/dist/{web-IGIGVEKS.js.map → web-BA2PGTWU.js.map} +1 -1
- package/dist/{winning-ads-2WS7FI4E.js → winning-ads-C6S2C5VP.js} +2 -2
- package/dist/{write-commands-5C7FUOVN.js → write-commands-7SJ3BOW5.js} +5 -4
- package/dist/{write-commands-5C7FUOVN.js.map → write-commands-7SJ3BOW5.js.map} +1 -1
- package/dist/{x-BFSKFCZD.js → x-CZHRC6U7.js} +6 -6
- package/package.json +1 -1
- package/dist/add-5GAN6CVO.js.map +0 -1
- package/dist/analytics-FKCXIMPO.js.map +0 -1
- package/dist/chunk-DWHIOO7E.js.map +0 -1
- package/dist/chunk-EDLZGTGN.js.map +0 -1
- package/dist/chunk-GKZ2WU75.js.map +0 -1
- package/dist/chunk-SSJK7FEV.js.map +0 -1
- package/dist/chunk-T2PC5AVH.js.map +0 -1
- package/dist/chunk-XF4JUKVF.js.map +0 -1
- package/dist/chunk-YRQYA2LR.js.map +0 -1
- package/dist/flows-KABCBS3S.js.map +0 -1
- package/dist/funnel-AAX27NH4.js.map +0 -1
- package/dist/get-QEYJRLV3.js.map +0 -1
- package/dist/scaffold-static-ad-HJY5HFDL.js.map +0 -1
- /package/dist/{actions-P35MEMGN.js.map → actions-6TQMSVWD.js.map} +0 -0
- /package/dist/{ads-73PGA4YC.js.map → ads-AGYCVD62.js.map} +0 -0
- /package/dist/{avatars-EKCKHCC3.js.map → avatars-467OSBD6.js.map} +0 -0
- /package/dist/{brand-C6PFGGQN.js.map → brand-YRTEPGBK.js.map} +0 -0
- /package/dist/{campaigns-KZYZTXDS.js.map → campaigns-OYMXDGWX.js.map} +0 -0
- /package/dist/{canvas-UJNSHD3B.js.map → canvas-YQFG52IG.js.map} +0 -0
- /package/dist/{catalog-ZQX6BGXS.js.map → catalog-XLXIM7IW.js.map} +0 -0
- /package/dist/{chunk-7YCRFMXF.js.map → chunk-24EB7EDR.js.map} +0 -0
- /package/dist/{chunk-5ZDLTE5T.js.map → chunk-2AOE2MZQ.js.map} +0 -0
- /package/dist/{chunk-4SG4RW2P.js.map → chunk-2VPBIT65.js.map} +0 -0
- /package/dist/{chunk-NPY4QUMQ.js.map → chunk-54C6YDGJ.js.map} +0 -0
- /package/dist/{chunk-LZ73CZGP.js.map → chunk-5WCSKQ7Z.js.map} +0 -0
- /package/dist/{chunk-3G3ZDLMI.js.map → chunk-5ZNTADVR.js.map} +0 -0
- /package/dist/{chunk-AEOSAVVL.js.map → chunk-6F7DVPOS.js.map} +0 -0
- /package/dist/{chunk-CJCVIEJ5.js.map → chunk-6NY2GPR4.js.map} +0 -0
- /package/dist/{chunk-CXWFX2AM.js.map → chunk-6Y7ZBENQ.js.map} +0 -0
- /package/dist/{chunk-M242LHLX.js.map → chunk-7CTMH5AK.js.map} +0 -0
- /package/dist/{chunk-QD7ESRLN.js.map → chunk-C46GUI2S.js.map} +0 -0
- /package/dist/{chunk-6N6WKAJM.js.map → chunk-CWYAELVG.js.map} +0 -0
- /package/dist/{chunk-MXYBTMKB.js.map → chunk-DCRPXOJJ.js.map} +0 -0
- /package/dist/{chunk-JQJDXPCO.js.map → chunk-FUHN4MFY.js.map} +0 -0
- /package/dist/{chunk-S77PZVYM.js.map → chunk-FYGR3I2A.js.map} +0 -0
- /package/dist/{chunk-OZRUJVIQ.js.map → chunk-H3427GPU.js.map} +0 -0
- /package/dist/{chunk-IR6D7K4H.js.map → chunk-I3ZR655O.js.map} +0 -0
- /package/dist/{chunk-YK32GUBN.js.map → chunk-KMKEYI37.js.map} +0 -0
- /package/dist/{chunk-W3ZHJJVT.js.map → chunk-KS2QY6MK.js.map} +0 -0
- /package/dist/{chunk-WNRV4QH7.js.map → chunk-LYQJ4PZW.js.map} +0 -0
- /package/dist/{chunk-CSYSX4D2.js.map → chunk-N4LAYIIN.js.map} +0 -0
- /package/dist/{chunk-4AUMTNVB.js.map → chunk-NA63BH7V.js.map} +0 -0
- /package/dist/{chunk-4BQXAE7Z.js.map → chunk-NDEE6G2J.js.map} +0 -0
- /package/dist/{chunk-MELOSESI.js.map → chunk-R25YLW6H.js.map} +0 -0
- /package/dist/{chunk-Y6O7EWYY.js.map → chunk-RL5CP7N6.js.map} +0 -0
- /package/dist/{chunk-DGUNI37S.js.map → chunk-RX2DKU3W.js.map} +0 -0
- /package/dist/{chunk-VTDMKARH.js.map → chunk-ULG4QRTV.js.map} +0 -0
- /package/dist/{chunk-QRP3PXWN.js.map → chunk-VL43TNIP.js.map} +0 -0
- /package/dist/{chunk-SHL7LOC3.js.map → chunk-VLMBTPXU.js.map} +0 -0
- /package/dist/{chunk-KHRXPQID.js.map → chunk-VYQ3QJ3C.js.map} +0 -0
- /package/dist/{chunk-A4LOJ2VD.js.map → chunk-WGUQHAJY.js.map} +0 -0
- /package/dist/{chunk-ZEYEWPK6.js.map → chunk-WKQG6TER.js.map} +0 -0
- /package/dist/{chunk-3IBYKLXR.js.map → chunk-ZDMTXQ2Q.js.map} +0 -0
- /package/dist/{connect-QCOGEPP4.js.map → connect-FCXNVTXG.js.map} +0 -0
- /package/dist/{creatives-NJF2U763.js.map → creatives-FXUQ5WSD.js.map} +0 -0
- /package/dist/{customers-A36LOZOB.js.map → customers-XH2DMTFH.js.map} +0 -0
- /package/dist/{feedback-PPQMOQ46.js.map → feedback-EIZKS4JU.js.map} +0 -0
- /package/dist/{find-OTDIX6V4.js.map → find-FRRHAPWX.js.map} +0 -0
- /package/dist/{fonts-EMMX3KII.js.map → fonts-MXR3ZKDX.js.map} +0 -0
- /package/dist/{ga4-UDQ2HA2J.js.map → ga4-DV2AXCSL.js.map} +0 -0
- /package/dist/{google-M7KEXVK5.js.map → google-6OGZX47I.js.map} +0 -0
- /package/dist/{google-KTO3PLEU.js.map → google-QYYYSSXI.js.map} +0 -0
- /package/dist/{gsc-P3QYGDV2.js.map → gsc-TAKOF7J5.js.map} +0 -0
- /package/dist/{icon-I43F77FV.js.map → icon-L4RSS6PZ.js.map} +0 -0
- /package/dist/{ideas-MIDU7YOA.js.map → ideas-NFOW3HKJ.js.map} +0 -0
- /package/dist/{images-S254MS6O.js.map → images-2EFFUNNV.js.map} +0 -0
- /package/dist/{ingest-YV2NLDBE.js.map → ingest-2EIKN4QC.js.map} +0 -0
- /package/dist/{inspiration-P265QJ2H.js.map → inspiration-S3DU4CMQ.js.map} +0 -0
- /package/dist/{landing-CJYGWCK4.js.map → landing-2ZB46LXH.js.map} +0 -0
- /package/dist/{line-items-7ZGIKEF2.js.map → line-items-5NECXUZT.js.map} +0 -0
- /package/dist/{logo-2IP663QO.js.map → logo-Q5D7PZY6.js.map} +0 -0
- /package/dist/{lookup-XK45W2SH.js.map → lookup-ETWY47F7.js.map} +0 -0
- /package/dist/{media-sources-O6ZRUA3N.js.map → media-sources-ZXHEEP6T.js.map} +0 -0
- /package/dist/{performance-6QW2KEEQ.js.map → performance-UF5VTY2U.js.map} +0 -0
- /package/dist/{promoted-tweets-SURKMHFI.js.map → promoted-tweets-LZKS5JIF.js.map} +0 -0
- /package/dist/{reddit-GIP3ADMS.js.map → reddit-NU2N3LZD.js.map} +0 -0
- /package/dist/{research-2BLEISBG.js.map → research-FMM6AWZC.js.map} +0 -0
- /package/dist/{run-MODGUNGT.js.map → run-EUO34T2J.js.map} +0 -0
- /package/dist/{scheduled-agents-6U44QE76.js.map → scheduled-agents-N4LJRM4C.js.map} +0 -0
- /package/dist/{sources-YBQ6KPFM.js.map → sources-FQ2UZTHL.js.map} +0 -0
- /package/dist/{stock-2YCDN3N6.js.map → stock-KXJ26BY4.js.map} +0 -0
- /package/dist/{studio-RA7QQH4O.js.map → studio-SYKOSNDB.js.map} +0 -0
- /package/dist/{sync-definition-IPUFS5XS.js.map → sync-definition-QR2N233R.js.map} +0 -0
- /package/dist/{tags-3WPW6PTV.js.map → tags-PYWFSBTR.js.map} +0 -0
- /package/dist/{targeting-criteria-NR47AF5C.js.map → targeting-criteria-RJFLFICN.js.map} +0 -0
- /package/dist/{testimonials-CVC4YIXO.js.map → testimonials-DII5DYLR.js.map} +0 -0
- /package/dist/{videos-YSXYGTBM.js.map → videos-LICG6ACJ.js.map} +0 -0
- /package/dist/{winning-ads-2WS7FI4E.js.map → winning-ads-C6S2C5VP.js.map} +0 -0
- /package/dist/{x-BFSKFCZD.js.map → x-CZHRC6U7.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/creatives/brief.ts","../src/commands/creatives/brief-model.ts"],"sourcesContent":["/**\n * `baker creatives brief`: everything the agent needs before deciding what ads to make, in one\n * compact read. Who sees the ads, what the account says works and where it loses people, what the\n * company's reviewers liked, what customers said, and which ideas already exist. Each part is\n * read on its own and a failed read is reported as missing, never as a failed brief.\n */\nimport { readFileSync } from \"node:fs\";\nimport { readdir, readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { CreativePerformance, CreativesFeedbackResponse, CreativesPerformanceResponse } from \"@baker/api\";\nimport type { ScopedWinnersSearchResponse } from \"@baker/api/ad-library\";\nimport { defineCommand } from \"citty\";\nimport { ApiError, apiGet, apiPost } from \"../../client.ts\";\nimport { getEnv } from \"../../env.ts\";\nimport { writeJson } from \"../../output.ts\";\nimport { registerSchema } from \"../../schemas.ts\";\nimport { type ViewerProfile, viewerFromKnowledge } from \"../../viewer-profile.ts\";\nimport { findWorkspaceRoot } from \"../canvas/normalize-paths.ts\";\nimport { liveViewerLookups } from \"../canvas/viewer-check.ts\";\nimport { researchCustomers } from \"../research/customers.ts\";\nimport { buildSearchBody } from \"../winning-ads/search.ts\";\nimport {\n type Bottleneck,\n type CustomerTruth,\n customerTruth,\n diagnoseBottleneck,\n type MarketMap,\n marketMap,\n resultsOf,\n} from \"./brief-model.ts\";\nimport { marketQuery } from \"./company-offer.ts\";\nimport { buildNext, ideasReport } from \"./ideas.ts\";\nimport { AWARENESS_STAGES, IDEA_ANGLES, IDEA_FORMATS } from \"./ideas-model.ts\";\nimport { readInsights } from \"./ideas-workspace.ts\";\nimport { withDefinitions } from \"./performance.ts\";\n\nconst DESCRIPTION = `Start here before making ads: one read of everything that decides what to make. Who sees the ads, what already works in the account and where it loses people (a verdict, not raw numbers), what this company's reviewers approved and rejected, what customers said in their own words, and the ideas already on file.\n\n baker creatives brief # the viewer from the Knowledge\n baker creatives brief --adset <id> # the viewer that ad set reaches\n baker creatives brief --account-id act_<id> # when more than one Meta account is connected\n\nThen write 4-8 ideas in src/creatives/_ideas/ and run \\`baker creatives ideas\\`. With few customer quotes on file it gathers them itself first (\\`baker research customers\\`, about 30 s; --no-research to skip).`;\n\nconst ARGS = {\n adset: {\n type: \"string\",\n description: \"The Meta ad set the ads are for: its viewer replaces the Knowledge's\",\n required: false,\n },\n \"account-id\": {\n type: \"string\",\n description: \"Meta ad account to read (act_<id>); default: the one connected account\",\n required: false,\n },\n full: {\n type: \"boolean\",\n description: \"Every quote, idea and creative instead of the top few\",\n required: false,\n default: false,\n },\n research: {\n type: \"boolean\",\n description: \"Gather customer quotes first when few are on file (default true; --no-research skips it)\",\n required: false,\n default: true,\n },\n} as const;\n\nregisterSchema({ command: \"creatives.brief\", description: DESCRIPTION, args: ARGS });\n\ntype Section<T> = T | { unavailable: string };\n\nconst unavailable = (err: unknown) => ({\n unavailable: err instanceof Error ? err.message.slice(0, 200) : \"could not be read\",\n});\n\nasync function section<T>(read: () => Promise<T>): Promise<Section<T>> {\n try {\n return await read();\n } catch (err) {\n return unavailable(err);\n }\n}\n\nfunction isAvailable<T>(value: Section<T>): value is T {\n return !(value !== null && typeof value === \"object\" && \"unavailable\" in value);\n}\n\nasync function companyStatus(root: string): Promise<\"ready\" | \"missing\"> {\n const doc = await readFile(path.join(root, \"COMPANY.md\"), \"utf8\").catch(() => \"\");\n return doc.trim() && !/^#\\s*Company\\s*\\n+\\s*TODO/m.test(doc) ? \"ready\" : \"missing\";\n}\n\nasync function readOffers(root: string): Promise<string[]> {\n const dir = path.join(root, \"src\", \"content\", \"offers\");\n const files = ((await readdir(dir, { recursive: true }).catch(() => [])) as string[]).filter((f) =>\n f.endsWith(\".md\"),\n );\n return files.map((f) => f.replace(/\\.md$/, \"\")).sort();\n}\n\nfunction readDefinition(root: string, slug: string): string | null {\n try {\n return readFileSync(path.join(root, \"src\", \"creatives\", slug, \"_definition.md\"), \"utf8\");\n } catch {\n return null;\n }\n}\n\nasync function readViewer(root: string, adSet: string | undefined): Promise<ViewerProfile> {\n const lookups = liveViewerLookups(root);\n if (adSet) {\n const read = await lookups.adSetViewer(adSet).catch(() => null);\n if (read) return read;\n }\n const personas = await lookups.personas().catch(() => []);\n return viewerFromKnowledge({ personas: personas.map((p) => p.segment ?? p.title ?? p.slug) });\n}\n\nconst MARKET_ADS = 40;\nconst MARKET_FALLBACK_ADS = 15;\n/**\n * The most a market search may hold the brief: a followed brands' browse answers in ~2 s, a short\n * library query in ~8 s (dev, Oct 2026). The market is context, not a step: a slow library leaves it out.\n */\nconst MARKET_SEARCH_MS = 12_000;\n\n/** What the market's ads already say: the brands the company follows, else the whole library. */\nasync function readMarket(root: string): Promise<MarketMap | null> {\n const query = marketQuery(await readFile(path.join(root, \"COMPANY.md\"), \"utf8\").catch(() => \"\"));\n if (!query) return null;\n const search = (body: Record<string, unknown>) =>\n apiPost<ScopedWinnersSearchResponse>(\"/api/ad-library/winners/search\", body, {\n timeoutMs: MARKET_SEARCH_MS,\n }).catch((err: unknown) => {\n if (err instanceof ApiError && err.code === \"TIMEOUT\") {\n throw new Error(\"the ad library did not answer in time, so competitors' claims are left out\");\n }\n throw err;\n });\n // The followed brands' best ads, browsed (no query, so no relevance judge), and the library's ads\n // for what the company sells, asked at once: the second answers in ~8 s, after the first's ~2 s.\n const [followed, all] = await Promise.allSettled([\n search(buildSearchBody({ scope: \"followed\", platform: \"meta\", limit: MARKET_ADS, maxPerAdvertiser: 8 })),\n search(buildSearchBody({ query, scope: \"all\", platform: \"meta\", limit: MARKET_FALLBACK_ADS, maxPerAdvertiser: 3 })),\n ]);\n if (followed.status === \"fulfilled\" && followed.value.results.length > 0)\n return marketMap(followed.value.results, \"followed\");\n if (all.status === \"rejected\") throw all.reason;\n return all.value.results.length > 0 ? marketMap(all.value.results, \"library\") : null;\n}\n\ntype MetaAccount = { externalId?: unknown; id?: unknown };\n\nasync function metaAccountId(given: string | undefined): Promise<string | null> {\n if (given) return given.startsWith(\"act_\") ? given : `act_${given}`;\n const named = getEnv().BAKER_META_AD_ACCOUNT_ID;\n if (named) return `act_${named.replace(/^act_/, \"\")}`;\n const accounts = await apiGet<MetaAccount[]>(\"/api/ads/meta/accounts\");\n const ids = accounts.flatMap((a) => {\n const id = a.externalId ?? a.id;\n return typeof id === \"string\" && id ? [id] : [];\n });\n if (ids.length !== 1) return null;\n const id = ids[0] as string;\n return id.startsWith(\"act_\") ? id : `act_${id}`;\n}\n\nasync function readBottleneck(accountId: string): Promise<Bottleneck> {\n const rows = await apiPost<Array<Record<string, unknown>>>(\"/api/ads/meta/insights\", {\n object: accountId,\n level: \"account\",\n fields: [\"impressions\", \"inline_link_clicks\", \"actions\", \"spend\"],\n actionBreakdowns: [\"action_type\"],\n datePreset: \"last_30d\",\n limit: 10,\n });\n const totals = { impressions: 0, linkClicks: 0, results: 0 };\n for (const row of rows) {\n totals.impressions += Number(row.impressions ?? 0);\n totals.linkClicks += Number(row.inline_link_clicks ?? 0);\n totals.results += resultsOf(row.actions);\n }\n return diagnoseBottleneck(totals);\n}\n\nfunction leanCreative(c: CreativePerformance) {\n return {\n creative: c.slug ?? c.title,\n costPerResult: c.costPerResult,\n ...(c.currency ? { currency: c.currency } : {}),\n ctr: c.ctr,\n fatigue: c.fatigue,\n ...(c.definition?.idea ? { idea: c.definition.idea } : {}),\n ...(c.definition?.angle ? { angle: c.definition.angle } : {}),\n };\n}\n\n/** The own-account read: the best creatives by cost per result, and the ones to replace. Pure. */\nexport function whatWorks(creatives: readonly CreativePerformance[], limit = 3) {\n const priced = creatives.filter((c) => c.costPerResult !== null && c.costPerResult > 0);\n const best = [...priced].sort((a, b) => (a.costPerResult ?? 0) - (b.costPerResult ?? 0)).slice(0, limit);\n const tired = creatives.filter((c) => c.fatigue === \"fatigued\" || c.fatigue === \"dead\");\n return { best: best.map(leanCreative), replace: tired.map(leanCreative) };\n}\n\ntype BriefParts = {\n company: \"ready\" | \"missing\";\n customers: CustomerTruth;\n bottleneck: Section<Bottleneck> | null;\n ideasToBuild: number;\n buildNext: string[];\n approved: number;\n rejected: number;\n market?: MarketMap | null;\n /** What earlier ideas did once their ads ran (`baker creatives learn`). */\n learned: { winners: LearnedIdea[]; failed: LearnedIdea[] };\n /** The customer research this brief ran itself, few quotes being on file. */\n researched?: { written: number };\n};\n\ntype LearnedIdea = { idea: string; message: string };\n\n/** A market whose ads mostly speak at stage s3 or later has heard the plain claim already. */\nconst HEARD_IT_ALL = /^s[345]/;\n\n/** What the brief says about customer quotes: what its own research found, or that it is needed. Pure. */\nfunction customersHint(parts: Pick<BriefParts, \"customers\" | \"researched\">): string | null {\n if (parts.researched) {\n return parts.researched.written > 0\n ? `${parts.researched.written} customer quotes were just gathered from reviews and Reddit and are in \\`customers\\`: cite them by id in each idea's \\`evidence\\`.`\n : \"Customer research found nothing to keep: ideas go in as explore bets (an empty `evidence` list). Never research customers again in this turn.\";\n }\n if (!parts.customers.thin) return null;\n return `Only ${parts.customers.observed} customer quotes on file: run \\`baker research customers\\` now, before writing ideas, so they stand on what customers said. It gathers reviews, Reddit and the web and writes the quotes with their sources in about a minute; never a subagent or web searches of your own for this.`;\n}\n\n/** The one or two next steps the brief points to. Pure. */\nexport function briefHints(parts: BriefParts): string[] {\n const hints: string[] = [];\n if (parts.company === \"missing\") {\n hints.push(\"COMPANY.md is empty: run /company-discovery first, or every idea is a guess about the business.\");\n }\n const customers = customersHint(parts);\n if (customers) hints.push(customers);\n if (parts.bottleneck && isAvailable(parts.bottleneck) && parts.bottleneck.verdict === \"after_click\") {\n hints.push(\"The account loses people after the click: tell the person, and make one idea an offer idea.\");\n }\n if (parts.market?.sophistication && HEARD_IT_ALL.test(parts.market.sophistication)) {\n hints.push(\n `This market has heard the plain claim (sophistication ${parts.market.sophistication}): lead with how it works (a mechanism), proof, or an angle nobody uses, never a bigger claim.`,\n );\n }\n // Every claim, not only the ones several brands share word for word: the same claim is often worded apart.\n const claims = parts.market?.saying.map((s) => `\"${s.angle}\"`) ?? [];\n if (claims.length > 0) {\n hints.push(\n `Competitors already say ${claims.join(\", \")}. A message one of them could also run is not a new idea, however it is worded: say what only we have (the offer, a proof, a customer's words) or how it works.`,\n );\n }\n for (const won of parts.learned.winners) {\n hints.push(\n `${won.idea} won in the account (\"${won.message}\"): build on it first, the same message in a new format or for a new persona.`,\n );\n }\n if (parts.learned.failed.length > 0) {\n const lost = parts.learned.failed.map((f) => `\"${f.message}\"`).join(\", \");\n hints.push(`Never repeat a message that lost in the account: ${lost}.`);\n }\n if (parts.rejected > parts.approved && parts.rejected > 0) {\n hints.push(\"Reviewers rejected more than they approved: read topRejectionReasons and avoid them in every idea.\");\n }\n if (parts.buildNext.length > 0) {\n hints.push(`Ideas ready to build: ${parts.buildNext.join(\", \")} (\\`baker creatives make <idea>\\`).`);\n } else {\n hints.push(\n `Write 4-8 ideas in src/creatives/_ideas/<idea>.md (who, message, evidence, awareness, angle, format, job, why), then \\`baker creatives ideas\\`. awareness: ${AWARENESS_STAGES.join(\" | \")}. angle: ${IDEA_ANGLES.join(\", \")}. format: ${IDEA_FORMATS.join(\", \")}.`,\n );\n }\n return hints;\n}\n\ntype BriefArgs = { adset?: string; accountId?: string; full: boolean };\n\nasync function readBrief(root: string, args: BriefArgs) {\n // Every read starts at once: the account's diagnosis waits only for the account, never for the rest.\n const account = metaAccountId(args.accountId).catch(() => null);\n const [company, offers, viewer, insights, ideas, performance, feedback, accountId, bottleneck, market] =\n await Promise.all([\n companyStatus(root),\n readOffers(root),\n readViewer(root, args.adset),\n readInsights(root),\n ideasReport(root),\n section(async () =>\n withDefinitions(await apiPost<CreativesPerformanceResponse>(\"/api/creatives/performance\", {}), (slug) =>\n readDefinition(root, slug),\n ),\n ),\n section(() => apiPost<CreativesFeedbackResponse>(\"/api/creatives/feedback\", {})),\n account,\n account.then((id) => (id ? section(() => readBottleneck(id)) : null)),\n section(() => readMarket(root)),\n ]);\n return { company, offers, viewer, insights, ideas, performance, feedback, accountId, bottleneck, market };\n}\n\ntype Brief = Awaited<ReturnType<typeof readBrief>>;\n\nfunction accountPart(brief: Brief, full: boolean) {\n if (!brief.accountId) {\n return { unavailable: \"no single Meta ad account connected: pass --account-id act_<id>, or work from customers\" };\n }\n const works = isAvailable(brief.performance)\n ? whatWorks(brief.performance.data.creatives, full ? 10 : 3)\n : { creatives: brief.performance };\n return { id: brief.accountId, bottleneck: brief.bottleneck, ...works };\n}\n\nfunction marketPart(market: Section<MarketMap | null>, full: boolean) {\n if (!isAvailable(market)) return market;\n if (!market) return { unavailable: \"no library ads match what COMPANY.md says the company sells\" };\n if (full) return market;\n const { containers: _containers, ...lean } = market;\n return lean;\n}\n\n/** The brief as the agent reads it, and the hints that point at the next step. */\nexport function briefEnvelope(brief: Brief, full: boolean, researched?: { written: number }) {\n const customers = customerTruth(brief.insights);\n const summary = isAvailable(brief.feedback) ? brief.feedback.data.summary : null;\n const next = buildNext(brief.ideas.ideas);\n const toBuild = brief.ideas.ideas.filter((i) => i.status === \"idea\").length;\n const withStatus = (status: string) =>\n brief.ideas.ideas.filter((i) => i.status === status).map((i) => ({ idea: i.id, message: i.message }));\n const learned = { winners: withStatus(\"winner\"), failed: withStatus(\"failed\") };\n return {\n ok: true as const,\n data: {\n company: brief.company,\n viewer: { temperature: brief.viewer.temperature, knows: brief.viewer.knows, source: brief.viewer.source },\n offers: brief.offers,\n account: accountPart(brief, full),\n taste: summary\n ? {\n approved: summary.approved,\n rejected: summary.rejected,\n topRejectionReasons: summary.topRejectionReasons.slice(0, 3).map((r) => r.label),\n }\n : brief.feedback,\n customers: full\n ? { ...customers, quotes: brief.insights.map((i) => ({ id: i.id, type: i.type, quote: i.quote })) }\n : customers,\n market: marketPart(brief.market, full),\n ideas: {\n to_build: toBuild,\n built: brief.ideas.ideas.length - toBuild,\n build_next: next,\n ...(learned.winners.length > 0 ? { winners: learned.winners } : {}),\n ...(learned.failed.length > 0 ? { failed: learned.failed } : {}),\n },\n },\n hints: briefHints({\n company: brief.company,\n customers,\n bottleneck: brief.bottleneck,\n ideasToBuild: toBuild,\n buildNext: next,\n approved: summary?.approved ?? 0,\n rejected: summary?.rejected ?? 0,\n market: isAvailable(brief.market) ? brief.market : null,\n learned,\n ...(researched ? { researched } : {}),\n }),\n };\n}\n\nexport const briefCommand = defineCommand({\n meta: { name: \"brief\", description: DESCRIPTION },\n args: ARGS,\n async run({ args }) {\n const root = findWorkspaceRoot(process.cwd()) ?? process.cwd();\n const full = args.full === true;\n // Few quotes on file: the research runs alongside the reads, never left to the agent (dev, Oct\n // 2026: told to run it first, the chat agent skipped it and every idea went in as an explore bet).\n const thin = args.research !== false && customerTruth(await readInsights(root)).thin;\n const research = thin ? researchCustomers(root, {}).catch(() => null) : null;\n const brief = await readBrief(root, {\n ...(typeof args.adset === \"string\" && args.adset ? { adset: args.adset } : {}),\n ...(typeof args[\"account-id\"] === \"string\" && args[\"account-id\"] ? { accountId: args[\"account-id\"] } : {}),\n full,\n });\n const found = research ? await research : null;\n const written = found?.shown.length ?? 0;\n const insights = written > 0 ? await readInsights(root) : brief.insights;\n writeJson(briefEnvelope({ ...brief, insights }, full, research ? { written } : undefined));\n },\n});\n","/**\n * The judgments `baker creatives brief` makes from the numbers, so the agent reads a verdict\n * instead of applying thresholds from prose. Pure.\n */\nimport { AWARENESS_STAGES, type Insight } from \"./ideas-model.ts\";\n\n/** Below this many impressions the account has not said anything yet. */\nconst MIN_IMPRESSIONS = 1000;\n/** meta-ads-playbook 17-testing-methodology § \"Bottleneck identification\". */\nconst LOW_CTR = 1.5;\nconst LOW_CVR = 1;\n\nexport type Bottleneck = {\n verdict: \"hook\" | \"after_click\" | \"none\" | \"too_little_data\";\n ctr: number | null;\n cvr: number | null;\n why: string;\n};\n\nconst round = (n: number) => Math.round(n * 100) / 100;\n\n/** Where the account loses people: before the click (the hook), after it (page or offer), or nowhere. */\nexport function diagnoseBottleneck(totals: { impressions: number; linkClicks: number; results: number }): Bottleneck {\n const ctr = totals.impressions > 0 ? round((totals.linkClicks / totals.impressions) * 100) : null;\n const cvr = totals.linkClicks > 0 ? round((totals.results / totals.linkClicks) * 100) : null;\n if (totals.impressions < MIN_IMPRESSIONS || ctr === null) {\n return { verdict: \"too_little_data\", ctr, cvr, why: \"Too little delivery in the last 30 days to call it.\" };\n }\n if (ctr < LOW_CTR) {\n return {\n verdict: \"hook\",\n ctr,\n cvr,\n why: `Link click-through ${ctr}% (under ${LOW_CTR}%): people scroll past. New ideas and hooks are the fix.`,\n };\n }\n if (cvr !== null && cvr < LOW_CVR) {\n return {\n verdict: \"after_click\",\n ctr,\n cvr,\n why: `People click (${ctr}%) but only ${cvr}% act: the page or the offer loses them, and a new ad will not fix that. Say so, make the ads' promise match the page, and make one idea an offer idea.`,\n };\n }\n return {\n verdict: \"none\",\n ctr,\n cvr,\n why: `Click-through ${ctr}% and ${cvr ?? 0}% of clicks act: the ads work. Build on the winners first.`,\n };\n}\n\nconst CONVERSION_ACTION =\n /^(lead|purchase|complete_registration|submit_application|schedule|contact|start_trial|subscribe|offsite_conversion\\.|onsite_conversion\\.lead|onsite_web_lead|omni_purchase|omni_complete_registration)/;\n\n/** The conversions in a Meta `actions[]` list, engagement left out. */\nexport function resultsOf(actions: unknown): number {\n if (!Array.isArray(actions)) return 0;\n let total = 0;\n for (const action of actions) {\n const type = (action as { action_type?: unknown })?.action_type;\n const value = Number((action as { value?: unknown })?.value ?? 0);\n if (typeof type === \"string\" && CONVERSION_ACTION.test(type) && Number.isFinite(value)) total += value;\n }\n return total;\n}\n\nconst MIN_OBSERVED = 5;\nconst MAX_QUOTES = 6;\n\nexport type CustomerTruth = {\n total: number;\n observed: number;\n thin: boolean;\n byType: Record<string, number>;\n /** One observed quote per kind of truth, the strongest material for ideas and hooks. */\n quotes: Array<{ id: string; type: string; quote: string }>;\n};\n\nexport function customerTruth(insights: readonly Insight[]): CustomerTruth {\n const byType: Record<string, number> = {};\n for (const insight of insights) byType[insight.type] = (byType[insight.type] ?? 0) + 1;\n const observed = insights.filter((i) => i.status === \"observed\");\n const seen = new Set<string>();\n const quotes: CustomerTruth[\"quotes\"] = [];\n for (const insight of observed) {\n if (seen.has(insight.type) || quotes.length >= MAX_QUOTES) continue;\n seen.add(insight.type);\n quotes.push({\n id: insight.id,\n type: insight.type,\n quote: insight.quote.length > 140 ? `${insight.quote.slice(0, 137)}...` : insight.quote,\n });\n }\n return { total: insights.length, observed: observed.length, thin: observed.length < MIN_OBSERVED, byType, quotes };\n}\n\n/** One library ad as the market map reads it: whose it is and what its DNA says. */\nexport type MarketAd = {\n advertiser: string | null;\n dna: {\n angle?: string | null;\n awareness_stage?: string | null;\n container?: string | null;\n sophistication_stage?: string | null;\n };\n};\n\nexport type MarketMap = {\n source: \"followed\" | \"library\";\n ads: number;\n brands: number;\n /** The stage most of the market's ads speak at: s1 first to say it … s5 tired of claims. */\n sophistication: string | null;\n /** What the market already says, most brands first: an idea that says the same is not a new idea. */\n saying: Array<{ angle: string; brands: number }>;\n awareness: Record<string, number>;\n containers: Record<string, number>;\n /** Awareness stages none of these ads speaks to. */\n unspoken: string[];\n};\n\nconst MAX_SAYING = 6;\n/** Two angles sharing this share of their content words say the same thing. */\nconst SAME_ANGLE = 0.4;\n\n/** An angle's content words: 4+ letters, a plural folded to its singular. */\nfunction angleWords(angle: string): Set<string> {\n return new Set(\n angle\n .toLowerCase()\n .split(/[^\\p{L}]+/u)\n .filter((w) => w.length >= 4 && w !== \"your\" && w !== \"with\")\n .map((w) => w.replace(/s$/, \"\")),\n );\n}\n\n/** Shared words over all words (Jaccard). */\nfunction overlap(a: ReadonlySet<string>, b: ReadonlySet<string>): number {\n const shared = [...a].filter((w) => b.has(w)).length;\n const all = new Set([...a, ...b]).size;\n return all === 0 ? 0 : shared / all;\n}\n\nfunction tally(values: ReadonlyArray<string | null | undefined>): Record<string, number> {\n const counts: Record<string, number> = {};\n for (const value of values) if (value) counts[value] = (counts[value] ?? 0) + 1;\n return counts;\n}\n\n/** What the market's ads already say and to whom, from a library search over it. Pure. */\nexport function marketMap(ads: readonly MarketAd[], source: MarketMap[\"source\"]): MarketMap {\n const groups: Array<{ angle: string; words: Set<string>; brands: Set<string> }> = [];\n for (const ad of ads) {\n const angle = ad.dna.angle?.trim();\n if (!angle) continue;\n const words = angleWords(angle);\n const group = groups.find((g) => overlap(g.words, words) >= SAME_ANGLE);\n if (group) group.brands.add(ad.advertiser ?? \"?\");\n else groups.push({ angle, words, brands: new Set([ad.advertiser ?? \"?\"]) });\n }\n const saying = groups\n .map((g) => ({ angle: g.angle, brands: g.brands.size }))\n .sort((a, b) => b.brands - a.brands)\n .slice(0, MAX_SAYING);\n const stages = tally(ads.map((a) => a.dna.sophistication_stage));\n const sophistication = Object.entries(stages).sort((a, b) => b[1] - a[1])[0]?.[0] ?? null;\n const awareness = tally(ads.map((a) => a.dna.awareness_stage));\n return {\n source,\n ads: ads.length,\n brands: new Set(ads.map((a) => a.advertiser ?? \"?\")).size,\n sophistication,\n saying,\n awareness,\n containers: tally(ads.map((a) => a.dna.container)),\n unspoken: AWARENESS_STAGES.filter((stage) => !awareness[stage]),\n };\n}\n"],"mappings":"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","names":["id"]}
|
|
1
|
+
{"version":3,"sources":["../src/commands/creatives/brief.ts","../src/commands/creatives/brief-model.ts"],"sourcesContent":["/**\n * `baker creatives brief`: everything the agent needs before deciding what ads to make, in one\n * compact read. Who sees the ads, what the account says works and where it loses people, what the\n * company's reviewers liked, what customers said, and which ideas already exist. Each part is\n * read on its own and a failed read is reported as missing, never as a failed brief.\n */\nimport { readFileSync } from \"node:fs\";\nimport { readdir, readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { CreativePerformance, CreativesFeedbackResponse, CreativesPerformanceResponse } from \"@baker/api\";\nimport type { ScopedWinnersSearchResponse } from \"@baker/api/ad-library\";\nimport { defineCommand } from \"citty\";\nimport { ApiError, apiGet, apiPost } from \"../../client.ts\";\nimport { getEnv } from \"../../env.ts\";\nimport { writeJson } from \"../../output.ts\";\nimport { registerSchema } from \"../../schemas.ts\";\nimport { type ViewerProfile, viewerFromKnowledge } from \"../../viewer-profile.ts\";\nimport { findWorkspaceRoot } from \"../canvas/normalize-paths.ts\";\nimport { liveViewerLookups } from \"../canvas/viewer-check.ts\";\nimport { researchCustomers } from \"../research/customers.ts\";\nimport { buildSearchBody } from \"../winning-ads/search.ts\";\nimport {\n type Bottleneck,\n type CustomerTruth,\n customerTruth,\n diagnoseBottleneck,\n type MarketMap,\n marketMap,\n resultsOf,\n} from \"./brief-model.ts\";\nimport { marketQuery } from \"./company-offer.ts\";\nimport { buildNext, ideasReport } from \"./ideas.ts\";\nimport { AWARENESS_STAGES, IDEA_ANGLES, IDEA_FORMATS } from \"./ideas-model.ts\";\nimport { readInsights } from \"./ideas-workspace.ts\";\nimport { withDefinitions } from \"./performance.ts\";\n\nconst DESCRIPTION = `Start here before making ads: one read of everything that decides what to make. Who sees the ads, what already works in the account and where it loses people (a verdict, not raw numbers), what this company's reviewers approved and rejected, what customers said in their own words, and the ideas already on file.\n\n baker creatives brief # the viewer from the Knowledge\n baker creatives brief --adset <id> # the viewer that ad set reaches\n baker creatives brief --account-id act_<id> # when more than one Meta account is connected\n\nThen write 4-8 ideas in src/creatives/_ideas/ and run \\`baker creatives ideas\\`. With few customer quotes on file it gathers them itself first (\\`baker research customers\\`, about 30 s; --no-research to skip).`;\n\nconst ARGS = {\n adset: {\n type: \"string\",\n description: \"The Meta ad set the ads are for: its viewer replaces the Knowledge's\",\n required: false,\n },\n \"account-id\": {\n type: \"string\",\n description: \"Meta ad account to read (act_<id>); default: the one connected account\",\n required: false,\n },\n full: {\n type: \"boolean\",\n description: \"Every quote, idea and creative instead of the top few\",\n required: false,\n default: false,\n },\n research: {\n type: \"boolean\",\n description: \"Gather customer quotes first when few are on file (default true; --no-research skips it)\",\n required: false,\n default: true,\n },\n} as const;\n\nregisterSchema({ command: \"creatives.brief\", description: DESCRIPTION, args: ARGS });\n\ntype Section<T> = T | { unavailable: string };\n\nconst unavailable = (err: unknown) => ({\n unavailable: err instanceof Error ? err.message.slice(0, 200) : \"could not be read\",\n});\n\nasync function section<T>(read: () => Promise<T>): Promise<Section<T>> {\n try {\n return await read();\n } catch (err) {\n return unavailable(err);\n }\n}\n\nfunction isAvailable<T>(value: Section<T>): value is T {\n return !(value !== null && typeof value === \"object\" && \"unavailable\" in value);\n}\n\nasync function companyStatus(root: string): Promise<\"ready\" | \"missing\"> {\n const doc = await readFile(path.join(root, \"COMPANY.md\"), \"utf8\").catch(() => \"\");\n return doc.trim() && !/^#\\s*Company\\s*\\n+\\s*TODO/m.test(doc) ? \"ready\" : \"missing\";\n}\n\nasync function readOffers(root: string): Promise<string[]> {\n const dir = path.join(root, \"src\", \"content\", \"offers\");\n const files = ((await readdir(dir, { recursive: true }).catch(() => [])) as string[]).filter((f) =>\n f.endsWith(\".md\"),\n );\n return files.map((f) => f.replace(/\\.md$/, \"\")).sort();\n}\n\nfunction readDefinition(root: string, slug: string): string | null {\n try {\n return readFileSync(path.join(root, \"src\", \"creatives\", slug, \"_definition.md\"), \"utf8\");\n } catch {\n return null;\n }\n}\n\nasync function readViewer(root: string, adSet: string | undefined): Promise<ViewerProfile> {\n const lookups = liveViewerLookups(root);\n if (adSet) {\n const read = await lookups.adSetViewer(adSet).catch(() => null);\n if (read) return read;\n }\n const personas = await lookups.personas().catch(() => []);\n return viewerFromKnowledge({ personas: personas.map((p) => p.segment ?? p.title ?? p.slug) });\n}\n\nconst MARKET_ADS = 40;\nconst MARKET_FALLBACK_ADS = 15;\n/**\n * The most a market search may hold the brief: a followed brands' browse answers in ~2 s, a short\n * library query in ~8 s (dev, Oct 2026). The market is context, not a step: a slow library leaves it out.\n */\nconst MARKET_SEARCH_MS = 12_000;\n\n/** What the market's ads already say: the brands the company follows, else the whole library. */\nasync function readMarket(root: string): Promise<MarketMap | null> {\n const query = marketQuery(await readFile(path.join(root, \"COMPANY.md\"), \"utf8\").catch(() => \"\"));\n if (!query) return null;\n const search = (body: Record<string, unknown>) =>\n apiPost<ScopedWinnersSearchResponse>(\"/api/ad-library/winners/search\", body, {\n timeoutMs: MARKET_SEARCH_MS,\n }).catch((err: unknown) => {\n if (err instanceof ApiError && err.code === \"TIMEOUT\") {\n throw new Error(\"the ad library did not answer in time, so competitors' claims are left out\");\n }\n throw err;\n });\n // The followed brands' best ads, browsed (no query, so no relevance judge), and the library's ads\n // for what the company sells, asked at once: the second answers in ~8 s, after the first's ~2 s.\n const [followed, all] = await Promise.allSettled([\n search(buildSearchBody({ scope: \"followed\", platform: \"meta\", limit: MARKET_ADS, maxPerAdvertiser: 8 })),\n search(buildSearchBody({ query, scope: \"all\", platform: \"meta\", limit: MARKET_FALLBACK_ADS, maxPerAdvertiser: 3 })),\n ]);\n if (followed.status === \"fulfilled\" && followed.value.results.length > 0)\n return marketMap(followed.value.results, \"followed\");\n if (all.status === \"rejected\") throw all.reason;\n return all.value.results.length > 0 ? marketMap(all.value.results, \"library\") : null;\n}\n\ntype MetaAccount = { externalId?: unknown; id?: unknown };\n\nasync function metaAccountId(given: string | undefined): Promise<string | null> {\n if (given) return given.startsWith(\"act_\") ? given : `act_${given}`;\n const named = getEnv().BAKER_META_AD_ACCOUNT_ID;\n if (named) return `act_${named.replace(/^act_/, \"\")}`;\n const accounts = await apiGet<MetaAccount[]>(\"/api/ads/meta/accounts\");\n const ids = accounts.flatMap((a) => {\n const id = a.externalId ?? a.id;\n return typeof id === \"string\" && id ? [id] : [];\n });\n if (ids.length !== 1) return null;\n const id = ids[0] as string;\n return id.startsWith(\"act_\") ? id : `act_${id}`;\n}\n\nasync function readBottleneck(accountId: string): Promise<Bottleneck> {\n const rows = await apiPost<Array<Record<string, unknown>>>(\"/api/ads/meta/insights\", {\n object: accountId,\n level: \"account\",\n fields: [\"impressions\", \"inline_link_clicks\", \"actions\", \"spend\"],\n actionBreakdowns: [\"action_type\"],\n datePreset: \"last_30d\",\n limit: 10,\n });\n const totals = { impressions: 0, linkClicks: 0, results: 0 };\n for (const row of rows) {\n totals.impressions += Number(row.impressions ?? 0);\n totals.linkClicks += Number(row.inline_link_clicks ?? 0);\n totals.results += resultsOf(row.actions);\n }\n return diagnoseBottleneck(totals);\n}\n\nfunction leanCreative(c: CreativePerformance) {\n return {\n creative: c.slug ?? c.title,\n costPerResult: c.costPerResult,\n ...(c.currency ? { currency: c.currency } : {}),\n ctr: c.ctr,\n fatigue: c.fatigue,\n ...(c.definition?.idea ? { idea: c.definition.idea } : {}),\n ...(c.definition?.angle ? { angle: c.definition.angle } : {}),\n };\n}\n\n/** The own-account read: the best creatives by cost per result, and the ones to replace. Pure. */\nexport function whatWorks(creatives: readonly CreativePerformance[], limit = 3) {\n const priced = creatives.filter((c) => c.costPerResult !== null && c.costPerResult > 0);\n const best = [...priced].sort((a, b) => (a.costPerResult ?? 0) - (b.costPerResult ?? 0)).slice(0, limit);\n const tired = creatives.filter((c) => c.fatigue === \"fatigued\" || c.fatigue === \"dead\");\n return { best: best.map(leanCreative), replace: tired.map(leanCreative) };\n}\n\ntype BriefParts = {\n company: \"ready\" | \"missing\";\n customers: CustomerTruth;\n bottleneck: Section<Bottleneck> | null;\n ideasToBuild: number;\n buildNext: string[];\n approved: number;\n rejected: number;\n market?: MarketMap | null;\n /** What earlier ideas did once their ads ran (`baker creatives learn`). */\n learned: { winners: LearnedIdea[]; failed: LearnedIdea[] };\n /** The customer research this brief ran itself, few quotes being on file. */\n researched?: { written: number };\n};\n\ntype LearnedIdea = { idea: string; message: string };\n\n/** A market whose ads mostly speak at stage s3 or later has heard the plain claim already. */\nconst HEARD_IT_ALL = /^s[345]/;\n\n/** What the brief says about customer quotes: what its own research found, or that it is needed. Pure. */\nfunction customersHint(parts: Pick<BriefParts, \"customers\" | \"researched\">): string | null {\n if (parts.researched) {\n return parts.researched.written > 0\n ? `${parts.researched.written} customer quotes were just gathered from reviews and Reddit and are in \\`customers\\`: cite them by id in each idea's \\`evidence\\`.`\n : \"Customer research found nothing to keep: ideas go in as explore bets (an empty `evidence` list). Never research customers again in this turn.\";\n }\n if (!parts.customers.thin) return null;\n return `Only ${parts.customers.observed} customer quotes on file: run \\`baker research customers\\` now, before writing ideas, so they stand on what customers said. It gathers reviews, Reddit and the web and writes the quotes with their sources in about a minute; never a subagent or web searches of your own for this.`;\n}\n\n/** The one or two next steps the brief points to. Pure. */\nexport function briefHints(parts: BriefParts): string[] {\n const hints: string[] = [];\n if (parts.company === \"missing\") {\n hints.push(\"COMPANY.md is empty: run /company-discovery first, or every idea is a guess about the business.\");\n }\n const customers = customersHint(parts);\n if (customers) hints.push(customers);\n if (parts.bottleneck && isAvailable(parts.bottleneck) && parts.bottleneck.verdict === \"after_click\") {\n hints.push(\"The account loses people after the click: tell the person, and make one idea an offer idea.\");\n }\n if (parts.market?.sophistication && HEARD_IT_ALL.test(parts.market.sophistication)) {\n hints.push(\n `This market has heard the plain claim (sophistication ${parts.market.sophistication}): lead with how it works (a mechanism), proof, or an angle nobody uses, never a bigger claim.`,\n );\n }\n // Every claim, not only the ones several brands share word for word: the same claim is often worded apart.\n const claims = parts.market?.saying.map((s) => `\"${s.angle}\"`) ?? [];\n if (claims.length > 0) {\n hints.push(\n `Competitors already say ${claims.join(\", \")}. A message one of them could also run is not a new idea, however it is worded: say what only we have (the offer, a proof, a customer's words) or how it works.`,\n );\n }\n for (const won of parts.learned.winners) {\n hints.push(\n `${won.idea} won in the account (\"${won.message}\"): build on it first, the same message in a new format or for a new persona.`,\n );\n }\n if (parts.learned.failed.length > 0) {\n const lost = parts.learned.failed.map((f) => `\"${f.message}\"`).join(\", \");\n hints.push(`Never repeat a message that lost in the account: ${lost}.`);\n }\n if (parts.rejected > parts.approved && parts.rejected > 0) {\n hints.push(\"Reviewers rejected more than they approved: read topRejectionReasons and avoid them in every idea.\");\n }\n if (parts.buildNext.length > 0) {\n hints.push(`Ideas ready to build: ${parts.buildNext.join(\", \")} (\\`baker creatives make <idea>\\`).`);\n } else {\n hints.push(\n `Write 4-8 ideas in src/creatives/_ideas/<idea>.md (who, message, evidence, awareness, angle, format, job, why), then \\`baker creatives ideas\\`. awareness: ${AWARENESS_STAGES.join(\" | \")}. angle: ${IDEA_ANGLES.join(\", \")}. format: ${IDEA_FORMATS.join(\", \")}.`,\n );\n }\n return hints;\n}\n\ntype BriefArgs = { adset?: string; accountId?: string; full: boolean };\n\nasync function readBrief(root: string, args: BriefArgs) {\n // Every read starts at once: the account's diagnosis waits only for the account, never for the rest.\n const account = metaAccountId(args.accountId).catch(() => null);\n const [company, offers, viewer, insights, ideas, performance, feedback, accountId, bottleneck, market] =\n await Promise.all([\n companyStatus(root),\n readOffers(root),\n readViewer(root, args.adset),\n readInsights(root),\n ideasReport(root),\n section(async () =>\n withDefinitions(await apiPost<CreativesPerformanceResponse>(\"/api/creatives/performance\", {}), (slug) =>\n readDefinition(root, slug),\n ),\n ),\n section(() => apiPost<CreativesFeedbackResponse>(\"/api/creatives/feedback\", {})),\n account,\n account.then((id) => (id ? section(() => readBottleneck(id)) : null)),\n section(() => readMarket(root)),\n ]);\n return { company, offers, viewer, insights, ideas, performance, feedback, accountId, bottleneck, market };\n}\n\ntype Brief = Awaited<ReturnType<typeof readBrief>>;\n\nfunction accountPart(brief: Brief, full: boolean) {\n if (!brief.accountId) {\n return { unavailable: \"no single Meta ad account connected: pass --account-id act_<id>, or work from customers\" };\n }\n const works = isAvailable(brief.performance)\n ? whatWorks(brief.performance.data.creatives, full ? 10 : 3)\n : { creatives: brief.performance };\n return { id: brief.accountId, bottleneck: brief.bottleneck, ...works };\n}\n\nfunction marketPart(market: Section<MarketMap | null>, full: boolean) {\n if (!isAvailable(market)) return market;\n if (!market) return { unavailable: \"no library ads match what COMPANY.md says the company sells\" };\n if (full) return market;\n const { containers: _containers, ...lean } = market;\n return lean;\n}\n\n/** The brief as the agent reads it, and the hints that point at the next step. */\nexport function briefEnvelope(brief: Brief, full: boolean, researched?: { written: number }) {\n const customers = customerTruth(brief.insights);\n const summary = isAvailable(brief.feedback) ? brief.feedback.data.summary : null;\n const next = buildNext(brief.ideas.ideas);\n const toBuild = brief.ideas.ideas.filter((i) => i.status === \"idea\").length;\n const withStatus = (status: string) =>\n brief.ideas.ideas.filter((i) => i.status === status).map((i) => ({ idea: i.id, message: i.message }));\n const learned = { winners: withStatus(\"winner\"), failed: withStatus(\"failed\") };\n return {\n ok: true as const,\n data: {\n company: brief.company,\n viewer: { temperature: brief.viewer.temperature, knows: brief.viewer.knows, source: brief.viewer.source },\n offers: brief.offers,\n account: accountPart(brief, full),\n taste: summary\n ? {\n approved: summary.approved,\n rejected: summary.rejected,\n topRejectionReasons: summary.topRejectionReasons.slice(0, 3).map((r) => r.label),\n }\n : brief.feedback,\n customers: full\n ? { ...customers, quotes: brief.insights.map((i) => ({ id: i.id, type: i.type, quote: i.quote })) }\n : customers,\n market: marketPart(brief.market, full),\n ideas: {\n to_build: toBuild,\n built: brief.ideas.ideas.length - toBuild,\n build_next: next,\n ...(learned.winners.length > 0 ? { winners: learned.winners } : {}),\n ...(learned.failed.length > 0 ? { failed: learned.failed } : {}),\n },\n },\n hints: briefHints({\n company: brief.company,\n customers,\n bottleneck: brief.bottleneck,\n ideasToBuild: toBuild,\n buildNext: next,\n approved: summary?.approved ?? 0,\n rejected: summary?.rejected ?? 0,\n market: isAvailable(brief.market) ? brief.market : null,\n learned,\n ...(researched ? { researched } : {}),\n }),\n };\n}\n\nexport const briefCommand = defineCommand({\n meta: { name: \"brief\", description: DESCRIPTION },\n args: ARGS,\n async run({ args }) {\n const root = findWorkspaceRoot(process.cwd()) ?? process.cwd();\n const full = args.full === true;\n // Few quotes on file: the research runs alongside the reads, never left to the agent (dev, Oct\n // 2026: told to run it first, the chat agent skipped it and every idea went in as an explore bet).\n const thin = args.research !== false && customerTruth(await readInsights(root)).thin;\n const research = thin ? researchCustomers(root, {}).catch(() => null) : null;\n const brief = await readBrief(root, {\n ...(typeof args.adset === \"string\" && args.adset ? { adset: args.adset } : {}),\n ...(typeof args[\"account-id\"] === \"string\" && args[\"account-id\"] ? { accountId: args[\"account-id\"] } : {}),\n full,\n });\n const found = research ? await research : null;\n const written = found?.shown.length ?? 0;\n const insights = written > 0 ? await readInsights(root) : brief.insights;\n writeJson(briefEnvelope({ ...brief, insights }, full, research ? { written } : undefined));\n },\n});\n","/**\n * The judgments `baker creatives brief` makes from the numbers, so the agent reads a verdict\n * instead of applying thresholds from prose. Pure.\n */\nimport { AWARENESS_STAGES, type Insight } from \"./ideas-model.ts\";\n\n/** Below this many impressions the account has not said anything yet. */\nconst MIN_IMPRESSIONS = 1000;\n/** meta-ads-playbook 17-testing-methodology § \"Bottleneck identification\". */\nconst LOW_CTR = 1.5;\nconst LOW_CVR = 1;\n\nexport type Bottleneck = {\n verdict: \"hook\" | \"after_click\" | \"none\" | \"too_little_data\";\n ctr: number | null;\n cvr: number | null;\n why: string;\n};\n\nconst round = (n: number) => Math.round(n * 100) / 100;\n\n/** Where the account loses people: before the click (the hook), after it (page or offer), or nowhere. */\nexport function diagnoseBottleneck(totals: { impressions: number; linkClicks: number; results: number }): Bottleneck {\n const ctr = totals.impressions > 0 ? round((totals.linkClicks / totals.impressions) * 100) : null;\n const cvr = totals.linkClicks > 0 ? round((totals.results / totals.linkClicks) * 100) : null;\n if (totals.impressions < MIN_IMPRESSIONS || ctr === null) {\n return { verdict: \"too_little_data\", ctr, cvr, why: \"Too little delivery in the last 30 days to call it.\" };\n }\n if (ctr < LOW_CTR) {\n return {\n verdict: \"hook\",\n ctr,\n cvr,\n why: `Link click-through ${ctr}% (under ${LOW_CTR}%): people scroll past. New ideas and hooks are the fix.`,\n };\n }\n if (cvr !== null && cvr < LOW_CVR) {\n return {\n verdict: \"after_click\",\n ctr,\n cvr,\n why: `People click (${ctr}%) but only ${cvr}% act: the page or the offer loses them, and a new ad will not fix that. Say so, make the ads' promise match the page, and make one idea an offer idea.`,\n };\n }\n return {\n verdict: \"none\",\n ctr,\n cvr,\n why: `Click-through ${ctr}% and ${cvr ?? 0}% of clicks act: the ads work. Build on the winners first.`,\n };\n}\n\nconst CONVERSION_ACTION =\n /^(lead|purchase|complete_registration|submit_application|schedule|contact|start_trial|subscribe|offsite_conversion\\.|onsite_conversion\\.lead|onsite_web_lead|omni_purchase|omni_complete_registration)/;\n\n/** The conversions in a Meta `actions[]` list, engagement left out. */\nexport function resultsOf(actions: unknown): number {\n if (!Array.isArray(actions)) return 0;\n let total = 0;\n for (const action of actions) {\n const type = (action as { action_type?: unknown })?.action_type;\n const value = Number((action as { value?: unknown })?.value ?? 0);\n if (typeof type === \"string\" && CONVERSION_ACTION.test(type) && Number.isFinite(value)) total += value;\n }\n return total;\n}\n\nconst MIN_OBSERVED = 5;\nconst MAX_QUOTES = 6;\n\nexport type CustomerTruth = {\n total: number;\n observed: number;\n thin: boolean;\n byType: Record<string, number>;\n /** One observed quote per kind of truth, the strongest material for ideas and hooks. */\n quotes: Array<{ id: string; type: string; quote: string }>;\n};\n\nexport function customerTruth(insights: readonly Insight[]): CustomerTruth {\n const byType: Record<string, number> = {};\n for (const insight of insights) byType[insight.type] = (byType[insight.type] ?? 0) + 1;\n const observed = insights.filter((i) => i.status === \"observed\");\n const seen = new Set<string>();\n const quotes: CustomerTruth[\"quotes\"] = [];\n for (const insight of observed) {\n if (seen.has(insight.type) || quotes.length >= MAX_QUOTES) continue;\n seen.add(insight.type);\n quotes.push({\n id: insight.id,\n type: insight.type,\n quote: insight.quote.length > 140 ? `${insight.quote.slice(0, 137)}...` : insight.quote,\n });\n }\n return { total: insights.length, observed: observed.length, thin: observed.length < MIN_OBSERVED, byType, quotes };\n}\n\n/** One library ad as the market map reads it: whose it is and what its DNA says. */\nexport type MarketAd = {\n advertiser: string | null;\n dna: {\n angle?: string | null;\n awareness_stage?: string | null;\n container?: string | null;\n sophistication_stage?: string | null;\n };\n};\n\nexport type MarketMap = {\n source: \"followed\" | \"library\";\n ads: number;\n brands: number;\n /** The stage most of the market's ads speak at: s1 first to say it … s5 tired of claims. */\n sophistication: string | null;\n /** What the market already says, most brands first: an idea that says the same is not a new idea. */\n saying: Array<{ angle: string; brands: number }>;\n awareness: Record<string, number>;\n containers: Record<string, number>;\n /** Awareness stages none of these ads speaks to. */\n unspoken: string[];\n};\n\nconst MAX_SAYING = 6;\n/** Two angles sharing this share of their content words say the same thing. */\nconst SAME_ANGLE = 0.4;\n\n/** An angle's content words: 4+ letters, a plural folded to its singular. */\nfunction angleWords(angle: string): Set<string> {\n return new Set(\n angle\n .toLowerCase()\n .split(/[^\\p{L}]+/u)\n .filter((w) => w.length >= 4 && w !== \"your\" && w !== \"with\")\n .map((w) => w.replace(/s$/, \"\")),\n );\n}\n\n/** Shared words over all words (Jaccard). */\nfunction overlap(a: ReadonlySet<string>, b: ReadonlySet<string>): number {\n const shared = [...a].filter((w) => b.has(w)).length;\n const all = new Set([...a, ...b]).size;\n return all === 0 ? 0 : shared / all;\n}\n\nfunction tally(values: ReadonlyArray<string | null | undefined>): Record<string, number> {\n const counts: Record<string, number> = {};\n for (const value of values) if (value) counts[value] = (counts[value] ?? 0) + 1;\n return counts;\n}\n\n/** What the market's ads already say and to whom, from a library search over it. Pure. */\nexport function marketMap(ads: readonly MarketAd[], source: MarketMap[\"source\"]): MarketMap {\n const groups: Array<{ angle: string; words: Set<string>; brands: Set<string> }> = [];\n for (const ad of ads) {\n const angle = ad.dna.angle?.trim();\n if (!angle) continue;\n const words = angleWords(angle);\n const group = groups.find((g) => overlap(g.words, words) >= SAME_ANGLE);\n if (group) group.brands.add(ad.advertiser ?? \"?\");\n else groups.push({ angle, words, brands: new Set([ad.advertiser ?? \"?\"]) });\n }\n const saying = groups\n .map((g) => ({ angle: g.angle, brands: g.brands.size }))\n .sort((a, b) => b.brands - a.brands)\n .slice(0, MAX_SAYING);\n const stages = tally(ads.map((a) => a.dna.sophistication_stage));\n const sophistication = Object.entries(stages).sort((a, b) => b[1] - a[1])[0]?.[0] ?? null;\n const awareness = tally(ads.map((a) => a.dna.awareness_stage));\n return {\n source,\n ads: ads.length,\n brands: new Set(ads.map((a) => a.advertiser ?? \"?\")).size,\n sophistication,\n saying,\n awareness,\n containers: tally(ads.map((a) => a.dna.container)),\n unspoken: AWARENESS_STAGES.filter((stage) => !awareness[stage]),\n };\n}\n"],"mappings":"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","names":["id"]}
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
resolveAccountIdArg,
|
|
5
5
|
resolveStatusFilter,
|
|
6
6
|
statusesArgDescription
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-N4LAYIIN.js";
|
|
8
8
|
import {
|
|
9
9
|
writeAdsJson,
|
|
10
10
|
writeAdsOutput
|
|
@@ -12,10 +12,11 @@ import {
|
|
|
12
12
|
import {
|
|
13
13
|
NO_CACHE_ARG
|
|
14
14
|
} from "./chunk-X7ZODEXJ.js";
|
|
15
|
-
import "./chunk-
|
|
15
|
+
import "./chunk-7EPXVICM.js";
|
|
16
16
|
import "./chunk-GXDLWBOY.js";
|
|
17
17
|
import "./chunk-TEINLN64.js";
|
|
18
18
|
import "./chunk-ZJWUBJYQ.js";
|
|
19
|
+
import "./chunk-HR6IWNKE.js";
|
|
19
20
|
import "./chunk-NE4F3FHN.js";
|
|
20
21
|
import {
|
|
21
22
|
apiGet
|
|
@@ -77,11 +78,11 @@ Examples:
|
|
|
77
78
|
},
|
|
78
79
|
subCommands: {
|
|
79
80
|
list: campaignGroupsListCommand,
|
|
80
|
-
create: () => import("./write-commands-
|
|
81
|
-
update: () => import("./write-commands-
|
|
82
|
-
pause: () => import("./write-commands-
|
|
83
|
-
resume: () => import("./write-commands-
|
|
84
|
-
duplicate: () => import("./write-commands-
|
|
81
|
+
create: () => import("./write-commands-7SJ3BOW5.js").then((m) => m.campaignGroupsCreateCommand),
|
|
82
|
+
update: () => import("./write-commands-7SJ3BOW5.js").then((m) => m.campaignGroupsUpdateCommand),
|
|
83
|
+
pause: () => import("./write-commands-7SJ3BOW5.js").then((m) => m.campaignGroupsPauseCommand),
|
|
84
|
+
resume: () => import("./write-commands-7SJ3BOW5.js").then((m) => m.campaignGroupsResumeCommand),
|
|
85
|
+
duplicate: () => import("./write-commands-7SJ3BOW5.js").then((m) => m.campaignGroupsDuplicateCommand)
|
|
85
86
|
},
|
|
86
87
|
// A parent must never declare `run`: citty falls through to it *after* running
|
|
87
88
|
// the matched subcommand, so every write would also trigger a full live list.
|
|
@@ -92,4 +93,4 @@ Examples:
|
|
|
92
93
|
export {
|
|
93
94
|
campaignGroupsCommand
|
|
94
95
|
};
|
|
95
|
-
//# sourceMappingURL=campaign-groups-
|
|
96
|
+
//# sourceMappingURL=campaign-groups-PQ6KSQJR.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/ads/linkedin/campaign-groups.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\nimport { NO_CACHE_ARG } from \"../../../cache-flag.ts\";\nimport { apiGet } from \"../../../client.ts\";\nimport { writeAdsJson, writeAdsOutput } from \"../output.ts\";\nimport {\n csvOrJson,\n handleLinkedinError,\n resolveAccountIdArg,\n resolveStatusFilter,\n statusesArgDescription,\n} from \"./shared.ts\";\n\ninterface LinkedinCampaignGroupRow {\n id: string;\n urn: string;\n account: string;\n name?: string;\n status?: string;\n test?: boolean;\n totalBudget?: { amount?: string; currencyCode?: string };\n runSchedule?: { start?: number; end?: number };\n}\n\nconst listArgs = {\n \"account-id\": { type: \"string\", description: \"Numeric account ID or urn:li:sponsoredAccount:N\" },\n \"account-urn\": { type: \"string\", description: \"Alias for --account-id\" },\n \"all-statuses\": { type: \"boolean\", description: \"Drop the default ACTIVE filter\" },\n statuses: { type: \"string\", description: statusesArgDescription(\"campaignGroups\") },\n limit: { type: \"string\", description: \"Max rows (default: 500)\" },\n \"no-cache\": NO_CACHE_ARG,\n output: { type: \"string\", description: \"json|csv|jsonl|md\", default: \"json\" },\n} as const;\n\nconst campaignGroupsListCommand = defineCommand({\n meta: {\n name: \"list\",\n description: \"List LinkedIn campaign groups. Runs by default when no subcommand is given.\",\n },\n args: listArgs,\n run: async ({ args }) => {\n const accountId = resolveAccountIdArg(args);\n try {\n const params: Record<string, string> = { \"account-id\": accountId };\n const statuses = resolveStatusFilter(args, \"campaignGroups\");\n if (statuses) params.statuses = statuses.join(\",\");\n if (args.limit) params.limit = String(args.limit);\n if (args[\"no-cache\"]) params[\"skip-cache\"] = \"true\";\n\n const data = await apiGet<LinkedinCampaignGroupRow[]>(\"/api/ads/linkedin/campaign-groups\", params);\n const fmt = csvOrJson(args);\n if (fmt !== \"json\") {\n writeAdsOutput(data as unknown as Array<Record<string, unknown>>, fmt);\n return;\n }\n writeAdsJson({ ok: true, data });\n } catch (err) {\n handleLinkedinError(err);\n }\n },\n});\n\nexport const campaignGroupsCommand = defineCommand({\n meta: {\n name: \"campaign-groups\",\n description: `List LinkedIn campaign groups, or stage writes (create/update/pause/resume/duplicate).\n\nDefault: ACTIVE only. Pass --all-statuses to widen, or --statuses ACTIVE,PAUSED to override.\nWrite subcommands stage ops on this chat's draft and apply only when the chat is published.\n\nExamples:\n baker ads linkedin campaign-groups --account-id 503001492\n baker ads linkedin campaign-groups --account-id 503001492 --all-statuses\n baker ads linkedin campaign-groups create --name \"Q3 ABM\" --start 2026-07-10 --total-budget 5000 --currency EUR`,\n },\n subCommands: {\n list: campaignGroupsListCommand,\n create: () => import(\"./write-commands.ts\").then((m) => m.campaignGroupsCreateCommand),\n update: () => import(\"./write-commands.ts\").then((m) => m.campaignGroupsUpdateCommand),\n pause: () => import(\"./write-commands.ts\").then((m) => m.campaignGroupsPauseCommand),\n resume: () => import(\"./write-commands.ts\").then((m) => m.campaignGroupsResumeCommand),\n duplicate: () => import(\"./write-commands.ts\").then((m) => m.campaignGroupsDuplicateCommand),\n },\n // A parent must never declare `run`: citty falls through to it *after* running\n // the matched subcommand, so every write would also trigger a full live list.\n // `args` stays here so citty's subcommand scan knows which flags take a value.\n args: listArgs,\n default: \"list\",\n});\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/commands/ads/linkedin/campaign-groups.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\nimport { NO_CACHE_ARG } from \"../../../cache-flag.ts\";\nimport { apiGet } from \"../../../client.ts\";\nimport { writeAdsJson, writeAdsOutput } from \"../output.ts\";\nimport {\n csvOrJson,\n handleLinkedinError,\n resolveAccountIdArg,\n resolveStatusFilter,\n statusesArgDescription,\n} from \"./shared.ts\";\n\ninterface LinkedinCampaignGroupRow {\n id: string;\n urn: string;\n account: string;\n name?: string;\n status?: string;\n test?: boolean;\n totalBudget?: { amount?: string; currencyCode?: string };\n runSchedule?: { start?: number; end?: number };\n}\n\nconst listArgs = {\n \"account-id\": { type: \"string\", description: \"Numeric account ID or urn:li:sponsoredAccount:N\" },\n \"account-urn\": { type: \"string\", description: \"Alias for --account-id\" },\n \"all-statuses\": { type: \"boolean\", description: \"Drop the default ACTIVE filter\" },\n statuses: { type: \"string\", description: statusesArgDescription(\"campaignGroups\") },\n limit: { type: \"string\", description: \"Max rows (default: 500)\" },\n \"no-cache\": NO_CACHE_ARG,\n output: { type: \"string\", description: \"json|csv|jsonl|md\", default: \"json\" },\n} as const;\n\nconst campaignGroupsListCommand = defineCommand({\n meta: {\n name: \"list\",\n description: \"List LinkedIn campaign groups. Runs by default when no subcommand is given.\",\n },\n args: listArgs,\n run: async ({ args }) => {\n const accountId = resolveAccountIdArg(args);\n try {\n const params: Record<string, string> = { \"account-id\": accountId };\n const statuses = resolveStatusFilter(args, \"campaignGroups\");\n if (statuses) params.statuses = statuses.join(\",\");\n if (args.limit) params.limit = String(args.limit);\n if (args[\"no-cache\"]) params[\"skip-cache\"] = \"true\";\n\n const data = await apiGet<LinkedinCampaignGroupRow[]>(\"/api/ads/linkedin/campaign-groups\", params);\n const fmt = csvOrJson(args);\n if (fmt !== \"json\") {\n writeAdsOutput(data as unknown as Array<Record<string, unknown>>, fmt);\n return;\n }\n writeAdsJson({ ok: true, data });\n } catch (err) {\n handleLinkedinError(err);\n }\n },\n});\n\nexport const campaignGroupsCommand = defineCommand({\n meta: {\n name: \"campaign-groups\",\n description: `List LinkedIn campaign groups, or stage writes (create/update/pause/resume/duplicate).\n\nDefault: ACTIVE only. Pass --all-statuses to widen, or --statuses ACTIVE,PAUSED to override.\nWrite subcommands stage ops on this chat's draft and apply only when the chat is published.\n\nExamples:\n baker ads linkedin campaign-groups --account-id 503001492\n baker ads linkedin campaign-groups --account-id 503001492 --all-statuses\n baker ads linkedin campaign-groups create --name \"Q3 ABM\" --start 2026-07-10 --total-budget 5000 --currency EUR`,\n },\n subCommands: {\n list: campaignGroupsListCommand,\n create: () => import(\"./write-commands.ts\").then((m) => m.campaignGroupsCreateCommand),\n update: () => import(\"./write-commands.ts\").then((m) => m.campaignGroupsUpdateCommand),\n pause: () => import(\"./write-commands.ts\").then((m) => m.campaignGroupsPauseCommand),\n resume: () => import(\"./write-commands.ts\").then((m) => m.campaignGroupsResumeCommand),\n duplicate: () => import(\"./write-commands.ts\").then((m) => m.campaignGroupsDuplicateCommand),\n },\n // A parent must never declare `run`: citty falls through to it *after* running\n // the matched subcommand, so every write would also trigger a full live list.\n // `args` stays here so citty's subcommand scan knows which flags take a value.\n args: listArgs,\n default: \"list\",\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,qBAAqB;AAuB9B,IAAM,WAAW;AAAA,EACf,cAAc,EAAE,MAAM,UAAU,aAAa,kDAAkD;AAAA,EAC/F,eAAe,EAAE,MAAM,UAAU,aAAa,yBAAyB;AAAA,EACvE,gBAAgB,EAAE,MAAM,WAAW,aAAa,iCAAiC;AAAA,EACjF,UAAU,EAAE,MAAM,UAAU,aAAa,uBAAuB,gBAAgB,EAAE;AAAA,EAClF,OAAO,EAAE,MAAM,UAAU,aAAa,0BAA0B;AAAA,EAChE,YAAY;AAAA,EACZ,QAAQ,EAAE,MAAM,UAAU,aAAa,qBAAqB,SAAS,OAAO;AAC9E;AAEA,IAAM,4BAA4B,cAAc;AAAA,EAC9C,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AAAA,EACA,MAAM;AAAA,EACN,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,UAAM,YAAY,oBAAoB,IAAI;AAC1C,QAAI;AACF,YAAM,SAAiC,EAAE,cAAc,UAAU;AACjE,YAAM,WAAW,oBAAoB,MAAM,gBAAgB;AAC3D,UAAI,SAAU,QAAO,WAAW,SAAS,KAAK,GAAG;AACjD,UAAI,KAAK,MAAO,QAAO,QAAQ,OAAO,KAAK,KAAK;AAChD,UAAI,KAAK,UAAU,EAAG,QAAO,YAAY,IAAI;AAE7C,YAAM,OAAO,MAAM,OAAmC,qCAAqC,MAAM;AACjG,YAAM,MAAM,UAAU,IAAI;AAC1B,UAAI,QAAQ,QAAQ;AAClB,uBAAe,MAAmD,GAAG;AACrE;AAAA,MACF;AACA,mBAAa,EAAE,IAAI,MAAM,KAAK,CAAC;AAAA,IACjC,SAAS,KAAK;AACZ,0BAAoB,GAAG;AAAA,IACzB;AAAA,EACF;AACF,CAAC;AAEM,IAAM,wBAAwB,cAAc;AAAA,EACjD,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASf;AAAA,EACA,aAAa;AAAA,IACX,MAAM;AAAA,IACN,QAAQ,MAAM,OAAO,8BAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,2BAA2B;AAAA,IACrF,QAAQ,MAAM,OAAO,8BAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,2BAA2B;AAAA,IACrF,OAAO,MAAM,OAAO,8BAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,0BAA0B;AAAA,IACnF,QAAQ,MAAM,OAAO,8BAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,2BAA2B;AAAA,IACrF,WAAW,MAAM,OAAO,8BAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,8BAA8B;AAAA,EAC7F;AAAA;AAAA;AAAA;AAAA,EAIA,MAAM;AAAA,EACN,SAAS;AACX,CAAC;","names":[]}
|
|
@@ -6,14 +6,15 @@ import {
|
|
|
6
6
|
stageAccountId,
|
|
7
7
|
stageXOp,
|
|
8
8
|
stageXOps
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-VYQ3QJ3C.js";
|
|
10
10
|
import "./chunk-M6UNISGO.js";
|
|
11
11
|
import "./chunk-C6U6UDHJ.js";
|
|
12
12
|
import "./chunk-VFIOJD5M.js";
|
|
13
|
-
import "./chunk-
|
|
13
|
+
import "./chunk-7EPXVICM.js";
|
|
14
14
|
import "./chunk-GXDLWBOY.js";
|
|
15
15
|
import "./chunk-TEINLN64.js";
|
|
16
16
|
import "./chunk-ZJWUBJYQ.js";
|
|
17
|
+
import "./chunk-HR6IWNKE.js";
|
|
17
18
|
import "./chunk-NE4F3FHN.js";
|
|
18
19
|
import "./chunk-XBOK23HI.js";
|
|
19
20
|
import "./chunk-IFWP3ZDO.js";
|
|
@@ -162,4 +163,4 @@ export {
|
|
|
162
163
|
campaignsResumeCommand,
|
|
163
164
|
campaignsUpdateCommand
|
|
164
165
|
};
|
|
165
|
-
//# sourceMappingURL=campaign-writes-
|
|
166
|
+
//# sourceMappingURL=campaign-writes-5OVLUD5E.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/ads/x/campaign-writes.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\nimport { registerSchema } from \"../../../schemas.ts\";\nimport {\n compact,\n microsFromArg,\n requireTarget,\n requireTargets,\n stageAccountId,\n stageXOp,\n stageXOps,\n} from \"./write-shared.ts\";\n\n/**\n * Staged campaign writes. Nothing here calls X: each command appends an op to\n * this chat's draft, which applies when the chat publishes.\n */\n\nconst BUDGET_ARGS = {\n \"daily-budget\": { type: \"string\", description: \"Daily budget in account currency, e.g. 12.50\" },\n \"total-budget\": { type: \"string\", description: \"Lifetime budget in account currency — must exceed the daily budget\" },\n} as const;\n\nregisterSchema({\n command: \"ads.x.campaigns.create\",\n description:\n \"Stage a new X campaign on this chat's draft. Needs a funding instrument (`baker ads x funding`). Defaults to PAUSED — an ACTIVE campaign starts spending the moment the chat publishes.\",\n args: {\n \"account-id\": { type: \"string\", description: \"X Ads account ID\", required: false },\n name: { type: \"string\", description: \"Campaign name\", required: true },\n \"funding-instrument-id\": { type: \"string\", description: \"From `baker ads x funding`\", required: true },\n status: { type: \"string\", description: \"ACTIVE | PAUSED | DRAFT (default PAUSED)\", required: false },\n \"daily-budget\": { type: \"string\", description: \"Daily budget in account currency\", required: false },\n \"total-budget\": { type: \"string\", description: \"Lifetime budget in account currency\", required: false },\n \"budget-optimization\": { type: \"string\", description: \"CAMPAIGN | LINE_ITEM\", required: false },\n },\n});\n\nexport const campaignsCreateCommand = defineCommand({\n meta: {\n name: \"create\",\n description: `Stage a new campaign (applies when the chat is published).\n\nExamples:\n baker ads x campaigns create --name \"zz-baker-harness\" --funding-instrument-id vtbot --daily-budget 5`,\n },\n args: {\n \"account-id\": { type: \"string\", description: \"X Ads account ID\" },\n name: { type: \"string\", description: \"Campaign name\", required: true },\n \"funding-instrument-id\": { type: \"string\", description: \"Funding instrument id\", required: true },\n status: { type: \"string\", description: \"ACTIVE | PAUSED | DRAFT (default PAUSED)\" },\n ...BUDGET_ARGS,\n \"budget-optimization\": { type: \"string\", description: \"CAMPAIGN | LINE_ITEM\" },\n },\n run: async ({ args }) => {\n const accountId = await stageAccountId(args);\n await stageXOp({\n kind: \"campaign.create\",\n accountId,\n payload: compact({\n name: args.name,\n fundingInstrumentId: args[\"funding-instrument-id\"],\n entityStatus: args.status,\n budgetOptimization: args[\"budget-optimization\"],\n dailyBudgetAmountLocalMicro: microsFromArg(args[\"daily-budget\"], \"--daily-budget\"),\n totalBudgetAmountLocalMicro: microsFromArg(args[\"total-budget\"], \"--total-budget\"),\n }),\n });\n },\n});\n\nregisterSchema({\n command: \"ads.x.campaigns.update\",\n description:\n \"Stage a change to an existing X campaign. Staging the same campaign twice amends the staged change in place rather than queueing two writes.\",\n args: {\n id: { type: \"string\", description: \"Campaign id\", required: true },\n \"account-id\": { type: \"string\", description: \"X Ads account ID\", required: false },\n name: { type: \"string\", description: \"New name\", required: false },\n status: { type: \"string\", description: \"ACTIVE | PAUSED\", required: false },\n \"daily-budget\": { type: \"string\", description: \"Daily budget in account currency\", required: false },\n \"total-budget\": { type: \"string\", description: \"Lifetime budget in account currency\", required: false },\n \"budget-optimization\": { type: \"string\", description: \"CAMPAIGN | LINE_ITEM\", required: false },\n },\n});\n\nexport const campaignsUpdateCommand = defineCommand({\n meta: {\n name: \"update\",\n description: `Stage a change to a campaign.\n\nExamples:\n baker ads x campaigns update oilf0 --daily-budget 20\n baker ads x campaigns update oilf0 --name \"Spring push\"`,\n },\n args: {\n id: { type: \"positional\", description: \"Campaign id\", required: true },\n \"account-id\": { type: \"string\", description: \"X Ads account ID\" },\n name: { type: \"string\", description: \"New name\" },\n status: { type: \"string\", description: \"ACTIVE | PAUSED\" },\n ...BUDGET_ARGS,\n \"budget-optimization\": { type: \"string\", description: \"CAMPAIGN | LINE_ITEM\" },\n },\n run: async ({ args }) => {\n const accountId = await stageAccountId(args);\n await stageXOp({\n kind: \"campaign.update\",\n accountId,\n target: requireTarget(args, \"id\"),\n payload: compact({\n name: args.name,\n entityStatus: args.status,\n budgetOptimization: args[\"budget-optimization\"],\n dailyBudgetAmountLocalMicro: microsFromArg(args[\"daily-budget\"], \"--daily-budget\"),\n totalBudgetAmountLocalMicro: microsFromArg(args[\"total-budget\"], \"--total-budget\"),\n }),\n });\n },\n});\n\nfunction statusCommand(name: \"pause\" | \"resume\", status: \"PAUSED\" | \"ACTIVE\") {\n registerSchema({\n command: `ads.x.campaigns.${name}`,\n description: `Stage ${name === \"pause\" ? \"a pause\" : \"a resume\"} for one or more X campaigns. Pass every id in one call.`,\n args: {\n ids: { type: \"string\", description: \"Campaign ids, comma-separated\", required: true },\n \"account-id\": { type: \"string\", description: \"X Ads account ID\", required: false },\n },\n });\n return defineCommand({\n meta: {\n name,\n description: `Stage ${name === \"pause\" ? \"pausing\" : \"resuming\"} campaigns.\n\nExample:\n baker ads x campaigns ${name} oilf0,omyq3`,\n },\n args: {\n ids: { type: \"positional\", description: \"Campaign ids, comma-separated\", required: true },\n \"account-id\": { type: \"string\", description: \"X Ads account ID\" },\n },\n run: async ({ args }) => {\n const accountId = await stageAccountId(args);\n await stageXOps(\n requireTargets(args, \"ids\").map((id) => ({\n kind: \"campaign.update\",\n accountId,\n target: id,\n payload: { entityStatus: status },\n })),\n );\n },\n });\n}\n\nexport const campaignsPauseCommand = statusCommand(\"pause\", \"PAUSED\");\nexport const campaignsResumeCommand = statusCommand(\"resume\", \"ACTIVE\");\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/commands/ads/x/campaign-writes.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\nimport { registerSchema } from \"../../../schemas.ts\";\nimport {\n compact,\n microsFromArg,\n requireTarget,\n requireTargets,\n stageAccountId,\n stageXOp,\n stageXOps,\n} from \"./write-shared.ts\";\n\n/**\n * Staged campaign writes. Nothing here calls X: each command appends an op to\n * this chat's draft, which applies when the chat publishes.\n */\n\nconst BUDGET_ARGS = {\n \"daily-budget\": { type: \"string\", description: \"Daily budget in account currency, e.g. 12.50\" },\n \"total-budget\": { type: \"string\", description: \"Lifetime budget in account currency — must exceed the daily budget\" },\n} as const;\n\nregisterSchema({\n command: \"ads.x.campaigns.create\",\n description:\n \"Stage a new X campaign on this chat's draft. Needs a funding instrument (`baker ads x funding`). Defaults to PAUSED — an ACTIVE campaign starts spending the moment the chat publishes.\",\n args: {\n \"account-id\": { type: \"string\", description: \"X Ads account ID\", required: false },\n name: { type: \"string\", description: \"Campaign name\", required: true },\n \"funding-instrument-id\": { type: \"string\", description: \"From `baker ads x funding`\", required: true },\n status: { type: \"string\", description: \"ACTIVE | PAUSED | DRAFT (default PAUSED)\", required: false },\n \"daily-budget\": { type: \"string\", description: \"Daily budget in account currency\", required: false },\n \"total-budget\": { type: \"string\", description: \"Lifetime budget in account currency\", required: false },\n \"budget-optimization\": { type: \"string\", description: \"CAMPAIGN | LINE_ITEM\", required: false },\n },\n});\n\nexport const campaignsCreateCommand = defineCommand({\n meta: {\n name: \"create\",\n description: `Stage a new campaign (applies when the chat is published).\n\nExamples:\n baker ads x campaigns create --name \"zz-baker-harness\" --funding-instrument-id vtbot --daily-budget 5`,\n },\n args: {\n \"account-id\": { type: \"string\", description: \"X Ads account ID\" },\n name: { type: \"string\", description: \"Campaign name\", required: true },\n \"funding-instrument-id\": { type: \"string\", description: \"Funding instrument id\", required: true },\n status: { type: \"string\", description: \"ACTIVE | PAUSED | DRAFT (default PAUSED)\" },\n ...BUDGET_ARGS,\n \"budget-optimization\": { type: \"string\", description: \"CAMPAIGN | LINE_ITEM\" },\n },\n run: async ({ args }) => {\n const accountId = await stageAccountId(args);\n await stageXOp({\n kind: \"campaign.create\",\n accountId,\n payload: compact({\n name: args.name,\n fundingInstrumentId: args[\"funding-instrument-id\"],\n entityStatus: args.status,\n budgetOptimization: args[\"budget-optimization\"],\n dailyBudgetAmountLocalMicro: microsFromArg(args[\"daily-budget\"], \"--daily-budget\"),\n totalBudgetAmountLocalMicro: microsFromArg(args[\"total-budget\"], \"--total-budget\"),\n }),\n });\n },\n});\n\nregisterSchema({\n command: \"ads.x.campaigns.update\",\n description:\n \"Stage a change to an existing X campaign. Staging the same campaign twice amends the staged change in place rather than queueing two writes.\",\n args: {\n id: { type: \"string\", description: \"Campaign id\", required: true },\n \"account-id\": { type: \"string\", description: \"X Ads account ID\", required: false },\n name: { type: \"string\", description: \"New name\", required: false },\n status: { type: \"string\", description: \"ACTIVE | PAUSED\", required: false },\n \"daily-budget\": { type: \"string\", description: \"Daily budget in account currency\", required: false },\n \"total-budget\": { type: \"string\", description: \"Lifetime budget in account currency\", required: false },\n \"budget-optimization\": { type: \"string\", description: \"CAMPAIGN | LINE_ITEM\", required: false },\n },\n});\n\nexport const campaignsUpdateCommand = defineCommand({\n meta: {\n name: \"update\",\n description: `Stage a change to a campaign.\n\nExamples:\n baker ads x campaigns update oilf0 --daily-budget 20\n baker ads x campaigns update oilf0 --name \"Spring push\"`,\n },\n args: {\n id: { type: \"positional\", description: \"Campaign id\", required: true },\n \"account-id\": { type: \"string\", description: \"X Ads account ID\" },\n name: { type: \"string\", description: \"New name\" },\n status: { type: \"string\", description: \"ACTIVE | PAUSED\" },\n ...BUDGET_ARGS,\n \"budget-optimization\": { type: \"string\", description: \"CAMPAIGN | LINE_ITEM\" },\n },\n run: async ({ args }) => {\n const accountId = await stageAccountId(args);\n await stageXOp({\n kind: \"campaign.update\",\n accountId,\n target: requireTarget(args, \"id\"),\n payload: compact({\n name: args.name,\n entityStatus: args.status,\n budgetOptimization: args[\"budget-optimization\"],\n dailyBudgetAmountLocalMicro: microsFromArg(args[\"daily-budget\"], \"--daily-budget\"),\n totalBudgetAmountLocalMicro: microsFromArg(args[\"total-budget\"], \"--total-budget\"),\n }),\n });\n },\n});\n\nfunction statusCommand(name: \"pause\" | \"resume\", status: \"PAUSED\" | \"ACTIVE\") {\n registerSchema({\n command: `ads.x.campaigns.${name}`,\n description: `Stage ${name === \"pause\" ? \"a pause\" : \"a resume\"} for one or more X campaigns. Pass every id in one call.`,\n args: {\n ids: { type: \"string\", description: \"Campaign ids, comma-separated\", required: true },\n \"account-id\": { type: \"string\", description: \"X Ads account ID\", required: false },\n },\n });\n return defineCommand({\n meta: {\n name,\n description: `Stage ${name === \"pause\" ? \"pausing\" : \"resuming\"} campaigns.\n\nExample:\n baker ads x campaigns ${name} oilf0,omyq3`,\n },\n args: {\n ids: { type: \"positional\", description: \"Campaign ids, comma-separated\", required: true },\n \"account-id\": { type: \"string\", description: \"X Ads account ID\" },\n },\n run: async ({ args }) => {\n const accountId = await stageAccountId(args);\n await stageXOps(\n requireTargets(args, \"ids\").map((id) => ({\n kind: \"campaign.update\",\n accountId,\n target: id,\n payload: { entityStatus: status },\n })),\n );\n },\n });\n}\n\nexport const campaignsPauseCommand = statusCommand(\"pause\", \"PAUSED\");\nexport const campaignsResumeCommand = statusCommand(\"resume\", \"ACTIVE\");\n"],"mappings":"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","names":[]}
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
resolveAccountIdArg,
|
|
5
5
|
resolveStatusFilter,
|
|
6
6
|
statusesArgDescription
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-N4LAYIIN.js";
|
|
8
8
|
import {
|
|
9
9
|
writeAdsJson,
|
|
10
10
|
writeAdsOutput
|
|
@@ -12,10 +12,11 @@ import {
|
|
|
12
12
|
import {
|
|
13
13
|
NO_CACHE_ARG
|
|
14
14
|
} from "./chunk-X7ZODEXJ.js";
|
|
15
|
-
import "./chunk-
|
|
15
|
+
import "./chunk-7EPXVICM.js";
|
|
16
16
|
import "./chunk-GXDLWBOY.js";
|
|
17
17
|
import "./chunk-TEINLN64.js";
|
|
18
18
|
import "./chunk-ZJWUBJYQ.js";
|
|
19
|
+
import "./chunk-HR6IWNKE.js";
|
|
19
20
|
import "./chunk-NE4F3FHN.js";
|
|
20
21
|
import {
|
|
21
22
|
apiGet
|
|
@@ -88,14 +89,14 @@ Examples:
|
|
|
88
89
|
},
|
|
89
90
|
subCommands: {
|
|
90
91
|
list: campaignsListCommand,
|
|
91
|
-
create: () => import("./write-commands-
|
|
92
|
-
update: () => import("./write-commands-
|
|
93
|
-
pause: () => import("./write-commands-
|
|
94
|
-
resume: () => import("./write-commands-
|
|
95
|
-
archive: () => import("./write-commands-
|
|
96
|
-
duplicate: () => import("./write-commands-
|
|
97
|
-
"url-params": () => import("./write-commands-
|
|
98
|
-
"exclude-companies": () => import("./write-commands-
|
|
92
|
+
create: () => import("./write-commands-7SJ3BOW5.js").then((m) => m.campaignsCreateCommand),
|
|
93
|
+
update: () => import("./write-commands-7SJ3BOW5.js").then((m) => m.campaignsUpdateCommand),
|
|
94
|
+
pause: () => import("./write-commands-7SJ3BOW5.js").then((m) => m.campaignsPauseCommand),
|
|
95
|
+
resume: () => import("./write-commands-7SJ3BOW5.js").then((m) => m.campaignsResumeCommand),
|
|
96
|
+
archive: () => import("./write-commands-7SJ3BOW5.js").then((m) => m.campaignsArchiveCommand),
|
|
97
|
+
duplicate: () => import("./write-commands-7SJ3BOW5.js").then((m) => m.campaignsDuplicateCommand),
|
|
98
|
+
"url-params": () => import("./write-commands-7SJ3BOW5.js").then((m) => m.campaignsUrlParamsCommand),
|
|
99
|
+
"exclude-companies": () => import("./write-commands-7SJ3BOW5.js").then((m) => m.campaignsExcludeCompaniesCommand)
|
|
99
100
|
},
|
|
100
101
|
// A parent must never declare `run`: citty falls through to it *after* running
|
|
101
102
|
// the matched subcommand, so every write would also trigger a full live list.
|
|
@@ -106,4 +107,4 @@ Examples:
|
|
|
106
107
|
export {
|
|
107
108
|
campaignsCommand
|
|
108
109
|
};
|
|
109
|
-
//# sourceMappingURL=campaigns-
|
|
110
|
+
//# sourceMappingURL=campaigns-6T3NSUT2.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/ads/linkedin/campaigns.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\nimport { NO_CACHE_ARG } from \"../../../cache-flag.ts\";\nimport { apiGet } from \"../../../client.ts\";\nimport { writeAdsJson, writeAdsOutput } from \"../output.ts\";\nimport {\n csvOrJson,\n handleLinkedinError,\n resolveAccountIdArg,\n resolveStatusFilter,\n statusesArgDescription,\n} from \"./shared.ts\";\n\ninterface LinkedinCampaignRow {\n id: string;\n urn: string;\n account: string;\n campaignGroup?: string;\n name?: string;\n type?: string;\n status?: string;\n servingStatuses?: string[];\n costType?: string;\n objectiveType?: string;\n optimizationTargetType?: string;\n unitCost?: { amount?: string; currencyCode?: string };\n dailyBudget?: { amount?: string; currencyCode?: string };\n totalBudget?: { amount?: string; currencyCode?: string };\n runSchedule?: { start?: number; end?: number };\n audienceExpansionEnabled?: boolean;\n offsiteDeliveryEnabled?: boolean;\n format?: string;\n test?: boolean;\n}\n\nconst listArgs = {\n \"account-id\": { type: \"string\", description: \"Numeric account ID or urn:li:sponsoredAccount:N\" },\n \"account-urn\": { type: \"string\", description: \"Alias for --account-id\" },\n \"campaign-group-id\": { type: \"string\", description: \"Filter by campaign group\" },\n \"all-statuses\": { type: \"boolean\", description: \"Drop the default ACTIVE filter\" },\n statuses: { type: \"string\", description: statusesArgDescription(\"campaigns\") },\n limit: { type: \"string\", description: \"Max rows (default: 500)\" },\n \"no-cache\": NO_CACHE_ARG,\n output: { type: \"string\", description: \"json|csv|jsonl|md\", default: \"json\" },\n} as const;\n\nconst campaignsListCommand = defineCommand({\n meta: {\n name: \"list\",\n description: \"List LinkedIn campaigns. Runs by default when no subcommand is given.\",\n },\n args: listArgs,\n run: async ({ args }) => {\n const accountId = resolveAccountIdArg(args);\n try {\n const params: Record<string, string> = { \"account-id\": accountId };\n const statuses = resolveStatusFilter(args, \"campaigns\");\n if (statuses) params.statuses = statuses.join(\",\");\n if (args[\"campaign-group-id\"]) params[\"campaign-group-id\"] = String(args[\"campaign-group-id\"]);\n if (args.limit) params.limit = String(args.limit);\n if (args[\"no-cache\"]) params[\"skip-cache\"] = \"true\";\n\n const data = await apiGet<LinkedinCampaignRow[]>(\"/api/ads/linkedin/campaigns\", params);\n const fmt = csvOrJson(args);\n if (fmt !== \"json\") {\n writeAdsOutput(data as unknown as Array<Record<string, unknown>>, fmt);\n return;\n }\n writeAdsJson({ ok: true, data });\n } catch (err) {\n handleLinkedinError(err);\n }\n },\n});\n\nexport const campaignsCommand = defineCommand({\n meta: {\n name: \"campaigns\",\n description: `List LinkedIn campaigns, or stage writes (create/update/pause/resume/archive/duplicate).\n\nDefault: ACTIVE only. The schema includes the audit-relevant settings:\n audienceExpansionEnabled — playbook §02 silent budget drain (should be false)\n offsiteDeliveryEnabled — LinkedIn Audience Network gate\n optimizationTargetType — driver of the bidding strategy\n costType — CPC | CPM | CPV | CPS\n\nWrite subcommands stage ops on this chat's draft — they never hit the LinkedIn\nAPI directly and apply only when the chat is published.\n\nExamples:\n baker ads linkedin campaigns --account-id 503001492\n baker ads linkedin campaigns --account-id 503001492 --all-statuses --output csv\n baker ads linkedin campaigns update 123456 --daily-budget 100 --currency EUR\n baker ads linkedin campaigns pause 123456\n baker ads linkedin campaigns url-params 123456 --param utm_source=linkedin — UTMs for every ad in the ad set\n baker ads linkedin campaigns exclude-companies 123456 --org 1035,1441 — stop reaching these companies`,\n },\n subCommands: {\n list: campaignsListCommand,\n create: () => import(\"./write-commands.ts\").then((m) => m.campaignsCreateCommand),\n update: () => import(\"./write-commands.ts\").then((m) => m.campaignsUpdateCommand),\n pause: () => import(\"./write-commands.ts\").then((m) => m.campaignsPauseCommand),\n resume: () => import(\"./write-commands.ts\").then((m) => m.campaignsResumeCommand),\n archive: () => import(\"./write-commands.ts\").then((m) => m.campaignsArchiveCommand),\n duplicate: () => import(\"./write-commands.ts\").then((m) => m.campaignsDuplicateCommand),\n \"url-params\": () => import(\"./write-commands.ts\").then((m) => m.campaignsUrlParamsCommand),\n \"exclude-companies\": () => import(\"./write-commands.ts\").then((m) => m.campaignsExcludeCompaniesCommand),\n },\n // A parent must never declare `run`: citty falls through to it *after* running\n // the matched subcommand, so every write would also trigger a full live list.\n // `args` stays here so citty's subcommand scan knows which flags take a value.\n args: listArgs,\n default: \"list\",\n});\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/commands/ads/linkedin/campaigns.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\nimport { NO_CACHE_ARG } from \"../../../cache-flag.ts\";\nimport { apiGet } from \"../../../client.ts\";\nimport { writeAdsJson, writeAdsOutput } from \"../output.ts\";\nimport {\n csvOrJson,\n handleLinkedinError,\n resolveAccountIdArg,\n resolveStatusFilter,\n statusesArgDescription,\n} from \"./shared.ts\";\n\ninterface LinkedinCampaignRow {\n id: string;\n urn: string;\n account: string;\n campaignGroup?: string;\n name?: string;\n type?: string;\n status?: string;\n servingStatuses?: string[];\n costType?: string;\n objectiveType?: string;\n optimizationTargetType?: string;\n unitCost?: { amount?: string; currencyCode?: string };\n dailyBudget?: { amount?: string; currencyCode?: string };\n totalBudget?: { amount?: string; currencyCode?: string };\n runSchedule?: { start?: number; end?: number };\n audienceExpansionEnabled?: boolean;\n offsiteDeliveryEnabled?: boolean;\n format?: string;\n test?: boolean;\n}\n\nconst listArgs = {\n \"account-id\": { type: \"string\", description: \"Numeric account ID or urn:li:sponsoredAccount:N\" },\n \"account-urn\": { type: \"string\", description: \"Alias for --account-id\" },\n \"campaign-group-id\": { type: \"string\", description: \"Filter by campaign group\" },\n \"all-statuses\": { type: \"boolean\", description: \"Drop the default ACTIVE filter\" },\n statuses: { type: \"string\", description: statusesArgDescription(\"campaigns\") },\n limit: { type: \"string\", description: \"Max rows (default: 500)\" },\n \"no-cache\": NO_CACHE_ARG,\n output: { type: \"string\", description: \"json|csv|jsonl|md\", default: \"json\" },\n} as const;\n\nconst campaignsListCommand = defineCommand({\n meta: {\n name: \"list\",\n description: \"List LinkedIn campaigns. Runs by default when no subcommand is given.\",\n },\n args: listArgs,\n run: async ({ args }) => {\n const accountId = resolveAccountIdArg(args);\n try {\n const params: Record<string, string> = { \"account-id\": accountId };\n const statuses = resolveStatusFilter(args, \"campaigns\");\n if (statuses) params.statuses = statuses.join(\",\");\n if (args[\"campaign-group-id\"]) params[\"campaign-group-id\"] = String(args[\"campaign-group-id\"]);\n if (args.limit) params.limit = String(args.limit);\n if (args[\"no-cache\"]) params[\"skip-cache\"] = \"true\";\n\n const data = await apiGet<LinkedinCampaignRow[]>(\"/api/ads/linkedin/campaigns\", params);\n const fmt = csvOrJson(args);\n if (fmt !== \"json\") {\n writeAdsOutput(data as unknown as Array<Record<string, unknown>>, fmt);\n return;\n }\n writeAdsJson({ ok: true, data });\n } catch (err) {\n handleLinkedinError(err);\n }\n },\n});\n\nexport const campaignsCommand = defineCommand({\n meta: {\n name: \"campaigns\",\n description: `List LinkedIn campaigns, or stage writes (create/update/pause/resume/archive/duplicate).\n\nDefault: ACTIVE only. The schema includes the audit-relevant settings:\n audienceExpansionEnabled — playbook §02 silent budget drain (should be false)\n offsiteDeliveryEnabled — LinkedIn Audience Network gate\n optimizationTargetType — driver of the bidding strategy\n costType — CPC | CPM | CPV | CPS\n\nWrite subcommands stage ops on this chat's draft — they never hit the LinkedIn\nAPI directly and apply only when the chat is published.\n\nExamples:\n baker ads linkedin campaigns --account-id 503001492\n baker ads linkedin campaigns --account-id 503001492 --all-statuses --output csv\n baker ads linkedin campaigns update 123456 --daily-budget 100 --currency EUR\n baker ads linkedin campaigns pause 123456\n baker ads linkedin campaigns url-params 123456 --param utm_source=linkedin — UTMs for every ad in the ad set\n baker ads linkedin campaigns exclude-companies 123456 --org 1035,1441 — stop reaching these companies`,\n },\n subCommands: {\n list: campaignsListCommand,\n create: () => import(\"./write-commands.ts\").then((m) => m.campaignsCreateCommand),\n update: () => import(\"./write-commands.ts\").then((m) => m.campaignsUpdateCommand),\n pause: () => import(\"./write-commands.ts\").then((m) => m.campaignsPauseCommand),\n resume: () => import(\"./write-commands.ts\").then((m) => m.campaignsResumeCommand),\n archive: () => import(\"./write-commands.ts\").then((m) => m.campaignsArchiveCommand),\n duplicate: () => import(\"./write-commands.ts\").then((m) => m.campaignsDuplicateCommand),\n \"url-params\": () => import(\"./write-commands.ts\").then((m) => m.campaignsUrlParamsCommand),\n \"exclude-companies\": () => import(\"./write-commands.ts\").then((m) => m.campaignsExcludeCompaniesCommand),\n },\n // A parent must never declare `run`: citty falls through to it *after* running\n // the matched subcommand, so every write would also trigger a full live list.\n // `args` stays here so citty's subcommand scan knows which flags take a value.\n args: listArgs,\n default: \"list\",\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,qBAAqB;AAkC9B,IAAM,WAAW;AAAA,EACf,cAAc,EAAE,MAAM,UAAU,aAAa,kDAAkD;AAAA,EAC/F,eAAe,EAAE,MAAM,UAAU,aAAa,yBAAyB;AAAA,EACvE,qBAAqB,EAAE,MAAM,UAAU,aAAa,2BAA2B;AAAA,EAC/E,gBAAgB,EAAE,MAAM,WAAW,aAAa,iCAAiC;AAAA,EACjF,UAAU,EAAE,MAAM,UAAU,aAAa,uBAAuB,WAAW,EAAE;AAAA,EAC7E,OAAO,EAAE,MAAM,UAAU,aAAa,0BAA0B;AAAA,EAChE,YAAY;AAAA,EACZ,QAAQ,EAAE,MAAM,UAAU,aAAa,qBAAqB,SAAS,OAAO;AAC9E;AAEA,IAAM,uBAAuB,cAAc;AAAA,EACzC,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AAAA,EACA,MAAM;AAAA,EACN,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,UAAM,YAAY,oBAAoB,IAAI;AAC1C,QAAI;AACF,YAAM,SAAiC,EAAE,cAAc,UAAU;AACjE,YAAM,WAAW,oBAAoB,MAAM,WAAW;AACtD,UAAI,SAAU,QAAO,WAAW,SAAS,KAAK,GAAG;AACjD,UAAI,KAAK,mBAAmB,EAAG,QAAO,mBAAmB,IAAI,OAAO,KAAK,mBAAmB,CAAC;AAC7F,UAAI,KAAK,MAAO,QAAO,QAAQ,OAAO,KAAK,KAAK;AAChD,UAAI,KAAK,UAAU,EAAG,QAAO,YAAY,IAAI;AAE7C,YAAM,OAAO,MAAM,OAA8B,+BAA+B,MAAM;AACtF,YAAM,MAAM,UAAU,IAAI;AAC1B,UAAI,QAAQ,QAAQ;AAClB,uBAAe,MAAmD,GAAG;AACrE;AAAA,MACF;AACA,mBAAa,EAAE,IAAI,MAAM,KAAK,CAAC;AAAA,IACjC,SAAS,KAAK;AACZ,0BAAoB,GAAG;AAAA,IACzB;AAAA,EACF;AACF,CAAC;AAEM,IAAM,mBAAmB,cAAc;AAAA,EAC5C,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBf;AAAA,EACA,aAAa;AAAA,IACX,MAAM;AAAA,IACN,QAAQ,MAAM,OAAO,8BAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,sBAAsB;AAAA,IAChF,QAAQ,MAAM,OAAO,8BAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,sBAAsB;AAAA,IAChF,OAAO,MAAM,OAAO,8BAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,qBAAqB;AAAA,IAC9E,QAAQ,MAAM,OAAO,8BAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,sBAAsB;AAAA,IAChF,SAAS,MAAM,OAAO,8BAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,uBAAuB;AAAA,IAClF,WAAW,MAAM,OAAO,8BAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,yBAAyB;AAAA,IACtF,cAAc,MAAM,OAAO,8BAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,yBAAyB;AAAA,IACzF,qBAAqB,MAAM,OAAO,8BAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,gCAAgC;AAAA,EACzG;AAAA;AAAA;AAAA;AAAA,EAIA,MAAM;AAAA,EACN,SAAS;AACX,CAAC;","names":[]}
|
|
@@ -91,10 +91,10 @@ Examples:
|
|
|
91
91
|
},
|
|
92
92
|
subCommands: {
|
|
93
93
|
list: campaignsListCommand,
|
|
94
|
-
create: () => import("./campaign-writes-
|
|
95
|
-
update: () => import("./campaign-writes-
|
|
96
|
-
pause: () => import("./campaign-writes-
|
|
97
|
-
resume: () => import("./campaign-writes-
|
|
94
|
+
create: () => import("./campaign-writes-5OVLUD5E.js").then((m) => m.campaignsCreateCommand),
|
|
95
|
+
update: () => import("./campaign-writes-5OVLUD5E.js").then((m) => m.campaignsUpdateCommand),
|
|
96
|
+
pause: () => import("./campaign-writes-5OVLUD5E.js").then((m) => m.campaignsPauseCommand),
|
|
97
|
+
resume: () => import("./campaign-writes-5OVLUD5E.js").then((m) => m.campaignsResumeCommand)
|
|
98
98
|
},
|
|
99
99
|
// A parent must never declare `run`: citty falls through to it AFTER the
|
|
100
100
|
// matched subcommand, so every write would also trigger a full live list.
|
|
@@ -104,4 +104,4 @@ Examples:
|
|
|
104
104
|
export {
|
|
105
105
|
campaignsCommand
|
|
106
106
|
};
|
|
107
|
-
//# sourceMappingURL=campaigns-
|
|
107
|
+
//# sourceMappingURL=campaigns-OYMXDGWX.js.map
|
|
@@ -25,22 +25,22 @@ Subcommands:
|
|
|
25
25
|
Full guide: __tooling__/docs/tools/baker/canvas.md`
|
|
26
26
|
},
|
|
27
27
|
subCommands: {
|
|
28
|
-
run: () => import("./run-
|
|
29
|
-
rerun: () => import("./rerun-
|
|
30
|
-
validate: () => import("./validate-
|
|
31
|
-
critique: () => import("./critique-
|
|
28
|
+
run: () => import("./run-EUO34T2J.js").then((m) => m.runCommand),
|
|
29
|
+
rerun: () => import("./rerun-PZK275DY.js").then((m) => m.rerunCommand),
|
|
30
|
+
validate: () => import("./validate-7YPOUKPB.js").then((m) => m.validateCommand),
|
|
31
|
+
critique: () => import("./critique-GS5VV5ZC.js").then((m) => m.critiqueCommand),
|
|
32
32
|
"viewer-check": () => import("./viewer-check-L4B4LIAX.js").then((m) => m.viewerCheckCommand),
|
|
33
|
-
catalog: () => import("./catalog-
|
|
34
|
-
inspect: () => import("./inspect-
|
|
35
|
-
"scaffold-ad": () => import("./scaffold-ad-
|
|
36
|
-
"scaffold-video": () => import("./scaffold-video-
|
|
37
|
-
"scaffold-static-ad": () => import("./scaffold-static-ad-
|
|
38
|
-
"set-prompt": () => import("./set-prompt-
|
|
39
|
-
"sync-definition": () => import("./sync-definition-
|
|
40
|
-
stale: () => import("./stale-
|
|
33
|
+
catalog: () => import("./catalog-XLXIM7IW.js").then((m) => m.catalogCommand),
|
|
34
|
+
inspect: () => import("./inspect-4OOS4APT.js").then((m) => m.inspectCommand),
|
|
35
|
+
"scaffold-ad": () => import("./scaffold-ad-SW2HEWM3.js").then((m) => m.scaffoldAdCommand),
|
|
36
|
+
"scaffold-video": () => import("./scaffold-video-EI7U7RBK.js").then((m) => m.scaffoldVideoCommand),
|
|
37
|
+
"scaffold-static-ad": () => import("./scaffold-static-ad-ECTJL54Y.js").then((m) => m.scaffoldStaticAdCommand),
|
|
38
|
+
"set-prompt": () => import("./set-prompt-2HASHGWC.js").then((m) => m.setPromptCommand),
|
|
39
|
+
"sync-definition": () => import("./sync-definition-QR2N233R.js").then((m) => m.syncDefinitionCommand),
|
|
40
|
+
stale: () => import("./stale-W756ACKC.js").then((m) => m.staleCommand)
|
|
41
41
|
}
|
|
42
42
|
});
|
|
43
43
|
export {
|
|
44
44
|
canvasCommand
|
|
45
45
|
};
|
|
46
|
-
//# sourceMappingURL=canvas-
|
|
46
|
+
//# sourceMappingURL=canvas-YQFG52IG.js.map
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
failApi
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-SJYEY5MV.js";
|
|
4
|
+
import "./chunk-7EPXVICM.js";
|
|
5
5
|
import "./chunk-GXDLWBOY.js";
|
|
6
6
|
import "./chunk-TEINLN64.js";
|
|
7
7
|
import {
|
|
8
8
|
CAPABILITY_SURFACES
|
|
9
9
|
} from "./chunk-ZJWUBJYQ.js";
|
|
10
|
+
import "./chunk-HR6IWNKE.js";
|
|
10
11
|
import "./chunk-NE4F3FHN.js";
|
|
11
12
|
import {
|
|
12
13
|
apiPost
|
|
@@ -141,4 +142,4 @@ export {
|
|
|
141
142
|
capabilitiesCommand,
|
|
142
143
|
capabilityHints
|
|
143
144
|
};
|
|
144
|
-
//# sourceMappingURL=capabilities-
|
|
145
|
+
//# sourceMappingURL=capabilities-PXBKUN2G.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/capabilities/index.ts"],"sourcesContent":["import {\n CAPABILITY_SURFACES,\n type CapabilitiesResponse,\n type CapabilitySurfaceReport,\n type CapabilityTool,\n} from \"@baker/api/capabilities\";\nimport { defineCommand } from \"citty\";\nimport { apiPost } from \"../../client.ts\";\nimport { getEnv } from \"../../env.ts\";\nimport { writeJson } from \"../../output.ts\";\nimport { registerSchema } from \"../../schemas.ts\";\nimport { failApi } from \"../actions/shared.ts\";\n\nregisterSchema({\n command: \"capabilities\",\n description:\n \"Start here, before promising the user anything on an ad platform, in Analytics, or in Tag Manager. Answers three questions in one call: what is connected and with what access, what a write on each surface actually does when it lands, and what CANNOT be done here and why. Run it with no arguments for every surface; name one surface to also get the exact fields every change on it accepts.\",\n args: {\n surface: {\n type: \"positional\",\n description: `One of: ${CAPABILITY_SURFACES.join(\" | \")}. Omit for all of them.`,\n required: false,\n },\n full: {\n type: \"boolean\",\n description: \"Include the field-level contract of every change on every surface\",\n required: false,\n default: false,\n },\n },\n});\n\n/**\n * What the agent must not miss even if it skims the payload.\n *\n * Every line here comes from a real session that went wrong: a Tag Manager\n * change described as a draft when it was about to go live, work promised on a\n * read-only surface, an ad change called a preview after it had already spent.\n */\nexport function capabilityHints(surfaces: CapabilitySurfaceReport[], tools: CapabilityTool[] = []): string[] {\n const hints: string[] = [];\n\n const immediate = surfaces.filter((surface) => surface.writeMode === \"applies-at-publish\");\n if (immediate.length > 0) {\n hints.push(\n `REAL AND IMMEDIATE: ${immediate.map((s) => s.label).join(\", \")}. Completing this chat changes the user's live setup, so agree the changes before you finish, not after.`,\n );\n }\n\n const blocked = surfaces.filter((surface) => surface.blockers.length > 0);\n if (blocked.length > 0) {\n hints.push(`BLOCKED: ${blocked.flatMap((surface) => surface.blockers).join(\" \")}`);\n }\n\n const limitCount = surfaces.reduce((total, surface) => total + surface.limits.length, 0);\n if (limitCount > 0) {\n hints.push(\n `${limitCount} thing(s) listed under \\`limits\\` cannot be done at all. Read them before you plan the work — each one says what to tell the user instead. Do not try them and report the failure as a surprise.`,\n );\n }\n\n if (surfaces.length > 1) {\n hints.push(\n \"Naming one surface (`baker capabilities google-ads`) adds `ops` — the exact fields and accepted values of every change there. Read that instead of guessing a field name.\",\n );\n }\n\n // The whole reason `tools` exists. An agent that read only `surfaces` used to\n // conclude a company had no session-recording tool while Microsoft Clarity\n // sat in its own tool list — and that is the source most likely to change\n // what it decides about a page.\n const usable = tools.filter((tool) => tool.ready);\n if (usable.length > 0) {\n hints.push(\n `ALSO AVAILABLE, and not on any surface above: ${usable.map((tool) => tool.label).join(\", \")}. These answer WHY a page behaves as it does, which no surface here can. See \\`tools[].reach\\` for how to call each one.`,\n );\n }\n\n const broken = tools.filter((tool) => !tool.ready);\n if (broken.length > 0) {\n hints.push(\n `CONNECTED BUT UNUSABLE: ${broken.map((tool) => `${tool.label} — ${tool.note ?? \"not reachable\"}`).join(\" \")} Tell the user rather than planning around it silently.`,\n );\n }\n\n return hints;\n}\n\nconst runCapabilities = defineCommand({\n meta: {\n name: \"capabilities\",\n description: `What Baker can and cannot do for this company, before any work starts.\n\nReports, per surface: what is connected and with what access, what a write there does when it lands, the entities that can be changed, and — the part nothing else tells you — what cannot be changed and why.\n\nAlso returns \\`tools\\`: everything else this company can reach that is not one of those surfaces — Microsoft Clarity and any other MCP toolkit, custom servers, HubSpot. This is the one call that answers \"what do I actually have\".\n\nExamples:\n baker capabilities\n baker capabilities google-ads\n baker capabilities tag-manager\n baker capabilities --full\n\nFull guide: __tooling__/docs/tools/baker/capabilities.md`,\n },\n args: {\n surface: {\n type: \"positional\",\n description: `Narrow to one surface: ${CAPABILITY_SURFACES.join(\" | \")}`,\n required: false,\n },\n full: {\n type: \"boolean\",\n description: \"Include the field-level contract of every change on every surface\",\n required: false,\n default: false,\n },\n },\n run: async ({ args }) => {\n try {\n const body: Record<string, unknown> = {};\n const surface = args.surface as string | undefined;\n if (surface) {\n if (!(CAPABILITY_SURFACES as readonly string[]).includes(surface)) {\n throw new Error(`\"${surface}\" is not a surface. Use one of: ${CAPABILITY_SURFACES.join(\", \")}`);\n }\n body.surface = surface;\n }\n if (args.full) {\n body.full = true;\n }\n // Who this chat acts as: their own connected tools load with it — a\n // personal inbox in a scheduled run of theirs — and are listed with it.\n const actingUserId = getEnv().BAKER_ACTING_USER_ID;\n if (actingUserId) {\n body.actingUserId = actingUserId;\n }\n const response = await apiPost<CapabilitiesResponse>(\"/api/capabilities\", body);\n const hints = capabilityHints(response.data.surfaces, response.data.tools);\n writeJson({\n ...response,\n meta: { count: response.data.surfaces.length },\n ...(hints.length > 0 ? { hints } : {}),\n });\n } catch (err) {\n failApi(err);\n }\n },\n});\n\nexport const capabilitiesCommand = runCapabilities;\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/commands/capabilities/index.ts"],"sourcesContent":["import {\n CAPABILITY_SURFACES,\n type CapabilitiesResponse,\n type CapabilitySurfaceReport,\n type CapabilityTool,\n} from \"@baker/api/capabilities\";\nimport { defineCommand } from \"citty\";\nimport { apiPost } from \"../../client.ts\";\nimport { getEnv } from \"../../env.ts\";\nimport { writeJson } from \"../../output.ts\";\nimport { registerSchema } from \"../../schemas.ts\";\nimport { failApi } from \"../actions/shared.ts\";\n\nregisterSchema({\n command: \"capabilities\",\n description:\n \"Start here, before promising the user anything on an ad platform, in Analytics, or in Tag Manager. Answers three questions in one call: what is connected and with what access, what a write on each surface actually does when it lands, and what CANNOT be done here and why. Run it with no arguments for every surface; name one surface to also get the exact fields every change on it accepts.\",\n args: {\n surface: {\n type: \"positional\",\n description: `One of: ${CAPABILITY_SURFACES.join(\" | \")}. Omit for all of them.`,\n required: false,\n },\n full: {\n type: \"boolean\",\n description: \"Include the field-level contract of every change on every surface\",\n required: false,\n default: false,\n },\n },\n});\n\n/**\n * What the agent must not miss even if it skims the payload.\n *\n * Every line here comes from a real session that went wrong: a Tag Manager\n * change described as a draft when it was about to go live, work promised on a\n * read-only surface, an ad change called a preview after it had already spent.\n */\nexport function capabilityHints(surfaces: CapabilitySurfaceReport[], tools: CapabilityTool[] = []): string[] {\n const hints: string[] = [];\n\n const immediate = surfaces.filter((surface) => surface.writeMode === \"applies-at-publish\");\n if (immediate.length > 0) {\n hints.push(\n `REAL AND IMMEDIATE: ${immediate.map((s) => s.label).join(\", \")}. Completing this chat changes the user's live setup, so agree the changes before you finish, not after.`,\n );\n }\n\n const blocked = surfaces.filter((surface) => surface.blockers.length > 0);\n if (blocked.length > 0) {\n hints.push(`BLOCKED: ${blocked.flatMap((surface) => surface.blockers).join(\" \")}`);\n }\n\n const limitCount = surfaces.reduce((total, surface) => total + surface.limits.length, 0);\n if (limitCount > 0) {\n hints.push(\n `${limitCount} thing(s) listed under \\`limits\\` cannot be done at all. Read them before you plan the work — each one says what to tell the user instead. Do not try them and report the failure as a surprise.`,\n );\n }\n\n if (surfaces.length > 1) {\n hints.push(\n \"Naming one surface (`baker capabilities google-ads`) adds `ops` — the exact fields and accepted values of every change there. Read that instead of guessing a field name.\",\n );\n }\n\n // The whole reason `tools` exists. An agent that read only `surfaces` used to\n // conclude a company had no session-recording tool while Microsoft Clarity\n // sat in its own tool list — and that is the source most likely to change\n // what it decides about a page.\n const usable = tools.filter((tool) => tool.ready);\n if (usable.length > 0) {\n hints.push(\n `ALSO AVAILABLE, and not on any surface above: ${usable.map((tool) => tool.label).join(\", \")}. These answer WHY a page behaves as it does, which no surface here can. See \\`tools[].reach\\` for how to call each one.`,\n );\n }\n\n const broken = tools.filter((tool) => !tool.ready);\n if (broken.length > 0) {\n hints.push(\n `CONNECTED BUT UNUSABLE: ${broken.map((tool) => `${tool.label} — ${tool.note ?? \"not reachable\"}`).join(\" \")} Tell the user rather than planning around it silently.`,\n );\n }\n\n return hints;\n}\n\nconst runCapabilities = defineCommand({\n meta: {\n name: \"capabilities\",\n description: `What Baker can and cannot do for this company, before any work starts.\n\nReports, per surface: what is connected and with what access, what a write there does when it lands, the entities that can be changed, and — the part nothing else tells you — what cannot be changed and why.\n\nAlso returns \\`tools\\`: everything else this company can reach that is not one of those surfaces — Microsoft Clarity and any other MCP toolkit, custom servers, HubSpot. This is the one call that answers \"what do I actually have\".\n\nExamples:\n baker capabilities\n baker capabilities google-ads\n baker capabilities tag-manager\n baker capabilities --full\n\nFull guide: __tooling__/docs/tools/baker/capabilities.md`,\n },\n args: {\n surface: {\n type: \"positional\",\n description: `Narrow to one surface: ${CAPABILITY_SURFACES.join(\" | \")}`,\n required: false,\n },\n full: {\n type: \"boolean\",\n description: \"Include the field-level contract of every change on every surface\",\n required: false,\n default: false,\n },\n },\n run: async ({ args }) => {\n try {\n const body: Record<string, unknown> = {};\n const surface = args.surface as string | undefined;\n if (surface) {\n if (!(CAPABILITY_SURFACES as readonly string[]).includes(surface)) {\n throw new Error(`\"${surface}\" is not a surface. Use one of: ${CAPABILITY_SURFACES.join(\", \")}`);\n }\n body.surface = surface;\n }\n if (args.full) {\n body.full = true;\n }\n // Who this chat acts as: their own connected tools load with it — a\n // personal inbox in a scheduled run of theirs — and are listed with it.\n const actingUserId = getEnv().BAKER_ACTING_USER_ID;\n if (actingUserId) {\n body.actingUserId = actingUserId;\n }\n const response = await apiPost<CapabilitiesResponse>(\"/api/capabilities\", body);\n const hints = capabilityHints(response.data.surfaces, response.data.tools);\n writeJson({\n ...response,\n meta: { count: response.data.surfaces.length },\n ...(hints.length > 0 ? { hints } : {}),\n });\n } catch (err) {\n failApi(err);\n }\n },\n});\n\nexport const capabilitiesCommand = runCapabilities;\n"],"mappings":"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","names":[]}
|
|
@@ -2,11 +2,11 @@ import {
|
|
|
2
2
|
catalogView,
|
|
3
3
|
defaultRegistry,
|
|
4
4
|
generateCatalog
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-W3B4BHQU.js";
|
|
5
|
+
} from "./chunk-LYQJ4PZW.js";
|
|
6
|
+
import "./chunk-FPOGPFAG.js";
|
|
8
7
|
import "./chunk-NCWCZY5P.js";
|
|
9
8
|
import "./chunk-DGCUPJZD.js";
|
|
9
|
+
import "./chunk-W3B4BHQU.js";
|
|
10
10
|
import "./chunk-PZXCWSKV.js";
|
|
11
11
|
import "./chunk-CAMX6OHF.js";
|
|
12
12
|
import "./chunk-RX6F3GEA.js";
|
|
@@ -62,4 +62,4 @@ var catalogCommand = defineCommand({
|
|
|
62
62
|
export {
|
|
63
63
|
catalogCommand
|
|
64
64
|
};
|
|
65
|
-
//# sourceMappingURL=catalog-
|
|
65
|
+
//# sourceMappingURL=catalog-XLXIM7IW.js.map
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
failApi
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-SJYEY5MV.js";
|
|
4
|
+
import "./chunk-7EPXVICM.js";
|
|
5
5
|
import "./chunk-GXDLWBOY.js";
|
|
6
6
|
import "./chunk-TEINLN64.js";
|
|
7
7
|
import "./chunk-ZJWUBJYQ.js";
|
|
8
|
+
import "./chunk-HR6IWNKE.js";
|
|
8
9
|
import "./chunk-NE4F3FHN.js";
|
|
9
10
|
import {
|
|
10
11
|
apiPost
|
|
@@ -259,4 +260,4 @@ Full guide: __tooling__/docs/tools/baker/chats.md`
|
|
|
259
260
|
export {
|
|
260
261
|
chatsCommand
|
|
261
262
|
};
|
|
262
|
-
//# sourceMappingURL=chats-
|
|
263
|
+
//# sourceMappingURL=chats-UK47UE7C.js.map
|