@dylanpiercey/work 0.0.222 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -31
- package/bin/work.mjs +121 -122
- package/dist/{_DNhDGBkH.js → _Bq7to522.js} +544 -254
- package/dist/_CkwTsHKB.js +2 -0
- package/dist/index.mjs +2813 -3240
- package/dist/public/assets/_1RHVsAcK.js +1 -0
- package/dist/public/assets/_4CShjaLP.js +1 -0
- package/dist/public/assets/_68JtNDO1.js +1 -0
- package/dist/public/assets/{_CtQ-4c6a.js → _8G2Mv7jG.js} +1 -1
- package/dist/public/assets/_8G2Mv7jG.js.br +0 -0
- package/dist/public/assets/{_DYBhy6q4.js → _8dvK2NDJ.js} +1 -1
- package/dist/public/assets/_8dvK2NDJ.js.br +0 -0
- package/dist/public/assets/_94L2SIJF.js +1 -0
- package/dist/public/assets/_9AnDb3YH.js +1 -0
- package/dist/public/assets/{_BJk5sqrB.js → _9kX9D09B.js} +1 -1
- package/dist/public/assets/_9kX9D09B.js.br +0 -0
- package/dist/public/assets/_9lErVegn.js +1 -0
- package/dist/public/assets/_B0oyGUU5.js +1 -0
- package/dist/public/assets/_B0oyGUU5.js.br +0 -0
- package/dist/public/assets/_B1mPnLlp.js +1 -0
- package/dist/public/assets/_B4fi2SSA.js +1 -0
- package/dist/public/assets/{_OZcBKgKS.js → _B582D2rg.js} +1 -1
- package/dist/public/assets/{_DYm1j3HZ.js → _B7GwDeKK.js} +1 -1
- package/dist/public/assets/_B7Qx25UP.js +1 -0
- package/dist/public/assets/_B7b8EVjA.js +1 -0
- package/dist/public/assets/{_Cp1dT7ox.js → _BBWaxDkO.js} +1 -1
- package/dist/public/assets/_BBWaxDkO.js.br +0 -0
- package/dist/public/assets/{_BYHfXvmU.js → _BDa-iwuj.js} +1 -1
- package/dist/public/assets/_BDa-iwuj.js.br +0 -0
- package/dist/public/assets/_BEKHKNmM.js +1 -0
- package/dist/public/assets/{_BHkMvOuI.js → _BE_Jyvqd.js} +1 -1
- package/dist/public/assets/_BE_Jyvqd.js.br +0 -0
- package/dist/public/assets/_BFU-kJkk.js +1 -0
- package/dist/public/assets/_BGCK5I_O.js +1 -0
- package/dist/public/assets/_BGCK5I_O.js.br +0 -0
- package/dist/public/assets/_BIJ2O2oU.js +1 -0
- package/dist/public/assets/_BJ59XAZ9.js +1 -0
- package/dist/public/assets/_BKqRYfOI.js +15 -0
- package/dist/public/assets/_BKqRYfOI.js.br +0 -0
- package/dist/public/assets/_BKr9Dzz1.js +1 -0
- package/dist/public/assets/_BN7xvxS_.js +1 -0
- package/dist/public/assets/_BNQTVBlH.js +1 -0
- package/dist/public/assets/{_DFiA_pht.js → _BNW5Jiec.js} +1 -1
- package/dist/public/assets/_BNW5Jiec.js.br +0 -0
- package/dist/public/assets/{_DW6AnxDW.js → _BOGkzMx9.js} +1 -1
- package/dist/public/assets/_BOGkzMx9.js.br +0 -0
- package/dist/public/assets/_BUEpqQ_m.js +1 -0
- package/dist/public/assets/{_BJIAaIh4.js → _BUvqweu0.js} +1 -1
- package/dist/public/assets/_BUvqweu0.js.br +0 -0
- package/dist/public/assets/_BZKB4fhr.js +1 -0
- package/dist/public/assets/_BZKB4fhr.js.br +0 -0
- package/dist/public/assets/_BZo9BjDF.js +1 -0
- package/dist/public/assets/{_4KGVbuYs.js → _BbbOvNRH.js} +1 -1
- package/dist/public/assets/_BbbOvNRH.js.br +0 -0
- package/dist/public/assets/_BdUNnSlC.js +1 -0
- package/dist/public/assets/{_KM7EGl2R.js → _Bf8WYPfh.js} +1 -1
- package/dist/public/assets/_Bf8WYPfh.js.br +0 -0
- package/dist/public/assets/{_buuWf96L.js → _Bhx319Hi.js} +1 -1
- package/dist/public/assets/_Bhx319Hi.js.br +0 -0
- package/dist/public/assets/{_BYgxEDpq.js → _Bm4SHrNp.js} +1 -1
- package/dist/public/assets/_Bm4SHrNp.js.br +0 -0
- package/dist/public/assets/_Bmrqq8Ro.js +2 -0
- package/dist/public/assets/_Bmrqq8Ro.js.br +0 -0
- package/dist/public/assets/_BnHZ6Npj.js +1 -0
- package/dist/public/assets/{_NGfZeYAt.js → _BoDxRJLS.js} +1 -1
- package/dist/public/assets/_BoDxRJLS.js.br +0 -0
- package/dist/public/assets/_Bo_Ru664.js +1 -0
- package/dist/public/assets/{_BxpaVKca.js → _Bp8-V8yl.js} +1 -1
- package/dist/public/assets/_Bp8-V8yl.js.br +0 -0
- package/dist/public/assets/{_Ct2VbISZ.js → _BpoeUr5j.js} +1 -1
- package/dist/public/assets/_BpoeUr5j.js.br +0 -0
- package/dist/public/assets/_Bq2G_Tid.js +1 -0
- package/dist/public/assets/_BsyoLB_D.js +1 -0
- package/dist/public/assets/{_CdWPIocC.js → _Bv3e3rg8.js} +1 -1
- package/dist/public/assets/_Bv3e3rg8.js.br +0 -0
- package/dist/public/assets/{_D74J3kwJ.js → _Bv3qNE1b.js} +1 -1
- package/dist/public/assets/{_BSliyqkf.js → _BvXp6HpX.js} +1 -1
- package/dist/public/assets/_BvXp6HpX.js.br +0 -0
- package/dist/public/assets/{_DNqoI_cd.js → _BwP07uVS.js} +1 -1
- package/dist/public/assets/_BwP07uVS.js.br +0 -0
- package/dist/public/assets/{_D93v6VDe.js → _Bx1CW-sF.js} +1 -1
- package/dist/public/assets/_Bx1CW-sF.js.br +0 -0
- package/dist/public/assets/{_DZLJGzpN.js → _BywcP-As.js} +1 -1
- package/dist/public/assets/_BywcP-As.js.br +0 -0
- package/dist/public/assets/_Bzgtwt3G.js +1 -0
- package/dist/public/assets/_Bzgtwt3G.js.br +0 -0
- package/dist/public/assets/{_U2n8Yyqy.js → _C0_s45qg.js} +1 -1
- package/dist/public/assets/_C0_s45qg.js.br +0 -0
- package/dist/public/assets/_C0ePgF6b.js +1 -0
- package/dist/public/assets/_C0oVtTqO.js +1 -0
- package/dist/public/assets/_C0oVtTqO.js.br +0 -0
- package/dist/public/assets/{_TxnhYSE5.js → _C654p96Z.js} +1 -1
- package/dist/public/assets/_C654p96Z.js.br +0 -0
- package/dist/public/assets/_C8_1Y2-z.js +1 -0
- package/dist/public/assets/_C8_1Y2-z.js.br +0 -0
- package/dist/public/assets/_C8v1AZFP.js +1 -0
- package/dist/public/assets/{_Dns259C4.js → _CAkPJLeF.js} +1 -1
- package/dist/public/assets/{_Dns259C4.js.br → _CAkPJLeF.js.br} +0 -0
- package/dist/public/assets/_CB0D5cRH.js +1 -0
- package/dist/public/assets/_CD05JUTh.js +1 -0
- package/dist/public/assets/{_BIul3uoC.js → _CEJUcePr.js} +1 -1
- package/dist/public/assets/_CEJUcePr.js.br +0 -0
- package/dist/public/assets/{_CN5iw4cA.js → _CEXHZd73.js} +1 -1
- package/dist/public/assets/_CEXHZd73.js.br +0 -0
- package/dist/public/assets/_CHcUMVR7.js +1 -0
- package/dist/public/assets/{_Dtx2usNe.js → _CHuLFr1f.js} +1 -1
- package/dist/public/assets/_CHuLFr1f.js.br +0 -0
- package/dist/public/assets/{_9xYWGqfi.js → _CIb7xw_1.js} +1 -1
- package/dist/public/assets/_CIb7xw_1.js.br +0 -0
- package/dist/public/assets/{_C1JRCVnT.js → _CMSBfO6u.js} +1 -1
- package/dist/public/assets/_CMSBfO6u.js.br +0 -0
- package/dist/public/assets/_CN7GPyBo.js +1 -0
- package/dist/public/assets/{_Cnl5owe1.js → _COcePo2y.js} +1 -1
- package/dist/public/assets/_COcePo2y.js.br +0 -0
- package/dist/public/assets/{_B7nG9Ktb.js → _CTINBWaG.js} +1 -1
- package/dist/public/assets/_CTINBWaG.js.br +0 -0
- package/dist/public/assets/_CTWrnAbz.js +1 -0
- package/dist/public/assets/{_CKwCTsbp.js → _CUXajOKj.js} +1 -1
- package/dist/public/assets/_CUXajOKj.js.br +0 -0
- package/dist/public/assets/{_BY6ayWBy.js → _CVru3vzC.js} +1 -1
- package/dist/public/assets/{_cSsv1ZjH.js → _CYjE__ml.js} +1 -1
- package/dist/public/assets/_CYjE__ml.js.br +0 -0
- package/dist/public/assets/{_BlSF31Ck.js → _CZ_OWtIT.js} +1 -1
- package/dist/public/assets/_CZ_OWtIT.js.br +0 -0
- package/dist/public/assets/{_CrV4JiE4.js → _C_37_B6u.js} +1 -1
- package/dist/public/assets/_C_37_B6u.js.br +0 -0
- package/dist/public/assets/_C_CIQL7J.js +1 -0
- package/dist/public/assets/_C_CIQL7J.js.br +0 -0
- package/dist/public/assets/_C_WdpYbK.js +1 -0
- package/dist/public/assets/_CaiH3VN9.js +1 -0
- package/dist/public/assets/{_BXU-ZvQb.js → _CamWDaoG.js} +1 -1
- package/dist/public/assets/_CamWDaoG.js.br +0 -0
- package/dist/public/assets/_CdDElA0V.js +1 -0
- package/dist/public/assets/_CfnsClzZ.js +1 -0
- package/dist/public/assets/_Cgo1fRhJ.js +1 -0
- package/dist/public/assets/_Cgo1fRhJ.js.br +0 -0
- package/dist/public/assets/_CjhGrlf3.js +1 -0
- package/dist/public/assets/_CjlbL4C_.js +1 -0
- package/dist/public/assets/_CjogTUXK.js +1 -0
- package/dist/public/assets/{_BS0AEB1V.js → _ClldMY37.js} +1 -1
- package/dist/public/assets/_ClldMY37.js.br +0 -0
- package/dist/public/assets/_CmFq6Gtp.js +1 -0
- package/dist/public/assets/_CoAPOKiP.js +1 -0
- package/dist/public/assets/_CoUUgh9P.js +1 -0
- package/dist/public/assets/{_BDCQoRmq.js → _CpjSCB1I.js} +1 -1
- package/dist/public/assets/_CpjSCB1I.js.br +0 -0
- package/dist/public/assets/{_CEvca0JK.js → _Ct3RF80L.js} +1 -1
- package/dist/public/assets/_Ct3RF80L.js.br +0 -0
- package/dist/public/assets/_CtYy5eZs.js +1 -0
- package/dist/public/assets/{_DvqvHR7_.js → _CxAPL49a.js} +1 -1
- package/dist/public/assets/_CxAPL49a.js.br +0 -0
- package/dist/public/assets/{_D_joWBEC.js → _CyBCIknf.js} +1 -1
- package/dist/public/assets/_CyBCIknf.js.br +0 -0
- package/dist/public/assets/{_KpWeECPp.js → _Cz5BPBG8.js} +1 -1
- package/dist/public/assets/_Cz5BPBG8.js.br +0 -0
- package/dist/public/assets/_D-eEFXaI.js +1 -0
- package/dist/public/assets/{_DPIQzOUl.js → _D0aoEFRx.js} +1 -1
- package/dist/public/assets/_D0aoEFRx.js.br +0 -0
- package/dist/public/assets/{_CluEtmrQ.js → _D1uRW1qz.js} +1 -1
- package/dist/public/assets/_D1uRW1qz.js.br +0 -0
- package/dist/public/assets/_D2oIr2T2.js +1 -0
- package/dist/public/assets/{_Bpf0Nyqk.js → _D2un443j.js} +1 -1
- package/dist/public/assets/_D2un443j.js.br +0 -0
- package/dist/public/assets/_D3MPx4-f.js +1 -0
- package/dist/public/assets/{_B-992FUw.js → _D4dJ2qEE.js} +1 -1
- package/dist/public/assets/{_CB-I9KUl.js → _D4q8XSMI.js} +1 -1
- package/dist/public/assets/_D4q8XSMI.js.br +0 -0
- package/dist/public/assets/{_BNPo3NaH.js → _D4quFMVQ.js} +1 -1
- package/dist/public/assets/_D4quFMVQ.js.br +0 -0
- package/dist/public/assets/{_6FNzwUcm.js → _D4rOX-Fa.js} +1 -1
- package/dist/public/assets/_D4rOX-Fa.js.br +0 -0
- package/dist/public/assets/_D5edrSyA.js +1 -0
- package/dist/public/assets/{_DJnXBrlD.js → _D6kktUFn.js} +1 -1
- package/dist/public/assets/_D6kktUFn.js.br +0 -0
- package/dist/public/assets/_D80-qtVY.js +1 -0
- package/dist/public/assets/_D9-3EVA4.js +1 -0
- package/dist/public/assets/{_Ca3bfNZI.js → _D9sS4J_w.js} +1 -1
- package/dist/public/assets/_D9sS4J_w.js.br +0 -0
- package/dist/public/assets/_DBLpxTDi.js +1 -0
- package/dist/public/assets/{_gP9nLV2Y.js → _DByHQ7nW.js} +117 -117
- package/dist/public/assets/_DByHQ7nW.js.br +0 -0
- package/dist/public/assets/{_C-oO7X9P.js → _DC-78WeM.js} +1 -1
- package/dist/public/assets/_DC-78WeM.js.br +0 -0
- package/dist/public/assets/{_SHB9zmh2.js → _DDl8KSWJ.js} +1 -1
- package/dist/public/assets/_DDl8KSWJ.js.br +0 -0
- package/dist/public/assets/{_CPMD0qdL.js → _DFWOMF-B.js} +1 -1
- package/dist/public/assets/_DFWOMF-B.js.br +0 -0
- package/dist/public/assets/_DKb-rt9n.js +1 -0
- package/dist/public/assets/_DMnSJCF_.js +1 -0
- package/dist/public/assets/_DOOIlrPh.js +1 -0
- package/dist/public/assets/_DPW-0yKP.js +1 -0
- package/dist/public/assets/_DR3BmvWU.js +1 -0
- package/dist/public/assets/{_BpLwQ1O8.js → _DSVLaMWS.js} +1 -1
- package/dist/public/assets/_DSVLaMWS.js.br +0 -0
- package/dist/public/assets/_DYNGNKLk.js +1 -0
- package/dist/public/assets/_DZnEgCbj.js +1 -0
- package/dist/public/assets/{_CgsPFJZy.js → _DaMVRI8f.js} +1 -1
- package/dist/public/assets/_DaMVRI8f.js.br +0 -0
- package/dist/public/assets/_DbvaGqOl.js +1 -0
- package/dist/public/assets/_DbvaGqOl.js.br +0 -0
- package/dist/public/assets/{_ItervcuA.js → _DcMIlvz-.js} +1 -1
- package/dist/public/assets/_DcMIlvz-.js.br +0 -0
- package/dist/public/assets/{_D5yRmwZD.js → _Dd6X3e7w.js} +1 -1
- package/dist/public/assets/_Dd6X3e7w.js.br +0 -0
- package/dist/public/assets/{_BxAKVWw-.js → _De7P3jUH.js} +1 -1
- package/dist/public/assets/_De7P3jUH.js.br +0 -0
- package/dist/public/assets/_DeiFEAar.js +1 -0
- package/dist/public/assets/{_tqD_68em.js → _DfI982PI.js} +1 -1
- package/dist/public/assets/_DfI982PI.js.br +0 -0
- package/dist/public/assets/_DfZ6emcw.js +1 -0
- package/dist/public/assets/{_M94yp4jo.js → _Dj1lZ1pa.js} +12 -12
- package/dist/public/assets/_Dj1lZ1pa.js.br +0 -0
- package/dist/public/assets/{_BCTeDxHC.js → _DkCaEf_h.js} +1 -1
- package/dist/public/assets/_DkCaEf_h.js.br +0 -0
- package/dist/public/assets/_DonAis0J.js +1 -0
- package/dist/public/assets/{_DktieTrd.js → _Dp3IZdH8.js} +1 -1
- package/dist/public/assets/_Dp3IZdH8.js.br +0 -0
- package/dist/public/assets/_DqYih4xk.js +1 -0
- package/dist/public/assets/_DqYih4xk.js.br +0 -0
- package/dist/public/assets/{_B9Ukk65G.js → _DqhphdU4.js} +1 -1
- package/dist/public/assets/_DqhphdU4.js.br +0 -0
- package/dist/public/assets/{_DLJu1hcD.js → _DrIgZJzN.js} +1 -1
- package/dist/public/assets/_DrIgZJzN.js.br +0 -0
- package/dist/public/assets/_Dt4hHR05.js +1 -0
- package/dist/public/assets/_DtTbTraA.js +1 -0
- package/dist/public/assets/_DwMxAJKP.js +1 -0
- package/dist/public/assets/{_LgS0G0uH.js → _DxEm-Gwj.js} +1 -1
- package/dist/public/assets/_DxEm-Gwj.js.br +0 -0
- package/dist/public/assets/{_C4KQv1VW.js → _Dytf99zx.js} +1 -1
- package/dist/public/assets/_Dytf99zx.js.br +0 -0
- package/dist/public/assets/_EAgv5jR9.js +1 -0
- package/dist/public/assets/_Iecpd0kS.js +1 -0
- package/dist/public/assets/_Iecpd0kS.js.br +0 -0
- package/dist/public/assets/{_QlXMW-cP.js → _MCwIJAuJ.js} +1 -1
- package/dist/public/assets/_MCwIJAuJ.js.br +0 -0
- package/dist/public/assets/_NM79Lu3L.js +6 -0
- package/dist/public/assets/_NM79Lu3L.js.br +0 -0
- package/dist/public/assets/_QpNKKuS9.js +1 -0
- package/dist/public/assets/{_B29iioj9.js → _SGDxiwE1.js} +1 -1
- package/dist/public/assets/_SGDxiwE1.js.br +0 -0
- package/dist/public/assets/_TA8pE7z9.js +1 -0
- package/dist/public/assets/_bE4sNDeU.js +1 -0
- package/dist/public/assets/{_Bk_g_9Bn.js → _bcsuBP7T.js} +1 -1
- package/dist/public/assets/_bcsuBP7T.js.br +0 -0
- package/dist/public/assets/_cdcAU4yY.js +1 -0
- package/dist/public/assets/{_aAORMS0u.js → _ch_yXAap.js} +1 -1
- package/dist/public/assets/_ch_yXAap.js.br +0 -0
- package/dist/public/assets/{_ByqDCoAZ.js → _d5u7EI97.js} +1 -1
- package/dist/public/assets/_d5u7EI97.js.br +0 -0
- package/dist/public/assets/{_i6oi77xC.js → _eoa1EOU-.js} +1 -1
- package/dist/public/assets/_eoa1EOU-.js.br +0 -0
- package/dist/public/assets/{_H7TtilBa.js → _j2tDSMvo.js} +1 -1
- package/dist/public/assets/_j2tDSMvo.js.br +0 -0
- package/dist/public/assets/_jNhIFgbc.js +1 -0
- package/dist/public/assets/_kDYiTaag.js +1 -0
- package/dist/public/assets/_lNMVVbUx.js +1 -0
- package/dist/public/assets/_nwJ7Hu3S.js +1 -0
- package/dist/public/assets/_tmDtUACa.js +1 -0
- package/dist/public/assets/_tmDtUACa.js.br +0 -0
- package/dist/public/assets/_wXDh-Z2N.js +1 -0
- package/dist/public/assets/_wXDh-Z2N.js.br +0 -0
- package/dist/public/assets/{_C3E24F_T.js → _wcshV0sZ.js} +1 -1
- package/dist/public/assets/_wcshV0sZ.js.br +0 -0
- package/dist/public/assets/_x-NwqgCn.js +1 -0
- package/dist/public/assets/{_DZD7yzH2.js → _xyw_DS5P.js} +1 -1
- package/dist/public/assets/_xyw_DS5P.js.br +0 -0
- package/dist/public/assets/{_CsicaM6z.js → _zSAfqXcm.js} +1 -1
- package/dist/public/assets/_zSAfqXcm.js.br +0 -0
- package/dist/public/assets/app-shell-ChQoVC5b.css +1 -0
- package/dist/public/assets/app-shell-ChQoVC5b.css.br +0 -0
- package/dist/public/assets/files-view-CLtLp_BW.js +2 -0
- package/dist/public/assets/files-view-CNHQapdI.css +1 -0
- package/dist/public/assets/files-view-CNHQapdI.css.br +0 -0
- package/dist/public/assets/group.css.ts-BG82htKb.css +1 -0
- package/dist/public/assets/group.css.ts-BG82htKb.css.br +0 -0
- package/dist/public/assets/icon-folder-DJOHuEpD.css +1 -0
- package/dist/public/assets/icon-folder-DJOHuEpD.css.br +0 -0
- package/dist/public/assets/{icon-search-C6A4IBPq.css → icon-search-DsJuFXUJ.css} +1 -1
- package/dist/public/assets/icon-search-DsJuFXUJ.css.br +0 -0
- package/dist/public/assets/manage-workspace-NBcFDyrB.js +2 -0
- package/dist/public/assets/manage-workspace-f_Np32TD.css +1 -0
- package/dist/public/assets/{modal-view-BY2E8mw2.css → modal-view-KVNBpNYi.css} +1 -1
- package/dist/public/assets/modal-view-KVNBpNYi.css.br +0 -0
- package/dist/public/assets/new-DHI77GvL.js +1 -0
- package/dist/public/assets/new-workspace-BFE-HpD_.css +1 -0
- package/dist/public/assets/new-workspace-BFE-HpD_.css.br +0 -0
- package/dist/public/assets/new-workspace-BRzimdd5.js +2 -0
- package/dist/public/assets/port-chip-CUUIDOVM.css +1 -0
- package/dist/public/assets/port-chip-CUUIDOVM.css.br +0 -0
- package/dist/public/assets/prompt-dialog-BGs6RXOV.css +1 -0
- package/dist/public/assets/prompt-dialog-BGs6RXOV.css.br +0 -0
- package/dist/public/assets/quick-open-Gx4so1bl.css +1 -0
- package/dist/public/assets/quick-open-Gx4so1bl.css.br +0 -0
- package/dist/public/assets/repo-picker-CUhd0vJN.css +1 -0
- package/dist/public/assets/repo-picker-CUhd0vJN.css.br +4 -0
- package/dist/public/assets/review-view-DFEK9VBa.js +2 -0
- package/dist/public/assets/review-view-deUY3OE5.css +1 -0
- package/dist/public/assets/review-view-deUY3OE5.css.br +0 -0
- package/dist/public/assets/section-CziSOSBR.css +1 -0
- package/dist/public/assets/section-CziSOSBR.css.br +0 -0
- package/dist/public/assets/settings-DHI77GvL.js +1 -0
- package/dist/public/assets/settings-page-OOtPOzIn.js +2 -0
- package/dist/public/assets/settings-page-wZhd7FLi.css +1 -0
- package/dist/public/assets/settings-page-wZhd7FLi.css.br +0 -0
- package/dist/public/assets/skill-row-BoCyFIXg.css +1 -0
- package/dist/public/assets/sso-auth-DV76tTpE.css +1 -0
- package/dist/public/assets/sso-auth-DV76tTpE.css.br +0 -0
- package/dist/public/assets/w-DHI77GvL.js +1 -0
- package/dist/public/assets/w._-DHI77GvL.js +1 -0
- package/dist/public/assets/w._-DsTgq3-C.js +1 -0
- package/dist/public/assets/w._-igEOSPR-.js +1 -0
- package/install.sh +1 -1
- package/lib/review/markdown.mjs +5 -5
- package/lib/setup/bridge.d.mts +10 -0
- package/lib/setup/bridge.mjs +84 -0
- package/lib/setup/catalog.d.mts +3 -0
- package/lib/setup/catalog.mjs +17 -0
- package/lib/setup/doctor.d.mts +6 -0
- package/lib/setup/doctor.mjs +50 -5
- package/lib/setup/install.d.mts +1 -0
- package/lib/setup/install.mjs +21 -1
- package/lib/setup/listen.mjs +2 -2
- package/lib/share/manifest.mjs +3 -2
- package/package.json +4 -5
- package/dist/_u9qRCTjI.js +0 -2
- package/dist/public/assets/_43qHqm_h.js +0 -1
- package/dist/public/assets/_4KGVbuYs.js.br +0 -0
- package/dist/public/assets/_4hbCil9D.js +0 -1
- package/dist/public/assets/_4hbCil9D.js.br +0 -0
- package/dist/public/assets/_69GBvJfT.js +0 -1
- package/dist/public/assets/_6FNzwUcm.js.br +0 -0
- package/dist/public/assets/_8SWI_CIk.js +0 -1
- package/dist/public/assets/_8SWI_CIk.js.br +0 -0
- package/dist/public/assets/_9fKCaxLn.js +0 -1
- package/dist/public/assets/_9xYWGqfi.js.br +0 -0
- package/dist/public/assets/_AKwHRUw2.js +0 -1
- package/dist/public/assets/_B29iioj9.js.br +0 -0
- package/dist/public/assets/_B3bcGOWb.js +0 -1
- package/dist/public/assets/_B3fa8s0p.js +0 -1
- package/dist/public/assets/_B6-AgBRx.js +0 -1
- package/dist/public/assets/_B6-AgBRx.js.br +0 -0
- package/dist/public/assets/_B68mxQgf.js +0 -15
- package/dist/public/assets/_B68mxQgf.js.br +0 -0
- package/dist/public/assets/_B7lNd0Fe.js +0 -1
- package/dist/public/assets/_B7nG9Ktb.js.br +0 -0
- package/dist/public/assets/_B9Ukk65G.js.br +0 -0
- package/dist/public/assets/_BCTeDxHC.js.br +0 -0
- package/dist/public/assets/_BDCQoRmq.js.br +0 -0
- package/dist/public/assets/_BHkMvOuI.js.br +0 -0
- package/dist/public/assets/_BIul3uoC.js.br +0 -0
- package/dist/public/assets/_BJIAaIh4.js.br +0 -5
- package/dist/public/assets/_BJk5sqrB.js.br +0 -0
- package/dist/public/assets/_BLOE-kpM.js +0 -1
- package/dist/public/assets/_BNK4RUnx.js +0 -1
- package/dist/public/assets/_BNPo3NaH.js.br +0 -0
- package/dist/public/assets/_BPMmLRzt.js +0 -1
- package/dist/public/assets/_BQ91qGf-.js +0 -1
- package/dist/public/assets/_BS0AEB1V.js.br +0 -0
- package/dist/public/assets/_BS66ieXF.js +0 -1
- package/dist/public/assets/_BSb0QOJN.js +0 -1
- package/dist/public/assets/_BSliyqkf.js.br +0 -0
- package/dist/public/assets/_BSydNGAC.js +0 -2
- package/dist/public/assets/_BSydNGAC.js.br +0 -0
- package/dist/public/assets/_BXU-ZvQb.js.br +0 -0
- package/dist/public/assets/_BYHfXvmU.js.br +0 -0
- package/dist/public/assets/_BYcB3W24.js +0 -1
- package/dist/public/assets/_BYgxEDpq.js.br +0 -0
- package/dist/public/assets/_BYi6z1C9.js +0 -1
- package/dist/public/assets/_BbM04KlN.js +0 -1
- package/dist/public/assets/_Bc5E_ez3.js +0 -1
- package/dist/public/assets/_BcWZ_-iA.js +0 -1
- package/dist/public/assets/_BkXPpVmm.js +0 -1
- package/dist/public/assets/_Bk_g_9Bn.js.br +0 -0
- package/dist/public/assets/_BlSF31Ck.js.br +0 -0
- package/dist/public/assets/_Bn4xIRpG.js +0 -1
- package/dist/public/assets/_BpLwQ1O8.js.br +0 -0
- package/dist/public/assets/_BpVNeKi-.js +0 -1
- package/dist/public/assets/_BpdpbMex.js +0 -1
- package/dist/public/assets/_Bpf0Nyqk.js.br +0 -0
- package/dist/public/assets/_BwBNAwDG.js +0 -1
- package/dist/public/assets/_BxAKVWw-.js.br +0 -0
- package/dist/public/assets/_BxpaVKca.js.br +0 -0
- package/dist/public/assets/_ByqDCoAZ.js.br +0 -0
- package/dist/public/assets/_Bzg_Rzcf.js +0 -1
- package/dist/public/assets/_C-oO7X9P.js.br +0 -0
- package/dist/public/assets/_C0KvehwH.js +0 -1
- package/dist/public/assets/_C1JRCVnT.js.br +0 -0
- package/dist/public/assets/_C2U9mANP.js +0 -1
- package/dist/public/assets/_C3E24F_T.js.br +0 -0
- package/dist/public/assets/_C4KQv1VW.js.br +0 -0
- package/dist/public/assets/_C5MTb3MY.js +0 -1
- package/dist/public/assets/_C7ha2DpU.js +0 -1
- package/dist/public/assets/_C7ha2DpU.js.br +0 -0
- package/dist/public/assets/_CAaW1fUv.js +0 -1
- package/dist/public/assets/_CB-I9KUl.js.br +0 -0
- package/dist/public/assets/_CEvca0JK.js.br +0 -0
- package/dist/public/assets/_CGZs9U_g.js +0 -1
- package/dist/public/assets/_CK6p4Zj1.js +0 -1
- package/dist/public/assets/_CK6p4Zj1.js.br +0 -0
- package/dist/public/assets/_CKwCTsbp.js.br +0 -0
- package/dist/public/assets/_CKyRgnW2.js +0 -1
- package/dist/public/assets/_CN5iw4cA.js.br +0 -0
- package/dist/public/assets/_CPAGQRmF.js +0 -1
- package/dist/public/assets/_CPMD0qdL.js.br +0 -0
- package/dist/public/assets/_CRi7-Tyh.js +0 -1
- package/dist/public/assets/_CU2T7o-W.js +0 -1
- package/dist/public/assets/_CVSAwdO1.js +0 -1
- package/dist/public/assets/_CZzsPgfD.js +0 -1
- package/dist/public/assets/_C_jQehPQ.js +0 -1
- package/dist/public/assets/_Ca3bfNZI.js.br +0 -0
- package/dist/public/assets/_CdWPIocC.js.br +0 -0
- package/dist/public/assets/_CeFqvzt1.js +0 -1
- package/dist/public/assets/_CgsPFJZy.js.br +0 -0
- package/dist/public/assets/_ClgoCZxV.js +0 -6
- package/dist/public/assets/_ClgoCZxV.js.br +0 -0
- package/dist/public/assets/_CluEtmrQ.js.br +0 -0
- package/dist/public/assets/_Cnl5owe1.js.br +0 -0
- package/dist/public/assets/_Cp1dT7ox.js.br +0 -0
- package/dist/public/assets/_Cpyx7Ldm.js +0 -1
- package/dist/public/assets/_Cq4-AZ6O.js +0 -1
- package/dist/public/assets/_CrV4JiE4.js.br +0 -0
- package/dist/public/assets/_Csdgg-p8.js +0 -1
- package/dist/public/assets/_Csdgg-p8.js.br +0 -0
- package/dist/public/assets/_CsicaM6z.js.br +0 -0
- package/dist/public/assets/_Ct2VbISZ.js.br +0 -0
- package/dist/public/assets/_CtQ-4c6a.js.br +0 -0
- package/dist/public/assets/_Cyfdf5Zc.js +0 -1
- package/dist/public/assets/_D1qsYd77.js +0 -1
- package/dist/public/assets/_D1qsYd77.js.br +0 -0
- package/dist/public/assets/_D5yRmwZD.js.br +0 -0
- package/dist/public/assets/_D78O__dl.js +0 -1
- package/dist/public/assets/_D93v6VDe.js.br +0 -0
- package/dist/public/assets/_DDfizRXp.js +0 -1
- package/dist/public/assets/_DDfizRXp.js.br +0 -0
- package/dist/public/assets/_DFiA_pht.js.br +0 -0
- package/dist/public/assets/_DGDsfGXN.js +0 -1
- package/dist/public/assets/_DGDsfGXN.js.br +0 -0
- package/dist/public/assets/_DJnXBrlD.js.br +0 -0
- package/dist/public/assets/_DKiEZYX8.js +0 -1
- package/dist/public/assets/_DLEnV6cR.js +0 -1
- package/dist/public/assets/_DLJu1hcD.js.br +0 -0
- package/dist/public/assets/_DL_rHJtD.js +0 -1
- package/dist/public/assets/_DNFF24hk.js +0 -1
- package/dist/public/assets/_DNqoI_cd.js.br +0 -0
- package/dist/public/assets/_DOLRYXID.js +0 -1
- package/dist/public/assets/_DPIQzOUl.js.br +0 -0
- package/dist/public/assets/_DQWcu2Z_.js +0 -1
- package/dist/public/assets/_DW6AnxDW.js.br +0 -0
- package/dist/public/assets/_DWYjkjOA.js +0 -1
- package/dist/public/assets/_DXE83VZw.js +0 -1
- package/dist/public/assets/_DYBhy6q4.js.br +0 -0
- package/dist/public/assets/_DYKZ1zvC.js +0 -1
- package/dist/public/assets/_DYbmgf-P.js +0 -1
- package/dist/public/assets/_DZD7yzH2.js.br +0 -0
- package/dist/public/assets/_DZLJGzpN.js.br +0 -0
- package/dist/public/assets/_D_joWBEC.js.br +0 -0
- package/dist/public/assets/_D_qiANiM.js +0 -1
- package/dist/public/assets/_D_qiANiM.js.br +0 -0
- package/dist/public/assets/_DhhUcrza.js +0 -1
- package/dist/public/assets/_Dik2fbTK.js +0 -1
- package/dist/public/assets/_Dik2fbTK.js.br +0 -0
- package/dist/public/assets/_DjGbHRs7.js +0 -1
- package/dist/public/assets/_DjdPagIm.js +0 -1
- package/dist/public/assets/_Djnp5vRt.js +0 -1
- package/dist/public/assets/_DktieTrd.js.br +0 -0
- package/dist/public/assets/_Dr2zRKuC.js +0 -1
- package/dist/public/assets/_Dtx2usNe.js.br +0 -0
- package/dist/public/assets/_DvnFb18d.js +0 -1
- package/dist/public/assets/_DvqvHR7_.js.br +0 -0
- package/dist/public/assets/_Dy57KGoU.js +0 -1
- package/dist/public/assets/_Dy57KGoU.js.br +0 -0
- package/dist/public/assets/_FdygZebO.js +0 -1
- package/dist/public/assets/_H7TtilBa.js.br +0 -0
- package/dist/public/assets/_HwOcVvTN.js +0 -1
- package/dist/public/assets/_ICJfUHY2.js +0 -1
- package/dist/public/assets/_ItervcuA.js.br +0 -0
- package/dist/public/assets/_JGwf6udl.js +0 -1
- package/dist/public/assets/_KM7EGl2R.js.br +0 -0
- package/dist/public/assets/_KpWeECPp.js.br +0 -0
- package/dist/public/assets/_LgS0G0uH.js.br +0 -0
- package/dist/public/assets/_M94yp4jo.js.br +0 -0
- package/dist/public/assets/_NGfZeYAt.js.br +0 -0
- package/dist/public/assets/_QlXMW-cP.js.br +0 -0
- package/dist/public/assets/_SHB9zmh2.js.br +0 -0
- package/dist/public/assets/_TSA_v82C.js +0 -1
- package/dist/public/assets/_TxnhYSE5.js.br +0 -0
- package/dist/public/assets/_U2n8Yyqy.js.br +0 -0
- package/dist/public/assets/_Vhpht63x.js +0 -1
- package/dist/public/assets/_Z9CaLBvo.js +0 -1
- package/dist/public/assets/__-FQNLs7.js +0 -1
- package/dist/public/assets/__CN8nA63.js +0 -1
- package/dist/public/assets/_aAORMS0u.js.br +0 -0
- package/dist/public/assets/_buuWf96L.js.br +0 -0
- package/dist/public/assets/_cSsv1ZjH.js.br +0 -0
- package/dist/public/assets/_gP9nLV2Y.js.br +0 -0
- package/dist/public/assets/_i6oi77xC.js.br +0 -0
- package/dist/public/assets/_jb3Fwzol.js +0 -1
- package/dist/public/assets/_lmVJ3O6t.js +0 -1
- package/dist/public/assets/_mloSZbwk.js +0 -1
- package/dist/public/assets/_sYOWcsEI.js +0 -1
- package/dist/public/assets/_tqD_68em.js.br +0 -0
- package/dist/public/assets/_y4SZiKqE.js +0 -1
- package/dist/public/assets/_y4SZiKqE.js.br +0 -0
- package/dist/public/assets/_zMYJngRw.js +0 -1
- package/dist/public/assets/_zTWXKPCk.js +0 -1
- package/dist/public/assets/app-shell-BXDHei7B.css +0 -1
- package/dist/public/assets/app-shell-BXDHei7B.css.br +0 -0
- package/dist/public/assets/files-view-BCnw4-08.js +0 -2
- package/dist/public/assets/files-view-Ds4k9TjY.css +0 -1
- package/dist/public/assets/files-view-Ds4k9TjY.css.br +0 -0
- package/dist/public/assets/group.css.ts-CZcH3cNI.css +0 -1
- package/dist/public/assets/group.css.ts-CZcH3cNI.css.br +0 -0
- package/dist/public/assets/icon-folder-De3LJVaT.css +0 -1
- package/dist/public/assets/icon-folder-De3LJVaT.css.br +0 -0
- package/dist/public/assets/icon-search-C6A4IBPq.css.br +0 -0
- package/dist/public/assets/manage-workspace-B2IJyc-s.js +0 -2
- package/dist/public/assets/manage-workspace-BYotHuev.css +0 -1
- package/dist/public/assets/modal-view-BY2E8mw2.css.br +0 -0
- package/dist/public/assets/new-workspace-9FQTNRn4.css +0 -1
- package/dist/public/assets/new-workspace-9FQTNRn4.css.br +0 -0
- package/dist/public/assets/new-workspace-B_6v9CYu.js +0 -2
- package/dist/public/assets/new-zQDWH4FQ.js +0 -1
- package/dist/public/assets/port-chip-V2q_q3UM.css +0 -1
- package/dist/public/assets/port-chip-V2q_q3UM.css.br +0 -0
- package/dist/public/assets/prompt-dialog-C_kDiYmC.css +0 -1
- package/dist/public/assets/prompt-dialog-C_kDiYmC.css.br +0 -0
- package/dist/public/assets/quick-open-IkoNJ7wT.css +0 -1
- package/dist/public/assets/quick-open-IkoNJ7wT.css.br +0 -0
- package/dist/public/assets/repo-picker-CMHPjNaZ.css +0 -1
- package/dist/public/assets/repo-picker-CMHPjNaZ.css.br +0 -0
- package/dist/public/assets/review-view-CqIbovDm.css +0 -1
- package/dist/public/assets/review-view-CqIbovDm.css.br +0 -0
- package/dist/public/assets/review-view-DJ3TxEP8.js +0 -2
- package/dist/public/assets/section-Bjoist2N.css +0 -1
- package/dist/public/assets/section-Bjoist2N.css.br +0 -0
- package/dist/public/assets/settings-page-CA4M6Hig.css +0 -1
- package/dist/public/assets/settings-page-CA4M6Hig.css.br +0 -0
- package/dist/public/assets/settings-page-Gf4hmpSr.js +0 -2
- package/dist/public/assets/settings-zQDWH4FQ.js +0 -1
- package/dist/public/assets/skill-row-y-AJuVyg.css +0 -1
- package/dist/public/assets/sso-auth-DCSrkI2L.css +0 -1
- package/dist/public/assets/sso-auth-DCSrkI2L.css.br +0 -0
- package/dist/public/assets/w-zQDWH4FQ.js +0 -1
- package/dist/public/assets/w._-B47BqhrV.js +0 -1
- package/dist/public/assets/w._-D0upu6g5.js +0 -1
- package/dist/public/assets/w._-zQDWH4FQ.js +0 -1
- package/scripts/migrate.mjs +0 -824
|
@@ -1,28 +1,103 @@
|
|
|
1
1
|
import { i as __require, o as __toESM, t as __commonJSMin } from "./_BMI-E3GI.js";
|
|
2
2
|
import { r as require_inherits, t as require_src$1 } from "./_xlrdOUsL.js";
|
|
3
3
|
import { t as require_safe_buffer } from "./_BmSjjJ2E.js";
|
|
4
|
+
import { createRequire } from "node:module";
|
|
4
5
|
import fs from "node:fs";
|
|
5
6
|
import path from "node:path";
|
|
6
|
-
import { execFile, execFileSync } from "node:child_process";
|
|
7
|
+
import { execFile, execFileSync, spawnSync } from "node:child_process";
|
|
8
|
+
import fs$1 from "node:fs/promises";
|
|
7
9
|
import os from "node:os";
|
|
8
10
|
import { promisify } from "node:util";
|
|
9
11
|
import { DatabaseSync } from "node:sqlite";
|
|
10
12
|
import { createHash } from "node:crypto";
|
|
11
|
-
//#region src/server/
|
|
12
|
-
/**
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
//#region src/server/cache.ts
|
|
14
|
+
/** Keyed stale-while-revalidate cache: a cached value is served immediately
|
|
15
|
+
* (revalidating in the background when older than `ttlMs`); loads are deduped
|
|
16
|
+
* per key, and `refresh` bypasses both the cache and any in-flight load. */
|
|
17
|
+
function swr(ttlMs, load, seed) {
|
|
18
|
+
const cache = /* @__PURE__ */ new Map();
|
|
19
|
+
const inflight = /* @__PURE__ */ new Map();
|
|
20
|
+
function start(key, refresh) {
|
|
21
|
+
const startedAt = Date.now();
|
|
22
|
+
const promise = load(key, refresh).then((value) => {
|
|
23
|
+
const existing = cache.get(key);
|
|
24
|
+
if (!existing || existing.at <= startedAt) cache.set(key, {
|
|
25
|
+
at: Date.now(),
|
|
26
|
+
value
|
|
27
|
+
});
|
|
28
|
+
return value;
|
|
29
|
+
}).finally(() => {
|
|
30
|
+
if (inflight.get(key)?.promise === promise) inflight.delete(key);
|
|
31
|
+
});
|
|
32
|
+
inflight.set(key, {
|
|
33
|
+
promise,
|
|
34
|
+
refresh
|
|
35
|
+
});
|
|
36
|
+
return promise;
|
|
37
|
+
}
|
|
38
|
+
const read = (key, refresh = false) => {
|
|
39
|
+
if (refresh) {
|
|
40
|
+
const current = inflight.get(key);
|
|
41
|
+
return current?.refresh ? current.promise : start(key, true);
|
|
42
|
+
}
|
|
43
|
+
let cached = cache.get(key);
|
|
44
|
+
if (!cached && seed) {
|
|
45
|
+
cached = seed(key);
|
|
46
|
+
if (cached) cache.set(key, cached);
|
|
47
|
+
}
|
|
48
|
+
if (cached) {
|
|
49
|
+
if (Date.now() - cached.at >= ttlMs && !inflight.has(key)) start(key, false).catch(() => {});
|
|
50
|
+
return Promise.resolve(cached.value);
|
|
51
|
+
}
|
|
52
|
+
return inflight.get(key)?.promise ?? start(key, false);
|
|
53
|
+
};
|
|
54
|
+
/** Inject an externally fetched value (e.g. from a batched load). */
|
|
55
|
+
read.set = (key, value) => {
|
|
56
|
+
cache.set(key, {
|
|
57
|
+
at: Date.now(),
|
|
58
|
+
value
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
/** Current cached value, if any — used when a batch update must merge
|
|
62
|
+
* with a richer per-key load rather than replace it. */
|
|
63
|
+
read.get = (key) => cache.get(key)?.value;
|
|
64
|
+
return read;
|
|
15
65
|
}
|
|
16
|
-
/**
|
|
17
|
-
*
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
66
|
+
/** Serialize async work per key: calls for one key run in submission order,
|
|
67
|
+
* each starting only after the previous settled. The stored tail is the
|
|
68
|
+
* all-settled form, so a rejection neither blocks the next caller nor leaves
|
|
69
|
+
* the entry behind — the map holds only keys with work still in flight. */
|
|
70
|
+
var locks = /* @__PURE__ */ new Map();
|
|
71
|
+
function withLock(key, fn) {
|
|
72
|
+
const run = (locks.get(key) ?? Promise.resolve()).then(fn);
|
|
73
|
+
const tail = run.then(() => {}, () => {});
|
|
74
|
+
locks.set(key, tail);
|
|
75
|
+
tail.then(() => {
|
|
76
|
+
if (locks.get(key) === tail) locks.delete(key);
|
|
77
|
+
});
|
|
78
|
+
return run;
|
|
22
79
|
}
|
|
23
|
-
/**
|
|
24
|
-
|
|
25
|
-
|
|
80
|
+
/** One load at a time, and a short reuse window: callers join the in-flight
|
|
81
|
+
* load, and a result younger than `ttlMs` is served without one. For an
|
|
82
|
+
* expensive process sweep (lsof, ps, list-panes) whose answer does not
|
|
83
|
+
* change within the window — `ttlMs` of 0 still collapses concurrent
|
|
84
|
+
* callers onto a single spawn. */
|
|
85
|
+
function shared(fn, ttlMs) {
|
|
86
|
+
let inflight = null;
|
|
87
|
+
let last = null;
|
|
88
|
+
return () => {
|
|
89
|
+
if (last && Date.now() - last.at < ttlMs) return Promise.resolve(last.value);
|
|
90
|
+
if (!inflight) inflight = fn().then((value) => {
|
|
91
|
+
last = {
|
|
92
|
+
at: Date.now(),
|
|
93
|
+
value
|
|
94
|
+
};
|
|
95
|
+
return value;
|
|
96
|
+
}).finally(() => {
|
|
97
|
+
inflight = null;
|
|
98
|
+
});
|
|
99
|
+
return inflight;
|
|
100
|
+
};
|
|
26
101
|
}
|
|
27
102
|
//#endregion
|
|
28
103
|
//#region lib/setup/listen.mjs
|
|
@@ -66,8 +141,9 @@ var config = {
|
|
|
66
141
|
appPort: Number(process.env.WORK_APP_PORT || 7171),
|
|
67
142
|
/** How a workspace port is named in a hostname the app proxies
|
|
68
143
|
* (server/port-proxy.ts): `sub` is `3000.work.example.com`, `dash` is
|
|
69
|
-
* `3000-work.example.com`. The
|
|
70
|
-
*
|
|
144
|
+
* `3000-work.example.com`. The port chips link to this one; the server
|
|
145
|
+
* takes `sub` either way, and `dash` only when it is picked
|
|
146
|
+
* (server/access.ts `dashPortName`). `dash` stays one label under the
|
|
71
147
|
* zone, which is what a free Cloudflare certificate covers. */
|
|
72
148
|
portHosts: process.env.WORK_PORT_HOSTS === "dash" ? "dash" : "sub",
|
|
73
149
|
/** The address the server listens on: this machine only, unless set
|
|
@@ -92,6 +168,11 @@ function list(value) {
|
|
|
92
168
|
return (value || "").split(",").map((s) => s.trim()).filter(Boolean);
|
|
93
169
|
}
|
|
94
170
|
fs.mkdirSync(config.dataDir, { recursive: true });
|
|
171
|
+
try {
|
|
172
|
+
fs.chmodSync(config.dataDir, 448);
|
|
173
|
+
} catch (err) {
|
|
174
|
+
console.warn(`[work] could not make ${config.dataDir} private: ${err.message}`);
|
|
175
|
+
}
|
|
95
176
|
//#endregion
|
|
96
177
|
//#region src/server/exec.ts
|
|
97
178
|
/** Dedicated tmux server so we never touch another multiplexer's or the
|
|
@@ -131,21 +212,25 @@ var GIT_NETWORK_MS = {
|
|
|
131
212
|
push: 3e5,
|
|
132
213
|
"ls-remote": 6e4
|
|
133
214
|
};
|
|
134
|
-
/**
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
215
|
+
/** What every git process work starts runs with, `extra` on top: `git`
|
|
216
|
+
* below, and the diff's streaming reads, which spawn their own. Never let
|
|
217
|
+
* git wait on a terminal it doesn't have — a missing credential fails with
|
|
218
|
+
* a message instead of hanging the clone forever. Optional locks are off
|
|
219
|
+
* because most of what runs here is a background probe (the review's
|
|
220
|
+
* stamp poll, Files, the language servers' change feed): a `git status`
|
|
221
|
+
* refreshing the index holds `index.lock`, and an agent's `git commit` or
|
|
222
|
+
* rebase step landing in that moment fails on it. */
|
|
223
|
+
var gitEnv = (extra) => ({
|
|
224
|
+
...process.env,
|
|
225
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
226
|
+
GIT_OPTIONAL_LOCKS: "0",
|
|
227
|
+
...extra
|
|
228
|
+
});
|
|
140
229
|
var git = async (args, cwd) => {
|
|
141
230
|
const verb = args.find((a) => !a.startsWith("-")) ?? "";
|
|
142
231
|
const timeoutMs = GIT_NETWORK_MS[verb];
|
|
143
232
|
try {
|
|
144
|
-
return await run$1("git", args, cwd, {
|
|
145
|
-
...process.env,
|
|
146
|
-
GIT_TERMINAL_PROMPT: "0",
|
|
147
|
-
GIT_OPTIONAL_LOCKS: "0"
|
|
148
|
-
}, timeoutMs ? { timeoutMs } : void 0);
|
|
233
|
+
return await run$1("git", args, cwd, gitEnv(), timeoutMs ? { timeoutMs } : void 0);
|
|
149
234
|
} catch (err) {
|
|
150
235
|
if (timeoutMs && err.killed) throw new Error(`git ${verb} timed out after ${Math.round(timeoutMs / 1e3)}s`);
|
|
151
236
|
throw err;
|
|
@@ -201,11 +286,281 @@ function utf8Locale(env) {
|
|
|
201
286
|
for (const [key, value] of Object.entries(env)) if (value !== void 0) out[key] = value;
|
|
202
287
|
return forceUtf8Locale(out);
|
|
203
288
|
}
|
|
289
|
+
/** The release that brings a database to the baseline. WORK_BRIDGE_SPEC
|
|
290
|
+
* names another (an `npm pack` tarball of it) to try the bridge before it
|
|
291
|
+
* is published. */
|
|
292
|
+
function bridgeSpec() {
|
|
293
|
+
return process.env.WORK_BRIDGE_SPEC || "@dylanpiercey/work@0.0.223";
|
|
294
|
+
}
|
|
295
|
+
/** What to run by hand for the database in `dataDir`: its data dir named
|
|
296
|
+
* outright, since the shell running it may not have the service's. */
|
|
297
|
+
function bridgeCommands(dataDir) {
|
|
298
|
+
return [`WORK_DATA_DIR=${/^[\w@%+=:,./-]+$/.test(dataDir) ? dataDir : `'${dataDir.replace(/'/g, `'\\''`)}'`} npx -y -p ${bridgeSpec()} work migrate`, "work setup"];
|
|
299
|
+
}
|
|
300
|
+
/** Whether the database at `file` predates the baseline: it has tables and
|
|
301
|
+
* no version. A missing or empty one is simply new. node:sqlite is loaded
|
|
302
|
+
* here, not at the top: it warns on load under older node, and every other
|
|
303
|
+
* CLI command would say so. */
|
|
304
|
+
function needsBridge(file) {
|
|
305
|
+
if (!fs.existsSync(file)) return false;
|
|
306
|
+
const { DatabaseSync } = createRequire(import.meta.url)("node:sqlite");
|
|
307
|
+
const db = new DatabaseSync(file, { readOnly: true });
|
|
308
|
+
try {
|
|
309
|
+
const { user_version } = db.prepare("PRAGMA user_version").get();
|
|
310
|
+
const tables = db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table'").get();
|
|
311
|
+
return user_version < 1 && !!tables;
|
|
312
|
+
} finally {
|
|
313
|
+
db.close();
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
/** Bring the database in `dataDir` to the baseline when it predates it,
|
|
317
|
+
* with `env` (the service's) so the sweeps see the same data dir and
|
|
318
|
+
* workspaces root the server does. True when it is there (or never needed
|
|
319
|
+
* to be). The package's install scripts are skipped: `migrate` needs none,
|
|
320
|
+
* and a native build that fails would fail the bridge with it. */
|
|
321
|
+
function bridgeIfNeeded(dataDir, env, log = () => {}) {
|
|
322
|
+
const file = path.join(dataDir, "work.db");
|
|
323
|
+
if (!needsBridge(file)) return true;
|
|
324
|
+
log(`${file} predates 0.1: bringing it forward once with ${bridgeSpec()} (a one-time download)`);
|
|
325
|
+
const sibling = path.join(path.dirname(process.execPath), "npx");
|
|
326
|
+
const npx = fs.existsSync(sibling) ? sibling : "npx";
|
|
327
|
+
spawnSync(npx, [
|
|
328
|
+
"-y",
|
|
329
|
+
"-p",
|
|
330
|
+
bridgeSpec(),
|
|
331
|
+
"work",
|
|
332
|
+
"migrate"
|
|
333
|
+
], {
|
|
334
|
+
stdio: "inherit",
|
|
335
|
+
env: {
|
|
336
|
+
...env,
|
|
337
|
+
WORK_DATA_DIR: dataDir,
|
|
338
|
+
npm_config_ignore_scripts: "true"
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
return !needsBridge(file);
|
|
342
|
+
}
|
|
343
|
+
/** The server's bridge, for db.ts to hand the migrations: with the server's
|
|
344
|
+
* own environment, before the database is opened, once per start. */
|
|
345
|
+
function bridgeForServer(dataDir) {
|
|
346
|
+
return bridgeIfNeeded(dataDir, process.env, (line) => console.log(`[work] ${line}`));
|
|
347
|
+
}
|
|
348
|
+
//#endregion
|
|
349
|
+
//#region src/server/migrations.ts
|
|
350
|
+
var STEPS = [{
|
|
351
|
+
version: 1,
|
|
352
|
+
name: "baseline",
|
|
353
|
+
up(db) {
|
|
354
|
+
db.exec(`
|
|
355
|
+
CREATE TABLE workspaces (
|
|
356
|
+
id TEXT PRIMARY KEY,
|
|
357
|
+
name TEXT NOT NULL,
|
|
358
|
+
path TEXT NOT NULL UNIQUE,
|
|
359
|
+
branch TEXT NOT NULL,
|
|
360
|
+
status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'archived')),
|
|
361
|
+
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
362
|
+
materialized INTEGER NOT NULL DEFAULT 1,
|
|
363
|
+
origin_branch TEXT,
|
|
364
|
+
imported_at TEXT
|
|
365
|
+
);
|
|
366
|
+
|
|
367
|
+
CREATE TABLE repos (
|
|
368
|
+
workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
|
|
369
|
+
full_name TEXT NOT NULL,
|
|
370
|
+
worktree TEXT NOT NULL,
|
|
371
|
+
base_branch TEXT NOT NULL,
|
|
372
|
+
default_branch TEXT NOT NULL,
|
|
373
|
+
PRIMARY KEY (workspace_id, full_name)
|
|
374
|
+
);
|
|
375
|
+
|
|
376
|
+
CREATE TABLE sessions (
|
|
377
|
+
id TEXT PRIMARY KEY,
|
|
378
|
+
workspace_id TEXT REFERENCES workspaces(id) ON DELETE SET NULL,
|
|
379
|
+
agent TEXT NOT NULL,
|
|
380
|
+
title TEXT,
|
|
381
|
+
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
|
|
382
|
+
);
|
|
383
|
+
|
|
384
|
+
CREATE TABLE settings (
|
|
385
|
+
key TEXT PRIMARY KEY,
|
|
386
|
+
value TEXT NOT NULL
|
|
387
|
+
);
|
|
388
|
+
|
|
389
|
+
CREATE TABLE review_comments (
|
|
390
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
391
|
+
workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
|
|
392
|
+
worktree TEXT NOT NULL,
|
|
393
|
+
path TEXT NOT NULL,
|
|
394
|
+
side TEXT NOT NULL DEFAULT 'additions',
|
|
395
|
+
line_start INTEGER NOT NULL,
|
|
396
|
+
line_end INTEGER NOT NULL,
|
|
397
|
+
text TEXT NOT NULL,
|
|
398
|
+
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
399
|
+
head TEXT,
|
|
400
|
+
snippet TEXT
|
|
401
|
+
);
|
|
402
|
+
|
|
403
|
+
CREATE TABLE push_subscriptions (
|
|
404
|
+
endpoint TEXT PRIMARY KEY,
|
|
405
|
+
data TEXT NOT NULL
|
|
406
|
+
);
|
|
407
|
+
|
|
408
|
+
CREATE TABLE dismissed_prs (
|
|
409
|
+
workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
|
|
410
|
+
full_name TEXT NOT NULL,
|
|
411
|
+
number INTEGER NOT NULL,
|
|
412
|
+
PRIMARY KEY (workspace_id, full_name, number)
|
|
413
|
+
);
|
|
414
|
+
|
|
415
|
+
CREATE TABLE review_marks (
|
|
416
|
+
workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
|
|
417
|
+
worktree TEXT NOT NULL,
|
|
418
|
+
branch TEXT NOT NULL,
|
|
419
|
+
path TEXT NOT NULL,
|
|
420
|
+
fingerprint TEXT NOT NULL,
|
|
421
|
+
PRIMARY KEY (workspace_id, worktree, branch, path)
|
|
422
|
+
);
|
|
423
|
+
`);
|
|
424
|
+
}
|
|
425
|
+
}, {
|
|
426
|
+
version: 2,
|
|
427
|
+
name: "drop what 0.0.x kept for its upgrades",
|
|
428
|
+
up(db) {
|
|
429
|
+
db.exec(`
|
|
430
|
+
DELETE FROM review_marks WHERE path = '';
|
|
431
|
+
DELETE FROM settings
|
|
432
|
+
WHERE key IN ('review-cleared-diff-v2', 'ui.diff-uncommitted', 'diff-uncommitted')
|
|
433
|
+
OR key GLOB 'review.seen:*';
|
|
434
|
+
`);
|
|
435
|
+
for (const name of [
|
|
436
|
+
"tab",
|
|
437
|
+
"diff-filter",
|
|
438
|
+
"diff-folded",
|
|
439
|
+
"diff-collapsed",
|
|
440
|
+
"diff-focus",
|
|
441
|
+
"diff-pos",
|
|
442
|
+
"files-recent"
|
|
443
|
+
]) {
|
|
444
|
+
const prefix = `ui.${name}:`;
|
|
445
|
+
db.prepare("DELETE FROM settings WHERE key GLOB ? AND substr(key, ?) NOT IN (SELECT id FROM workspaces)").run(`${prefix}*`, prefix.length + 1);
|
|
446
|
+
}
|
|
447
|
+
const pref = (key) => db.prepare("SELECT value FROM settings WHERE key = ?").get(key)?.value;
|
|
448
|
+
const parse = (text) => {
|
|
449
|
+
try {
|
|
450
|
+
return text === void 0 ? void 0 : JSON.parse(text);
|
|
451
|
+
} catch {
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
};
|
|
455
|
+
const font = parse(pref("ui.term-font"));
|
|
456
|
+
if (font && typeof font === "object") {
|
|
457
|
+
for (const device of ["desktop", "touch"]) if (Number.isInteger(font[device])) db.prepare("INSERT OR IGNORE INTO settings (key, value) VALUES (?, ?)").run(`ui.term-font-${device}`, String(font[device]));
|
|
458
|
+
}
|
|
459
|
+
db.exec("DELETE FROM settings WHERE key = 'ui.term-font'");
|
|
460
|
+
const keys = parse(pref("ui.phone-keys"));
|
|
461
|
+
if (Array.isArray(keys)) db.prepare("UPDATE settings SET value = ? WHERE key = 'ui.phone-keys'").run(JSON.stringify({
|
|
462
|
+
base: [],
|
|
463
|
+
extra: keys
|
|
464
|
+
}));
|
|
465
|
+
}
|
|
466
|
+
}];
|
|
467
|
+
var LATEST = STEPS.at(-1).version;
|
|
468
|
+
/** The database at `file`, at the latest version: an empty one is built by
|
|
469
|
+
* every step, an existing one gets those it lacks — each in a transaction
|
|
470
|
+
* of its own with its version stamp inside it, after a copy of the whole
|
|
471
|
+
* file (`work.db.v<from>.bak` beside it, the newest two kept). One from
|
|
472
|
+
* before the baseline is handed to `bridge` first, when given (the
|
|
473
|
+
* server's: lib/setup/bridge.mjs). Throws, with what to do in its message,
|
|
474
|
+
* for a database this code cannot open: one still from before the
|
|
475
|
+
* baseline, one from a newer release, or one a step failed on (rolled back
|
|
476
|
+
* to the step before). */
|
|
477
|
+
function openDatabase(file, { bridge } = {}) {
|
|
478
|
+
if (bridge && needsBridge(file)) bridge(path.dirname(file));
|
|
479
|
+
const db = new DatabaseSync(file);
|
|
480
|
+
try {
|
|
481
|
+
db.exec("PRAGMA busy_timeout = 5000");
|
|
482
|
+
db.exec("PRAGMA journal_mode = WAL");
|
|
483
|
+
migrate(db, file);
|
|
484
|
+
db.exec("PRAGMA foreign_keys = ON");
|
|
485
|
+
return db;
|
|
486
|
+
} catch (err) {
|
|
487
|
+
db.close();
|
|
488
|
+
throw err;
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
function versionOf(db) {
|
|
492
|
+
return db.prepare("PRAGMA user_version").get().user_version;
|
|
493
|
+
}
|
|
494
|
+
function migrate(db, file) {
|
|
495
|
+
const from = versionOf(db);
|
|
496
|
+
const empty = !db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table'").get();
|
|
497
|
+
if (from < 1 && !empty) throw new Error(`${file} predates 0.1 and has not been brought forward (once, with the network: \`work setup\`, or this server on its next start). By hand:\n ${bridgeCommands(path.dirname(file)).join("\n ")}`);
|
|
498
|
+
if (from > LATEST) {
|
|
499
|
+
const backup = newestBackup(file, LATEST);
|
|
500
|
+
throw new Error(`${file} is at schema version ${from}, and this work knows up to ${LATEST}: a newer release upgraded it. Update work (\`work update\`)${backup ? `, or restore ${backup}, the copy taken before it did` : ""}.`);
|
|
501
|
+
}
|
|
502
|
+
const pending = STEPS.filter((s) => s.version > from);
|
|
503
|
+
if (!pending.length) return;
|
|
504
|
+
const backup = empty ? null : snapshot(db, file, from);
|
|
505
|
+
for (const step of pending) {
|
|
506
|
+
db.exec("BEGIN IMMEDIATE");
|
|
507
|
+
try {
|
|
508
|
+
if (versionOf(db) >= step.version) {
|
|
509
|
+
db.exec("ROLLBACK");
|
|
510
|
+
continue;
|
|
511
|
+
}
|
|
512
|
+
step.up(db);
|
|
513
|
+
db.exec(`PRAGMA user_version = ${step.version}`);
|
|
514
|
+
db.exec("COMMIT");
|
|
515
|
+
} catch (err) {
|
|
516
|
+
try {
|
|
517
|
+
db.exec("ROLLBACK");
|
|
518
|
+
} catch {}
|
|
519
|
+
throw new Error(`${file}: step ${step.version} (${step.name}) failed and was rolled back, leaving the database at version ${versionOf(db)}: ${err.message}${backup ? `. The copy from before this upgrade is ${backup}` : ""}`);
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
var backupName = (file, version) => `${path.basename(file)}.v${version}.bak`;
|
|
524
|
+
/** The file's backups, newest version first. */
|
|
525
|
+
function backups(file) {
|
|
526
|
+
const dir = path.dirname(file);
|
|
527
|
+
const re = new RegExp(`^${path.basename(file).replace(/\./g, "\\.")}\\.v(\\d+)\\.bak$`);
|
|
528
|
+
let names = [];
|
|
529
|
+
try {
|
|
530
|
+
names = fs.readdirSync(dir);
|
|
531
|
+
} catch {}
|
|
532
|
+
return names.map((name) => re.exec(name)).filter((m) => !!m).map((m) => ({
|
|
533
|
+
file: path.join(dir, m[0]),
|
|
534
|
+
version: Number(m[1])
|
|
535
|
+
})).sort((a, b) => b.version - a.version);
|
|
536
|
+
}
|
|
537
|
+
function newestBackup(file, atMost) {
|
|
538
|
+
return backups(file).find((b) => b.version <= atMost)?.file ?? null;
|
|
539
|
+
}
|
|
540
|
+
/** A copy of the whole database as it is before an upgrade from `version`,
|
|
541
|
+
* which a release that knows `version` can open. */
|
|
542
|
+
function snapshot(db, file, version) {
|
|
543
|
+
const dest = path.join(path.dirname(file), backupName(file, version));
|
|
544
|
+
fs.rmSync(dest, { force: true });
|
|
545
|
+
db.prepare("VACUUM INTO ?").run(dest);
|
|
546
|
+
for (const old of backups(file).slice(2)) fs.rmSync(old.file, { force: true });
|
|
547
|
+
return dest;
|
|
548
|
+
}
|
|
204
549
|
//#endregion
|
|
205
550
|
//#region src/server/db.ts
|
|
206
551
|
if (!path.isAbsolute(config.dataDir)) throw new Error(`data dir must be absolute, got "${config.dataDir}" — check WORK_DATA_DIR and $HOME`);
|
|
207
|
-
|
|
208
|
-
|
|
552
|
+
/** The app's database, at the latest schema version before anything reads
|
|
553
|
+
* it (server/migrations.ts), one from before 0.1 bridged first. One this
|
|
554
|
+
* release cannot open stops the server here, saying what to do: a stack
|
|
555
|
+
* trace would bury that under itself. */
|
|
556
|
+
var db = (() => {
|
|
557
|
+
try {
|
|
558
|
+
return openDatabase(path.join(config.dataDir, "work.db"), { bridge: bridgeForServer });
|
|
559
|
+
} catch (err) {
|
|
560
|
+
console.error(`[work] ${err.message}`);
|
|
561
|
+
process.exit(1);
|
|
562
|
+
}
|
|
563
|
+
})();
|
|
209
564
|
/** Prepared statements, kept by their SQL: preparing is most of a small
|
|
210
565
|
* query's cost (10 µs against 4), and a status build runs hundreds. The
|
|
211
566
|
* texts are the call sites' own, so the set is small; the cap covers any
|
|
@@ -229,90 +584,33 @@ function get(sql, ...params) {
|
|
|
229
584
|
function workspacePath(id) {
|
|
230
585
|
return get("SELECT path FROM workspaces WHERE id = ?", id)?.path;
|
|
231
586
|
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
title TEXT,
|
|
260
|
-
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
|
|
261
|
-
);
|
|
262
|
-
|
|
263
|
-
CREATE TABLE IF NOT EXISTS settings (
|
|
264
|
-
key TEXT PRIMARY KEY,
|
|
265
|
-
value TEXT NOT NULL
|
|
266
|
-
);
|
|
267
|
-
|
|
268
|
-
CREATE TABLE IF NOT EXISTS review_comments (
|
|
269
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
270
|
-
workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
|
|
271
|
-
worktree TEXT NOT NULL,
|
|
272
|
-
path TEXT NOT NULL,
|
|
273
|
-
side TEXT NOT NULL DEFAULT 'additions',
|
|
274
|
-
line_start INTEGER NOT NULL,
|
|
275
|
-
line_end INTEGER NOT NULL,
|
|
276
|
-
text TEXT NOT NULL,
|
|
277
|
-
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
|
|
278
|
-
);
|
|
279
|
-
|
|
280
|
-
CREATE TABLE IF NOT EXISTS push_subscriptions (
|
|
281
|
-
endpoint TEXT PRIMARY KEY,
|
|
282
|
-
data TEXT NOT NULL
|
|
283
|
-
);
|
|
284
|
-
|
|
285
|
-
CREATE TABLE IF NOT EXISTS dismissed_prs (
|
|
286
|
-
workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
|
|
287
|
-
full_name TEXT NOT NULL,
|
|
288
|
-
number INTEGER NOT NULL,
|
|
289
|
-
PRIMARY KEY (workspace_id, full_name, number)
|
|
290
|
-
);
|
|
291
|
-
|
|
292
|
-
-- Viewed marks (server/viewed.ts): a file of a branch, and its change
|
|
293
|
-
-- as it was when marked. Keep in sync with scripts/migrate.mjs, which
|
|
294
|
-
-- creates it too.
|
|
295
|
-
CREATE TABLE IF NOT EXISTS review_marks (
|
|
296
|
-
workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
|
|
297
|
-
worktree TEXT NOT NULL,
|
|
298
|
-
branch TEXT NOT NULL,
|
|
299
|
-
path TEXT NOT NULL,
|
|
300
|
-
fingerprint TEXT NOT NULL,
|
|
301
|
-
PRIMARY KEY (workspace_id, worktree, branch, path)
|
|
302
|
-
);
|
|
303
|
-
`);
|
|
304
|
-
if (freshReview) db.prepare("INSERT OR IGNORE INTO settings (key, value) VALUES ('review-cleared-diff-v2', '1')").run();
|
|
305
|
-
/** Additive schema changes: `CREATE TABLE IF NOT EXISTS` never revisits a
|
|
306
|
-
* table that already exists, so a column added after a release has to be
|
|
307
|
-
* bolted on here for databases created before it. */
|
|
308
|
-
function ensureColumn(table, column, decl) {
|
|
309
|
-
if (!db.prepare(`PRAGMA table_info(${table})`).all().some((c) => c.name === column)) db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${decl}`);
|
|
310
|
-
}
|
|
311
|
-
ensureColumn("review_comments", "head", "TEXT");
|
|
312
|
-
ensureColumn("review_comments", "snippet", "TEXT");
|
|
313
|
-
ensureColumn("workspaces", "materialized", "INTEGER NOT NULL DEFAULT 1");
|
|
314
|
-
ensureColumn("workspaces", "origin_branch", "TEXT");
|
|
315
|
-
ensureColumn("workspaces", "imported_at", "TEXT");
|
|
587
|
+
//#endregion
|
|
588
|
+
//#region src/server/http.ts
|
|
589
|
+
/** Who may frame the app's own responses: the app alone (the review's PDF
|
|
590
|
+
* preview). A page elsewhere that frames it can dress a click on it as a
|
|
591
|
+
* click on something of its own. A route that sends a
|
|
592
|
+
* Content-Security-Policy of its own replaces this one, so it names
|
|
593
|
+
* `FRAME_ANCESTORS` too. */
|
|
594
|
+
var FRAME_ANCESTORS = "frame-ancestors 'self'";
|
|
595
|
+
var FRAME_HEADERS = {
|
|
596
|
+
"content-security-policy": FRAME_ANCESTORS,
|
|
597
|
+
"x-frame-options": "SAMEORIGIN"
|
|
598
|
+
};
|
|
599
|
+
/** Error whose `status` the API error-boundary middleware uses for the response. */
|
|
600
|
+
function httpError(status, message) {
|
|
601
|
+
return Object.assign(new Error(message), { status });
|
|
602
|
+
}
|
|
603
|
+
/** The value of a Standard Schema `[value, issues]` pair, or a thrown 400
|
|
604
|
+
* built from the issues. */
|
|
605
|
+
function checked(result, what = "request") {
|
|
606
|
+
const [value, issues] = result;
|
|
607
|
+
if (issues) throw httpError(400, `invalid ${what}: ${issues.map((issue) => issue.message).join("; ")}`);
|
|
608
|
+
return value;
|
|
609
|
+
}
|
|
610
|
+
/** Validated request body, or a thrown 400 built from the valibot issues. */
|
|
611
|
+
async function readBody(ctx) {
|
|
612
|
+
return checked(await ctx.body, "request body");
|
|
613
|
+
}
|
|
316
614
|
//#endregion
|
|
317
615
|
//#region src/client/pref-change.ts
|
|
318
616
|
/** The stored text after `change`, or null when nothing is left. A value
|
|
@@ -642,6 +940,18 @@ var DEFAULT_GITHUB_HOST = "github.com";
|
|
|
642
940
|
function toolById(id) {
|
|
643
941
|
return TOOLS.find((t) => t.id === id) || PROJECT_TOOLS.find((t) => t.id === id) || null;
|
|
644
942
|
}
|
|
943
|
+
/** A version that is only a version (`latest`, `lts`, `22`, `1.2.3-rc.1`),
|
|
944
|
+
* not one of mise's forms that build from a git ref or point at a path
|
|
945
|
+
* (`ref:`, `path:`, `prefix:`). */
|
|
946
|
+
var PLAIN_VERSION = /^(?!-)[\w.+-]+$/;
|
|
947
|
+
/** Whether a mise pin is one of the tools above, as they install, at a
|
|
948
|
+
* plain version: what a restore takes without asking. Any other name —
|
|
949
|
+
* a registry tool the catalog does not list, a backend (`npm:`, `ubi:`,
|
|
950
|
+
* `github:`, `cargo:`, `go:`, `pipx:` …), a URL — installs and runs
|
|
951
|
+
* whatever it names, so a restore takes it only when it is named. */
|
|
952
|
+
function catalogPin(name, version) {
|
|
953
|
+
return [...TOOLS, ...PROJECT_TOOLS].some((t) => t.mise === name) && PLAIN_VERSION.test(version);
|
|
954
|
+
}
|
|
645
955
|
function agentById(id) {
|
|
646
956
|
return AGENTS$1.find((a) => a.id === id) || null;
|
|
647
957
|
}
|
|
@@ -711,8 +1021,9 @@ function setupDirs() {
|
|
|
711
1021
|
};
|
|
712
1022
|
return dirsFor.dirs;
|
|
713
1023
|
}
|
|
714
|
-
/** `~/…` for anything under the home directory — every path
|
|
715
|
-
* display (Settings rows, `work doctor
|
|
1024
|
+
/** `~/…` for anything under the home directory — every path given it is
|
|
1025
|
+
* for display (Settings rows, `work doctor`, a language server's
|
|
1026
|
+
* definition outside every checkout), never re-used to exec. */
|
|
716
1027
|
function tilde(p) {
|
|
717
1028
|
if (!p) return p;
|
|
718
1029
|
return p === home ? "~" : p.startsWith(home + path.sep) ? "~" + p.slice(home.length) : p;
|
|
@@ -779,6 +1090,40 @@ async function readMiseInstalls() {
|
|
|
779
1090
|
} catch {}
|
|
780
1091
|
return out;
|
|
781
1092
|
}
|
|
1093
|
+
/** A path owned by one release of a version manager — mise/asdf
|
|
1094
|
+
* `installs`, homebrew's `Cellar`, nvm's `versions` — which that tool
|
|
1095
|
+
* deletes on its next update. */
|
|
1096
|
+
var VERSIONED_PATH = /\/(installs|Cellar|versions|toolchains)\//;
|
|
1097
|
+
/** The gh for git to run as a credential helper: the launcher on PATH
|
|
1098
|
+
* (mise's shim, /usr/bin/gh), when it is not itself one release's. Still an
|
|
1099
|
+
* absolute path, so it works for GUI clients and cron jobs that never
|
|
1100
|
+
* sourced a shell profile, but one that follows upgrades. */
|
|
1101
|
+
function stableGh() {
|
|
1102
|
+
const gh = which("gh");
|
|
1103
|
+
return gh && !VERSIONED_PATH.test(gh) ? gh : null;
|
|
1104
|
+
}
|
|
1105
|
+
/** Credential helpers in ~/.gitconfig that run a gh which is gone, by
|
|
1106
|
+
* config key. `gh auth setup-git` writes the absolute path of the gh that
|
|
1107
|
+
* ran it, and git runs that string literally: once a version manager's
|
|
1108
|
+
* upgrade deletes it, every https push fails with "could not read
|
|
1109
|
+
* Username" while `gh` itself still works. Listed only when there is a
|
|
1110
|
+
* stable gh to point them at, which `work setup` does. */
|
|
1111
|
+
async function staleGhHelpers() {
|
|
1112
|
+
if (!stableGh()) return [];
|
|
1113
|
+
const { stdout } = await run("git", [
|
|
1114
|
+
"config",
|
|
1115
|
+
"--global",
|
|
1116
|
+
"--get-regexp",
|
|
1117
|
+
String.raw`^credential\..*\.helper$`
|
|
1118
|
+
]);
|
|
1119
|
+
const keys = /* @__PURE__ */ new Set();
|
|
1120
|
+
for (const line of stdout.split("\n")) {
|
|
1121
|
+
const sp = line.indexOf(" ");
|
|
1122
|
+
const bin = /^!(\S+) auth git-credential$/.exec(line.slice(sp + 1))?.[1];
|
|
1123
|
+
if (sp > 0 && bin && !fs.existsSync(bin)) keys.add(line.slice(0, sp));
|
|
1124
|
+
}
|
|
1125
|
+
return [...keys];
|
|
1126
|
+
}
|
|
782
1127
|
/** Hosts `gh` knows about (~/.config/gh/hosts.yml top-level keys) — the
|
|
783
1128
|
* source of truth for "which GitHub hosts has this machine signed in to",
|
|
784
1129
|
* merged with whatever the caller has configured. */
|
|
@@ -949,11 +1294,12 @@ async function doctor(opts = {}) {
|
|
|
949
1294
|
...opts.hosts || [],
|
|
950
1295
|
...ghKnownHosts()
|
|
951
1296
|
]);
|
|
952
|
-
const [versions, github, awake, extensions] = await Promise.all([
|
|
1297
|
+
const [versions, github, awake, extensions, helpers] = await Promise.all([
|
|
953
1298
|
miseVersions(),
|
|
954
1299
|
Promise.all([...hostSet].map(githubHostStatus)),
|
|
955
1300
|
canStayAwake(),
|
|
956
|
-
ghExtensions()
|
|
1301
|
+
ghExtensions(),
|
|
1302
|
+
staleGhHelpers()
|
|
957
1303
|
]);
|
|
958
1304
|
const tools = TOOLS.map((t) => {
|
|
959
1305
|
if (t.ghExtension) {
|
|
@@ -994,7 +1340,8 @@ async function doctor(opts = {}) {
|
|
|
994
1340
|
tools,
|
|
995
1341
|
agents,
|
|
996
1342
|
github,
|
|
997
|
-
awake
|
|
1343
|
+
awake,
|
|
1344
|
+
staleGhHelpers: helpers
|
|
998
1345
|
};
|
|
999
1346
|
}
|
|
1000
1347
|
//#endregion
|
|
@@ -1017,8 +1364,7 @@ var PREF_MAX = 4096;
|
|
|
1017
1364
|
/** The prefs kept per workspace, keyed `<name>:<workspace id>`. They ride
|
|
1018
1365
|
* every page's HTML, so they go with the workspace (`deleteWorkspacePrefs`)
|
|
1019
1366
|
* and /api/prefs refuses them for one that is gone; one missing here
|
|
1020
|
-
* outlives its workspace for good.
|
|
1021
|
-
* the same list. */
|
|
1367
|
+
* outlives its workspace for good. */
|
|
1022
1368
|
var WORKSPACE_PREFS = [
|
|
1023
1369
|
"tab",
|
|
1024
1370
|
"diff-filter",
|
|
@@ -1106,96 +1452,6 @@ function preferredAgent(enabled = enabledAgents()) {
|
|
|
1106
1452
|
return enabled[0] || "shell";
|
|
1107
1453
|
}
|
|
1108
1454
|
//#endregion
|
|
1109
|
-
//#region src/server/cache.ts
|
|
1110
|
-
/** Keyed stale-while-revalidate cache: a cached value is served immediately
|
|
1111
|
-
* (revalidating in the background when older than `ttlMs`); loads are deduped
|
|
1112
|
-
* per key, and `refresh` bypasses both the cache and any in-flight load. */
|
|
1113
|
-
function swr(ttlMs, load, seed) {
|
|
1114
|
-
const cache = /* @__PURE__ */ new Map();
|
|
1115
|
-
const inflight = /* @__PURE__ */ new Map();
|
|
1116
|
-
function start(key, refresh) {
|
|
1117
|
-
const startedAt = Date.now();
|
|
1118
|
-
const promise = load(key, refresh).then((value) => {
|
|
1119
|
-
const existing = cache.get(key);
|
|
1120
|
-
if (!existing || existing.at <= startedAt) cache.set(key, {
|
|
1121
|
-
at: Date.now(),
|
|
1122
|
-
value
|
|
1123
|
-
});
|
|
1124
|
-
return value;
|
|
1125
|
-
}).finally(() => {
|
|
1126
|
-
if (inflight.get(key)?.promise === promise) inflight.delete(key);
|
|
1127
|
-
});
|
|
1128
|
-
inflight.set(key, {
|
|
1129
|
-
promise,
|
|
1130
|
-
refresh
|
|
1131
|
-
});
|
|
1132
|
-
return promise;
|
|
1133
|
-
}
|
|
1134
|
-
const read = (key, refresh = false) => {
|
|
1135
|
-
if (refresh) {
|
|
1136
|
-
const current = inflight.get(key);
|
|
1137
|
-
return current?.refresh ? current.promise : start(key, true);
|
|
1138
|
-
}
|
|
1139
|
-
let cached = cache.get(key);
|
|
1140
|
-
if (!cached && seed) {
|
|
1141
|
-
cached = seed(key);
|
|
1142
|
-
if (cached) cache.set(key, cached);
|
|
1143
|
-
}
|
|
1144
|
-
if (cached) {
|
|
1145
|
-
if (Date.now() - cached.at >= ttlMs && !inflight.has(key)) start(key, false).catch(() => {});
|
|
1146
|
-
return Promise.resolve(cached.value);
|
|
1147
|
-
}
|
|
1148
|
-
return inflight.get(key)?.promise ?? start(key, false);
|
|
1149
|
-
};
|
|
1150
|
-
/** Inject an externally fetched value (e.g. from a batched load). */
|
|
1151
|
-
read.set = (key, value) => {
|
|
1152
|
-
cache.set(key, {
|
|
1153
|
-
at: Date.now(),
|
|
1154
|
-
value
|
|
1155
|
-
});
|
|
1156
|
-
};
|
|
1157
|
-
/** Current cached value, if any — used when a batch update must merge
|
|
1158
|
-
* with a richer per-key load rather than replace it. */
|
|
1159
|
-
read.get = (key) => cache.get(key)?.value;
|
|
1160
|
-
return read;
|
|
1161
|
-
}
|
|
1162
|
-
/** Serialize async work per key: calls for one key run in submission order,
|
|
1163
|
-
* each starting only after the previous settled. The stored tail is the
|
|
1164
|
-
* all-settled form, so a rejection neither blocks the next caller nor leaves
|
|
1165
|
-
* the entry behind — the map holds only keys with work still in flight. */
|
|
1166
|
-
var locks = /* @__PURE__ */ new Map();
|
|
1167
|
-
function withLock(key, fn) {
|
|
1168
|
-
const run = (locks.get(key) ?? Promise.resolve()).then(fn);
|
|
1169
|
-
const tail = run.then(() => {}, () => {});
|
|
1170
|
-
locks.set(key, tail);
|
|
1171
|
-
tail.then(() => {
|
|
1172
|
-
if (locks.get(key) === tail) locks.delete(key);
|
|
1173
|
-
});
|
|
1174
|
-
return run;
|
|
1175
|
-
}
|
|
1176
|
-
/** One load at a time, and a short reuse window: callers join the in-flight
|
|
1177
|
-
* load, and a result younger than `ttlMs` is served without one. For an
|
|
1178
|
-
* expensive process sweep (lsof, ps, list-panes) whose answer does not
|
|
1179
|
-
* change within the window — `ttlMs` of 0 still collapses concurrent
|
|
1180
|
-
* callers onto a single spawn. */
|
|
1181
|
-
function shared(fn, ttlMs) {
|
|
1182
|
-
let inflight = null;
|
|
1183
|
-
let last = null;
|
|
1184
|
-
return () => {
|
|
1185
|
-
if (last && Date.now() - last.at < ttlMs) return Promise.resolve(last.value);
|
|
1186
|
-
if (!inflight) inflight = fn().then((value) => {
|
|
1187
|
-
last = {
|
|
1188
|
-
at: Date.now(),
|
|
1189
|
-
value
|
|
1190
|
-
};
|
|
1191
|
-
return value;
|
|
1192
|
-
}).finally(() => {
|
|
1193
|
-
inflight = null;
|
|
1194
|
-
});
|
|
1195
|
-
return inflight;
|
|
1196
|
-
};
|
|
1197
|
-
}
|
|
1198
|
-
//#endregion
|
|
1199
1455
|
//#region src/server/events.ts
|
|
1200
1456
|
var listeners$1 = /* @__PURE__ */ new Set();
|
|
1201
1457
|
function publish(type, data) {
|
|
@@ -1219,7 +1475,7 @@ function subscribe(listener) {
|
|
|
1219
1475
|
listeners$1.add(listener);
|
|
1220
1476
|
return () => listeners$1.delete(listener);
|
|
1221
1477
|
}
|
|
1222
|
-
/** Connected
|
|
1478
|
+
/** Connected events-bus clients — lets background watchers idle when no one
|
|
1223
1479
|
* is listening. */
|
|
1224
1480
|
function subscriberCount() {
|
|
1225
1481
|
return listeners$1.size;
|
|
@@ -7177,7 +7433,7 @@ var background = /* @__PURE__ */ new Map();
|
|
|
7177
7433
|
/** A turn's end is pushed once it has stayed ended this long. Stop fires
|
|
7178
7434
|
* again each time something sends the agent back to work (a stop hook
|
|
7179
7435
|
* that continues it, a goal loop, background subagents reporting in), and
|
|
7180
|
-
* each of those ends
|
|
7436
|
+
* each of those ends would be a "Finished" on the phone while it carries on. */
|
|
7181
7437
|
var DONE_SETTLE_MS = 3e3;
|
|
7182
7438
|
var listeners = /* @__PURE__ */ new Set();
|
|
7183
7439
|
/** Called on every phase transition (the status snapshot drops itself). */
|
|
@@ -7350,7 +7606,7 @@ function publishChange(sessionId) {
|
|
|
7350
7606
|
const row = get("SELECT workspace_id FROM sessions WHERE id = ?", sessionId);
|
|
7351
7607
|
if (row?.workspace_id) {
|
|
7352
7608
|
const workspaceId = row.workspace_id;
|
|
7353
|
-
import("./
|
|
7609
|
+
import("./_CkwTsHKB.js").then((m) => m.notifySessionsChanged(workspaceId));
|
|
7354
7610
|
return;
|
|
7355
7611
|
}
|
|
7356
7612
|
publish("sessions.changed");
|
|
@@ -7760,10 +8016,10 @@ async function fetchUsage$3(account) {
|
|
|
7760
8016
|
var PROFILE_TTL_MS = 36e5;
|
|
7761
8017
|
var profiles = /* @__PURE__ */ new Map();
|
|
7762
8018
|
/** The account's plan as Anthropic has it now. `.claude.json` holds what
|
|
7763
|
-
* Claude Code saw at sign-in, and it only asks again on a new login, so
|
|
7764
|
-
* upgrade (Max 5x → 20x)
|
|
7765
|
-
* with the same token as the usage; the cached plan stands in
|
|
7766
|
-
* cannot be. */
|
|
8019
|
+
* Claude Code saw at sign-in, and it only asks again on a new login, so
|
|
8020
|
+
* from it alone an upgrade (Max 5x → 20x) reads as the old plan until
|
|
8021
|
+
* then. Asked with the same token as the usage; the cached plan stands in
|
|
8022
|
+
* when it cannot be. */
|
|
7767
8023
|
async function livePlan(account) {
|
|
7768
8024
|
const hit = profiles.get(account.dir);
|
|
7769
8025
|
if (hit && Date.now() - hit.at < PROFILE_TTL_MS) return hit.plan;
|
|
@@ -8664,6 +8920,47 @@ var cursor = {
|
|
|
8664
8920
|
usage: () => cursorRow().then((row) => [row])
|
|
8665
8921
|
};
|
|
8666
8922
|
//#endregion
|
|
8923
|
+
//#region src/server/paths.ts
|
|
8924
|
+
/** Whether `target` is `root` or somewhere under it, by name alone. Both
|
|
8925
|
+
* are normalised first, so `..` and a trailing slash count as the
|
|
8926
|
+
* filesystem would count them, and the separator after `root` is the
|
|
8927
|
+
* whole point: a sibling `…/work-2` is not in `…/work`. A relative
|
|
8928
|
+
* `target` is in nothing — an empty one is a process cwd that could not
|
|
8929
|
+
* be read, not the root. A symlink under `root` can still lead out: what
|
|
8930
|
+
* is read through one wants `realInside`. */
|
|
8931
|
+
function inside(target, root) {
|
|
8932
|
+
if (!path.isAbsolute(target)) return false;
|
|
8933
|
+
const top = path.resolve(root);
|
|
8934
|
+
const full = path.resolve(target);
|
|
8935
|
+
return full === top || full.startsWith(top.endsWith(path.sep) ? top : top + path.sep);
|
|
8936
|
+
}
|
|
8937
|
+
/** Where `file` — named from `root`, as git and the pages name a
|
|
8938
|
+
* checkout's files, or absolute — really leads through every symlink,
|
|
8939
|
+
* when that is still `root` or under it; null when it leads out or is not
|
|
8940
|
+
* there. The check by name alone lets a symlink in a repo, which a branch
|
|
8941
|
+
* can add, point a read at any file on the machine. */
|
|
8942
|
+
async function realInside(file, root) {
|
|
8943
|
+
const full = path.resolve(root, file);
|
|
8944
|
+
if (!inside(full, root)) return null;
|
|
8945
|
+
try {
|
|
8946
|
+
const [top, real] = await Promise.all([fs$1.realpath(root), fs$1.realpath(full)]);
|
|
8947
|
+
return inside(real, top) ? real : null;
|
|
8948
|
+
} catch {
|
|
8949
|
+
return null;
|
|
8950
|
+
}
|
|
8951
|
+
}
|
|
8952
|
+
/** `realInside` for a caller that cannot wait. */
|
|
8953
|
+
function realInsideSync(file, root) {
|
|
8954
|
+
const full = path.resolve(root, file);
|
|
8955
|
+
if (!inside(full, root)) return null;
|
|
8956
|
+
try {
|
|
8957
|
+
const real = fs.realpathSync(full);
|
|
8958
|
+
return inside(real, fs.realpathSync(root)) ? real : null;
|
|
8959
|
+
} catch {
|
|
8960
|
+
return null;
|
|
8961
|
+
}
|
|
8962
|
+
}
|
|
8963
|
+
//#endregion
|
|
8667
8964
|
//#region src/agents/grok/usage.ts
|
|
8668
8965
|
var AUTH = path.join(HOME, ".grok", "auth.json");
|
|
8669
8966
|
var LOG = path.join(HOME, ".grok", "logs", "unified.jsonl");
|
|
@@ -8836,7 +9133,7 @@ function scratch() {
|
|
|
8836
9133
|
return os.tmpdir();
|
|
8837
9134
|
}
|
|
8838
9135
|
})();
|
|
8839
|
-
return hookFile()
|
|
9136
|
+
return inside(hookFile(), tmp);
|
|
8840
9137
|
}
|
|
8841
9138
|
/** Whether Grok's hook registry names work's hook file — without it Grok
|
|
8842
9139
|
* reports nothing and the screen has to speak for it. Read from disk, not
|
|
@@ -9364,10 +9661,10 @@ function tmuxWasStarted(id) {
|
|
|
9364
9661
|
function clearTmuxStarted(id) {
|
|
9365
9662
|
tmuxStarted.delete(id);
|
|
9366
9663
|
}
|
|
9367
|
-
/**
|
|
9368
|
-
* Coalesced per workspace: a turn boundary lands as a burst
|
|
9369
|
-
* transitions (hook, then scrape), and each one cost a list-panes
|
|
9370
|
-
* and a broadcast for a list that came out the same. */
|
|
9664
|
+
/** Events-bus payload: session rows + live tmux/hook state so clients
|
|
9665
|
+
* don't refetch. Coalesced per workspace: a turn boundary lands as a burst
|
|
9666
|
+
* of phase transitions (hook, then scrape), and each one cost a list-panes
|
|
9667
|
+
* spawn and a broadcast for a list that came out the same. */
|
|
9371
9668
|
var EMIT_DEBOUNCE_MS = 50;
|
|
9372
9669
|
var pendingEmits = /* @__PURE__ */ new Map();
|
|
9373
9670
|
function notifySessionsChanged(workspaceId) {
|
|
@@ -9394,8 +9691,14 @@ async function emitSessionsChanged(workspaceId) {
|
|
|
9394
9691
|
async function killWorkspaceSessions(workspaceId) {
|
|
9395
9692
|
for (const session of listSessions(workspaceId)) await killSession(session.id);
|
|
9396
9693
|
}
|
|
9694
|
+
/** Control characters a paste never means: C0 but tab and line breaks,
|
|
9695
|
+
* ESC, DEL and C1. The text can quote a reviewed file, which is repo
|
|
9696
|
+
* content, and an ESC in it can end the bracketed paste early on a tmux
|
|
9697
|
+
* that passes one through, typing the rest into the pane as keys. */
|
|
9698
|
+
var PASTE_UNSAFE = /[\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\x9f]/g;
|
|
9397
9699
|
/** Type text into a session's tmux (bracketed paste + Enter), creating it if needed. */
|
|
9398
|
-
async function sendToSession(id,
|
|
9700
|
+
async function sendToSession(id, raw, size) {
|
|
9701
|
+
const text = raw.replace(PASTE_UNSAFE, "");
|
|
9399
9702
|
const session = getSession(id);
|
|
9400
9703
|
if (!session) throw new Error("unknown session");
|
|
9401
9704
|
const wsPath = workspacePath(session.workspace_id);
|
|
@@ -9534,28 +9837,12 @@ async function listPanesNow() {
|
|
|
9534
9837
|
};
|
|
9535
9838
|
return panes;
|
|
9536
9839
|
}
|
|
9537
|
-
/** Cleared once per process — boot already runs this, and a server we
|
|
9538
|
-
* create below never has PORT set, so re-running on every attach only
|
|
9539
|
-
* unsets something already unset. */
|
|
9540
|
-
var portCleared = false;
|
|
9541
9840
|
/** Start the tmux server in its own systemd user unit so it escapes this
|
|
9542
9841
|
* service's cgroup — otherwise `systemctl restart work` kills every
|
|
9543
9842
|
* session with it. A hidden "work-keeper" session pins the server alive
|
|
9544
9843
|
* (tmux exits when its last session closes). */
|
|
9545
9844
|
async function ensureTmuxServer() {
|
|
9546
|
-
if (await tmux(["has-session"]).then(() => true, () => false))
|
|
9547
|
-
if (!portCleared) {
|
|
9548
|
-
await tmux([
|
|
9549
|
-
"set-environment",
|
|
9550
|
-
"-g",
|
|
9551
|
-
"-u",
|
|
9552
|
-
"PORT"
|
|
9553
|
-
]).catch(() => {});
|
|
9554
|
-
portCleared = true;
|
|
9555
|
-
}
|
|
9556
|
-
return;
|
|
9557
|
-
}
|
|
9558
|
-
portCleared = true;
|
|
9845
|
+
if (await tmux(["has-session"]).then(() => true, () => false)) return;
|
|
9559
9846
|
await run$1("systemd-run", [
|
|
9560
9847
|
"--user",
|
|
9561
9848
|
`--unit=${TMUX_SOCKET === "work" ? "work-tmux" : `work-tmux-${TMUX_SOCKET.replace(/[^\w.:-]/g, "_")}`}`,
|
|
@@ -9573,68 +9860,71 @@ async function ensureTmuxServer() {
|
|
|
9573
9860
|
], os.homedir()).catch(() => {});
|
|
9574
9861
|
}
|
|
9575
9862
|
/** Full tmux command (options + new-session) for creating/attaching a
|
|
9576
|
-
* session's tmux; `mode` is "-d" (create detached) or "-A" (attach-or-create).
|
|
9863
|
+
* session's tmux; `mode` is "-d" (create detached) or "-A" (attach-or-create).
|
|
9864
|
+
* Every `set-option` is `-q`: one failed command drops the rest of a `;`
|
|
9865
|
+
* chain, new-session included, and a tmux older than an option
|
|
9866
|
+
* (`fill-character`, `extended-keys-format`) rejects its name. */
|
|
9577
9867
|
function newSessionArgs(session, wsPath, mode, initialPrompt, size) {
|
|
9578
9868
|
return [
|
|
9579
9869
|
"start-server",
|
|
9580
9870
|
";",
|
|
9581
9871
|
"set-option",
|
|
9582
|
-
"-
|
|
9872
|
+
"-gq",
|
|
9583
9873
|
"status",
|
|
9584
9874
|
"off",
|
|
9585
9875
|
";",
|
|
9586
9876
|
"set-option",
|
|
9587
|
-
"-
|
|
9877
|
+
"-gq",
|
|
9588
9878
|
"mouse",
|
|
9589
9879
|
"on",
|
|
9590
9880
|
";",
|
|
9591
9881
|
"set-option",
|
|
9592
|
-
"-
|
|
9882
|
+
"-gq",
|
|
9593
9883
|
"history-limit",
|
|
9594
9884
|
"5000",
|
|
9595
9885
|
";",
|
|
9596
9886
|
"set-option",
|
|
9597
|
-
"-
|
|
9887
|
+
"-gq",
|
|
9598
9888
|
"fill-character",
|
|
9599
9889
|
" ",
|
|
9600
9890
|
";",
|
|
9601
9891
|
"set-option",
|
|
9602
|
-
"-
|
|
9892
|
+
"-sq",
|
|
9603
9893
|
"set-clipboard",
|
|
9604
9894
|
"on",
|
|
9605
9895
|
";",
|
|
9606
9896
|
"set-option",
|
|
9607
|
-
"-
|
|
9897
|
+
"-gq",
|
|
9608
9898
|
"focus-events",
|
|
9609
9899
|
"on",
|
|
9610
9900
|
";",
|
|
9611
9901
|
"set-option",
|
|
9612
|
-
"-
|
|
9902
|
+
"-sq",
|
|
9613
9903
|
"extended-keys",
|
|
9614
9904
|
"on",
|
|
9615
9905
|
";",
|
|
9616
9906
|
"set-option",
|
|
9617
|
-
"-
|
|
9907
|
+
"-sq",
|
|
9618
9908
|
"extended-keys-format",
|
|
9619
9909
|
"csi-u",
|
|
9620
9910
|
";",
|
|
9621
9911
|
"set-option",
|
|
9622
|
-
"-
|
|
9912
|
+
"-sq",
|
|
9623
9913
|
"terminal-features[100]",
|
|
9624
9914
|
"*:hyperlinks",
|
|
9625
9915
|
";",
|
|
9626
9916
|
"set-option",
|
|
9627
|
-
"-
|
|
9917
|
+
"-sq",
|
|
9628
9918
|
"terminal-features[101]",
|
|
9629
9919
|
"*:clipboard",
|
|
9630
9920
|
";",
|
|
9631
9921
|
"set-option",
|
|
9632
|
-
"-
|
|
9922
|
+
"-sq",
|
|
9633
9923
|
"terminal-features[102]",
|
|
9634
9924
|
"*:sync:RGB",
|
|
9635
9925
|
";",
|
|
9636
9926
|
"set-option",
|
|
9637
|
-
"-
|
|
9927
|
+
"-sq",
|
|
9638
9928
|
"terminal-features[103]",
|
|
9639
9929
|
"*:sixel",
|
|
9640
9930
|
";",
|
|
@@ -9825,4 +10115,4 @@ function sleep(ms) {
|
|
|
9825
10115
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
9826
10116
|
}
|
|
9827
10117
|
//#endregion
|
|
9828
|
-
export {
|
|
10118
|
+
export { saveSubscription as $, swr as $t, clearAgentPhase as A, TOOLS as At, agentBadge as B, readBody as Bt, readHookPayload as C, miseVersions as Ct, realInsideSync as D, which as Dt, realInside as E, tilde as Et, onPhaseChange as F, applyPrefChange as Ft, ACCENT_RE as G, TMUX_SOCKET as Gt, agentFromCommand as H, db as Ht, setAgentPhase as I, FRAME_ANCESTORS as It, manifest as J, gitEnv as Jt, getInstance as K, gh as Kt, setScrapedPhase as L, FRAME_HEADERS as Lt, hookReportedAt as M, agentLabel$1 as Mt, noteBackground as N, catalogPin as Nt, blankRow as O, DEFAULT_GITHUB_HOST as Ot, noteUserAnswered as P, toolById as Pt, pushPublicKey as Q, shared as Qt, setSessionViewers as R, checked as Rt, AGENTS as S, miseInstalls as St, inside as T, stableGh as Tt, agentLabel as U, get as Ut, agentFamily as V, all as Vt, agentMeta as W, workspacePath as Wt, setInstance as X, tmux as Xt, normalizeAccent as Y, run$1 as Yt, deleteSubscription as Z, config as Zt, renameSession as _, setPref as _t, ensureTmuxServer as a, subscriberCount as at, tmuxName as b, doctor as bt, killSession as c, agentChoices as ct, listPanesWithin as d, deleteWorkspacePrefs as dt, withLock as en, sendPush as et, listSessions as f, disabledAgents as ft, panePids as g, setDisabledAgents as gt, notifySessionsChanged as h, preferredAgent as ht, disposeSessions as i, subscribe as it, hookPhase as j, agentById as jt, agentPhase as k, PROJECT_TOOLS as kt, killWorkspaceSessions as l, allPrefs as lt, newSessionArgs as m, getSetting as mt, clearTmuxStarted as n, publish as nt, forgetPanes as o, PREF_MAX as ot, markTmuxStarted as p, enabledAgents as pt, iconSvg as q, git as qt, createSession as r, publishJson as rt, getSession as s, WORKSPACE_PREFS as st, cleanEnv as t, validSubscription as tt, listPanes as u, changePref as ut, sendToSession as v, setSetting as vt, reportsWorking as w, setupPath as wt, tmuxWasStarted as x, ghKnownHosts as xt, sessionStates as y, discoverAgents as yt, settleQuietWorking as z, httpError as zt };
|