@koda-sl/baker-cli 0.450.0-dev.b454c3dd2 → 0.450.0-dev.d6701597d

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (443) hide show
  1. package/README.md +10 -11
  2. package/dist/{account-XQXC7BR6.js → account-AL2ZDSR7.js} +4 -5
  3. package/dist/{account-XQXC7BR6.js.map → account-AL2ZDSR7.js.map} +1 -1
  4. package/dist/{accounts-722UY53A.js → accounts-HAFCLSR5.js} +3 -4
  5. package/dist/{accounts-722UY53A.js.map → accounts-HAFCLSR5.js.map} +1 -1
  6. package/dist/{accounts-E67BMK7T.js → accounts-O5MFO3QQ.js} +5 -6
  7. package/dist/{accounts-E67BMK7T.js.map → accounts-O5MFO3QQ.js.map} +1 -1
  8. package/dist/{actions-6TQMSVWD.js → actions-P35MEMGN.js} +18 -18
  9. package/dist/{add-2BEGRHUX.js → add-5GAN6CVO.js} +5 -28
  10. package/dist/add-5GAN6CVO.js.map +1 -0
  11. package/dist/{add-LEMKEOPO.js → add-6DTC6X5G.js} +2 -3
  12. package/dist/{add-LEMKEOPO.js.map → add-6DTC6X5G.js.map} +1 -1
  13. package/dist/{ads-AGYCVD62.js → ads-73PGA4YC.js} +4 -4
  14. package/dist/{advertisers-2VQKAYKG.js → advertisers-AE75CGVE.js} +3 -4
  15. package/dist/{advertisers-2VQKAYKG.js.map → advertisers-AE75CGVE.js.map} +1 -1
  16. package/dist/{analytics-IFELDWLL.js → analytics-FKCXIMPO.js} +20 -24
  17. package/dist/analytics-FKCXIMPO.js.map +1 -0
  18. package/dist/{analytics-OH5QEH7F.js → analytics-FPWQQGRM.js} +3 -4
  19. package/dist/{analytics-OH5QEH7F.js.map → analytics-FPWQQGRM.js.map} +1 -1
  20. package/dist/{assign-PTUJUCEL.js → assign-ABN2AQ4J.js} +3 -4
  21. package/dist/{assign-PTUJUCEL.js.map → assign-ABN2AQ4J.js.map} +1 -1
  22. package/dist/{audience-size-LRI6GJRT.js → audience-size-GNBJY35X.js} +3 -4
  23. package/dist/{audience-size-LRI6GJRT.js.map → audience-size-GNBJY35X.js.map} +1 -1
  24. package/dist/{audit-HWP7OPB7.js → audit-3VS63TBW.js} +3 -4
  25. package/dist/{audit-HWP7OPB7.js.map → audit-3VS63TBW.js.map} +1 -1
  26. package/dist/{autocomplete-J6DHU6MR.js → autocomplete-VS3XG3B7.js} +3 -4
  27. package/dist/{autocomplete-J6DHU6MR.js.map → autocomplete-VS3XG3B7.js.map} +1 -1
  28. package/dist/{avatars-467OSBD6.js → avatars-EKCKHCC3.js} +4 -4
  29. package/dist/{bid-pricing-EO5WLHGV.js → bid-pricing-Q72B65AY.js} +3 -4
  30. package/dist/{bid-pricing-EO5WLHGV.js.map → bid-pricing-Q72B65AY.js.map} +1 -1
  31. package/dist/{brand-YRTEPGBK.js → brand-C6PFGGQN.js} +2 -2
  32. package/dist/{brief-OSFJ2V7F.js → brief-YFJHQ5VQ.js} +7 -8
  33. package/dist/{brief-OSFJ2V7F.js.map → brief-YFJHQ5VQ.js.map} +1 -1
  34. package/dist/{campaign-groups-PQ6KSQJR.js → campaign-groups-KFFYQPU3.js} +8 -9
  35. package/dist/{campaign-groups-PQ6KSQJR.js.map → campaign-groups-KFFYQPU3.js.map} +1 -1
  36. package/dist/{campaign-writes-5OVLUD5E.js → campaign-writes-FHOS5XZY.js} +3 -4
  37. package/dist/{campaign-writes-5OVLUD5E.js.map → campaign-writes-FHOS5XZY.js.map} +1 -1
  38. package/dist/{campaigns-6T3NSUT2.js → campaigns-2NHWBF5C.js} +11 -12
  39. package/dist/{campaigns-6T3NSUT2.js.map → campaigns-2NHWBF5C.js.map} +1 -1
  40. package/dist/{campaigns-OYMXDGWX.js → campaigns-KZYZTXDS.js} +5 -5
  41. package/dist/{canvas-YQFG52IG.js → canvas-5NB27FX2.js} +13 -13
  42. package/dist/{capabilities-PXBKUN2G.js → capabilities-DJFTRJKS.js} +3 -4
  43. package/dist/{capabilities-PXBKUN2G.js.map → capabilities-DJFTRJKS.js.map} +1 -1
  44. package/dist/{catalog-XLXIM7IW.js → catalog-VSSY6FGI.js} +4 -4
  45. package/dist/{chats-UK47UE7C.js → chats-D2CSDX5Q.js} +3 -4
  46. package/dist/{chats-UK47UE7C.js.map → chats-D2CSDX5Q.js.map} +1 -1
  47. package/dist/{chunk-5ZNTADVR.js → chunk-3G3ZDLMI.js} +2 -2
  48. package/dist/{chunk-SJYEY5MV.js → chunk-3HJLHTWP.js} +3 -12
  49. package/dist/{chunk-SJYEY5MV.js.map → chunk-3HJLHTWP.js.map} +1 -1
  50. package/dist/{chunk-ZDMTXQ2Q.js → chunk-3IBYKLXR.js} +2 -2
  51. package/dist/{chunk-CWYAELVG.js → chunk-464O4MT2.js} +2 -2
  52. package/dist/{chunk-NA63BH7V.js → chunk-4AUMTNVB.js} +3 -3
  53. package/dist/{chunk-NDEE6G2J.js → chunk-4BQXAE7Z.js} +2 -2
  54. package/dist/{chunk-2AOE2MZQ.js → chunk-5ZDLTE5T.js} +3 -3
  55. package/dist/{chunk-ULG4QRTV.js → chunk-6NB47MRW.js} +2 -2
  56. package/dist/{chunk-24EB7EDR.js → chunk-7YCRFMXF.js} +3 -3
  57. package/dist/{chunk-WGUQHAJY.js → chunk-A4LOJ2VD.js} +2 -2
  58. package/dist/{chunk-6F7DVPOS.js → chunk-AEOSAVVL.js} +3 -3
  59. package/dist/{chunk-MACCF4JZ.js → chunk-CMPEUZOR.js} +22 -16
  60. package/dist/{chunk-MACCF4JZ.js.map → chunk-CMPEUZOR.js.map} +1 -1
  61. package/dist/{chunk-N4LAYIIN.js → chunk-CSYSX4D2.js} +2 -2
  62. package/dist/{chunk-RX2DKU3W.js → chunk-DGUNI37S.js} +2 -2
  63. package/dist/{chunk-QE7W555R.js → chunk-DWHIOO7E.js} +12 -163
  64. package/dist/chunk-DWHIOO7E.js.map +1 -0
  65. package/dist/{chunk-FPOGPFAG.js → chunk-EBWBG6YV.js} +51 -24
  66. package/dist/chunk-EBWBG6YV.js.map +1 -0
  67. package/dist/{chunk-NYIGXDUG.js → chunk-EDLZGTGN.js} +39 -1
  68. package/dist/chunk-EDLZGTGN.js.map +1 -0
  69. package/dist/{chunk-I3ZR655O.js → chunk-IR6D7K4H.js} +2 -2
  70. package/dist/{chunk-FUHN4MFY.js → chunk-JQJDXPCO.js} +2 -2
  71. package/dist/{chunk-7CTMH5AK.js → chunk-KAUOHQTF.js} +3 -3
  72. package/dist/{chunk-VYQ3QJ3C.js → chunk-KHRXPQID.js} +2 -2
  73. package/dist/{chunk-6Y7ZBENQ.js → chunk-LECGCWT5.js} +6 -6
  74. package/dist/{chunk-5WCSKQ7Z.js → chunk-LZ73CZGP.js} +6 -6
  75. package/dist/{chunk-R25YLW6H.js → chunk-MELOSESI.js} +2 -2
  76. package/dist/{chunk-DCRPXOJJ.js → chunk-MXYBTMKB.js} +2 -2
  77. package/dist/{chunk-54C6YDGJ.js → chunk-NPY4QUMQ.js} +2 -2
  78. package/dist/{chunk-LYQJ4PZW.js → chunk-OQ6663F4.js} +5 -5
  79. package/dist/{chunk-H3427GPU.js → chunk-OZRUJVIQ.js} +2 -2
  80. package/dist/{chunk-KMKEYI37.js → chunk-Q2V6E6SL.js} +3 -3
  81. package/dist/{chunk-VL43TNIP.js → chunk-QRP3PXWN.js} +2 -2
  82. package/dist/{chunk-HDLYPC6K.js → chunk-RPUSTYHL.js} +3 -5
  83. package/dist/{chunk-HDLYPC6K.js.map → chunk-RPUSTYHL.js.map} +1 -1
  84. package/dist/{chunk-C46GUI2S.js → chunk-RZBEK2VE.js} +2 -2
  85. package/dist/{chunk-2VPBIT65.js → chunk-S3A3YOKO.js} +8 -8
  86. package/dist/{chunk-FYGR3I2A.js → chunk-S77PZVYM.js} +3 -3
  87. package/dist/{chunk-VLMBTPXU.js → chunk-SHL7LOC3.js} +3 -3
  88. package/dist/{chunk-HR6IWNKE.js → chunk-SSJK7FEV.js} +1140 -1196
  89. package/dist/chunk-SSJK7FEV.js.map +1 -0
  90. package/dist/{chunk-KS2QY6MK.js → chunk-W3ZHJJVT.js} +4 -4
  91. package/dist/{chunk-7EPXVICM.js → chunk-XF4JUKVF.js} +5 -38
  92. package/dist/chunk-XF4JUKVF.js.map +1 -0
  93. package/dist/{chunk-RL5CP7N6.js → chunk-Y6O7EWYY.js} +5 -5
  94. package/dist/{chunk-6NY2GPR4.js → chunk-Y6ZQXUZ7.js} +3 -3
  95. package/dist/{chunk-HROZYQ5H.js → chunk-YRQYA2LR.js} +5 -63
  96. package/dist/chunk-YRQYA2LR.js.map +1 -0
  97. package/dist/{chunk-ASI4P6X2.js → chunk-YUCLMOEG.js} +6 -6
  98. package/dist/chunk-YUCLMOEG.js.map +1 -0
  99. package/dist/{chunk-WKQG6TER.js → chunk-ZEYEWPK6.js} +2 -2
  100. package/dist/{claim-W6G6VEG5.js → claim-FZ5OQLMU.js} +3 -4
  101. package/dist/{claim-W6G6VEG5.js.map → claim-FZ5OQLMU.js.map} +1 -1
  102. package/dist/cli.js +30 -30
  103. package/dist/{companies-TS6KBATJ.js → companies-DNI634RC.js} +3 -4
  104. package/dist/{companies-TS6KBATJ.js.map → companies-DNI634RC.js.map} +1 -1
  105. package/dist/{complete-LYR2HMQU.js → complete-2FZMGJV5.js} +3 -4
  106. package/dist/{complete-LYR2HMQU.js.map → complete-2FZMGJV5.js.map} +1 -1
  107. package/dist/{connect-FCXNVTXG.js → connect-QCOGEPP4.js} +6 -13
  108. package/dist/{conversation-6ZJGPCXM.js → conversation-6IOGV7B7.js} +3 -4
  109. package/dist/{conversation-6ZJGPCXM.js.map → conversation-6IOGV7B7.js.map} +1 -1
  110. package/dist/{conversions-UHB55MMQ.js → conversions-4SRZPBBX.js} +7 -8
  111. package/dist/{conversions-UHB55MMQ.js.map → conversions-4SRZPBBX.js.map} +1 -1
  112. package/dist/{create-EX6OWLNM.js → create-BJNMO6HT.js} +2 -3
  113. package/dist/{create-EX6OWLNM.js.map → create-BJNMO6HT.js.map} +1 -1
  114. package/dist/{create-JFSK4BOP.js → create-FX4OJ2XF.js} +3 -4
  115. package/dist/{create-JFSK4BOP.js.map → create-FX4OJ2XF.js.map} +1 -1
  116. package/dist/{create-JCA7JPLP.js → create-RM7HV77Y.js} +3 -4
  117. package/dist/{create-JCA7JPLP.js.map → create-RM7HV77Y.js.map} +1 -1
  118. package/dist/{create-WU22YYU2.js → create-VXM34ZWH.js} +3 -4
  119. package/dist/{create-WU22YYU2.js.map → create-VXM34ZWH.js.map} +1 -1
  120. package/dist/{creatives-FXUQ5WSD.js → creatives-B5NTXPUB.js} +10 -10
  121. package/dist/{creatives-KGXUOYPE.js → creatives-JSWBFQ5R.js} +8 -9
  122. package/dist/{creatives-KGXUOYPE.js.map → creatives-JSWBFQ5R.js.map} +1 -1
  123. package/dist/{credentials-MJC7PGKR.js → credentials-C33K6XCJ.js} +3 -4
  124. package/dist/{credentials-MJC7PGKR.js.map → credentials-C33K6XCJ.js.map} +1 -1
  125. package/dist/{critique-GS5VV5ZC.js → critique-4V5SKH7C.js} +6 -7
  126. package/dist/{critique-GS5VV5ZC.js.map → critique-4V5SKH7C.js.map} +1 -1
  127. package/dist/{critique-TPHR27KH.js → critique-ZS4ON3SU.js} +3 -4
  128. package/dist/{critique-TPHR27KH.js.map → critique-ZS4ON3SU.js.map} +1 -1
  129. package/dist/{crm-VK44O3ED.js → crm-52ROSWH5.js} +4 -5
  130. package/dist/{crm-VK44O3ED.js.map → crm-52ROSWH5.js.map} +1 -1
  131. package/dist/{crm-AVCM5D4G.js → crm-R5IXIFIV.js} +4 -5
  132. package/dist/{crm-AVCM5D4G.js.map → crm-R5IXIFIV.js.map} +1 -1
  133. package/dist/{customers-XH2DMTFH.js → customers-A36LOZOB.js} +5 -6
  134. package/dist/{delete-WI5E3DR3.js → delete-AIGE4Y4H.js} +3 -4
  135. package/dist/{delete-WI5E3DR3.js.map → delete-AIGE4Y4H.js.map} +1 -1
  136. package/dist/{delete-KRH2YMSZ.js → delete-HGHXY24R.js} +3 -4
  137. package/dist/{delete-KRH2YMSZ.js.map → delete-HGHXY24R.js.map} +1 -1
  138. package/dist/{delete-E3R3TKIL.js → delete-M2GDLPYN.js} +2 -3
  139. package/dist/{delete-E3R3TKIL.js.map → delete-M2GDLPYN.js.map} +1 -1
  140. package/dist/{demographics-XV5PBA77.js → demographics-NTWB2IMG.js} +3 -4
  141. package/dist/{demographics-XV5PBA77.js.map → demographics-NTWB2IMG.js.map} +1 -1
  142. package/dist/{discard-HTQUUHJR.js → discard-2WWQG6OU.js} +3 -4
  143. package/dist/{discard-HTQUUHJR.js.map → discard-2WWQG6OU.js.map} +1 -1
  144. package/dist/{domain-RECGZXJB.js → domain-Y2LT6JLT.js} +3 -4
  145. package/dist/{domain-RECGZXJB.js.map → domain-Y2LT6JLT.js.map} +1 -1
  146. package/dist/{draft-Q546QPPU.js → draft-EJXNNJ3Y.js} +4 -5
  147. package/dist/{draft-Q546QPPU.js.map → draft-EJXNNJ3Y.js.map} +1 -1
  148. package/dist/{draft-PVTX6QT6.js → draft-FJ7WHIXW.js} +3 -4
  149. package/dist/{draft-PVTX6QT6.js.map → draft-FJ7WHIXW.js.map} +1 -1
  150. package/dist/{draft-2IBSJEKC.js → draft-SLHAKJ2A.js} +3 -4
  151. package/dist/{draft-2IBSJEKC.js.map → draft-SLHAKJ2A.js.map} +1 -1
  152. package/dist/engine/index.js +3 -3
  153. package/dist/{facets-7EVPJMKS.js → facets-U7AQC4H6.js} +3 -4
  154. package/dist/{facets-7EVPJMKS.js.map → facets-U7AQC4H6.js.map} +1 -1
  155. package/dist/{feedback-EIZKS4JU.js → feedback-OLTCHE6C.js} +2 -2
  156. package/dist/{feedback-record-TKO54BOE.js → feedback-record-7WZ4H7EP.js} +8 -9
  157. package/dist/{feedback-record-TKO54BOE.js.map → feedback-record-7WZ4H7EP.js.map} +1 -1
  158. package/dist/{fetch-4BY6HYUM.js → fetch-W7NULDEO.js} +3 -4
  159. package/dist/{fetch-4BY6HYUM.js.map → fetch-W7NULDEO.js.map} +1 -1
  160. package/dist/{find-FRRHAPWX.js → find-OTDIX6V4.js} +4 -4
  161. package/dist/{flows-KTFAML22.js → flows-KABCBS3S.js} +17 -21
  162. package/dist/flows-KABCBS3S.js.map +1 -0
  163. package/dist/{fonts-MXR3ZKDX.js → fonts-EMMX3KII.js} +5 -6
  164. package/dist/{forecast-3QTJYVND.js → forecast-GNODEIIC.js} +3 -4
  165. package/dist/{forecast-3QTJYVND.js.map → forecast-GNODEIIC.js.map} +1 -1
  166. package/dist/{funnel-I6XIAEHG.js → funnel-AAX27NH4.js} +455 -11
  167. package/dist/funnel-AAX27NH4.js.map +1 -0
  168. package/dist/{ga4-DV2AXCSL.js → ga4-UDQ2HA2J.js} +1 -1
  169. package/dist/{get-5PKNKJ5S.js → get-QEYJRLV3.js} +4 -7
  170. package/dist/get-QEYJRLV3.js.map +1 -0
  171. package/dist/{get-72YPHJGV.js → get-RTVUZM6E.js} +3 -4
  172. package/dist/{get-72YPHJGV.js.map → get-RTVUZM6E.js.map} +1 -1
  173. package/dist/{google-QYYYSSXI.js → google-KTO3PLEU.js} +5 -5
  174. package/dist/{google-6OGZX47I.js → google-M7KEXVK5.js} +2 -2
  175. package/dist/{google-ads-QGMQKZQD.js → google-ads-OK6IG3UV.js} +3 -4
  176. package/dist/{google-ads-QGMQKZQD.js.map → google-ads-OK6IG3UV.js.map} +1 -1
  177. package/dist/{gsc-TAKOF7J5.js → gsc-P3QYGDV2.js} +1 -1
  178. package/dist/{history-6AVQX2OQ.js → history-PQUJKK26.js} +3 -4
  179. package/dist/{history-6AVQX2OQ.js.map → history-PQUJKK26.js.map} +1 -1
  180. package/dist/{hubspot-SVEMFK5S.js → hubspot-Y77VLY6Y.js} +8 -9
  181. package/dist/{hubspot-SVEMFK5S.js.map → hubspot-Y77VLY6Y.js.map} +1 -1
  182. package/dist/{icon-L4RSS6PZ.js → icon-I43F77FV.js} +4 -4
  183. package/dist/{ideas-NFOW3HKJ.js → ideas-MIDU7YOA.js} +2 -3
  184. package/dist/{images-2EFFUNNV.js → images-S254MS6O.js} +9 -9
  185. package/dist/{ingest-2SO62RRI.js → ingest-J4I3HKM3.js} +2 -3
  186. package/dist/{ingest-2SO62RRI.js.map → ingest-J4I3HKM3.js.map} +1 -1
  187. package/dist/{ingest-2EIKN4QC.js → ingest-YV2NLDBE.js} +3 -4
  188. package/dist/{inspect-4OOS4APT.js → inspect-Q5NHBBHX.js} +3 -4
  189. package/dist/{inspect-4OOS4APT.js.map → inspect-Q5NHBBHX.js.map} +1 -1
  190. package/dist/{inspiration-S3DU4CMQ.js → inspiration-P265QJ2H.js} +1 -1
  191. package/dist/{keyword-metrics-SF4CSNZ2.js → keyword-metrics-PDY4ZXSP.js} +3 -4
  192. package/dist/{keyword-metrics-SF4CSNZ2.js.map → keyword-metrics-PDY4ZXSP.js.map} +1 -1
  193. package/dist/{keywords-for-site-WDAOPNKC.js → keywords-for-site-GALSCV77.js} +3 -4
  194. package/dist/{keywords-for-site-WDAOPNKC.js.map → keywords-for-site-GALSCV77.js.map} +1 -1
  195. package/dist/{landing-2ZB46LXH.js → landing-CJYGWCK4.js} +3 -3
  196. package/dist/{leads-A4W5KTWB.js → leads-PHKG6CP3.js} +3 -4
  197. package/dist/{leads-A4W5KTWB.js.map → leads-PHKG6CP3.js.map} +1 -1
  198. package/dist/{learn-IPULBCOD.js → learn-FUQSY7DN.js} +4 -5
  199. package/dist/{learn-IPULBCOD.js.map → learn-FUQSY7DN.js.map} +1 -1
  200. package/dist/{line-item-writes-EMYSOJKM.js → line-item-writes-E6MZPIZZ.js} +3 -4
  201. package/dist/{line-item-writes-EMYSOJKM.js.map → line-item-writes-E6MZPIZZ.js.map} +1 -1
  202. package/dist/{line-items-5NECXUZT.js → line-items-7ZGIKEF2.js} +5 -5
  203. package/dist/{link-CI45HWFN.js → link-QYAW6A2W.js} +3 -4
  204. package/dist/{link-CI45HWFN.js.map → link-QYAW6A2W.js.map} +1 -1
  205. package/dist/{linkedin-B7SYR75X.js → linkedin-FFSDSGGS.js} +26 -27
  206. package/dist/{linkedin-B7SYR75X.js.map → linkedin-FFSDSGGS.js.map} +1 -1
  207. package/dist/{list-ZBT3EBVZ.js → list-5IC6KIKO.js} +3 -4
  208. package/dist/{list-ZBT3EBVZ.js.map → list-5IC6KIKO.js.map} +1 -1
  209. package/dist/{list-2BARXOT5.js → list-NVQC5SNY.js} +2 -3
  210. package/dist/{list-2BARXOT5.js.map → list-NVQC5SNY.js.map} +1 -1
  211. package/dist/{list-BIEVLEHS.js → list-SAV3LQHY.js} +3 -4
  212. package/dist/{list-BIEVLEHS.js.map → list-SAV3LQHY.js.map} +1 -1
  213. package/dist/{log-C23OOAJZ.js → log-XZPVOALD.js} +3 -4
  214. package/dist/{log-C23OOAJZ.js.map → log-XZPVOALD.js.map} +1 -1
  215. package/dist/{logo-Q5D7PZY6.js → logo-2IP663QO.js} +3 -3
  216. package/dist/{lookup-ETWY47F7.js → lookup-XK45W2SH.js} +5 -6
  217. package/dist/{make-TPKKJXGL.js → make-BMWRKIIY.js} +20 -18
  218. package/dist/{make-TPKKJXGL.js.map → make-BMWRKIIY.js.map} +1 -1
  219. package/dist/{map-SYZMPHLL.js → map-4J5WIWIG.js} +4 -5
  220. package/dist/{map-SYZMPHLL.js.map → map-4J5WIWIG.js.map} +1 -1
  221. package/dist/{mcp-6FQBVJ6F.js → mcp-XXD7ZQCP.js} +2 -3
  222. package/dist/{mcp-6FQBVJ6F.js.map → mcp-XXD7ZQCP.js.map} +1 -1
  223. package/dist/{media-sources-ZXHEEP6T.js → media-sources-O6ZRUA3N.js} +2 -2
  224. package/dist/{members-UDY4OOJW.js → members-D5ZYLS4Y.js} +3 -4
  225. package/dist/{members-UDY4OOJW.js.map → members-D5ZYLS4Y.js.map} +1 -1
  226. package/dist/{normalize-DAKHYS3V.js → normalize-PCNC6E2N.js} +3 -7
  227. package/dist/{normalize-DAKHYS3V.js.map → normalize-PCNC6E2N.js.map} +1 -1
  228. package/dist/{options-QL3ULED5.js → options-MQ65VEVD.js} +6 -7
  229. package/dist/{options-QL3ULED5.js.map → options-MQ65VEVD.js.map} +1 -1
  230. package/dist/{performance-UF5VTY2U.js → performance-6QW2KEEQ.js} +4 -5
  231. package/dist/{promoted-tweet-writes-7HGESJ46.js → promoted-tweet-writes-JPLHY3GM.js} +3 -4
  232. package/dist/{promoted-tweet-writes-7HGESJ46.js.map → promoted-tweet-writes-JPLHY3GM.js.map} +1 -1
  233. package/dist/{promoted-tweets-LZKS5JIF.js → promoted-tweets-SURKMHFI.js} +3 -3
  234. package/dist/{publish-NPD3SMZL.js → publish-HCQ6MXLB.js} +3 -4
  235. package/dist/{publish-NPD3SMZL.js.map → publish-HCQ6MXLB.js.map} +1 -1
  236. package/dist/{reddit-NU2N3LZD.js → reddit-GIP3ADMS.js} +4 -5
  237. package/dist/{refresh-EBVJ2C6L.js → refresh-UXQSLCR3.js} +2 -3
  238. package/dist/{refresh-EBVJ2C6L.js.map → refresh-UXQSLCR3.js.map} +1 -1
  239. package/dist/{release-V43YB2PY.js → release-5KVLXNP6.js} +3 -4
  240. package/dist/{release-V43YB2PY.js.map → release-5KVLXNP6.js.map} +1 -1
  241. package/dist/{remove-QPSWLFI4.js → remove-6FIVKCJI.js} +2 -3
  242. package/dist/{remove-QPSWLFI4.js.map → remove-6FIVKCJI.js.map} +1 -1
  243. package/dist/{reopen-GQ66NMWF.js → reopen-YM5LNOLB.js} +3 -4
  244. package/dist/{reopen-GQ66NMWF.js.map → reopen-YM5LNOLB.js.map} +1 -1
  245. package/dist/{rerun-PZK275DY.js → rerun-6XZG7BGK.js} +17 -18
  246. package/dist/{rerun-PZK275DY.js.map → rerun-6XZG7BGK.js.map} +1 -1
  247. package/dist/{research-FMM6AWZC.js → research-2BLEISBG.js} +10 -10
  248. package/dist/{research-GEOCUBXB.js → research-YOGE7GT2.js} +2 -3
  249. package/dist/{research-GEOCUBXB.js.map → research-YOGE7GT2.js.map} +1 -1
  250. package/dist/{reset-REXJ6AUK.js → reset-C4UHQ3EU.js} +2 -3
  251. package/dist/{reset-REXJ6AUK.js.map → reset-C4UHQ3EU.js.map} +1 -1
  252. package/dist/{reset-Y72IVESB.js → reset-OLVB6AE6.js} +2 -3
  253. package/dist/{reset-Y72IVESB.js.map → reset-OLVB6AE6.js.map} +1 -1
  254. package/dist/{resolve-OGX7C4TV.js → resolve-XYH2GDAE.js} +3 -4
  255. package/dist/{resolve-OGX7C4TV.js.map → resolve-XYH2GDAE.js.map} +1 -1
  256. package/dist/{retry-TCUBBFR5.js → retry-726GKI6V.js} +2 -3
  257. package/dist/{retry-TCUBBFR5.js.map → retry-726GKI6V.js.map} +1 -1
  258. package/dist/{retry-CD6JAQ3F.js → retry-7EELDEQP.js} +2 -3
  259. package/dist/{retry-CD6JAQ3F.js.map → retry-7EELDEQP.js.map} +1 -1
  260. package/dist/{run-EUO34T2J.js → run-MMEDKJDB.js} +17 -18
  261. package/dist/{run-A5ZDXTOI.js → run-P4KR2MXC.js} +3 -4
  262. package/dist/{run-A5ZDXTOI.js.map → run-P4KR2MXC.js.map} +1 -1
  263. package/dist/{scaffold-ad-SW2HEWM3.js → scaffold-ad-PBTEWDAC.js} +12 -13
  264. package/dist/{scaffold-ad-SW2HEWM3.js.map → scaffold-ad-PBTEWDAC.js.map} +1 -1
  265. package/dist/{scaffold-static-ad-ECTJL54Y.js → scaffold-static-ad-RM4M4X5U.js} +36 -37
  266. package/dist/scaffold-static-ad-RM4M4X5U.js.map +1 -0
  267. package/dist/{scaffold-video-EI7U7RBK.js → scaffold-video-O2TTKZIE.js} +11 -12
  268. package/dist/{scaffold-video-EI7U7RBK.js.map → scaffold-video-O2TTKZIE.js.map} +1 -1
  269. package/dist/{schedule-S5YZJZ5U.js → schedule-RDK4GEPI.js} +2 -3
  270. package/dist/{schedule-S5YZJZ5U.js.map → schedule-RDK4GEPI.js.map} +1 -1
  271. package/dist/{scheduled-agents-N4LJRM4C.js → scheduled-agents-6U44QE76.js} +11 -11
  272. package/dist/{schema-R7JWWOF4.js → schema-CHJDC7GQ.js} +4 -8
  273. package/dist/{schema-R7JWWOF4.js.map → schema-CHJDC7GQ.js.map} +1 -1
  274. package/dist/{search-KHMQH3AT.js → search-PMJRU3C4.js} +2 -3
  275. package/dist/{search-KHMQH3AT.js.map → search-PMJRU3C4.js.map} +1 -1
  276. package/dist/{select-O2FN2JEQ.js → select-OEUKOVZ5.js} +8 -9
  277. package/dist/{select-O2FN2JEQ.js.map → select-OEUKOVZ5.js.map} +1 -1
  278. package/dist/{sends-BQZM5PLS.js → sends-WGJVQUMF.js} +4 -5
  279. package/dist/{sends-BQZM5PLS.js.map → sends-WGJVQUMF.js.map} +1 -1
  280. package/dist/{set-prompt-2HASHGWC.js → set-prompt-5E5I7QAZ.js} +8 -9
  281. package/dist/{set-prompt-2HASHGWC.js.map → set-prompt-5E5I7QAZ.js.map} +1 -1
  282. package/dist/{setup-links-GYSE56GX.js → setup-links-REPREN3C.js} +3 -4
  283. package/dist/{setup-links-GYSE56GX.js.map → setup-links-REPREN3C.js.map} +1 -1
  284. package/dist/{site-4SKM7RKG.js → site-WFSWIA3S.js} +4 -5
  285. package/dist/{site-4SKM7RKG.js.map → site-WFSWIA3S.js.map} +1 -1
  286. package/dist/{sources-R2NKNC6J.js → sources-AMI2AWKZ.js} +9 -10
  287. package/dist/{sources-R2NKNC6J.js.map → sources-AMI2AWKZ.js.map} +1 -1
  288. package/dist/{sources-FQ2UZTHL.js → sources-YBQ6KPFM.js} +6 -6
  289. package/dist/{stale-W756ACKC.js → stale-IGFUKEN2.js} +7 -8
  290. package/dist/{stale-W756ACKC.js.map → stale-IGFUKEN2.js.map} +1 -1
  291. package/dist/{status-SE2VZJJB.js → status-7F2KHFGA.js} +3 -4
  292. package/dist/{status-SE2VZJJB.js.map → status-7F2KHFGA.js.map} +1 -1
  293. package/dist/{stock-KXJ26BY4.js → stock-2YCDN3N6.js} +5 -5
  294. package/dist/{studio-SYKOSNDB.js → studio-RA7QQH4O.js} +1 -1
  295. package/dist/{sync-LJGSODK3.js → sync-GWTLKZTU.js} +2 -3
  296. package/dist/{sync-LJGSODK3.js.map → sync-GWTLKZTU.js.map} +1 -1
  297. package/dist/{sync-definition-QR2N233R.js → sync-definition-UGSDX2SZ.js} +11 -12
  298. package/dist/{tags-PYWFSBTR.js → tags-3WPW6PTV.js} +4 -4
  299. package/dist/{tags-QQU3OKMZ.js → tags-6342FQEB.js} +3 -4
  300. package/dist/{tags-QQU3OKMZ.js.map → tags-6342FQEB.js.map} +1 -1
  301. package/dist/{tags-5SBMRC2A.js → tags-ABHSX6M5.js} +3 -4
  302. package/dist/{tags-5SBMRC2A.js.map → tags-ABHSX6M5.js.map} +1 -1
  303. package/dist/{tags-YYLNF3PK.js → tags-FJIBBBRG.js} +3 -4
  304. package/dist/{tags-YYLNF3PK.js.map → tags-FJIBBBRG.js.map} +1 -1
  305. package/dist/{tags-4BAVFH4S.js → tags-KFYLZLB3.js} +2 -3
  306. package/dist/{tags-4BAVFH4S.js.map → tags-KFYLZLB3.js.map} +1 -1
  307. package/dist/{targeting-criteria-RJFLFICN.js → targeting-criteria-NR47AF5C.js} +3 -3
  308. package/dist/{targets-S2MT2PNB.js → targets-L56KOVQE.js} +3 -4
  309. package/dist/{targets-S2MT2PNB.js.map → targets-L56KOVQE.js.map} +1 -1
  310. package/dist/{templates-ZE5TOGRT.js → templates-B6XGDYUF.js} +3 -4
  311. package/dist/{templates-ZE5TOGRT.js.map → templates-B6XGDYUF.js.map} +1 -1
  312. package/dist/{testimonials-DII5DYLR.js → testimonials-CVC4YIXO.js} +6 -6
  313. package/dist/{top-companies-PGIAEHDF.js → top-companies-45X3DT7Z.js} +3 -4
  314. package/dist/{top-companies-PGIAEHDF.js.map → top-companies-45X3DT7Z.js.map} +1 -1
  315. package/dist/{translate-GXTS633J.js → translate-VP5R67PL.js} +11 -12
  316. package/dist/{translate-GXTS633J.js.map → translate-VP5R67PL.js.map} +1 -1
  317. package/dist/{triggers-2PTONXRU.js → triggers-22EMIVFD.js} +3 -4
  318. package/dist/{triggers-2PTONXRU.js.map → triggers-22EMIVFD.js.map} +1 -1
  319. package/dist/{unlink-XRMYJ6DB.js → unlink-65KUN6ID.js} +3 -4
  320. package/dist/{unlink-XRMYJ6DB.js.map → unlink-65KUN6ID.js.map} +1 -1
  321. package/dist/{unstage-FY7A3YFF.js → unstage-2E3I5SWF.js} +3 -4
  322. package/dist/{unstage-FY7A3YFF.js.map → unstage-2E3I5SWF.js.map} +1 -1
  323. package/dist/{unstage-RM2RLXKD.js → unstage-4ZEULXEQ.js} +4 -5
  324. package/dist/{unstage-RM2RLXKD.js.map → unstage-4ZEULXEQ.js.map} +1 -1
  325. package/dist/{update-S4562V3O.js → update-2S7CSEAW.js} +3 -4
  326. package/dist/{update-S4562V3O.js.map → update-2S7CSEAW.js.map} +1 -1
  327. package/dist/{update-V6YVEUI2.js → update-7NCOTAQZ.js} +3 -4
  328. package/dist/{update-V6YVEUI2.js.map → update-7NCOTAQZ.js.map} +1 -1
  329. package/dist/{update-PJ67D2OG.js → update-D6DJC6T7.js} +2 -3
  330. package/dist/{update-PJ67D2OG.js.map → update-D6DJC6T7.js.map} +1 -1
  331. package/dist/{update-E5SRBXQR.js → update-KREBPGBH.js} +3 -4
  332. package/dist/{update-E5SRBXQR.js.map → update-KREBPGBH.js.map} +1 -1
  333. package/dist/{upload-R6CQVLKF.js → upload-O6NHRPS7.js} +3 -4
  334. package/dist/{upload-R6CQVLKF.js.map → upload-O6NHRPS7.js.map} +1 -1
  335. package/dist/{url-options-JOKU46F2.js → url-options-GGXAL3J4.js} +3 -4
  336. package/dist/{url-options-JOKU46F2.js.map → url-options-GGXAL3J4.js.map} +1 -1
  337. package/dist/{url-params-7U2XMOWF.js → url-params-3EFGVTZZ.js} +3 -4
  338. package/dist/{url-params-7U2XMOWF.js.map → url-params-3EFGVTZZ.js.map} +1 -1
  339. package/dist/{validate-7YPOUKPB.js → validate-CSJM7XZM.js} +9 -10
  340. package/dist/{validate-7YPOUKPB.js.map → validate-CSJM7XZM.js.map} +1 -1
  341. package/dist/{videos-LICG6ACJ.js → videos-YSXYGTBM.js} +5 -5
  342. package/dist/{web-BA2PGTWU.js → web-IGIGVEKS.js} +3 -4
  343. package/dist/{web-BA2PGTWU.js.map → web-IGIGVEKS.js.map} +1 -1
  344. package/dist/{winning-ads-C6S2C5VP.js → winning-ads-2WS7FI4E.js} +2 -2
  345. package/dist/{write-commands-7SJ3BOW5.js → write-commands-5C7FUOVN.js} +4 -5
  346. package/dist/{write-commands-7SJ3BOW5.js.map → write-commands-5C7FUOVN.js.map} +1 -1
  347. package/dist/{x-CZHRC6U7.js → x-BFSKFCZD.js} +6 -6
  348. package/package.json +1 -1
  349. package/dist/add-2BEGRHUX.js.map +0 -1
  350. package/dist/analytics-IFELDWLL.js.map +0 -1
  351. package/dist/chunk-4PDHHHUJ.js +0 -537
  352. package/dist/chunk-4PDHHHUJ.js.map +0 -1
  353. package/dist/chunk-7EPXVICM.js.map +0 -1
  354. package/dist/chunk-ASI4P6X2.js.map +0 -1
  355. package/dist/chunk-FPOGPFAG.js.map +0 -1
  356. package/dist/chunk-HR6IWNKE.js.map +0 -1
  357. package/dist/chunk-HROZYQ5H.js.map +0 -1
  358. package/dist/chunk-NYIGXDUG.js.map +0 -1
  359. package/dist/chunk-QE7W555R.js.map +0 -1
  360. package/dist/flows-KTFAML22.js.map +0 -1
  361. package/dist/funnel-I6XIAEHG.js.map +0 -1
  362. package/dist/get-5PKNKJ5S.js.map +0 -1
  363. package/dist/plan-FT632COT.js +0 -51
  364. package/dist/plan-FT632COT.js.map +0 -1
  365. package/dist/questionnaire-JNGYJTAY.js +0 -37
  366. package/dist/questionnaire-JNGYJTAY.js.map +0 -1
  367. package/dist/scaffold-static-ad-ECTJL54Y.js.map +0 -1
  368. /package/dist/{actions-6TQMSVWD.js.map → actions-P35MEMGN.js.map} +0 -0
  369. /package/dist/{ads-AGYCVD62.js.map → ads-73PGA4YC.js.map} +0 -0
  370. /package/dist/{avatars-467OSBD6.js.map → avatars-EKCKHCC3.js.map} +0 -0
  371. /package/dist/{brand-YRTEPGBK.js.map → brand-C6PFGGQN.js.map} +0 -0
  372. /package/dist/{campaigns-OYMXDGWX.js.map → campaigns-KZYZTXDS.js.map} +0 -0
  373. /package/dist/{canvas-YQFG52IG.js.map → canvas-5NB27FX2.js.map} +0 -0
  374. /package/dist/{catalog-XLXIM7IW.js.map → catalog-VSSY6FGI.js.map} +0 -0
  375. /package/dist/{chunk-5ZNTADVR.js.map → chunk-3G3ZDLMI.js.map} +0 -0
  376. /package/dist/{chunk-ZDMTXQ2Q.js.map → chunk-3IBYKLXR.js.map} +0 -0
  377. /package/dist/{chunk-CWYAELVG.js.map → chunk-464O4MT2.js.map} +0 -0
  378. /package/dist/{chunk-NA63BH7V.js.map → chunk-4AUMTNVB.js.map} +0 -0
  379. /package/dist/{chunk-NDEE6G2J.js.map → chunk-4BQXAE7Z.js.map} +0 -0
  380. /package/dist/{chunk-2AOE2MZQ.js.map → chunk-5ZDLTE5T.js.map} +0 -0
  381. /package/dist/{chunk-ULG4QRTV.js.map → chunk-6NB47MRW.js.map} +0 -0
  382. /package/dist/{chunk-24EB7EDR.js.map → chunk-7YCRFMXF.js.map} +0 -0
  383. /package/dist/{chunk-WGUQHAJY.js.map → chunk-A4LOJ2VD.js.map} +0 -0
  384. /package/dist/{chunk-6F7DVPOS.js.map → chunk-AEOSAVVL.js.map} +0 -0
  385. /package/dist/{chunk-N4LAYIIN.js.map → chunk-CSYSX4D2.js.map} +0 -0
  386. /package/dist/{chunk-RX2DKU3W.js.map → chunk-DGUNI37S.js.map} +0 -0
  387. /package/dist/{chunk-I3ZR655O.js.map → chunk-IR6D7K4H.js.map} +0 -0
  388. /package/dist/{chunk-FUHN4MFY.js.map → chunk-JQJDXPCO.js.map} +0 -0
  389. /package/dist/{chunk-7CTMH5AK.js.map → chunk-KAUOHQTF.js.map} +0 -0
  390. /package/dist/{chunk-VYQ3QJ3C.js.map → chunk-KHRXPQID.js.map} +0 -0
  391. /package/dist/{chunk-6Y7ZBENQ.js.map → chunk-LECGCWT5.js.map} +0 -0
  392. /package/dist/{chunk-5WCSKQ7Z.js.map → chunk-LZ73CZGP.js.map} +0 -0
  393. /package/dist/{chunk-R25YLW6H.js.map → chunk-MELOSESI.js.map} +0 -0
  394. /package/dist/{chunk-DCRPXOJJ.js.map → chunk-MXYBTMKB.js.map} +0 -0
  395. /package/dist/{chunk-54C6YDGJ.js.map → chunk-NPY4QUMQ.js.map} +0 -0
  396. /package/dist/{chunk-LYQJ4PZW.js.map → chunk-OQ6663F4.js.map} +0 -0
  397. /package/dist/{chunk-H3427GPU.js.map → chunk-OZRUJVIQ.js.map} +0 -0
  398. /package/dist/{chunk-KMKEYI37.js.map → chunk-Q2V6E6SL.js.map} +0 -0
  399. /package/dist/{chunk-VL43TNIP.js.map → chunk-QRP3PXWN.js.map} +0 -0
  400. /package/dist/{chunk-C46GUI2S.js.map → chunk-RZBEK2VE.js.map} +0 -0
  401. /package/dist/{chunk-2VPBIT65.js.map → chunk-S3A3YOKO.js.map} +0 -0
  402. /package/dist/{chunk-FYGR3I2A.js.map → chunk-S77PZVYM.js.map} +0 -0
  403. /package/dist/{chunk-VLMBTPXU.js.map → chunk-SHL7LOC3.js.map} +0 -0
  404. /package/dist/{chunk-KS2QY6MK.js.map → chunk-W3ZHJJVT.js.map} +0 -0
  405. /package/dist/{chunk-RL5CP7N6.js.map → chunk-Y6O7EWYY.js.map} +0 -0
  406. /package/dist/{chunk-6NY2GPR4.js.map → chunk-Y6ZQXUZ7.js.map} +0 -0
  407. /package/dist/{chunk-WKQG6TER.js.map → chunk-ZEYEWPK6.js.map} +0 -0
  408. /package/dist/{connect-FCXNVTXG.js.map → connect-QCOGEPP4.js.map} +0 -0
  409. /package/dist/{creatives-FXUQ5WSD.js.map → creatives-B5NTXPUB.js.map} +0 -0
  410. /package/dist/{customers-XH2DMTFH.js.map → customers-A36LOZOB.js.map} +0 -0
  411. /package/dist/{feedback-EIZKS4JU.js.map → feedback-OLTCHE6C.js.map} +0 -0
  412. /package/dist/{find-FRRHAPWX.js.map → find-OTDIX6V4.js.map} +0 -0
  413. /package/dist/{fonts-MXR3ZKDX.js.map → fonts-EMMX3KII.js.map} +0 -0
  414. /package/dist/{ga4-DV2AXCSL.js.map → ga4-UDQ2HA2J.js.map} +0 -0
  415. /package/dist/{google-QYYYSSXI.js.map → google-KTO3PLEU.js.map} +0 -0
  416. /package/dist/{google-6OGZX47I.js.map → google-M7KEXVK5.js.map} +0 -0
  417. /package/dist/{gsc-TAKOF7J5.js.map → gsc-P3QYGDV2.js.map} +0 -0
  418. /package/dist/{icon-L4RSS6PZ.js.map → icon-I43F77FV.js.map} +0 -0
  419. /package/dist/{ideas-NFOW3HKJ.js.map → ideas-MIDU7YOA.js.map} +0 -0
  420. /package/dist/{images-2EFFUNNV.js.map → images-S254MS6O.js.map} +0 -0
  421. /package/dist/{ingest-2EIKN4QC.js.map → ingest-YV2NLDBE.js.map} +0 -0
  422. /package/dist/{inspiration-S3DU4CMQ.js.map → inspiration-P265QJ2H.js.map} +0 -0
  423. /package/dist/{landing-2ZB46LXH.js.map → landing-CJYGWCK4.js.map} +0 -0
  424. /package/dist/{line-items-5NECXUZT.js.map → line-items-7ZGIKEF2.js.map} +0 -0
  425. /package/dist/{logo-Q5D7PZY6.js.map → logo-2IP663QO.js.map} +0 -0
  426. /package/dist/{lookup-ETWY47F7.js.map → lookup-XK45W2SH.js.map} +0 -0
  427. /package/dist/{media-sources-ZXHEEP6T.js.map → media-sources-O6ZRUA3N.js.map} +0 -0
  428. /package/dist/{performance-UF5VTY2U.js.map → performance-6QW2KEEQ.js.map} +0 -0
  429. /package/dist/{promoted-tweets-LZKS5JIF.js.map → promoted-tweets-SURKMHFI.js.map} +0 -0
  430. /package/dist/{reddit-NU2N3LZD.js.map → reddit-GIP3ADMS.js.map} +0 -0
  431. /package/dist/{research-FMM6AWZC.js.map → research-2BLEISBG.js.map} +0 -0
  432. /package/dist/{run-EUO34T2J.js.map → run-MMEDKJDB.js.map} +0 -0
  433. /package/dist/{scheduled-agents-N4LJRM4C.js.map → scheduled-agents-6U44QE76.js.map} +0 -0
  434. /package/dist/{sources-FQ2UZTHL.js.map → sources-YBQ6KPFM.js.map} +0 -0
  435. /package/dist/{stock-KXJ26BY4.js.map → stock-2YCDN3N6.js.map} +0 -0
  436. /package/dist/{studio-SYKOSNDB.js.map → studio-RA7QQH4O.js.map} +0 -0
  437. /package/dist/{sync-definition-QR2N233R.js.map → sync-definition-UGSDX2SZ.js.map} +0 -0
  438. /package/dist/{tags-PYWFSBTR.js.map → tags-3WPW6PTV.js.map} +0 -0
  439. /package/dist/{targeting-criteria-RJFLFICN.js.map → targeting-criteria-NR47AF5C.js.map} +0 -0
  440. /package/dist/{testimonials-DII5DYLR.js.map → testimonials-CVC4YIXO.js.map} +0 -0
  441. /package/dist/{videos-LICG6ACJ.js.map → videos-YSXYGTBM.js.map} +0 -0
  442. /package/dist/{winning-ads-C6S2C5VP.js.map → winning-ads-2WS7FI4E.js.map} +0 -0
  443. /package/dist/{x-CZHRC6U7.js.map → x-BFSKFCZD.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/ads/linkedin/draft.ts","../src/commands/ads/linkedin/draft-status.ts"],"sourcesContent":["import type {\n LinkedinDraftAmendRequest,\n LinkedinDraftClearResponse,\n LinkedinDraftListResponse,\n LinkedinDraftRemoveResponse,\n LinkedinDraftShowRequest,\n LinkedinDraftShowResponse,\n LinkedinDraftStageResponse,\n} from \"@baker/api\";\nimport { defineCommand } from \"citty\";\nimport { apiPost } from \"../../../client.ts\";\nimport { requireChatId, resolveChatId } from \"../../../env.ts\";\nimport { CHAT_READ_ARG } from \"../../chat-arg.ts\";\nimport { hintLines } from \"../hints.ts\";\nimport { writeJsonEnvelope } from \"../output.ts\";\nimport { renderDraftStatus } from \"./draft-status.ts\";\nimport { handleLinkedinError } from \"./shared.ts\";\nimport { loadPatchArg, requireTarget } from \"./write-shared.ts\";\n\n/**\n * List the staged draft. By default renders a readable Campaign group ▸ Campaign ▸ Creative status\n * tree so the agent can review everything it has staged at a glance; `--json` returns the raw\n * envelope for tools.\n */\nasync function listDraft(json: boolean, chat?: unknown): Promise<void> {\n try {\n const chatId = resolveChatId(chat);\n const response = await apiPost<{ ok: boolean; data?: LinkedinDraftListResponse }>(\"/api/ads/linkedin/draft\", {\n chatId,\n });\n if (json || !response.ok || !response.data) {\n writeJsonEnvelope(response);\n return;\n }\n process.stdout.write(`${renderDraftStatus(response.data)}${hintLines(response)}\\n`);\n } catch (err) {\n handleLinkedinError(err);\n }\n}\n\nconst listCommand = defineCommand({\n meta: {\n name: \"list\",\n description:\n \"Review everything staged as a Campaign group ▸ Campaign ▸ Creative tree (--json for the raw envelope). Example: baker ads linkedin draft\",\n },\n args: {\n json: { type: \"boolean\", description: \"Print the raw JSON envelope instead of the readable tree\" },\n chat: CHAT_READ_ARG,\n },\n run: async ({ args }) => {\n await listDraft(args.json === true, args.chat);\n },\n});\n\nconst removeCommand = defineCommand({\n meta: {\n name: \"remove\",\n description:\n \"Drop one staged LinkedIn op. Removing a create cascades to everything that depends on it — except a company exclusion, which only loses the removed audience and keeps its companies (listed under `updated`). Example: baker ads linkedin draft remove li_temp_abc123\",\n },\n args: {\n ref: {\n type: \"positional\",\n description: \"Op ref (li_temp_* for creates, target id/URN for updates)\",\n required: true,\n },\n },\n run: async ({ args }) => {\n try {\n const chatId = requireChatId();\n const response = await apiPost<{ ok: true; data: LinkedinDraftRemoveResponse }>(\n \"/api/ads/linkedin/draft/remove\",\n { chatId, ref: args.ref },\n );\n writeJsonEnvelope(response);\n } catch (err) {\n handleLinkedinError(err);\n }\n },\n});\n\nconst clearCommand = defineCommand({\n meta: {\n name: \"clear\",\n description:\n \"Discard ALL staged LinkedIn ops in this chat's draft — nothing will apply on publish. Example: baker ads linkedin draft clear\",\n },\n run: async () => {\n try {\n const chatId = requireChatId();\n const response = await apiPost<{ ok: true; data: LinkedinDraftClearResponse }>(\"/api/ads/linkedin/draft/clear\", {\n chatId,\n });\n writeJsonEnvelope(response);\n } catch (err) {\n handleLinkedinError(err);\n }\n },\n});\n\nconst amendCommand = defineCommand({\n meta: {\n name: \"amend\",\n description:\n \"Update a staged op in place — merges a JSON patch into its payload (RFC-7386: objects deep-merge, null deletes a key, arrays/scalars replace) and re-validates. Use this instead of remove + re-create.\",\n },\n args: {\n ref: { type: \"positional\", description: \"Staged op ref (li_temp_*) or target id/URN\", required: true },\n file: { type: \"string\", description: \"JSON file with the patch object\" },\n patch: { type: \"string\", description: \"Inline JSON patch object\" },\n },\n run: async ({ args }) => {\n const ref = requireTarget(args as Record<string, unknown>, \"op\");\n const patch = loadPatchArg(args as Record<string, unknown>);\n try {\n const chatId = requireChatId();\n const body: LinkedinDraftAmendRequest = { chatId, ref, patch };\n const response = await apiPost<{ ok: true; data: LinkedinDraftStageResponse }>(\n \"/api/ads/linkedin/draft/amend\",\n body,\n );\n writeJsonEnvelope(response);\n } catch (err) {\n handleLinkedinError(err);\n }\n },\n});\n\nconst showCommand = defineCommand({\n meta: {\n name: \"show\",\n description:\n \"Print the full staged payload for one op — the receipt to verify a change looks right before publish (never truncated).\",\n },\n args: {\n ref: { type: \"positional\", description: \"Staged op ref (li_temp_*) or target id/URN\", required: true },\n chat: CHAT_READ_ARG,\n },\n run: async ({ args }) => {\n const ref = requireTarget(args as Record<string, unknown>, \"op\");\n try {\n const chatId = resolveChatId(args.chat);\n const body: LinkedinDraftShowRequest = { chatId, ref };\n const response = await apiPost<{ ok: true; data: LinkedinDraftShowResponse }>(\n \"/api/ads/linkedin/draft/show\",\n body,\n );\n writeJsonEnvelope(response);\n } catch (err) {\n handleLinkedinError(err);\n }\n },\n});\n\nexport const linkedinDraftCommand = defineCommand({\n meta: {\n name: \"draft\",\n description:\n \"Review and edit the LinkedIn write ops staged in this chat BEFORE publish. Subcommands: list (default), remove, clear, amend, show. Ops never hit LinkedIn until the chat is published. `list` and `show` take --chat <id> to read an earlier chat's changes instead.\",\n },\n // Declared on the parent too: `default: \"list\"` dispatches the bare `draft --chat <id>` form, and\n // citty prints help for a flag the parent does not know instead of forwarding it.\n args: { chat: CHAT_READ_ARG },\n subCommands: {\n list: listCommand,\n remove: removeCommand,\n clear: clearCommand,\n amend: amendCommand,\n show: showCommand,\n },\n // A parent must never declare `run`: citty falls through to it *after* running\n // the matched subcommand, so `draft show <ref>` would also re-list the draft.\n default: \"list\",\n});\n","import type { LinkedinDraftListResponse, LinkedinDraftStatusCollection, LinkedinDraftStatusNode } from \"@baker/api\";\n\n/**\n * Render the staged LinkedIn draft as a readable Campaign group ▸ Campaign ▸ Creative tree — the\n * CLI counterpart to `ads google draft list`'s campaign ▸ ad group ▸ ad tree, using the identical\n * node shape (`LinkedinDraftStatusNode` mirrors `GoogleDraftStatusNode`). Pure: takes the draft-list\n * response, returns text.\n */\n\nconst OPERATION_LABELS: Record<string, string> = {\n create: \"Creating\",\n update: \"Updating\",\n pause: \"Pausing\",\n resume: \"Resuming\",\n archive: \"Archiving\",\n};\n\nfunction badge(node: LinkedinDraftStatusNode): string {\n const label = node.operation ? OPERATION_LABELS[node.operation] : undefined;\n if (label) {\n return label;\n }\n return node.existing ? \"on LinkedIn\" : \"staged\";\n}\n\nfunction collectionLine(collection: LinkedinDraftStatusCollection): string | undefined {\n const parts: string[] = [];\n if (collection.added > 0) {\n parts.push(`+${collection.added}`);\n }\n if (collection.existing > 0) {\n parts.push(`${collection.existing} existing`);\n }\n if (collection.removed > 0) {\n parts.push(`-${collection.removed}`);\n }\n return parts.length > 0 ? `${collection.label}: ${parts.join(\", \")}` : undefined;\n}\n\n/**\n * Every ad account the tree touches. A draft may legitimately span several, and\n * two accounts can hold identically-named campaigns — so the account is printed\n * on each node once there is more than one, and left off when there is not.\n */\nfunction accountsInTree(nodes: readonly LinkedinDraftStatusNode[]): Set<string> {\n const accounts = new Set<string>();\n const walk = (node: LinkedinDraftStatusNode): void => {\n accounts.add(node.accountId);\n for (const child of node.children) {\n walk(child);\n }\n };\n for (const node of nodes) {\n walk(node);\n }\n return accounts;\n}\n\nfunction renderNode(node: LinkedinDraftStatusNode, depth: number, lines: string[], showAccount: boolean): void {\n const indent = \" \".repeat(depth);\n const account = showAccount ? ` · account ${node.accountId}` : \"\";\n lines.push(`${indent}• ${node.name} · ${badge(node)}${account}`);\n for (const warning of node.warnings ?? []) {\n lines.push(`${indent} ⚠ ${warning}`);\n }\n for (const collection of node.collections) {\n const line = collectionLine(collection);\n if (line) {\n lines.push(`${indent} ${line}`);\n }\n }\n for (const child of node.children) {\n renderNode(child, depth + 1, lines, showAccount);\n }\n}\n\nfunction renderSection(title: string, nodes: LinkedinDraftStatusNode[], lines: string[], showAccount: boolean): void {\n if (nodes.length === 0) {\n return;\n }\n lines.push(\"\");\n lines.push(title);\n for (const node of nodes) {\n renderNode(node, 1, lines, showAccount);\n }\n}\n\n/** Campaign group ▸ Campaign ▸ Creative roots go under \"Campaigns\" (campaign group is the group parent). */\nconst CAMPAIGN_TREE_ENTITIES = new Set([\"campaignGroup\", \"campaign\", \"creative\"]);\n\n/**\n * What the publish did, once there is a publish to report.\n *\n * A published draft used to render exactly like a staged one — same count, same\n * tree, no mention of the outcome — so the surface an agent reaches for to see\n * what a publish did could not answer, and a publish that changed LinkedIn and\n * then failed to finish was indistinguishable from one that had not run yet.\n * The per-op results were in the response the whole time; only the renderer\n * dropped them.\n */\nfunction renderOutcome(data: LinkedinDraftListResponse, lines: string[]): void {\n const counts = new Map<string, number>();\n for (const op of data.ops ?? []) {\n const status = op.result?.status ?? \"pending\";\n counts.set(status, (counts.get(status) ?? 0) + 1);\n }\n const summary = [...counts].map(([status, count]) => `${count} ${status}`).join(\", \");\n lines.push(`LinkedIn Ads — published · ${summary || `${data.count} op(s)`} · ${data.mode}`);\n // A failure is the reason to read this at all, so it is named with its error\n // rather than left as a number to go and look up.\n for (const op of data.ops ?? []) {\n const status = op.result?.status;\n // An audience whose segment was created but whose rule or rows did not\n // land is `applied` with an error: it exists on LinkedIn and stays empty.\n if (status === \"applied\" && op.result?.error) {\n lines.push(` ⚠ ${op.summary} — applied in part: ${op.result.error}`);\n continue;\n }\n if (status !== \"failed\" && status !== \"skipped\") {\n continue;\n }\n const reason = op.result?.error ?? op.result?.skippedBecause ?? \"no reason recorded\";\n lines.push(` ✗ ${op.summary} — ${status}: ${reason}`);\n }\n}\n\nexport function renderDraftStatus(data: LinkedinDraftListResponse): string {\n if (data.status === \"none\" || data.count === 0) {\n return \"No staged LinkedIn changes on this chat.\";\n }\n const modeNote =\n data.mode === \"live\"\n ? \"Live — publishing writes directly to LinkedIn.\"\n : \"Simulated — publishing completes the whole draft without calling LinkedIn.\";\n const lines: string[] = [];\n if (data.status === \"applied\") {\n renderOutcome(data, lines);\n } else if (data.status === \"publishing\") {\n lines.push(`LinkedIn Ads — publishing ${data.count} change${data.count === 1 ? \"\" : \"s\"} · ${data.mode}`);\n } else {\n lines.push(`LinkedIn Ads — ${data.count} staged change${data.count === 1 ? \"\" : \"s\"} · ${data.mode}`);\n }\n lines.push(modeNote);\n\n const tree = data.tree ?? [];\n const showAccount = accountsInTree(tree).size > 1;\n renderSection(\n \"Campaigns\",\n tree.filter((node) => CAMPAIGN_TREE_ENTITIES.has(node.entity)),\n lines,\n showAccount,\n );\n const rest = tree.filter((node) => !CAMPAIGN_TREE_ENTITIES.has(node.entity));\n renderSection(\"Other\", rest, lines, showAccount);\n\n return lines.join(\"\\n\");\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/commands/ads/linkedin/draft.ts","../src/commands/ads/linkedin/draft-status.ts"],"sourcesContent":["import type {\n LinkedinDraftAmendRequest,\n LinkedinDraftClearResponse,\n LinkedinDraftListResponse,\n LinkedinDraftRemoveResponse,\n LinkedinDraftShowRequest,\n LinkedinDraftShowResponse,\n LinkedinDraftStageResponse,\n} from \"@baker/api\";\nimport { defineCommand } from \"citty\";\nimport { apiPost } from \"../../../client.ts\";\nimport { requireChatId, resolveChatId } from \"../../../env.ts\";\nimport { CHAT_READ_ARG } from \"../../chat-arg.ts\";\nimport { hintLines } from \"../hints.ts\";\nimport { writeJsonEnvelope } from \"../output.ts\";\nimport { renderDraftStatus } from \"./draft-status.ts\";\nimport { handleLinkedinError } from \"./shared.ts\";\nimport { loadPatchArg, requireTarget } from \"./write-shared.ts\";\n\n/**\n * List the staged draft. By default renders a readable Campaign group ▸ Campaign ▸ Creative status\n * tree so the agent can review everything it has staged at a glance; `--json` returns the raw\n * envelope for tools.\n */\nasync function listDraft(json: boolean, chat?: unknown): Promise<void> {\n try {\n const chatId = resolveChatId(chat);\n const response = await apiPost<{ ok: boolean; data?: LinkedinDraftListResponse }>(\"/api/ads/linkedin/draft\", {\n chatId,\n });\n if (json || !response.ok || !response.data) {\n writeJsonEnvelope(response);\n return;\n }\n process.stdout.write(`${renderDraftStatus(response.data)}${hintLines(response)}\\n`);\n } catch (err) {\n handleLinkedinError(err);\n }\n}\n\nconst listCommand = defineCommand({\n meta: {\n name: \"list\",\n description:\n \"Review everything staged as a Campaign group ▸ Campaign ▸ Creative tree (--json for the raw envelope). Example: baker ads linkedin draft\",\n },\n args: {\n json: { type: \"boolean\", description: \"Print the raw JSON envelope instead of the readable tree\" },\n chat: CHAT_READ_ARG,\n },\n run: async ({ args }) => {\n await listDraft(args.json === true, args.chat);\n },\n});\n\nconst removeCommand = defineCommand({\n meta: {\n name: \"remove\",\n description:\n \"Drop one staged LinkedIn op. Removing a create cascades to everything that depends on it — except a company exclusion, which only loses the removed audience and keeps its companies (listed under `updated`). Example: baker ads linkedin draft remove li_temp_abc123\",\n },\n args: {\n ref: {\n type: \"positional\",\n description: \"Op ref (li_temp_* for creates, target id/URN for updates)\",\n required: true,\n },\n },\n run: async ({ args }) => {\n try {\n const chatId = requireChatId();\n const response = await apiPost<{ ok: true; data: LinkedinDraftRemoveResponse }>(\n \"/api/ads/linkedin/draft/remove\",\n { chatId, ref: args.ref },\n );\n writeJsonEnvelope(response);\n } catch (err) {\n handleLinkedinError(err);\n }\n },\n});\n\nconst clearCommand = defineCommand({\n meta: {\n name: \"clear\",\n description:\n \"Discard ALL staged LinkedIn ops in this chat's draft — nothing will apply on publish. Example: baker ads linkedin draft clear\",\n },\n run: async () => {\n try {\n const chatId = requireChatId();\n const response = await apiPost<{ ok: true; data: LinkedinDraftClearResponse }>(\"/api/ads/linkedin/draft/clear\", {\n chatId,\n });\n writeJsonEnvelope(response);\n } catch (err) {\n handleLinkedinError(err);\n }\n },\n});\n\nconst amendCommand = defineCommand({\n meta: {\n name: \"amend\",\n description:\n \"Update a staged op in place — merges a JSON patch into its payload (RFC-7386: objects deep-merge, null deletes a key, arrays/scalars replace) and re-validates. Use this instead of remove + re-create.\",\n },\n args: {\n ref: { type: \"positional\", description: \"Staged op ref (li_temp_*) or target id/URN\", required: true },\n file: { type: \"string\", description: \"JSON file with the patch object\" },\n patch: { type: \"string\", description: \"Inline JSON patch object\" },\n },\n run: async ({ args }) => {\n const ref = requireTarget(args as Record<string, unknown>, \"op\");\n const patch = loadPatchArg(args as Record<string, unknown>);\n try {\n const chatId = requireChatId();\n const body: LinkedinDraftAmendRequest = { chatId, ref, patch };\n const response = await apiPost<{ ok: true; data: LinkedinDraftStageResponse }>(\n \"/api/ads/linkedin/draft/amend\",\n body,\n );\n writeJsonEnvelope(response);\n } catch (err) {\n handleLinkedinError(err);\n }\n },\n});\n\nconst showCommand = defineCommand({\n meta: {\n name: \"show\",\n description:\n \"Print the full staged payload for one op — the receipt to verify a change looks right before publish (never truncated).\",\n },\n args: {\n ref: { type: \"positional\", description: \"Staged op ref (li_temp_*) or target id/URN\", required: true },\n chat: CHAT_READ_ARG,\n },\n run: async ({ args }) => {\n const ref = requireTarget(args as Record<string, unknown>, \"op\");\n try {\n const chatId = resolveChatId(args.chat);\n const body: LinkedinDraftShowRequest = { chatId, ref };\n const response = await apiPost<{ ok: true; data: LinkedinDraftShowResponse }>(\n \"/api/ads/linkedin/draft/show\",\n body,\n );\n writeJsonEnvelope(response);\n } catch (err) {\n handleLinkedinError(err);\n }\n },\n});\n\nexport const linkedinDraftCommand = defineCommand({\n meta: {\n name: \"draft\",\n description:\n \"Review and edit the LinkedIn write ops staged in this chat BEFORE publish. Subcommands: list (default), remove, clear, amend, show. Ops never hit LinkedIn until the chat is published. `list` and `show` take --chat <id> to read an earlier chat's changes instead.\",\n },\n // Declared on the parent too: `default: \"list\"` dispatches the bare `draft --chat <id>` form, and\n // citty prints help for a flag the parent does not know instead of forwarding it.\n args: { chat: CHAT_READ_ARG },\n subCommands: {\n list: listCommand,\n remove: removeCommand,\n clear: clearCommand,\n amend: amendCommand,\n show: showCommand,\n },\n // A parent must never declare `run`: citty falls through to it *after* running\n // the matched subcommand, so `draft show <ref>` would also re-list the draft.\n default: \"list\",\n});\n","import type { LinkedinDraftListResponse, LinkedinDraftStatusCollection, LinkedinDraftStatusNode } from \"@baker/api\";\n\n/**\n * Render the staged LinkedIn draft as a readable Campaign group ▸ Campaign ▸ Creative tree — the\n * CLI counterpart to `ads google draft list`'s campaign ▸ ad group ▸ ad tree, using the identical\n * node shape (`LinkedinDraftStatusNode` mirrors `GoogleDraftStatusNode`). Pure: takes the draft-list\n * response, returns text.\n */\n\nconst OPERATION_LABELS: Record<string, string> = {\n create: \"Creating\",\n update: \"Updating\",\n pause: \"Pausing\",\n resume: \"Resuming\",\n archive: \"Archiving\",\n};\n\nfunction badge(node: LinkedinDraftStatusNode): string {\n const label = node.operation ? OPERATION_LABELS[node.operation] : undefined;\n if (label) {\n return label;\n }\n return node.existing ? \"on LinkedIn\" : \"staged\";\n}\n\nfunction collectionLine(collection: LinkedinDraftStatusCollection): string | undefined {\n const parts: string[] = [];\n if (collection.added > 0) {\n parts.push(`+${collection.added}`);\n }\n if (collection.existing > 0) {\n parts.push(`${collection.existing} existing`);\n }\n if (collection.removed > 0) {\n parts.push(`-${collection.removed}`);\n }\n return parts.length > 0 ? `${collection.label}: ${parts.join(\", \")}` : undefined;\n}\n\n/**\n * Every ad account the tree touches. A draft may legitimately span several, and\n * two accounts can hold identically-named campaigns — so the account is printed\n * on each node once there is more than one, and left off when there is not.\n */\nfunction accountsInTree(nodes: readonly LinkedinDraftStatusNode[]): Set<string> {\n const accounts = new Set<string>();\n const walk = (node: LinkedinDraftStatusNode): void => {\n accounts.add(node.accountId);\n for (const child of node.children) {\n walk(child);\n }\n };\n for (const node of nodes) {\n walk(node);\n }\n return accounts;\n}\n\nfunction renderNode(node: LinkedinDraftStatusNode, depth: number, lines: string[], showAccount: boolean): void {\n const indent = \" \".repeat(depth);\n const account = showAccount ? ` · account ${node.accountId}` : \"\";\n lines.push(`${indent}• ${node.name} · ${badge(node)}${account}`);\n for (const warning of node.warnings ?? []) {\n lines.push(`${indent} ⚠ ${warning}`);\n }\n for (const collection of node.collections) {\n const line = collectionLine(collection);\n if (line) {\n lines.push(`${indent} ${line}`);\n }\n }\n for (const child of node.children) {\n renderNode(child, depth + 1, lines, showAccount);\n }\n}\n\nfunction renderSection(title: string, nodes: LinkedinDraftStatusNode[], lines: string[], showAccount: boolean): void {\n if (nodes.length === 0) {\n return;\n }\n lines.push(\"\");\n lines.push(title);\n for (const node of nodes) {\n renderNode(node, 1, lines, showAccount);\n }\n}\n\n/** Campaign group ▸ Campaign ▸ Creative roots go under \"Campaigns\" (campaign group is the group parent). */\nconst CAMPAIGN_TREE_ENTITIES = new Set([\"campaignGroup\", \"campaign\", \"creative\"]);\n\n/**\n * What the publish did, once there is a publish to report.\n *\n * A published draft used to render exactly like a staged one — same count, same\n * tree, no mention of the outcome — so the surface an agent reaches for to see\n * what a publish did could not answer, and a publish that changed LinkedIn and\n * then failed to finish was indistinguishable from one that had not run yet.\n * The per-op results were in the response the whole time; only the renderer\n * dropped them.\n */\nfunction renderOutcome(data: LinkedinDraftListResponse, lines: string[]): void {\n const counts = new Map<string, number>();\n for (const op of data.ops ?? []) {\n const status = op.result?.status ?? \"pending\";\n counts.set(status, (counts.get(status) ?? 0) + 1);\n }\n const summary = [...counts].map(([status, count]) => `${count} ${status}`).join(\", \");\n lines.push(`LinkedIn Ads — published · ${summary || `${data.count} op(s)`} · ${data.mode}`);\n // A failure is the reason to read this at all, so it is named with its error\n // rather than left as a number to go and look up.\n for (const op of data.ops ?? []) {\n const status = op.result?.status;\n // An audience whose segment was created but whose rule or rows did not\n // land is `applied` with an error: it exists on LinkedIn and stays empty.\n if (status === \"applied\" && op.result?.error) {\n lines.push(` ⚠ ${op.summary} — applied in part: ${op.result.error}`);\n continue;\n }\n if (status !== \"failed\" && status !== \"skipped\") {\n continue;\n }\n const reason = op.result?.error ?? op.result?.skippedBecause ?? \"no reason recorded\";\n lines.push(` ✗ ${op.summary} — ${status}: ${reason}`);\n }\n}\n\nexport function renderDraftStatus(data: LinkedinDraftListResponse): string {\n if (data.status === \"none\" || data.count === 0) {\n return \"No staged LinkedIn changes on this chat.\";\n }\n const modeNote =\n data.mode === \"live\"\n ? \"Live — publishing writes directly to LinkedIn.\"\n : \"Simulated — publishing completes the whole draft without calling LinkedIn.\";\n const lines: string[] = [];\n if (data.status === \"applied\") {\n renderOutcome(data, lines);\n } else if (data.status === \"publishing\") {\n lines.push(`LinkedIn Ads — publishing ${data.count} change${data.count === 1 ? \"\" : \"s\"} · ${data.mode}`);\n } else {\n lines.push(`LinkedIn Ads — ${data.count} staged change${data.count === 1 ? \"\" : \"s\"} · ${data.mode}`);\n }\n lines.push(modeNote);\n\n const tree = data.tree ?? [];\n const showAccount = accountsInTree(tree).size > 1;\n renderSection(\n \"Campaigns\",\n tree.filter((node) => CAMPAIGN_TREE_ENTITIES.has(node.entity)),\n lines,\n showAccount,\n );\n const rest = tree.filter((node) => !CAMPAIGN_TREE_ENTITIES.has(node.entity));\n renderSection(\"Other\", rest, lines, showAccount);\n\n return lines.join(\"\\n\");\n}\n"],"mappings":"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","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  failWriteValidation
3
- } from "./chunk-VYQ3QJ3C.js";
3
+ } from "./chunk-KHRXPQID.js";
4
4
  import {
5
5
  parseXApiError
6
6
  } from "./chunk-M6UNISGO.js";
@@ -12,11 +12,10 @@ import {
12
12
  import {
13
13
  CHAT_READ_ARG
14
14
  } from "./chunk-PFBQERWX.js";
15
- import "./chunk-7EPXVICM.js";
15
+ import "./chunk-XF4JUKVF.js";
16
16
  import "./chunk-GXDLWBOY.js";
17
17
  import "./chunk-TEINLN64.js";
18
18
  import "./chunk-ZJWUBJYQ.js";
19
- import "./chunk-HR6IWNKE.js";
20
19
  import "./chunk-NE4F3FHN.js";
21
20
  import {
22
21
  ApiError,
@@ -326,4 +325,4 @@ Examples:
326
325
  export {
327
326
  draftCommand
328
327
  };
329
- //# sourceMappingURL=draft-PVTX6QT6.js.map
328
+ //# sourceMappingURL=draft-FJ7WHIXW.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/ads/x/draft.ts","../src/commands/ads/x/draft-status.ts"],"sourcesContent":["import { readFileSync } from \"node:fs\";\nimport type {\n XDraftClearResponse,\n XDraftListResponse,\n XDraftRemoveResponse,\n XDraftShowResponse,\n XDraftStageResponse,\n} from \"@baker/api\";\nimport { defineCommand } from \"citty\";\nimport { ApiError, apiPost } from \"../../../client.ts\";\nimport { requireChatId, resolveChatId } from \"../../../env.ts\";\nimport { registerSchema } from \"../../../schemas.ts\";\nimport { CHAT_READ_ARG } from \"../../chat-arg.ts\";\nimport { writeAdsJson, writeJsonEnvelope } from \"../output.ts\";\nimport { renderDraftStatus } from \"./draft-status.ts\";\nimport { parseXApiError } from \"./error-parser.ts\";\nimport { failWriteValidation } from \"./write-shared.ts\";\n\nfunction handleDraftError(err: unknown): never {\n if (err instanceof ApiError) {\n writeAdsJson(parseXApiError(err.message, \"—\"));\n process.exit(1);\n }\n writeAdsJson({ ok: false, error: { code: \"NETWORK_ERROR\", message: \"Unexpected error\" } });\n process.exit(1);\n}\n\nregisterSchema({\n command: \"ads.x.draft\",\n description:\n \"Review everything staged for X Ads on this chat as a Campaign ▸ Ad group ▸ Ad tree. After a publish this is the authoritative record: `published · N applied`, or a `✗ … failed:` line per op that did not land.\",\n args: {\n json: { type: \"boolean\", description: \"Raw JSON envelope instead of the readable tree\", required: false },\n chat: { type: \"string\", description: \"Read another chat's draft instead of this one\", required: false },\n },\n});\n\nasync function listDraft(json: boolean, chat?: unknown): Promise<void> {\n try {\n const chatId = resolveChatId(chat);\n const response = await apiPost<{ ok: boolean; data?: XDraftListResponse }>(\"/api/ads/x/draft\", { chatId });\n if (json || !response.ok || !response.data) {\n writeJsonEnvelope(response);\n return;\n }\n process.stdout.write(`${renderDraftStatus(response.data)}\\n`);\n } catch (err) {\n handleDraftError(err);\n }\n}\n\nconst listCommand = defineCommand({\n meta: {\n name: \"list\",\n description: \"Review everything staged as a Campaign ▸ Ad group ▸ Ad tree. Example: baker ads x draft\",\n },\n args: {\n json: { type: \"boolean\", description: \"Print the raw JSON envelope instead of the readable tree\" },\n chat: CHAT_READ_ARG,\n },\n run: async ({ args }) => {\n await listDraft(args.json === true, args.chat);\n },\n});\n\nregisterSchema({\n command: \"ads.x.draft.show\",\n description:\n \"The full staged payload, warnings and before-snapshot for one op — the receipt to check before publishing.\",\n args: {\n ref: { type: \"string\", description: \"Op ref (x_temp_* for creates, the target id for updates)\", required: true },\n chat: { type: \"string\", description: \"Read another chat's draft instead of this one\", required: false },\n },\n});\n\nconst showCommand = defineCommand({\n meta: {\n name: \"show\",\n description: \"Show one staged op in full. Example: baker ads x draft show x_temp_abc123\",\n },\n args: {\n ref: { type: \"positional\", description: \"Op ref, or the target id for a staged update\", required: true },\n chat: CHAT_READ_ARG,\n },\n run: async ({ args }) => {\n try {\n const chatId = resolveChatId(args.chat);\n const response = await apiPost<{ ok: boolean; data?: XDraftShowResponse }>(\"/api/ads/x/draft/show\", {\n chatId,\n ref: String(args.ref),\n });\n writeJsonEnvelope(response);\n } catch (err) {\n handleDraftError(err);\n }\n },\n});\n\nregisterSchema({\n command: \"ads.x.draft.amend\",\n description:\n \"Change a staged op in place instead of removing and re-staging it. The patch merges into the payload (JSON merge-patch: `null` deletes a key) and the whole op re-validates.\",\n args: {\n ref: { type: \"string\", description: \"Op ref or target id\", required: true },\n patch: { type: \"string\", description: \"JSON object, or @path to a file holding one\", required: true },\n },\n});\n\nconst amendCommand = defineCommand({\n meta: {\n name: \"amend\",\n description: `Change a staged op in place.\n\nExample:\n baker ads x draft amend x_temp_abc '{\"dailyBudgetAmountLocalMicro\": 20000000}'`,\n },\n args: {\n ref: { type: \"positional\", description: \"Op ref or target id\", required: true },\n patch: { type: \"positional\", description: \"JSON object, or @path to a file\", required: true },\n },\n run: async ({ args }) => {\n const raw = String(args.patch);\n let patch: unknown;\n try {\n patch = JSON.parse(raw.startsWith(\"@\") ? readFileSync(raw.slice(1), \"utf8\") : raw);\n } catch {\n failWriteValidation(\"patch must be a JSON object, or @path to a file holding one\");\n }\n if (patch === null || typeof patch !== \"object\" || Array.isArray(patch)) {\n failWriteValidation(\"patch must be a JSON object\");\n }\n try {\n const chatId = requireChatId();\n const response = await apiPost<{ ok: boolean; data?: XDraftStageResponse }>(\"/api/ads/x/draft/amend\", {\n chatId,\n ref: String(args.ref),\n patch,\n });\n writeJsonEnvelope(response);\n } catch (err) {\n handleDraftError(err);\n }\n },\n});\n\nregisterSchema({\n command: \"ads.x.draft.remove\",\n description: \"Drop one staged X op. Removing a create cascades to everything staged that depends on it.\",\n args: { ref: { type: \"string\", description: \"Op ref or target id\", required: true } },\n});\n\nconst removeCommand = defineCommand({\n meta: {\n name: \"remove\",\n description: \"Drop one staged op (cascades to its dependents). Example: baker ads x draft remove x_temp_abc123\",\n },\n args: { ref: { type: \"positional\", description: \"Op ref or target id\", required: true } },\n run: async ({ args }) => {\n try {\n const chatId = requireChatId();\n const response = await apiPost<{ ok: boolean; data?: XDraftRemoveResponse }>(\"/api/ads/x/draft/remove\", {\n chatId,\n ref: String(args.ref),\n });\n writeJsonEnvelope(response);\n } catch (err) {\n handleDraftError(err);\n }\n },\n});\n\nregisterSchema({\n command: \"ads.x.draft.clear\",\n description: \"Drop every staged X op on this chat. Nothing reached X, so nothing needs reversing.\",\n args: {},\n});\n\nconst clearCommand = defineCommand({\n meta: { name: \"clear\", description: \"Drop every staged X op on this chat. Example: baker ads x draft clear\" },\n args: {},\n run: async () => {\n try {\n const chatId = requireChatId();\n const response = await apiPost<{ ok: boolean; data?: XDraftClearResponse }>(\"/api/ads/x/draft/clear\", { chatId });\n writeJsonEnvelope(response);\n } catch (err) {\n handleDraftError(err);\n }\n },\n});\n\nexport const draftCommand = defineCommand({\n meta: {\n name: \"draft\",\n description: `Review and edit the X Ads changes staged on this chat.\n\nNothing staged has reached X. Everything applies when the chat is published,\nand discarding the chat reverses all of it.\n\nExamples:\n baker ads x draft — the Campaign ▸ Ad group ▸ Ad tree\n baker ads x draft show x_temp_abc123 — one op in full\n baker ads x draft amend x_temp_abc '{\"name\":\"New\"}'\n baker ads x draft remove x_temp_abc123\n baker ads x draft clear`,\n },\n subCommands: {\n list: listCommand,\n show: showCommand,\n amend: amendCommand,\n remove: removeCommand,\n clear: clearCommand,\n },\n // A parent must never declare `run`: citty falls through to it AFTER running\n // the matched subcommand, so every edit would also trigger a full list.\n args: { json: { type: \"boolean\", description: \"Raw JSON envelope\" }, chat: CHAT_READ_ARG },\n default: \"list\",\n});\n","import type { XDraftListResponse, XDraftOpView, XDraftStatusCollection, XDraftStatusNode } from \"@baker/api\";\n\n/**\n * Render the staged X draft as a readable Campaign ▸ Ad group ▸ Ad tree — the\n * counterpart to the Google and LinkedIn renderers, using the identical node\n * shape. Pure: takes the draft-list response, returns text.\n */\n\nconst OPERATION_LABELS: Record<string, string> = {\n create: \"Creating\",\n update: \"Updating\",\n pause: \"Pausing\",\n resume: \"Resuming\",\n remove: \"Removing\",\n};\n\nfunction badge(node: XDraftStatusNode): string {\n const label = node.operation ? OPERATION_LABELS[node.operation] : undefined;\n return label ?? (node.existing ? \"on X\" : \"staged\");\n}\n\nfunction collectionLine(collection: XDraftStatusCollection): string | undefined {\n const parts: string[] = [];\n if (collection.added > 0) {\n parts.push(`+${collection.added}`);\n }\n if (collection.existing > 0) {\n parts.push(`${collection.existing} existing`);\n }\n if (collection.removed > 0) {\n parts.push(`-${collection.removed}`);\n }\n return parts.length > 0 ? `${collection.label}: ${parts.join(\", \")}` : undefined;\n}\n\n/**\n * Every ad account the tree touches. A draft may span several, and two accounts\n * can hold identically-named campaigns — so the account is printed on each node\n * once there is more than one, and left off when there is not.\n */\nfunction accountsInTree(nodes: readonly XDraftStatusNode[]): Set<string> {\n const accounts = new Set<string>();\n const walk = (node: XDraftStatusNode): void => {\n accounts.add(node.accountId);\n for (const child of node.children) {\n walk(child);\n }\n };\n for (const node of nodes) {\n walk(node);\n }\n return accounts;\n}\n\nfunction renderNode(node: XDraftStatusNode, depth: number, showAccount: boolean, out: string[]): void {\n const indent = \" \".repeat(depth);\n const account = showAccount ? ` [${node.accountId}]` : \"\";\n out.push(`${indent}${node.entity}: ${node.name} — ${badge(node)}${account}`);\n for (const collection of node.collections) {\n const line = collectionLine(collection);\n if (line) {\n out.push(`${indent} ${line}`);\n }\n }\n for (const warning of node.warnings ?? []) {\n out.push(`${indent} ! ${warning}`);\n }\n for (const child of node.children) {\n renderNode(child, depth + 1, showAccount, out);\n }\n}\n\nconst NO_CHANGES = \"No X Ads changes staged\";\n\nconst STATUS_HEADINGS: Record<string, string> = {\n active: \"staged\",\n publishing: \"publishing\",\n applied: \"published\",\n discarded: \"discarded\",\n};\n\nfunction didNotApply(op: XDraftOpView): boolean {\n return op.result?.status === \"failed\" || op.result?.status === \"skipped\";\n}\n\nfunction didApply(op: XDraftOpView): boolean {\n return op.result?.status === \"applied\" || op.result?.status === \"simulated\";\n}\n\n/**\n * The outcome line, which is the authoritative record after a publish: a draft\n * still reading `publishing` minutes later did not finish, whatever X shows.\n */\nfunction headingLine(draft: XDraftListResponse): string {\n const heading = STATUS_HEADINGS[draft.status] ?? draft.status;\n if (draft.status !== \"applied\" && draft.status !== \"publishing\") {\n return `X Ads: ${draft.count} change${draft.count === 1 ? \"\" : \"s\"} ${heading}`;\n }\n const applied = draft.ops.filter(didApply).length;\n const failed = draft.ops.filter(didNotApply).length;\n return `X Ads: ${heading} · ${applied} applied${failed > 0 ? `, ${failed} failed` : \"\"}`;\n}\n\nfunction problemLines(draft: XDraftListResponse): string[] {\n return draft.ops.filter(didNotApply).map((op) => {\n const reason =\n op.result?.error ?? `skipped: waiting on ${op.result?.skippedBecause ?? \"a change that did not apply\"}`;\n return `✗ ${op.summary} — failed: ${reason}`;\n });\n}\n\nexport function renderDraftStatus(draft: XDraftListResponse): string {\n if (draft.status === \"none\" || draft.count === 0) {\n return NO_CHANGES;\n }\n const out: string[] = [headingLine(draft), \"\"];\n const tree = draft.tree ?? [];\n const showAccount = accountsInTree(tree).size > 1;\n for (const node of tree) {\n renderNode(node, 0, showAccount, out);\n }\n const problems = problemLines(draft);\n if (problems.length > 0) {\n out.push(\"\", ...problems);\n }\n return out.join(\"\\n\");\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/commands/ads/x/draft.ts","../src/commands/ads/x/draft-status.ts"],"sourcesContent":["import { readFileSync } from \"node:fs\";\nimport type {\n XDraftClearResponse,\n XDraftListResponse,\n XDraftRemoveResponse,\n XDraftShowResponse,\n XDraftStageResponse,\n} from \"@baker/api\";\nimport { defineCommand } from \"citty\";\nimport { ApiError, apiPost } from \"../../../client.ts\";\nimport { requireChatId, resolveChatId } from \"../../../env.ts\";\nimport { registerSchema } from \"../../../schemas.ts\";\nimport { CHAT_READ_ARG } from \"../../chat-arg.ts\";\nimport { writeAdsJson, writeJsonEnvelope } from \"../output.ts\";\nimport { renderDraftStatus } from \"./draft-status.ts\";\nimport { parseXApiError } from \"./error-parser.ts\";\nimport { failWriteValidation } from \"./write-shared.ts\";\n\nfunction handleDraftError(err: unknown): never {\n if (err instanceof ApiError) {\n writeAdsJson(parseXApiError(err.message, \"—\"));\n process.exit(1);\n }\n writeAdsJson({ ok: false, error: { code: \"NETWORK_ERROR\", message: \"Unexpected error\" } });\n process.exit(1);\n}\n\nregisterSchema({\n command: \"ads.x.draft\",\n description:\n \"Review everything staged for X Ads on this chat as a Campaign ▸ Ad group ▸ Ad tree. After a publish this is the authoritative record: `published · N applied`, or a `✗ … failed:` line per op that did not land.\",\n args: {\n json: { type: \"boolean\", description: \"Raw JSON envelope instead of the readable tree\", required: false },\n chat: { type: \"string\", description: \"Read another chat's draft instead of this one\", required: false },\n },\n});\n\nasync function listDraft(json: boolean, chat?: unknown): Promise<void> {\n try {\n const chatId = resolveChatId(chat);\n const response = await apiPost<{ ok: boolean; data?: XDraftListResponse }>(\"/api/ads/x/draft\", { chatId });\n if (json || !response.ok || !response.data) {\n writeJsonEnvelope(response);\n return;\n }\n process.stdout.write(`${renderDraftStatus(response.data)}\\n`);\n } catch (err) {\n handleDraftError(err);\n }\n}\n\nconst listCommand = defineCommand({\n meta: {\n name: \"list\",\n description: \"Review everything staged as a Campaign ▸ Ad group ▸ Ad tree. Example: baker ads x draft\",\n },\n args: {\n json: { type: \"boolean\", description: \"Print the raw JSON envelope instead of the readable tree\" },\n chat: CHAT_READ_ARG,\n },\n run: async ({ args }) => {\n await listDraft(args.json === true, args.chat);\n },\n});\n\nregisterSchema({\n command: \"ads.x.draft.show\",\n description:\n \"The full staged payload, warnings and before-snapshot for one op — the receipt to check before publishing.\",\n args: {\n ref: { type: \"string\", description: \"Op ref (x_temp_* for creates, the target id for updates)\", required: true },\n chat: { type: \"string\", description: \"Read another chat's draft instead of this one\", required: false },\n },\n});\n\nconst showCommand = defineCommand({\n meta: {\n name: \"show\",\n description: \"Show one staged op in full. Example: baker ads x draft show x_temp_abc123\",\n },\n args: {\n ref: { type: \"positional\", description: \"Op ref, or the target id for a staged update\", required: true },\n chat: CHAT_READ_ARG,\n },\n run: async ({ args }) => {\n try {\n const chatId = resolveChatId(args.chat);\n const response = await apiPost<{ ok: boolean; data?: XDraftShowResponse }>(\"/api/ads/x/draft/show\", {\n chatId,\n ref: String(args.ref),\n });\n writeJsonEnvelope(response);\n } catch (err) {\n handleDraftError(err);\n }\n },\n});\n\nregisterSchema({\n command: \"ads.x.draft.amend\",\n description:\n \"Change a staged op in place instead of removing and re-staging it. The patch merges into the payload (JSON merge-patch: `null` deletes a key) and the whole op re-validates.\",\n args: {\n ref: { type: \"string\", description: \"Op ref or target id\", required: true },\n patch: { type: \"string\", description: \"JSON object, or @path to a file holding one\", required: true },\n },\n});\n\nconst amendCommand = defineCommand({\n meta: {\n name: \"amend\",\n description: `Change a staged op in place.\n\nExample:\n baker ads x draft amend x_temp_abc '{\"dailyBudgetAmountLocalMicro\": 20000000}'`,\n },\n args: {\n ref: { type: \"positional\", description: \"Op ref or target id\", required: true },\n patch: { type: \"positional\", description: \"JSON object, or @path to a file\", required: true },\n },\n run: async ({ args }) => {\n const raw = String(args.patch);\n let patch: unknown;\n try {\n patch = JSON.parse(raw.startsWith(\"@\") ? readFileSync(raw.slice(1), \"utf8\") : raw);\n } catch {\n failWriteValidation(\"patch must be a JSON object, or @path to a file holding one\");\n }\n if (patch === null || typeof patch !== \"object\" || Array.isArray(patch)) {\n failWriteValidation(\"patch must be a JSON object\");\n }\n try {\n const chatId = requireChatId();\n const response = await apiPost<{ ok: boolean; data?: XDraftStageResponse }>(\"/api/ads/x/draft/amend\", {\n chatId,\n ref: String(args.ref),\n patch,\n });\n writeJsonEnvelope(response);\n } catch (err) {\n handleDraftError(err);\n }\n },\n});\n\nregisterSchema({\n command: \"ads.x.draft.remove\",\n description: \"Drop one staged X op. Removing a create cascades to everything staged that depends on it.\",\n args: { ref: { type: \"string\", description: \"Op ref or target id\", required: true } },\n});\n\nconst removeCommand = defineCommand({\n meta: {\n name: \"remove\",\n description: \"Drop one staged op (cascades to its dependents). Example: baker ads x draft remove x_temp_abc123\",\n },\n args: { ref: { type: \"positional\", description: \"Op ref or target id\", required: true } },\n run: async ({ args }) => {\n try {\n const chatId = requireChatId();\n const response = await apiPost<{ ok: boolean; data?: XDraftRemoveResponse }>(\"/api/ads/x/draft/remove\", {\n chatId,\n ref: String(args.ref),\n });\n writeJsonEnvelope(response);\n } catch (err) {\n handleDraftError(err);\n }\n },\n});\n\nregisterSchema({\n command: \"ads.x.draft.clear\",\n description: \"Drop every staged X op on this chat. Nothing reached X, so nothing needs reversing.\",\n args: {},\n});\n\nconst clearCommand = defineCommand({\n meta: { name: \"clear\", description: \"Drop every staged X op on this chat. Example: baker ads x draft clear\" },\n args: {},\n run: async () => {\n try {\n const chatId = requireChatId();\n const response = await apiPost<{ ok: boolean; data?: XDraftClearResponse }>(\"/api/ads/x/draft/clear\", { chatId });\n writeJsonEnvelope(response);\n } catch (err) {\n handleDraftError(err);\n }\n },\n});\n\nexport const draftCommand = defineCommand({\n meta: {\n name: \"draft\",\n description: `Review and edit the X Ads changes staged on this chat.\n\nNothing staged has reached X. Everything applies when the chat is published,\nand discarding the chat reverses all of it.\n\nExamples:\n baker ads x draft — the Campaign ▸ Ad group ▸ Ad tree\n baker ads x draft show x_temp_abc123 — one op in full\n baker ads x draft amend x_temp_abc '{\"name\":\"New\"}'\n baker ads x draft remove x_temp_abc123\n baker ads x draft clear`,\n },\n subCommands: {\n list: listCommand,\n show: showCommand,\n amend: amendCommand,\n remove: removeCommand,\n clear: clearCommand,\n },\n // A parent must never declare `run`: citty falls through to it AFTER running\n // the matched subcommand, so every edit would also trigger a full list.\n args: { json: { type: \"boolean\", description: \"Raw JSON envelope\" }, chat: CHAT_READ_ARG },\n default: \"list\",\n});\n","import type { XDraftListResponse, XDraftOpView, XDraftStatusCollection, XDraftStatusNode } from \"@baker/api\";\n\n/**\n * Render the staged X draft as a readable Campaign ▸ Ad group ▸ Ad tree — the\n * counterpart to the Google and LinkedIn renderers, using the identical node\n * shape. Pure: takes the draft-list response, returns text.\n */\n\nconst OPERATION_LABELS: Record<string, string> = {\n create: \"Creating\",\n update: \"Updating\",\n pause: \"Pausing\",\n resume: \"Resuming\",\n remove: \"Removing\",\n};\n\nfunction badge(node: XDraftStatusNode): string {\n const label = node.operation ? OPERATION_LABELS[node.operation] : undefined;\n return label ?? (node.existing ? \"on X\" : \"staged\");\n}\n\nfunction collectionLine(collection: XDraftStatusCollection): string | undefined {\n const parts: string[] = [];\n if (collection.added > 0) {\n parts.push(`+${collection.added}`);\n }\n if (collection.existing > 0) {\n parts.push(`${collection.existing} existing`);\n }\n if (collection.removed > 0) {\n parts.push(`-${collection.removed}`);\n }\n return parts.length > 0 ? `${collection.label}: ${parts.join(\", \")}` : undefined;\n}\n\n/**\n * Every ad account the tree touches. A draft may span several, and two accounts\n * can hold identically-named campaigns — so the account is printed on each node\n * once there is more than one, and left off when there is not.\n */\nfunction accountsInTree(nodes: readonly XDraftStatusNode[]): Set<string> {\n const accounts = new Set<string>();\n const walk = (node: XDraftStatusNode): void => {\n accounts.add(node.accountId);\n for (const child of node.children) {\n walk(child);\n }\n };\n for (const node of nodes) {\n walk(node);\n }\n return accounts;\n}\n\nfunction renderNode(node: XDraftStatusNode, depth: number, showAccount: boolean, out: string[]): void {\n const indent = \" \".repeat(depth);\n const account = showAccount ? ` [${node.accountId}]` : \"\";\n out.push(`${indent}${node.entity}: ${node.name} — ${badge(node)}${account}`);\n for (const collection of node.collections) {\n const line = collectionLine(collection);\n if (line) {\n out.push(`${indent} ${line}`);\n }\n }\n for (const warning of node.warnings ?? []) {\n out.push(`${indent} ! ${warning}`);\n }\n for (const child of node.children) {\n renderNode(child, depth + 1, showAccount, out);\n }\n}\n\nconst NO_CHANGES = \"No X Ads changes staged\";\n\nconst STATUS_HEADINGS: Record<string, string> = {\n active: \"staged\",\n publishing: \"publishing\",\n applied: \"published\",\n discarded: \"discarded\",\n};\n\nfunction didNotApply(op: XDraftOpView): boolean {\n return op.result?.status === \"failed\" || op.result?.status === \"skipped\";\n}\n\nfunction didApply(op: XDraftOpView): boolean {\n return op.result?.status === \"applied\" || op.result?.status === \"simulated\";\n}\n\n/**\n * The outcome line, which is the authoritative record after a publish: a draft\n * still reading `publishing` minutes later did not finish, whatever X shows.\n */\nfunction headingLine(draft: XDraftListResponse): string {\n const heading = STATUS_HEADINGS[draft.status] ?? draft.status;\n if (draft.status !== \"applied\" && draft.status !== \"publishing\") {\n return `X Ads: ${draft.count} change${draft.count === 1 ? \"\" : \"s\"} ${heading}`;\n }\n const applied = draft.ops.filter(didApply).length;\n const failed = draft.ops.filter(didNotApply).length;\n return `X Ads: ${heading} · ${applied} applied${failed > 0 ? `, ${failed} failed` : \"\"}`;\n}\n\nfunction problemLines(draft: XDraftListResponse): string[] {\n return draft.ops.filter(didNotApply).map((op) => {\n const reason =\n op.result?.error ?? `skipped: waiting on ${op.result?.skippedBecause ?? \"a change that did not apply\"}`;\n return `✗ ${op.summary} — failed: ${reason}`;\n });\n}\n\nexport function renderDraftStatus(draft: XDraftListResponse): string {\n if (draft.status === \"none\" || draft.count === 0) {\n return NO_CHANGES;\n }\n const out: string[] = [headingLine(draft), \"\"];\n const tree = draft.tree ?? [];\n const showAccount = accountsInTree(tree).size > 1;\n for (const node of tree) {\n renderNode(node, 0, showAccount, out);\n }\n const problems = problemLines(draft);\n if (problems.length > 0) {\n out.push(\"\", ...problems);\n }\n return out.join(\"\\n\");\n}\n"],"mappings":"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","names":[]}
@@ -5,14 +5,13 @@ import {
5
5
  failApi,
6
6
  failValidation,
7
7
  isTempId
8
- } from "./chunk-SJYEY5MV.js";
8
+ } from "./chunk-3HJLHTWP.js";
9
9
  import {
10
10
  REMOVABLE_DRAFT_OP_KINDS
11
- } from "./chunk-7EPXVICM.js";
11
+ } from "./chunk-XF4JUKVF.js";
12
12
  import "./chunk-GXDLWBOY.js";
13
13
  import "./chunk-TEINLN64.js";
14
14
  import "./chunk-ZJWUBJYQ.js";
15
- import "./chunk-HR6IWNKE.js";
16
15
  import "./chunk-NE4F3FHN.js";
17
16
  import {
18
17
  apiPost,
@@ -215,4 +214,4 @@ export {
215
214
  draftCommand,
216
215
  draftOpNormalizer
217
216
  };
218
- //# sourceMappingURL=draft-2IBSJEKC.js.map
217
+ //# sourceMappingURL=draft-SLHAKJ2A.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/actions/draft.ts"],"sourcesContent":["import {\n type ActionsDraftClearResponse,\n type ActionsDraftResponse,\n type ActionsRemoveDraftOpResponse,\n REMOVABLE_DRAFT_OP_KINDS,\n} from \"@baker/api\";\nimport { defineCommand } from \"citty\";\nimport { apiPost, validateConvexId } from \"../../client.ts\";\nimport { requireChatId, resolveChatId } from \"../../env.ts\";\nimport { type OutputFormat, writeJson, writeOutput } from \"../../output.ts\";\nimport { registerSchema } from \"../../schemas.ts\";\nimport { CHAT_READ_ARG } from \"../chat-arg.ts\";\nimport { failApi, failValidation, isTempId } from \"./shared.ts\";\n\ntype RemoveOpKind = (typeof REMOVABLE_DRAFT_OP_KINDS)[number];\nconst REMOVE_OP_KINDS: readonly RemoveOpKind[] = REMOVABLE_DRAFT_OP_KINDS;\n\nregisterSchema({\n command: \"actions.draft.list\",\n description:\n \"Review the action ops staged in THIS chat's draft before publish (creates/updates/completes/discards/links). Staged ops are invisible to `actions list`/`status` until the chat publishes — use this to verify what will apply and catch duplicates. Takes --chat <id> to read an earlier chat's staged ops instead. Start here: `baker actions draft --output md` for a one-row-per-op table; add --fields to pick columns.\",\n args: {\n chat: { type: \"string\", description: CHAT_READ_ARG.description, required: false },\n output: {\n type: \"string\",\n description:\n \"Output format: json (default, full envelope with status/count/warnings) | md | files. md and files render one row per staged op.\",\n required: false,\n enum: [\"json\", \"md\", \"files\"],\n },\n fields: {\n type: \"string\",\n description: \"Comma-separated columns for md/files output, e.g. kind,name,ref,tags\",\n required: false,\n },\n full: {\n type: \"boolean\",\n description: \"Include each op's payload (description, note, reason, blocker) in md/files output\",\n required: false,\n default: false,\n },\n },\n});\n\nconst OUTPUT_ARGS = {\n output: { type: \"string\", description: \"Output format: json|md|files\", required: false, default: \"json\" },\n fields: { type: \"string\", description: \"Comma-separated field names to include (md/files)\", required: false },\n full: { type: \"boolean\", description: \"Include each op's full payload\", required: false, default: false },\n} as const;\n\nfunction text(value: unknown): string {\n return typeof value === \"string\" ? value : \"\";\n}\n\n/**\n * One staged op as a table row. `ref` is the handle the agent needs next —\n * `draft remove <ref>`, `update <ref>` — which is the tempId for a staged create\n * and the real action id for an op against a published action.\n */\nexport function draftOpNormalizer(record: Record<string, unknown>, full: boolean): Record<string, unknown> {\n const compact = {\n kind: text(record.kind),\n name: text(record.targetName),\n ref: text(record.tempId) || text(record.targetActionId),\n tags: Array.isArray(record.tags) ? record.tags.join(\",\") : \"\",\n };\n if (!full) {\n return compact;\n }\n return {\n ...compact,\n description: text(record.description),\n note: text(record.note),\n reason: text(record.reason),\n blocker: text(record.blockerTempId) || text(record.blockerActionId) || text(record.blockerName),\n };\n}\n\nregisterSchema({\n command: \"actions.draft.remove\",\n description:\n \"Drop a single staged action op from this chat's draft before publish. For a tempId, removing the create cascades into its complete/link ops. For a real action ID, pass --op to say which op to drop. Use this to UNDO a staged op — never stage `complete` to delete an action.\",\n args: {\n ref: { type: \"string\", description: \"tempId (temp_*) or real action ID to drop from the draft\", required: true },\n op: {\n type: \"string\",\n description: \"Required for real action IDs: which op to drop (update|complete|discard|assign|reopen)\",\n required: false,\n },\n },\n});\n\nregisterSchema({\n command: \"actions.draft.clear\",\n description:\n \"Discard ALL staged action ops in this chat's draft before publish. Nothing applies on publish. Does not touch already-published actions.\",\n args: {},\n});\n\nconst listCommand = defineCommand({\n meta: {\n name: \"list\",\n description:\n \"Show every action op staged in this chat's draft, with footgun warnings. Example: baker actions draft --output md\",\n },\n args: { chat: CHAT_READ_ARG, ...OUTPUT_ARGS },\n run: async ({ args }) => {\n try {\n const chatId = resolveChatId(args.chat);\n const response = await apiPost<ActionsDraftResponse>(\"/api/actions/draft\", { chatId });\n // Anything that isn't a table format falls back to the full JSON envelope\n // — a typo'd `--output` must not silently print nothing.\n const format: OutputFormat = args.output === \"md\" || args.output === \"files\" ? args.output : \"json\";\n if (format === \"json\") {\n writeJson(response);\n return;\n }\n // md/files render the ops as rows; `status`, `count` and the footgun\n // warnings have no column to live in, so they go to stderr rather than\n // being dropped — a warning nobody sees is the reason this format exists.\n writeOutput(\n { ok: true, data: response.data.ops },\n format,\n args.fields ? (args.fields as string).split(\",\") : undefined,\n args.full as boolean,\n draftOpNormalizer,\n );\n process.stderr.write(`draft status: ${response.data.status}, ${response.data.count} op(s)\\n`);\n for (const warning of response.data.warnings) {\n process.stderr.write(`warning: ${warning.tempId} — ${warning.name}\\n`);\n }\n } catch (err) {\n failApi(err);\n }\n },\n});\n\nconst removeCommand = defineCommand({\n meta: {\n name: \"remove\",\n description:\n \"Drop one staged op from the draft. Example: baker actions draft remove temp_abc123 | baker actions draft remove jx7... --op complete\",\n },\n args: {\n ref: { type: \"positional\", description: \"tempId or real action ID\", required: false },\n op: {\n type: \"string\",\n description: \"Op kind for real IDs: update|complete|discard|assign|reopen\",\n required: false,\n },\n },\n run: async ({ args }) => {\n try {\n const ref = args.ref as string | undefined;\n if (!ref) {\n failValidation(\"A tempId or action ID is required.\");\n }\n const chatId = requireChatId();\n\n if (isTempId(ref)) {\n await apiPost<ActionsRemoveDraftOpResponse>(\"/api/actions/draft-op/remove\", {\n chatId,\n target: { kind: \"tempId\", tempId: ref },\n });\n writeJson({ ok: true, data: { removed: ref, kind: \"tempId\" } });\n return;\n }\n\n validateConvexId(ref);\n const op = args.op as string | undefined;\n if (!op || !REMOVE_OP_KINDS.includes(op as RemoveOpKind)) {\n failValidation(\n `Removing a staged op for a real action ID requires --op (one of: ${REMOVE_OP_KINDS.join(\"|\")}).`,\n );\n }\n await apiPost<ActionsRemoveDraftOpResponse>(\"/api/actions/draft-op/remove\", {\n chatId,\n target: { kind: \"actionId\", actionId: ref, opKind: op },\n });\n writeJson({ ok: true, data: { removed: ref, kind: \"actionId\", op } });\n } catch (err) {\n failApi(err);\n }\n },\n});\n\nconst clearCommand = defineCommand({\n meta: {\n name: \"clear\",\n description: \"Discard every staged op in this chat's draft. Example: baker actions draft clear\",\n },\n run: async () => {\n try {\n const chatId = requireChatId();\n await apiPost<ActionsDraftClearResponse>(\"/api/actions/draft/clear\", { chatId });\n writeJson({ ok: true, data: { cleared: true } });\n } catch (err) {\n failApi(err);\n }\n },\n});\n\nexport const draftCommand = defineCommand({\n meta: {\n name: \"draft\",\n description:\n \"Review and edit the action ops staged in this chat BEFORE publish. Subcommands: list (default), remove, clear. Staged ops are invisible to `actions list`/`status` until publish, so check here before finishing. `list` takes --chat <id> to read an earlier chat's staged ops instead.\",\n },\n // Declared on the parent too: `default: \"list\"` dispatches the bare `draft --chat <id>` form, and\n // citty prints help for a flag the parent does not know instead of forwarding it.\n args: { chat: CHAT_READ_ARG, ...OUTPUT_ARGS },\n subCommands: {\n list: listCommand,\n remove: removeCommand,\n clear: clearCommand,\n },\n // Bare `baker actions draft` (no subcommand) shows the staged ops. This must be\n // `default`, not `run`: citty falls through to `run` after dispatching a subcommand,\n // so a `run` here would also list the draft on every `remove` / `clear`.\n default: \"list\",\n});\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/commands/actions/draft.ts"],"sourcesContent":["import {\n type ActionsDraftClearResponse,\n type ActionsDraftResponse,\n type ActionsRemoveDraftOpResponse,\n REMOVABLE_DRAFT_OP_KINDS,\n} from \"@baker/api\";\nimport { defineCommand } from \"citty\";\nimport { apiPost, validateConvexId } from \"../../client.ts\";\nimport { requireChatId, resolveChatId } from \"../../env.ts\";\nimport { type OutputFormat, writeJson, writeOutput } from \"../../output.ts\";\nimport { registerSchema } from \"../../schemas.ts\";\nimport { CHAT_READ_ARG } from \"../chat-arg.ts\";\nimport { failApi, failValidation, isTempId } from \"./shared.ts\";\n\ntype RemoveOpKind = (typeof REMOVABLE_DRAFT_OP_KINDS)[number];\nconst REMOVE_OP_KINDS: readonly RemoveOpKind[] = REMOVABLE_DRAFT_OP_KINDS;\n\nregisterSchema({\n command: \"actions.draft.list\",\n description:\n \"Review the action ops staged in THIS chat's draft before publish (creates/updates/completes/discards/links). Staged ops are invisible to `actions list`/`status` until the chat publishes — use this to verify what will apply and catch duplicates. Takes --chat <id> to read an earlier chat's staged ops instead. Start here: `baker actions draft --output md` for a one-row-per-op table; add --fields to pick columns.\",\n args: {\n chat: { type: \"string\", description: CHAT_READ_ARG.description, required: false },\n output: {\n type: \"string\",\n description:\n \"Output format: json (default, full envelope with status/count/warnings) | md | files. md and files render one row per staged op.\",\n required: false,\n enum: [\"json\", \"md\", \"files\"],\n },\n fields: {\n type: \"string\",\n description: \"Comma-separated columns for md/files output, e.g. kind,name,ref,tags\",\n required: false,\n },\n full: {\n type: \"boolean\",\n description: \"Include each op's payload (description, note, reason, blocker) in md/files output\",\n required: false,\n default: false,\n },\n },\n});\n\nconst OUTPUT_ARGS = {\n output: { type: \"string\", description: \"Output format: json|md|files\", required: false, default: \"json\" },\n fields: { type: \"string\", description: \"Comma-separated field names to include (md/files)\", required: false },\n full: { type: \"boolean\", description: \"Include each op's full payload\", required: false, default: false },\n} as const;\n\nfunction text(value: unknown): string {\n return typeof value === \"string\" ? value : \"\";\n}\n\n/**\n * One staged op as a table row. `ref` is the handle the agent needs next —\n * `draft remove <ref>`, `update <ref>` — which is the tempId for a staged create\n * and the real action id for an op against a published action.\n */\nexport function draftOpNormalizer(record: Record<string, unknown>, full: boolean): Record<string, unknown> {\n const compact = {\n kind: text(record.kind),\n name: text(record.targetName),\n ref: text(record.tempId) || text(record.targetActionId),\n tags: Array.isArray(record.tags) ? record.tags.join(\",\") : \"\",\n };\n if (!full) {\n return compact;\n }\n return {\n ...compact,\n description: text(record.description),\n note: text(record.note),\n reason: text(record.reason),\n blocker: text(record.blockerTempId) || text(record.blockerActionId) || text(record.blockerName),\n };\n}\n\nregisterSchema({\n command: \"actions.draft.remove\",\n description:\n \"Drop a single staged action op from this chat's draft before publish. For a tempId, removing the create cascades into its complete/link ops. For a real action ID, pass --op to say which op to drop. Use this to UNDO a staged op — never stage `complete` to delete an action.\",\n args: {\n ref: { type: \"string\", description: \"tempId (temp_*) or real action ID to drop from the draft\", required: true },\n op: {\n type: \"string\",\n description: \"Required for real action IDs: which op to drop (update|complete|discard|assign|reopen)\",\n required: false,\n },\n },\n});\n\nregisterSchema({\n command: \"actions.draft.clear\",\n description:\n \"Discard ALL staged action ops in this chat's draft before publish. Nothing applies on publish. Does not touch already-published actions.\",\n args: {},\n});\n\nconst listCommand = defineCommand({\n meta: {\n name: \"list\",\n description:\n \"Show every action op staged in this chat's draft, with footgun warnings. Example: baker actions draft --output md\",\n },\n args: { chat: CHAT_READ_ARG, ...OUTPUT_ARGS },\n run: async ({ args }) => {\n try {\n const chatId = resolveChatId(args.chat);\n const response = await apiPost<ActionsDraftResponse>(\"/api/actions/draft\", { chatId });\n // Anything that isn't a table format falls back to the full JSON envelope\n // — a typo'd `--output` must not silently print nothing.\n const format: OutputFormat = args.output === \"md\" || args.output === \"files\" ? args.output : \"json\";\n if (format === \"json\") {\n writeJson(response);\n return;\n }\n // md/files render the ops as rows; `status`, `count` and the footgun\n // warnings have no column to live in, so they go to stderr rather than\n // being dropped — a warning nobody sees is the reason this format exists.\n writeOutput(\n { ok: true, data: response.data.ops },\n format,\n args.fields ? (args.fields as string).split(\",\") : undefined,\n args.full as boolean,\n draftOpNormalizer,\n );\n process.stderr.write(`draft status: ${response.data.status}, ${response.data.count} op(s)\\n`);\n for (const warning of response.data.warnings) {\n process.stderr.write(`warning: ${warning.tempId} — ${warning.name}\\n`);\n }\n } catch (err) {\n failApi(err);\n }\n },\n});\n\nconst removeCommand = defineCommand({\n meta: {\n name: \"remove\",\n description:\n \"Drop one staged op from the draft. Example: baker actions draft remove temp_abc123 | baker actions draft remove jx7... --op complete\",\n },\n args: {\n ref: { type: \"positional\", description: \"tempId or real action ID\", required: false },\n op: {\n type: \"string\",\n description: \"Op kind for real IDs: update|complete|discard|assign|reopen\",\n required: false,\n },\n },\n run: async ({ args }) => {\n try {\n const ref = args.ref as string | undefined;\n if (!ref) {\n failValidation(\"A tempId or action ID is required.\");\n }\n const chatId = requireChatId();\n\n if (isTempId(ref)) {\n await apiPost<ActionsRemoveDraftOpResponse>(\"/api/actions/draft-op/remove\", {\n chatId,\n target: { kind: \"tempId\", tempId: ref },\n });\n writeJson({ ok: true, data: { removed: ref, kind: \"tempId\" } });\n return;\n }\n\n validateConvexId(ref);\n const op = args.op as string | undefined;\n if (!op || !REMOVE_OP_KINDS.includes(op as RemoveOpKind)) {\n failValidation(\n `Removing a staged op for a real action ID requires --op (one of: ${REMOVE_OP_KINDS.join(\"|\")}).`,\n );\n }\n await apiPost<ActionsRemoveDraftOpResponse>(\"/api/actions/draft-op/remove\", {\n chatId,\n target: { kind: \"actionId\", actionId: ref, opKind: op },\n });\n writeJson({ ok: true, data: { removed: ref, kind: \"actionId\", op } });\n } catch (err) {\n failApi(err);\n }\n },\n});\n\nconst clearCommand = defineCommand({\n meta: {\n name: \"clear\",\n description: \"Discard every staged op in this chat's draft. Example: baker actions draft clear\",\n },\n run: async () => {\n try {\n const chatId = requireChatId();\n await apiPost<ActionsDraftClearResponse>(\"/api/actions/draft/clear\", { chatId });\n writeJson({ ok: true, data: { cleared: true } });\n } catch (err) {\n failApi(err);\n }\n },\n});\n\nexport const draftCommand = defineCommand({\n meta: {\n name: \"draft\",\n description:\n \"Review and edit the action ops staged in this chat BEFORE publish. Subcommands: list (default), remove, clear. Staged ops are invisible to `actions list`/`status` until publish, so check here before finishing. `list` takes --chat <id> to read an earlier chat's staged ops instead.\",\n },\n // Declared on the parent too: `default: \"list\"` dispatches the bare `draft --chat <id>` form, and\n // citty prints help for a flag the parent does not know instead of forwarding it.\n args: { chat: CHAT_READ_ARG, ...OUTPUT_ARGS },\n subCommands: {\n list: listCommand,\n remove: removeCommand,\n clear: clearCommand,\n },\n // Bare `baker actions draft` (no subcommand) shows the staged ops. This must be\n // `default`, not `run`: citty falls through to `run` after dispatching a subcommand,\n // so a `run` here would also list the draft on every `remove` / `clear`.\n default: \"list\",\n});\n"],"mappings":"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","names":[]}
@@ -8,11 +8,11 @@ import {
8
8
  defaultRegistry,
9
9
  generateCatalog,
10
10
  validateCanvasDeep
11
- } from "../chunk-LYQJ4PZW.js";
12
- import "../chunk-FPOGPFAG.js";
11
+ } from "../chunk-OQ6663F4.js";
12
+ import "../chunk-EBWBG6YV.js";
13
+ import "../chunk-W3B4BHQU.js";
13
14
  import "../chunk-NCWCZY5P.js";
14
15
  import "../chunk-DGCUPJZD.js";
15
- import "../chunk-W3B4BHQU.js";
16
16
  import "../chunk-PZXCWSKV.js";
17
17
  import "../chunk-CAMX6OHF.js";
18
18
  import "../chunk-RX6F3GEA.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  csvOrJson,
3
3
  handleLinkedinError
4
- } from "./chunk-N4LAYIIN.js";
4
+ } from "./chunk-CSYSX4D2.js";
5
5
  import {
6
6
  writeAdsJson,
7
7
  writeAdsOutput
@@ -9,11 +9,10 @@ import {
9
9
  import {
10
10
  NO_CACHE_ARG
11
11
  } from "./chunk-X7ZODEXJ.js";
12
- import "./chunk-7EPXVICM.js";
12
+ import "./chunk-XF4JUKVF.js";
13
13
  import "./chunk-GXDLWBOY.js";
14
14
  import "./chunk-TEINLN64.js";
15
15
  import "./chunk-ZJWUBJYQ.js";
16
- import "./chunk-HR6IWNKE.js";
17
16
  import "./chunk-NE4F3FHN.js";
18
17
  import {
19
18
  apiGet
@@ -112,4 +111,4 @@ Subcommands:
112
111
  export {
113
112
  facetsCommand
114
113
  };
115
- //# sourceMappingURL=facets-7EVPJMKS.js.map
114
+ //# sourceMappingURL=facets-U7AQC4H6.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/ads/linkedin/facets.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 { csvOrJson, handleLinkedinError } from \"./shared.ts\";\n\ninterface LinkedinFacet {\n facet: string;\n facetUrn: string;\n name: string;\n entityTypes?: string[];\n availableEntityFinders?: string[];\n}\n\ninterface LinkedinFacetEntity {\n urn: string;\n facet?: string;\n name?: string;\n parents?: string[];\n}\n\nconst listCmd = defineCommand({\n meta: {\n name: \"list\",\n description: `List every targeting facet LinkedIn supports.\n\nCached 7 days. Use this to discover what dimensions you can target on (industries,\nseniorities, titles, employers, growthRate, companyCategory, skills, etc.).`,\n },\n args: {\n \"no-cache\": NO_CACHE_ARG,\n output: { type: \"string\", description: \"json|csv|jsonl|md\", default: \"json\" },\n },\n run: async ({ args }) => {\n try {\n const params: Record<string, string> = {};\n if (args[\"no-cache\"]) params[\"skip-cache\"] = \"true\";\n const data = await apiGet<LinkedinFacet[]>(\"/api/ads/linkedin/facets\", 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\nconst valuesCmd = defineCommand({\n meta: {\n name: \"values\",\n description: `Look up entity values for a single facet — full list or typeahead search.\n\nExamples:\n baker ads linkedin facets values --facet seniorities — all seniority URNs\n baker ads linkedin facets values --facet titles --query \"marketing director\" — typeahead\n baker ads linkedin facets values --facet industries --output csv\n\nThe --facet flag accepts the bare name (industries, seniorities, titles, etc.)\nor the full URN (urn:li:adTargetingFacet:industries).`,\n },\n args: {\n facet: { type: \"string\", description: \"Facet name (e.g. industries) or URN\", required: true },\n query: { type: \"string\", description: \"Typeahead query (auto-switches finder to typeahead)\" },\n finder: { type: \"string\", description: \"adTargetingFacet | typeahead | similarEntities (default: auto)\" },\n locale: { type: \"string\", description: \"Locale (default: en_US)\" },\n \"no-cache\": NO_CACHE_ARG,\n output: { type: \"string\", description: \"json|csv|jsonl|md\", default: \"json\" },\n },\n run: async ({ args }) => {\n try {\n const params: Record<string, string> = { facet: String(args.facet) };\n const finder = (args.finder as string | undefined) ?? (args.query ? \"typeahead\" : \"adTargetingFacet\");\n params.finder = finder;\n if (args.query) params.query = String(args.query);\n if (args.locale) params.locale = String(args.locale);\n if (args[\"no-cache\"]) params[\"skip-cache\"] = \"true\";\n\n const data = await apiGet<LinkedinFacetEntity[]>(\"/api/ads/linkedin/facets/entities\", 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 facetsCommand = defineCommand({\n meta: {\n name: \"facets\",\n description: `LinkedIn targeting facets and entity lookup.\n\nSubcommands:\n list — every facet (industries, seniorities, titles, employers, …)\n values --facet titles — entity URNs for one facet\n values --facet titles --query \"marketing director\" — typeahead`,\n },\n subCommands: {\n list: listCmd,\n values: valuesCmd,\n },\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,qBAAqB;AAqB9B,IAAM,UAAU,cAAc;AAAA,EAC5B,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA;AAAA;AAAA;AAAA,EAIf;AAAA,EACA,MAAM;AAAA,IACJ,YAAY;AAAA,IACZ,QAAQ,EAAE,MAAM,UAAU,aAAa,qBAAqB,SAAS,OAAO;AAAA,EAC9E;AAAA,EACA,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,QAAI;AACF,YAAM,SAAiC,CAAC;AACxC,UAAI,KAAK,UAAU,EAAG,QAAO,YAAY,IAAI;AAC7C,YAAM,OAAO,MAAM,OAAwB,4BAA4B,MAAM;AAC7E,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;AAED,IAAM,YAAY,cAAc;AAAA,EAC9B,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASf;AAAA,EACA,MAAM;AAAA,IACJ,OAAO,EAAE,MAAM,UAAU,aAAa,uCAAuC,UAAU,KAAK;AAAA,IAC5F,OAAO,EAAE,MAAM,UAAU,aAAa,sDAAsD;AAAA,IAC5F,QAAQ,EAAE,MAAM,UAAU,aAAa,iEAAiE;AAAA,IACxG,QAAQ,EAAE,MAAM,UAAU,aAAa,0BAA0B;AAAA,IACjE,YAAY;AAAA,IACZ,QAAQ,EAAE,MAAM,UAAU,aAAa,qBAAqB,SAAS,OAAO;AAAA,EAC9E;AAAA,EACA,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,QAAI;AACF,YAAM,SAAiC,EAAE,OAAO,OAAO,KAAK,KAAK,EAAE;AACnE,YAAM,SAAU,KAAK,WAAkC,KAAK,QAAQ,cAAc;AAClF,aAAO,SAAS;AAChB,UAAI,KAAK,MAAO,QAAO,QAAQ,OAAO,KAAK,KAAK;AAChD,UAAI,KAAK,OAAQ,QAAO,SAAS,OAAO,KAAK,MAAM;AACnD,UAAI,KAAK,UAAU,EAAG,QAAO,YAAY,IAAI;AAE7C,YAAM,OAAO,MAAM,OAA8B,qCAAqC,MAAM;AAC5F,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,gBAAgB,cAAc;AAAA,EACzC,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMf;AAAA,EACA,aAAa;AAAA,IACX,MAAM;AAAA,IACN,QAAQ;AAAA,EACV;AACF,CAAC;","names":[]}
1
+ {"version":3,"sources":["../src/commands/ads/linkedin/facets.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 { csvOrJson, handleLinkedinError } from \"./shared.ts\";\n\ninterface LinkedinFacet {\n facet: string;\n facetUrn: string;\n name: string;\n entityTypes?: string[];\n availableEntityFinders?: string[];\n}\n\ninterface LinkedinFacetEntity {\n urn: string;\n facet?: string;\n name?: string;\n parents?: string[];\n}\n\nconst listCmd = defineCommand({\n meta: {\n name: \"list\",\n description: `List every targeting facet LinkedIn supports.\n\nCached 7 days. Use this to discover what dimensions you can target on (industries,\nseniorities, titles, employers, growthRate, companyCategory, skills, etc.).`,\n },\n args: {\n \"no-cache\": NO_CACHE_ARG,\n output: { type: \"string\", description: \"json|csv|jsonl|md\", default: \"json\" },\n },\n run: async ({ args }) => {\n try {\n const params: Record<string, string> = {};\n if (args[\"no-cache\"]) params[\"skip-cache\"] = \"true\";\n const data = await apiGet<LinkedinFacet[]>(\"/api/ads/linkedin/facets\", 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\nconst valuesCmd = defineCommand({\n meta: {\n name: \"values\",\n description: `Look up entity values for a single facet — full list or typeahead search.\n\nExamples:\n baker ads linkedin facets values --facet seniorities — all seniority URNs\n baker ads linkedin facets values --facet titles --query \"marketing director\" — typeahead\n baker ads linkedin facets values --facet industries --output csv\n\nThe --facet flag accepts the bare name (industries, seniorities, titles, etc.)\nor the full URN (urn:li:adTargetingFacet:industries).`,\n },\n args: {\n facet: { type: \"string\", description: \"Facet name (e.g. industries) or URN\", required: true },\n query: { type: \"string\", description: \"Typeahead query (auto-switches finder to typeahead)\" },\n finder: { type: \"string\", description: \"adTargetingFacet | typeahead | similarEntities (default: auto)\" },\n locale: { type: \"string\", description: \"Locale (default: en_US)\" },\n \"no-cache\": NO_CACHE_ARG,\n output: { type: \"string\", description: \"json|csv|jsonl|md\", default: \"json\" },\n },\n run: async ({ args }) => {\n try {\n const params: Record<string, string> = { facet: String(args.facet) };\n const finder = (args.finder as string | undefined) ?? (args.query ? \"typeahead\" : \"adTargetingFacet\");\n params.finder = finder;\n if (args.query) params.query = String(args.query);\n if (args.locale) params.locale = String(args.locale);\n if (args[\"no-cache\"]) params[\"skip-cache\"] = \"true\";\n\n const data = await apiGet<LinkedinFacetEntity[]>(\"/api/ads/linkedin/facets/entities\", 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 facetsCommand = defineCommand({\n meta: {\n name: \"facets\",\n description: `LinkedIn targeting facets and entity lookup.\n\nSubcommands:\n list — every facet (industries, seniorities, titles, employers, …)\n values --facet titles — entity URNs for one facet\n values --facet titles --query \"marketing director\" — typeahead`,\n },\n subCommands: {\n list: listCmd,\n values: valuesCmd,\n },\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,qBAAqB;AAqB9B,IAAM,UAAU,cAAc;AAAA,EAC5B,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA;AAAA;AAAA;AAAA,EAIf;AAAA,EACA,MAAM;AAAA,IACJ,YAAY;AAAA,IACZ,QAAQ,EAAE,MAAM,UAAU,aAAa,qBAAqB,SAAS,OAAO;AAAA,EAC9E;AAAA,EACA,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,QAAI;AACF,YAAM,SAAiC,CAAC;AACxC,UAAI,KAAK,UAAU,EAAG,QAAO,YAAY,IAAI;AAC7C,YAAM,OAAO,MAAM,OAAwB,4BAA4B,MAAM;AAC7E,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;AAED,IAAM,YAAY,cAAc;AAAA,EAC9B,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASf;AAAA,EACA,MAAM;AAAA,IACJ,OAAO,EAAE,MAAM,UAAU,aAAa,uCAAuC,UAAU,KAAK;AAAA,IAC5F,OAAO,EAAE,MAAM,UAAU,aAAa,sDAAsD;AAAA,IAC5F,QAAQ,EAAE,MAAM,UAAU,aAAa,iEAAiE;AAAA,IACxG,QAAQ,EAAE,MAAM,UAAU,aAAa,0BAA0B;AAAA,IACjE,YAAY;AAAA,IACZ,QAAQ,EAAE,MAAM,UAAU,aAAa,qBAAqB,SAAS,OAAO;AAAA,EAC9E;AAAA,EACA,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,QAAI;AACF,YAAM,SAAiC,EAAE,OAAO,OAAO,KAAK,KAAK,EAAE;AACnE,YAAM,SAAU,KAAK,WAAkC,KAAK,QAAQ,cAAc;AAClF,aAAO,SAAS;AAChB,UAAI,KAAK,MAAO,QAAO,QAAQ,OAAO,KAAK,KAAK;AAChD,UAAI,KAAK,OAAQ,QAAO,SAAS,OAAO,KAAK,MAAM;AACnD,UAAI,KAAK,UAAU,EAAG,QAAO,YAAY,IAAI;AAE7C,YAAM,OAAO,MAAM,OAA8B,qCAAqC,MAAM;AAC5F,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,gBAAgB,cAAc;AAAA,EACzC,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMf;AAAA,EACA,aAAa;AAAA,IACX,MAAM;AAAA,IACN,QAAQ;AAAA,EACV;AACF,CAAC;","names":[]}
@@ -51,7 +51,7 @@ var feedbackCommand = defineCommand({
51
51
  meta: { name: "feedback", description: DESCRIPTION },
52
52
  subCommands: {
53
53
  read: feedbackReadCommand,
54
- record: () => import("./feedback-record-TKO54BOE.js").then((m) => m.feedbackRecordCommand)
54
+ record: () => import("./feedback-record-7WZ4H7EP.js").then((m) => m.feedbackRecordCommand)
55
55
  },
56
56
  // `args` stays although the parent has no `run`: citty finds the subcommand
57
57
  // name with THIS command's arg defs, so without them `--slug spring-offer`
@@ -63,4 +63,4 @@ var feedbackCommand = defineCommand({
63
63
  export {
64
64
  feedbackCommand
65
65
  };
66
- //# sourceMappingURL=feedback-EIZKS4JU.js.map
66
+ //# sourceMappingURL=feedback-OLTCHE6C.js.map
@@ -1,17 +1,17 @@
1
1
  import {
2
2
  versionOf
3
- } from "./chunk-C46GUI2S.js";
4
- import "./chunk-7CTMH5AK.js";
5
- import "./chunk-ASI4P6X2.js";
3
+ } from "./chunk-RZBEK2VE.js";
4
+ import "./chunk-KAUOHQTF.js";
5
+ import "./chunk-YUCLMOEG.js";
6
6
  import "./chunk-4QEY2L6U.js";
7
- import "./chunk-VL43TNIP.js";
8
- import "./chunk-ZDMTXQ2Q.js";
7
+ import "./chunk-QRP3PXWN.js";
8
+ import "./chunk-3IBYKLXR.js";
9
9
  import "./chunk-F2S5BLPE.js";
10
10
  import {
11
11
  holdWorkspaceSpend
12
12
  } from "./chunk-WTOYCUKH.js";
13
13
  import "./chunk-DZSIUEGH.js";
14
- import "./chunk-FPOGPFAG.js";
14
+ import "./chunk-EBWBG6YV.js";
15
15
  import "./chunk-NCWCZY5P.js";
16
16
  import "./chunk-DGCUPJZD.js";
17
17
  import "./chunk-PZXCWSKV.js";
@@ -28,11 +28,10 @@ import "./chunk-YBMVHGY3.js";
28
28
  import {
29
29
  CREATIVE_FEEDBACK_REASONS,
30
30
  creativesFeedbackRecordRequestSchema
31
- } from "./chunk-7EPXVICM.js";
31
+ } from "./chunk-XF4JUKVF.js";
32
32
  import "./chunk-GXDLWBOY.js";
33
33
  import "./chunk-TEINLN64.js";
34
34
  import "./chunk-ZJWUBJYQ.js";
35
- import "./chunk-HR6IWNKE.js";
36
35
  import "./chunk-NE4F3FHN.js";
37
36
  import {
38
37
  ApiError,
@@ -173,4 +172,4 @@ var feedbackRecordCommand = defineCommand({
173
172
  export {
174
173
  feedbackRecordCommand
175
174
  };
176
- //# sourceMappingURL=feedback-record-TKO54BOE.js.map
175
+ //# sourceMappingURL=feedback-record-7WZ4H7EP.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/creatives/feedback-record.ts","../src/commands/creatives/agent-option-note.ts"],"sourcesContent":["import {\n CREATIVE_FEEDBACK_REASONS,\n type CreativesFeedbackRecordResponse,\n creativesFeedbackRecordRequestSchema,\n} from \"@baker/api\";\nimport { defineCommand } from \"citty\";\nimport { ApiError, apiPost } from \"../../client.ts\";\nimport { writeJson } from \"../../output.ts\";\nimport { registerSchema } from \"../../schemas.ts\";\nimport { jevNoteJudge, readNoteAuthor } from \"./agent-option-note.ts\";\nimport { versionOf } from \"./version-of.ts\";\n\nconst DESCRIPTION = `Record what the user said about one version of a creative in this chat: an approval, or a rejection with reasons. Saved as their verdict (the person who wrote the latest message here) and read back by baker creatives feedback. One verdict per person per version or option: a later one replaces it.\nStart here: baker creatives feedback record --slug spring-offer --verdict rejected --reasons text_mistakes --note \"<their words>\"\nOnly record what the user said, never your own judgment. Picking one of several concepts is not a rejection of the others.`;\n\nconst ARGS = {\n slug: { type: \"string\", description: \"The creative: its folder name under src/creatives/.\", required: true },\n run: {\n type: \"string\",\n description: \"The version: its canvas run id (r_…) Left out, the version the creative shows now (its last render).\",\n required: false,\n },\n option: {\n type: \"string\",\n description:\n 'One option of a version that made several: its label (\"ugc\"), its number (\"2\") or its slot. Left out, the whole version.',\n required: false,\n },\n verdict: { type: \"string\", description: \"approved | rejected\", required: true },\n reasons: {\n type: \"string\",\n description: `Why it was rejected, comma-separated: ${CREATIVE_FEEDBACK_REASONS.join(\", \")}. Map the user's words to these; \"other\" when none fits. On a video, voice_or_sound covers the voiceover, music and mix (\"the voice sounds robotic\", \"music too loud\") and pacing covers the timing (\"too slow\", \"the hook comes too late\").`,\n required: false,\n },\n note: {\n type: \"string\",\n description: \"The user's own words, verbatim (not your summary). Up to 1000 characters.\",\n required: false,\n },\n} as const;\n\nregisterSchema({ command: \"creatives.feedback.record\", description: DESCRIPTION, args: ARGS });\n\nfunction splitList(value: unknown): string[] | undefined {\n if (typeof value !== \"string\" || value.trim() === \"\") return undefined;\n return value\n .split(\",\")\n .map((item) => item.trim())\n .filter((item) => item.length > 0);\n}\n\nfunction fail(code: string, message: string): never {\n writeJson({ ok: false, error: { code, message } });\n process.exit(1);\n}\n\n/**\n * A rejection whose note only answers the agent's own question, or that says nothing, is not the\n * person's feedback. Returns whether the note could not be confirmed as the person's words.\n */\nasync function refuseNotFeedback(body: {\n verdict: string;\n reasons?: readonly string[];\n note?: string;\n}): Promise<boolean> {\n if (body.verdict === \"rejected\" && !body.reasons?.length && !body.note) {\n fail(\n \"VALIDATION_ERROR\",\n \"A rejection needs --reasons or --note (the user's words), so the next version knows what to change.\",\n );\n }\n if (body.verdict !== \"rejected\" || !body.note) return false;\n const author = await readNoteAuthor(body.note, jevNoteJudge);\n if (author === \"agent_option\") {\n fail(\n \"AGENT_OPTION_NOT_FEEDBACK\",\n `\"${body.note}\" is the answer to your own question, not the person's taste: a defect the checks found is yours to fix inside this version (\\`baker canvas run --fix\\`), never feedback to record. Record only what the person says about the ad in their own words.`,\n );\n }\n return author === \"unconfirmed\";\n}\n\nexport const feedbackRecordCommand = defineCommand({\n meta: { name: \"record\", description: DESCRIPTION },\n args: ARGS,\n run: async ({ args }) => {\n const reasons = splitList(args.reasons);\n const unknown = (reasons ?? []).filter(\n (reason) => !(CREATIVE_FEEDBACK_REASONS as readonly string[]).includes(reason),\n );\n if (unknown.length > 0) {\n fail(\"VALIDATION_ERROR\", `Unknown reason ${unknown.join(\", \")}. Use: ${CREATIVE_FEEDBACK_REASONS.join(\", \")}.`);\n }\n const parsed = creativesFeedbackRecordRequestSchema.safeParse({\n slug: args.slug,\n runId: await versionOf(String(args.slug), args.run).then(\n (run) => run ?? fail(\"VALIDATION_ERROR\", \"--run: this creative has no rendered version here; name one (r_…).\"),\n ),\n ...(typeof args.option === \"string\" && args.option.trim() ? { option: args.option.trim() } : {}),\n verdict: args.verdict,\n ...(reasons ? { reasons } : {}),\n ...(typeof args.note === \"string\" && args.note.trim() ? { note: args.note } : {}),\n });\n if (!parsed.success) {\n const issue = parsed.error.issues[0];\n fail(\"VALIDATION_ERROR\", `--${String(issue?.path[0] ?? \"args\")}: ${issue?.message ?? \"invalid\"}`);\n }\n const body = parsed.data;\n const noteUnconfirmed = await refuseNotFeedback(body);\n try {\n const response = await apiPost<CreativesFeedbackRecordResponse>(\n \"/api/creatives/feedback/record\",\n noteUnconfirmed ? { ...body, noteUnconfirmed } : body,\n );\n writeJson(response);\n } catch (err) {\n if (err instanceof ApiError) fail(err.code, err.message);\n fail(\"INTERNAL_ERROR\", \"Unexpected error\");\n }\n },\n});\n","/**\n * Whether a rejection's note is the agent's own words rather than the person's taste: the label\n * of an option the agent offered (\"Sí, corrige todo (Recomendado)\") or the answer to its own\n * \"fix what is pending?\" (\"Fix everything\"). Production Oct 2026: both were recorded as\n * rejections, so every fix became a new version and later chats read the agent's own defects as\n * the company's taste. The agent writes those options in the marketer's language, so the decision\n * model reads the note in whatever language it is in (docs/decision-model.md).\n */\nimport { askJev } from \"../../engine/nodes/local/lib/jev.ts\";\nimport type { ReviewUsage } from \"../../engine/nodes/local/lib/render-review.ts\";\nimport { holdWorkspaceSpend } from \"../canvas/unbilled-spend.ts\";\n\n/**\n * The bands, measured 2026-10-07 on 30 notes in 8 languages (scripts/agent-option-note-evals,\n * three runs). A recommended tag scored 0.92 or more on the agent's labels and 0.03 or less on\n * people's notes. A bare yes to fixing scored 0.59 or more on the agent's untagged answers and\n * 0.31 or less on people's, except \"fix all the typos\" (0.52-0.56), which names its problem\n * (0.86; the agent's answers 0.12 or less).\n */\nexport const NOTE_BANDS = { tagged: 0.5, bareFix: 0.45, namesProblem: 0.5 } as const;\n\nconst TAGGED = \"Does `note` end with a tag marking it as the recommended option, like (Recommended), in any language?\";\nconst BARE_FIX =\n 'Is `note` a bare yes to an offer to fix things, like \"fix everything\" or \"fix what is pending\", naming no particular problem? A note that names what is wrong or what to change (the typos, the price, cut-off text, redo the pieces) is not.';\nconst NAMES_PROBLEM =\n \"Does `note` name a particular problem, element or part of an ad (a typo, the price, the logo, the audio, the text, the colours, a person), apart from a whole format or size?\";\n\n/** Three judgments about one note, each a probability; one judgment per question, combined in code. */\nexport type NoteReading = { tagged: number; bareFix: number; namesProblem: number };\n\n/** The decision model's reading of `note`; null when no judgment came back. */\nexport type NoteJudge = (note: string) => Promise<NoteReading | null>;\n\n/** The decision model as the judge: three Nouls in one request. */\nexport const jevNoteJudge: NoteJudge = async (note) => {\n const spent: ReviewUsage[] = [];\n const answers = await askJev(\n [TAGGED, BARE_FIX, NAMES_PROBLEM].map((question) => ({ instructions: { note, question } })),\n (usage) => spent.push(usage),\n );\n await holdWorkspaceSpend(spent);\n if (answers === null) return null;\n const [tagged = 0, bareFix = 0, namesProblem = 1] = answers;\n return { tagged, bareFix, namesProblem };\n};\n\n/** The agent's option label, or its bare fix answer naming nothing of the ad. Pure. */\nexport function readsAsAgentOption(reading: NoteReading): boolean {\n if (reading.tagged >= NOTE_BANDS.tagged) return true;\n return reading.bareFix >= NOTE_BANDS.bareFix && reading.namesProblem < NOTE_BANDS.namesProblem;\n}\n\n/** Whose words a note is: the agent's own option, the person's, or unconfirmed when no judgment came back. */\nexport type NoteAuthor = \"agent_option\" | \"person\" | \"unconfirmed\";\n\n/**\n * Who wrote `note`, as the decision model reads it. No judgment (no key, a timeout, an outage) is\n * \"unconfirmed\", never the person's: Baker keeps that note but does not read it as taste (B5).\n */\nexport async function readNoteAuthor(note: string, judge: NoteJudge): Promise<NoteAuthor> {\n const text = note.trim();\n if (!text) return \"person\";\n const reading = await judge(text).catch(() => null);\n if (reading === null) return \"unconfirmed\";\n return readsAsAgentOption(reading) ? \"agent_option\" : \"person\";\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKA,SAAS,qBAAqB;;;ACcvB,IAAM,aAAa,EAAE,QAAQ,KAAK,SAAS,MAAM,cAAc,IAAI;AAE1E,IAAM,SAAS;AACf,IAAM,WACJ;AACF,IAAM,gBACJ;AASK,IAAM,eAA0B,OAAO,SAAS;AACrD,QAAM,QAAuB,CAAC;AAC9B,QAAM,UAAU,MAAM;AAAA,IACpB,CAAC,QAAQ,UAAU,aAAa,EAAE,IAAI,CAAC,cAAc,EAAE,cAAc,EAAE,MAAM,SAAS,EAAE,EAAE;AAAA,IAC1F,CAAC,UAAU,MAAM,KAAK,KAAK;AAAA,EAC7B;AACA,QAAM,mBAAmB,KAAK;AAC9B,MAAI,YAAY,KAAM,QAAO;AAC7B,QAAM,CAAC,SAAS,GAAG,UAAU,GAAG,eAAe,CAAC,IAAI;AACpD,SAAO,EAAE,QAAQ,SAAS,aAAa;AACzC;AAGO,SAAS,mBAAmB,SAA+B;AAChE,MAAI,QAAQ,UAAU,WAAW,OAAQ,QAAO;AAChD,SAAO,QAAQ,WAAW,WAAW,WAAW,QAAQ,eAAe,WAAW;AACpF;AASA,eAAsB,eAAe,MAAc,OAAuC;AACxF,QAAM,OAAO,KAAK,KAAK;AACvB,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,UAAU,MAAM,MAAM,IAAI,EAAE,MAAM,MAAM,IAAI;AAClD,MAAI,YAAY,KAAM,QAAO;AAC7B,SAAO,mBAAmB,OAAO,IAAI,iBAAiB;AACxD;;;ADrDA,IAAM,cAAc;AAAA;AAAA;AAIpB,IAAM,OAAO;AAAA,EACX,MAAM,EAAE,MAAM,UAAU,aAAa,uDAAuD,UAAU,KAAK;AAAA,EAC3G,KAAK;AAAA,IACH,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,EACZ;AAAA,EACA,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,aACE;AAAA,IACF,UAAU;AAAA,EACZ;AAAA,EACA,SAAS,EAAE,MAAM,UAAU,aAAa,uBAAuB,UAAU,KAAK;AAAA,EAC9E,SAAS;AAAA,IACP,MAAM;AAAA,IACN,aAAa,yCAAyC,0BAA0B,KAAK,IAAI,CAAC;AAAA,IAC1F,UAAU;AAAA,EACZ;AAAA,EACA,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,EACZ;AACF;AAEA,eAAe,EAAE,SAAS,6BAA6B,aAAa,aAAa,MAAM,KAAK,CAAC;AAE7F,SAAS,UAAU,OAAsC;AACvD,MAAI,OAAO,UAAU,YAAY,MAAM,KAAK,MAAM,GAAI,QAAO;AAC7D,SAAO,MACJ,MAAM,GAAG,EACT,IAAI,CAAC,SAAS,KAAK,KAAK,CAAC,EACzB,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC;AACrC;AAEA,SAAS,KAAK,MAAc,SAAwB;AAClD,YAAU,EAAE,IAAI,OAAO,OAAO,EAAE,MAAM,QAAQ,EAAE,CAAC;AACjD,UAAQ,KAAK,CAAC;AAChB;AAMA,eAAe,kBAAkB,MAIZ;AACnB,MAAI,KAAK,YAAY,cAAc,CAAC,KAAK,SAAS,UAAU,CAAC,KAAK,MAAM;AACtE;AAAA,MACE;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,MAAI,KAAK,YAAY,cAAc,CAAC,KAAK,KAAM,QAAO;AACtD,QAAM,SAAS,MAAM,eAAe,KAAK,MAAM,YAAY;AAC3D,MAAI,WAAW,gBAAgB;AAC7B;AAAA,MACE;AAAA,MACA,IAAI,KAAK,IAAI;AAAA,IACf;AAAA,EACF;AACA,SAAO,WAAW;AACpB;AAEO,IAAM,wBAAwB,cAAc;AAAA,EACjD,MAAM,EAAE,MAAM,UAAU,aAAa,YAAY;AAAA,EACjD,MAAM;AAAA,EACN,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,UAAM,UAAU,UAAU,KAAK,OAAO;AACtC,UAAM,WAAW,WAAW,CAAC,GAAG;AAAA,MAC9B,CAAC,WAAW,CAAE,0BAAgD,SAAS,MAAM;AAAA,IAC/E;AACA,QAAI,QAAQ,SAAS,GAAG;AACtB,WAAK,oBAAoB,kBAAkB,QAAQ,KAAK,IAAI,CAAC,UAAU,0BAA0B,KAAK,IAAI,CAAC,GAAG;AAAA,IAChH;AACA,UAAM,SAAS,qCAAqC,UAAU;AAAA,MAC5D,MAAM,KAAK;AAAA,MACX,OAAO,MAAM,UAAU,OAAO,KAAK,IAAI,GAAG,KAAK,GAAG,EAAE;AAAA,QAClD,CAAC,QAAQ,OAAO,KAAK,oBAAoB,yEAAoE;AAAA,MAC/G;AAAA,MACA,GAAI,OAAO,KAAK,WAAW,YAAY,KAAK,OAAO,KAAK,IAAI,EAAE,QAAQ,KAAK,OAAO,KAAK,EAAE,IAAI,CAAC;AAAA,MAC9F,SAAS,KAAK;AAAA,MACd,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,MAC7B,GAAI,OAAO,KAAK,SAAS,YAAY,KAAK,KAAK,KAAK,IAAI,EAAE,MAAM,KAAK,KAAK,IAAI,CAAC;AAAA,IACjF,CAAC;AACD,QAAI,CAAC,OAAO,SAAS;AACnB,YAAM,QAAQ,OAAO,MAAM,OAAO,CAAC;AACnC,WAAK,oBAAoB,KAAK,OAAO,OAAO,KAAK,CAAC,KAAK,MAAM,CAAC,KAAK,OAAO,WAAW,SAAS,EAAE;AAAA,IAClG;AACA,UAAM,OAAO,OAAO;AACpB,UAAM,kBAAkB,MAAM,kBAAkB,IAAI;AACpD,QAAI;AACF,YAAM,WAAW,MAAM;AAAA,QACrB;AAAA,QACA,kBAAkB,EAAE,GAAG,MAAM,gBAAgB,IAAI;AAAA,MACnD;AACA,gBAAU,QAAQ;AAAA,IACpB,SAAS,KAAK;AACZ,UAAI,eAAe,SAAU,MAAK,IAAI,MAAM,IAAI,OAAO;AACvD,WAAK,kBAAkB,kBAAkB;AAAA,IAC3C;AAAA,EACF;AACF,CAAC;","names":[]}
1
+ {"version":3,"sources":["../src/commands/creatives/feedback-record.ts","../src/commands/creatives/agent-option-note.ts"],"sourcesContent":["import {\n CREATIVE_FEEDBACK_REASONS,\n type CreativesFeedbackRecordResponse,\n creativesFeedbackRecordRequestSchema,\n} from \"@baker/api\";\nimport { defineCommand } from \"citty\";\nimport { ApiError, apiPost } from \"../../client.ts\";\nimport { writeJson } from \"../../output.ts\";\nimport { registerSchema } from \"../../schemas.ts\";\nimport { jevNoteJudge, readNoteAuthor } from \"./agent-option-note.ts\";\nimport { versionOf } from \"./version-of.ts\";\n\nconst DESCRIPTION = `Record what the user said about one version of a creative in this chat: an approval, or a rejection with reasons. Saved as their verdict (the person who wrote the latest message here) and read back by baker creatives feedback. One verdict per person per version or option: a later one replaces it.\nStart here: baker creatives feedback record --slug spring-offer --verdict rejected --reasons text_mistakes --note \"<their words>\"\nOnly record what the user said, never your own judgment. Picking one of several concepts is not a rejection of the others.`;\n\nconst ARGS = {\n slug: { type: \"string\", description: \"The creative: its folder name under src/creatives/.\", required: true },\n run: {\n type: \"string\",\n description: \"The version: its canvas run id (r_…) Left out, the version the creative shows now (its last render).\",\n required: false,\n },\n option: {\n type: \"string\",\n description:\n 'One option of a version that made several: its label (\"ugc\"), its number (\"2\") or its slot. Left out, the whole version.',\n required: false,\n },\n verdict: { type: \"string\", description: \"approved | rejected\", required: true },\n reasons: {\n type: \"string\",\n description: `Why it was rejected, comma-separated: ${CREATIVE_FEEDBACK_REASONS.join(\", \")}. Map the user's words to these; \"other\" when none fits. On a video, voice_or_sound covers the voiceover, music and mix (\"the voice sounds robotic\", \"music too loud\") and pacing covers the timing (\"too slow\", \"the hook comes too late\").`,\n required: false,\n },\n note: {\n type: \"string\",\n description: \"The user's own words, verbatim (not your summary). Up to 1000 characters.\",\n required: false,\n },\n} as const;\n\nregisterSchema({ command: \"creatives.feedback.record\", description: DESCRIPTION, args: ARGS });\n\nfunction splitList(value: unknown): string[] | undefined {\n if (typeof value !== \"string\" || value.trim() === \"\") return undefined;\n return value\n .split(\",\")\n .map((item) => item.trim())\n .filter((item) => item.length > 0);\n}\n\nfunction fail(code: string, message: string): never {\n writeJson({ ok: false, error: { code, message } });\n process.exit(1);\n}\n\n/**\n * A rejection whose note only answers the agent's own question, or that says nothing, is not the\n * person's feedback. Returns whether the note could not be confirmed as the person's words.\n */\nasync function refuseNotFeedback(body: {\n verdict: string;\n reasons?: readonly string[];\n note?: string;\n}): Promise<boolean> {\n if (body.verdict === \"rejected\" && !body.reasons?.length && !body.note) {\n fail(\n \"VALIDATION_ERROR\",\n \"A rejection needs --reasons or --note (the user's words), so the next version knows what to change.\",\n );\n }\n if (body.verdict !== \"rejected\" || !body.note) return false;\n const author = await readNoteAuthor(body.note, jevNoteJudge);\n if (author === \"agent_option\") {\n fail(\n \"AGENT_OPTION_NOT_FEEDBACK\",\n `\"${body.note}\" is the answer to your own question, not the person's taste: a defect the checks found is yours to fix inside this version (\\`baker canvas run --fix\\`), never feedback to record. Record only what the person says about the ad in their own words.`,\n );\n }\n return author === \"unconfirmed\";\n}\n\nexport const feedbackRecordCommand = defineCommand({\n meta: { name: \"record\", description: DESCRIPTION },\n args: ARGS,\n run: async ({ args }) => {\n const reasons = splitList(args.reasons);\n const unknown = (reasons ?? []).filter(\n (reason) => !(CREATIVE_FEEDBACK_REASONS as readonly string[]).includes(reason),\n );\n if (unknown.length > 0) {\n fail(\"VALIDATION_ERROR\", `Unknown reason ${unknown.join(\", \")}. Use: ${CREATIVE_FEEDBACK_REASONS.join(\", \")}.`);\n }\n const parsed = creativesFeedbackRecordRequestSchema.safeParse({\n slug: args.slug,\n runId: await versionOf(String(args.slug), args.run).then(\n (run) => run ?? fail(\"VALIDATION_ERROR\", \"--run: this creative has no rendered version here; name one (r_…).\"),\n ),\n ...(typeof args.option === \"string\" && args.option.trim() ? { option: args.option.trim() } : {}),\n verdict: args.verdict,\n ...(reasons ? { reasons } : {}),\n ...(typeof args.note === \"string\" && args.note.trim() ? { note: args.note } : {}),\n });\n if (!parsed.success) {\n const issue = parsed.error.issues[0];\n fail(\"VALIDATION_ERROR\", `--${String(issue?.path[0] ?? \"args\")}: ${issue?.message ?? \"invalid\"}`);\n }\n const body = parsed.data;\n const noteUnconfirmed = await refuseNotFeedback(body);\n try {\n const response = await apiPost<CreativesFeedbackRecordResponse>(\n \"/api/creatives/feedback/record\",\n noteUnconfirmed ? { ...body, noteUnconfirmed } : body,\n );\n writeJson(response);\n } catch (err) {\n if (err instanceof ApiError) fail(err.code, err.message);\n fail(\"INTERNAL_ERROR\", \"Unexpected error\");\n }\n },\n});\n","/**\n * Whether a rejection's note is the agent's own words rather than the person's taste: the label\n * of an option the agent offered (\"Sí, corrige todo (Recomendado)\") or the answer to its own\n * \"fix what is pending?\" (\"Fix everything\"). Production Oct 2026: both were recorded as\n * rejections, so every fix became a new version and later chats read the agent's own defects as\n * the company's taste. The agent writes those options in the marketer's language, so the decision\n * model reads the note in whatever language it is in (docs/decision-model.md).\n */\nimport { askJev } from \"../../engine/nodes/local/lib/jev.ts\";\nimport type { ReviewUsage } from \"../../engine/nodes/local/lib/render-review.ts\";\nimport { holdWorkspaceSpend } from \"../canvas/unbilled-spend.ts\";\n\n/**\n * The bands, measured 2026-10-07 on 30 notes in 8 languages (scripts/agent-option-note-evals,\n * three runs). A recommended tag scored 0.92 or more on the agent's labels and 0.03 or less on\n * people's notes. A bare yes to fixing scored 0.59 or more on the agent's untagged answers and\n * 0.31 or less on people's, except \"fix all the typos\" (0.52-0.56), which names its problem\n * (0.86; the agent's answers 0.12 or less).\n */\nexport const NOTE_BANDS = { tagged: 0.5, bareFix: 0.45, namesProblem: 0.5 } as const;\n\nconst TAGGED = \"Does `note` end with a tag marking it as the recommended option, like (Recommended), in any language?\";\nconst BARE_FIX =\n 'Is `note` a bare yes to an offer to fix things, like \"fix everything\" or \"fix what is pending\", naming no particular problem? A note that names what is wrong or what to change (the typos, the price, cut-off text, redo the pieces) is not.';\nconst NAMES_PROBLEM =\n \"Does `note` name a particular problem, element or part of an ad (a typo, the price, the logo, the audio, the text, the colours, a person), apart from a whole format or size?\";\n\n/** Three judgments about one note, each a probability; one judgment per question, combined in code. */\nexport type NoteReading = { tagged: number; bareFix: number; namesProblem: number };\n\n/** The decision model's reading of `note`; null when no judgment came back. */\nexport type NoteJudge = (note: string) => Promise<NoteReading | null>;\n\n/** The decision model as the judge: three Nouls in one request. */\nexport const jevNoteJudge: NoteJudge = async (note) => {\n const spent: ReviewUsage[] = [];\n const answers = await askJev(\n [TAGGED, BARE_FIX, NAMES_PROBLEM].map((question) => ({ instructions: { note, question } })),\n (usage) => spent.push(usage),\n );\n await holdWorkspaceSpend(spent);\n if (answers === null) return null;\n const [tagged = 0, bareFix = 0, namesProblem = 1] = answers;\n return { tagged, bareFix, namesProblem };\n};\n\n/** The agent's option label, or its bare fix answer naming nothing of the ad. Pure. */\nexport function readsAsAgentOption(reading: NoteReading): boolean {\n if (reading.tagged >= NOTE_BANDS.tagged) return true;\n return reading.bareFix >= NOTE_BANDS.bareFix && reading.namesProblem < NOTE_BANDS.namesProblem;\n}\n\n/** Whose words a note is: the agent's own option, the person's, or unconfirmed when no judgment came back. */\nexport type NoteAuthor = \"agent_option\" | \"person\" | \"unconfirmed\";\n\n/**\n * Who wrote `note`, as the decision model reads it. No judgment (no key, a timeout, an outage) is\n * \"unconfirmed\", never the person's: Baker keeps that note but does not read it as taste (B5).\n */\nexport async function readNoteAuthor(note: string, judge: NoteJudge): Promise<NoteAuthor> {\n const text = note.trim();\n if (!text) return \"person\";\n const reading = await judge(text).catch(() => null);\n if (reading === null) return \"unconfirmed\";\n return readsAsAgentOption(reading) ? \"agent_option\" : \"person\";\n}\n"],"mappings":"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","names":[]}
@@ -1,16 +1,15 @@
1
1
  import {
2
2
  fetchHints,
3
3
  redditPageFix
4
- } from "./chunk-H3427GPU.js";
4
+ } from "./chunk-OZRUJVIQ.js";
5
5
  import {
6
6
  handleResearchError,
7
7
  writeResearchJson
8
8
  } from "./chunk-WNFIJAUO.js";
9
- import "./chunk-7EPXVICM.js";
9
+ import "./chunk-XF4JUKVF.js";
10
10
  import "./chunk-GXDLWBOY.js";
11
11
  import "./chunk-TEINLN64.js";
12
12
  import "./chunk-ZJWUBJYQ.js";
13
- import "./chunk-HR6IWNKE.js";
14
13
  import "./chunk-NE4F3FHN.js";
15
14
  import {
16
15
  apiPost
@@ -174,4 +173,4 @@ Examples:
174
173
  export {
175
174
  fetchCommand
176
175
  };
177
- //# sourceMappingURL=fetch-4BY6HYUM.js.map
176
+ //# sourceMappingURL=fetch-W7NULDEO.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/research/fetch.ts"],"sourcesContent":["import type { ResearchFetchRequest, ResearchFetchResponse } from \"@baker/api\";\nimport { defineCommand } from \"citty\";\nimport { apiPost } from \"../../client.ts\";\nimport { registerSchema } from \"../../schemas.ts\";\nimport { fetchHints, redditPageFix } from \"./hints.ts\";\nimport { handleResearchError, type ResearchFix, writeResearchJson } from \"./output.ts\";\n\n/**\n * A page big enough to matter is bigger than a turn wants to carry, and the\n * read is cached — so the default shows the top of it and `--full` returns for\n * the rest at no extra cost.\n */\nconst CONTENT_PREVIEW_CHARS = 20_000;\n\n/** A page behind a bot wall can take a while to clear; the default 60s is not enough. */\nconst TIMEOUT_MS = 180_000;\n\nregisterSchema({\n command: \"research.fetch\",\n description:\n \"Read a page an ordinary web fetch could not — bot walls and JavaScript-rendered pages are resolved for you. Use it when your normal page read came back with a security check, an error page, or an empty shell.\",\n args: {\n url: { type: \"string\", description: \"Full URL of the page to read\", required: true },\n format: {\n type: \"string\",\n description: \"markdown (default, best for reading) or html (when you need the markup)\",\n required: false,\n enum: [\"markdown\", \"html\"],\n },\n \"wait-for\": {\n type: \"number\",\n description: \"Extra ms to let late content settle (0-30000). Only for pages that fill in after load\",\n required: false,\n },\n \"whole-page\": {\n type: \"boolean\",\n description: \"Include nav, footer and sidebars (default: main content only)\",\n required: false,\n default: false,\n },\n full: {\n type: \"boolean\",\n description: `Return the whole page instead of the first ${CONTENT_PREVIEW_CHARS} characters`,\n required: false,\n default: false,\n },\n },\n});\n\nconst FIELDS: Record<string, string> = {\n url: \"The URL as asked for\",\n final_url: \"Where the read landed after redirects\",\n title: \"Page title, or null when the page declares none\",\n content: \"The page text (markdown by default)\",\n content_chars: \"Length of the full page available on the server\",\n content_shown: \"Characters in `content` — below content_chars unless --full\",\n truncated: \"The page was longer than one read returns, so the tail is missing\",\n provider: \"Who resolved the read\",\n};\n\n/**\n * Every failure here is one source out of a larger job, so the remediation is\n * about finishing the job: name the gap, keep going. The only case worth a\n * second attempt is a page that never settled.\n */\nfunction fetchFix(code: string): ResearchFix {\n if (code === \"VALIDATION_ERROR\") {\n return {\n action: \"retry_with_changes\",\n explanation: \"Re-run with a complete address, including https://.\",\n };\n }\n if (code === \"TIMEOUT\") {\n return {\n action: \"retry_with_changes\",\n explanation:\n \"The page never settled. Retry this URL once with `--wait-for 10000`; if that fails too, carry on with the rest of the job and say this page couldn't be read.\",\n };\n }\n if (code === \"RATE_LIMITED\") {\n return {\n action: \"continue_without\",\n explanation:\n \"The page reader is busy. Do the rest of the job first and come back to this URL once, later — don't loop on it.\",\n };\n }\n if (code === \"FORBIDDEN\" || code === \"NOT_FOUND\") {\n return {\n action: \"continue_without\",\n explanation:\n \"This page will not open for us, and retrying will not change that. Carry on with the sources you can reach and say plainly which page you couldn't read.\",\n };\n }\n return {\n action: \"continue_without\",\n explanation:\n \"This read failed. Don't build a retry ladder around it — finish the rest of the job with what you can reach and name this page as a gap.\",\n };\n}\n\nexport const fetchCommand = defineCommand({\n meta: {\n name: \"fetch\",\n description: `Read a page an ordinary web fetch could not. Bot walls and JavaScript-rendered pages are resolved for you — you never have to retry, wait, or drive a browser yourself.\n\nReach for this the moment a normal page read comes back with a security check, an error page, or an empty shell. One call, no escalation ladder.\n\nExamples:\n baker research fetch \"https://competitor.com/pricing\"\n baker research fetch \"https://competitor.com/pricing\" --full\n baker research fetch \"https://app.competitor.com/blog/post\" --wait-for 5000\n baker research fetch \"https://competitor.com\" --format html --whole-page`,\n },\n args: {\n url: { type: \"positional\", description: \"URL of the page to read\", required: false },\n format: { type: \"string\", description: \"markdown (default) or html\", required: false },\n \"wait-for\": { type: \"string\", description: \"Extra ms to let late content settle (0-30000)\", required: false },\n \"whole-page\": { type: \"boolean\", description: \"Include nav, footer and sidebars\", required: false },\n full: { type: \"boolean\", description: \"Return the whole page, not just the first chunk\", required: false },\n },\n run: async ({ args }) => {\n const url = args.url as string | undefined;\n if (!url) {\n writeResearchJson({\n ok: false,\n error: {\n code: \"VALIDATION_ERROR\",\n message: \"A URL is required\",\n fix: fetchFix(\"VALIDATION_ERROR\"),\n },\n });\n process.exit(1);\n }\n\n const format = (args.format as string | undefined) ?? \"markdown\";\n if (format !== \"markdown\" && format !== \"html\") {\n writeResearchJson({\n ok: false,\n error: {\n code: \"VALIDATION_ERROR\",\n message: \"Format must be markdown or html\",\n fix: { action: \"retry_with_changes\", explanation: \"Re-run with --format markdown or --format html.\" },\n },\n });\n process.exit(1);\n }\n\n const body: ResearchFetchRequest = { url, format };\n if (args[\"wait-for\"]) body.waitFor = Number(args[\"wait-for\"]);\n if (args[\"whole-page\"]) body.onlyMainContent = false;\n\n try {\n const page = await apiPost<ResearchFetchResponse>(\"/api/research/fetch\", body, { timeoutMs: TIMEOUT_MS });\n const content = args.full ? page.content : page.content.slice(0, CONTENT_PREVIEW_CHARS);\n\n writeResearchJson({\n ok: true,\n data: {\n url: page.url,\n final_url: page.finalUrl,\n title: page.title,\n content_chars: page.contentChars,\n content_shown: content.length,\n truncated: page.truncated,\n provider: page.provider,\n content,\n },\n fields: FIELDS,\n hints: fetchHints({\n truncated: page.truncated,\n contentChars: page.contentChars,\n shownChars: content.length,\n }),\n });\n } catch (err) {\n handleResearchError(err, (code) => redditPageFix(url, code) ?? fetchFix(code));\n }\n },\n});\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/commands/research/fetch.ts"],"sourcesContent":["import type { ResearchFetchRequest, ResearchFetchResponse } from \"@baker/api\";\nimport { defineCommand } from \"citty\";\nimport { apiPost } from \"../../client.ts\";\nimport { registerSchema } from \"../../schemas.ts\";\nimport { fetchHints, redditPageFix } from \"./hints.ts\";\nimport { handleResearchError, type ResearchFix, writeResearchJson } from \"./output.ts\";\n\n/**\n * A page big enough to matter is bigger than a turn wants to carry, and the\n * read is cached — so the default shows the top of it and `--full` returns for\n * the rest at no extra cost.\n */\nconst CONTENT_PREVIEW_CHARS = 20_000;\n\n/** A page behind a bot wall can take a while to clear; the default 60s is not enough. */\nconst TIMEOUT_MS = 180_000;\n\nregisterSchema({\n command: \"research.fetch\",\n description:\n \"Read a page an ordinary web fetch could not — bot walls and JavaScript-rendered pages are resolved for you. Use it when your normal page read came back with a security check, an error page, or an empty shell.\",\n args: {\n url: { type: \"string\", description: \"Full URL of the page to read\", required: true },\n format: {\n type: \"string\",\n description: \"markdown (default, best for reading) or html (when you need the markup)\",\n required: false,\n enum: [\"markdown\", \"html\"],\n },\n \"wait-for\": {\n type: \"number\",\n description: \"Extra ms to let late content settle (0-30000). Only for pages that fill in after load\",\n required: false,\n },\n \"whole-page\": {\n type: \"boolean\",\n description: \"Include nav, footer and sidebars (default: main content only)\",\n required: false,\n default: false,\n },\n full: {\n type: \"boolean\",\n description: `Return the whole page instead of the first ${CONTENT_PREVIEW_CHARS} characters`,\n required: false,\n default: false,\n },\n },\n});\n\nconst FIELDS: Record<string, string> = {\n url: \"The URL as asked for\",\n final_url: \"Where the read landed after redirects\",\n title: \"Page title, or null when the page declares none\",\n content: \"The page text (markdown by default)\",\n content_chars: \"Length of the full page available on the server\",\n content_shown: \"Characters in `content` — below content_chars unless --full\",\n truncated: \"The page was longer than one read returns, so the tail is missing\",\n provider: \"Who resolved the read\",\n};\n\n/**\n * Every failure here is one source out of a larger job, so the remediation is\n * about finishing the job: name the gap, keep going. The only case worth a\n * second attempt is a page that never settled.\n */\nfunction fetchFix(code: string): ResearchFix {\n if (code === \"VALIDATION_ERROR\") {\n return {\n action: \"retry_with_changes\",\n explanation: \"Re-run with a complete address, including https://.\",\n };\n }\n if (code === \"TIMEOUT\") {\n return {\n action: \"retry_with_changes\",\n explanation:\n \"The page never settled. Retry this URL once with `--wait-for 10000`; if that fails too, carry on with the rest of the job and say this page couldn't be read.\",\n };\n }\n if (code === \"RATE_LIMITED\") {\n return {\n action: \"continue_without\",\n explanation:\n \"The page reader is busy. Do the rest of the job first and come back to this URL once, later — don't loop on it.\",\n };\n }\n if (code === \"FORBIDDEN\" || code === \"NOT_FOUND\") {\n return {\n action: \"continue_without\",\n explanation:\n \"This page will not open for us, and retrying will not change that. Carry on with the sources you can reach and say plainly which page you couldn't read.\",\n };\n }\n return {\n action: \"continue_without\",\n explanation:\n \"This read failed. Don't build a retry ladder around it — finish the rest of the job with what you can reach and name this page as a gap.\",\n };\n}\n\nexport const fetchCommand = defineCommand({\n meta: {\n name: \"fetch\",\n description: `Read a page an ordinary web fetch could not. Bot walls and JavaScript-rendered pages are resolved for you — you never have to retry, wait, or drive a browser yourself.\n\nReach for this the moment a normal page read comes back with a security check, an error page, or an empty shell. One call, no escalation ladder.\n\nExamples:\n baker research fetch \"https://competitor.com/pricing\"\n baker research fetch \"https://competitor.com/pricing\" --full\n baker research fetch \"https://app.competitor.com/blog/post\" --wait-for 5000\n baker research fetch \"https://competitor.com\" --format html --whole-page`,\n },\n args: {\n url: { type: \"positional\", description: \"URL of the page to read\", required: false },\n format: { type: \"string\", description: \"markdown (default) or html\", required: false },\n \"wait-for\": { type: \"string\", description: \"Extra ms to let late content settle (0-30000)\", required: false },\n \"whole-page\": { type: \"boolean\", description: \"Include nav, footer and sidebars\", required: false },\n full: { type: \"boolean\", description: \"Return the whole page, not just the first chunk\", required: false },\n },\n run: async ({ args }) => {\n const url = args.url as string | undefined;\n if (!url) {\n writeResearchJson({\n ok: false,\n error: {\n code: \"VALIDATION_ERROR\",\n message: \"A URL is required\",\n fix: fetchFix(\"VALIDATION_ERROR\"),\n },\n });\n process.exit(1);\n }\n\n const format = (args.format as string | undefined) ?? \"markdown\";\n if (format !== \"markdown\" && format !== \"html\") {\n writeResearchJson({\n ok: false,\n error: {\n code: \"VALIDATION_ERROR\",\n message: \"Format must be markdown or html\",\n fix: { action: \"retry_with_changes\", explanation: \"Re-run with --format markdown or --format html.\" },\n },\n });\n process.exit(1);\n }\n\n const body: ResearchFetchRequest = { url, format };\n if (args[\"wait-for\"]) body.waitFor = Number(args[\"wait-for\"]);\n if (args[\"whole-page\"]) body.onlyMainContent = false;\n\n try {\n const page = await apiPost<ResearchFetchResponse>(\"/api/research/fetch\", body, { timeoutMs: TIMEOUT_MS });\n const content = args.full ? page.content : page.content.slice(0, CONTENT_PREVIEW_CHARS);\n\n writeResearchJson({\n ok: true,\n data: {\n url: page.url,\n final_url: page.finalUrl,\n title: page.title,\n content_chars: page.contentChars,\n content_shown: content.length,\n truncated: page.truncated,\n provider: page.provider,\n content,\n },\n fields: FIELDS,\n hints: fetchHints({\n truncated: page.truncated,\n contentChars: page.contentChars,\n shownChars: content.length,\n }),\n });\n } catch (err) {\n handleResearchError(err, (code) => redditPageFix(url, code) ?? fetchFix(code));\n }\n },\n});\n"],"mappings":"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","names":[]}
@@ -2,13 +2,13 @@ import {
2
2
  OUTPUT_ARGS,
3
3
  writeProviderHits
4
4
  } from "./chunk-WS2GMOSG.js";
5
+ import {
6
+ emptyResultHints
7
+ } from "./chunk-Q6ULQMWG.js";
5
8
  import {
6
9
  AUTO_INGEST_MAX,
7
10
  parseAutoIngest
8
11
  } from "./chunk-KKJ4KJCW.js";
9
- import {
10
- emptyResultHints
11
- } from "./chunk-Q6ULQMWG.js";
12
12
  import {
13
13
  ApiError,
14
14
  apiPost
@@ -131,4 +131,4 @@ var findCommand = defineCommand({
131
131
  export {
132
132
  findCommand
133
133
  };
134
- //# sourceMappingURL=find-FRRHAPWX.js.map
134
+ //# sourceMappingURL=find-OTDIX6V4.js.map