@dylanpiercey/work 0.0.47 → 0.0.49
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/bin/work.mjs +77 -47
- package/dist/_B1U5NJd1.js +2 -0
- package/dist/{_DM_oFS_v.js → _Bi2N56tu.js} +490 -75
- package/dist/{_o0dwm0Ww.js → _DPQxTPYF.js} +59 -59
- package/dist/{_Dm4BVuln.js → _DdgmjMNU.js} +22 -21
- package/dist/index.mjs +2779 -1100
- package/dist/public/assets/{_D1Ecsx8-2.js → _4zqifGZf2.js} +1 -1
- package/dist/public/assets/_4zqifGZf2.js.br +0 -0
- package/dist/public/assets/{_QZ7jIJEp.js → _8D88iC2Y.js} +1 -1
- package/dist/public/assets/_8D88iC2Y.js.br +0 -0
- package/dist/public/assets/{_COmscE442.js → _B-7M0VuK2.js} +1 -1
- package/dist/public/assets/_B-7M0VuK2.js.br +0 -0
- package/dist/public/assets/{_B8PQyubX.js → _B-XihPlt.js} +1 -1
- package/dist/public/assets/_B-XihPlt.js.br +0 -0
- package/dist/public/assets/{_ClduJgR5.js → _B01yJM_n.js} +1 -1
- package/dist/public/assets/_B01yJM_n.js.br +0 -0
- package/dist/public/assets/{_CYb-TtX12.js → _B3dWhBsL2.js} +1 -1
- package/dist/public/assets/_B3dWhBsL2.js.br +0 -0
- package/dist/public/assets/{_CRF3psRH.js → _B6JLzfQk.js} +1 -1
- package/dist/public/assets/_B6JLzfQk.js.br +0 -0
- package/dist/public/assets/{_DU0F-fSc.js → _B92xkQnk.js} +1 -1
- package/dist/public/assets/_B92xkQnk.js.br +0 -0
- package/dist/public/assets/{_CXsVxa93.js → _B9STxcPh.js} +1 -1
- package/dist/public/assets/{_BxuGlOMJ.js → _BH7cFvM5.js} +1 -1
- package/dist/public/assets/_BH7cFvM5.js.br +0 -0
- package/dist/public/assets/_BP2BHaYT2.js +1 -0
- package/dist/public/assets/_BP2BHaYT2.js.br +0 -0
- package/dist/public/assets/{_Btx74Q-k.js → _BPmHfnJD.js} +1 -1
- package/dist/public/assets/_BPmHfnJD.js.br +0 -0
- package/dist/public/assets/{_BRHBgjBP2.js → _BRURAzLu2.js} +1 -1
- package/dist/public/assets/_BRURAzLu2.js.br +0 -0
- package/dist/public/assets/{_CpxRirGf.js → _BUhKc7uT.js} +1 -1
- package/dist/public/assets/_BUhKc7uT.js.br +0 -0
- package/dist/public/assets/{_By0S6RFm2.js → _BX76n7oq2.js} +1 -1
- package/dist/public/assets/_BX76n7oq2.js.br +0 -0
- package/dist/public/assets/{_DPc97sYv2.js → _BYn0odAU2.js} +1 -1
- package/dist/public/assets/{_BIP7B1g62.js → _BZDb9Hzx2.js} +1 -1
- package/dist/public/assets/{_BMWhe7UA2.js → _B_Wegq962.js} +1 -1
- package/dist/public/assets/_B_Wegq962.js.br +0 -0
- package/dist/public/assets/{_B2pxLNBO.js → _Bb4a7oF1.js} +1 -1
- package/dist/public/assets/_Bb4a7oF1.js.br +0 -0
- package/dist/public/assets/{_zkaPdW0C2.js → _BhAegdMF2.js} +1 -1
- package/dist/public/assets/_BhAegdMF2.js.br +0 -0
- package/dist/public/assets/{_DbkqHev42.js → _BlPl6sCu2.js} +1 -1
- package/dist/public/assets/_BlPl6sCu2.js.br +0 -0
- package/dist/public/assets/{_D5DIKC5J2.js → _BmEd20O42.js} +1 -1
- package/dist/public/assets/_BmEd20O42.js.br +0 -0
- package/dist/public/assets/{_CrvHv7e4.js → _BpxZLi8K.js} +1 -1
- package/dist/public/assets/_BpxZLi8K.js.br +0 -0
- package/dist/public/assets/{_Dj0FqIsq2.js → _BrNzM4EC2.js} +1 -1
- package/dist/public/assets/_BrNzM4EC2.js.br +0 -0
- package/dist/public/assets/{_CYLr_2iE.js → _Bvgyberk.js} +1 -1
- package/dist/public/assets/_Bvgyberk.js.br +0 -0
- package/dist/public/assets/{_2_8X99jw.js → _ByKU0Hfi.js} +1 -1
- package/dist/public/assets/_ByKU0Hfi.js.br +0 -0
- package/dist/public/assets/{_C9YvMapn.js → _ByaG8bWs.js} +1 -1
- package/dist/public/assets/_ByaG8bWs.js.br +0 -0
- package/dist/public/assets/{_BmtVFK052.js → _BziqIADV2.js} +1 -1
- package/dist/public/assets/_BziqIADV2.js.br +0 -0
- package/dist/public/assets/{_9CHuxVRu.js → _C2-Kd826.js} +1 -1
- package/dist/public/assets/_C2-Kd826.js.br +0 -0
- package/dist/public/assets/{_DgucIXC9.js → _C2rSDO7f.js} +1 -1
- package/dist/public/assets/_C2rSDO7f.js.br +0 -0
- package/dist/public/assets/{_CRpvVy-g.js → _C6jAYlE8.js} +1 -1
- package/dist/public/assets/_C6jAYlE8.js.br +0 -0
- package/dist/public/assets/{_C7kYFLNM.js → _C9E3fz2-.js} +1 -1
- package/dist/public/assets/_C9E3fz2-.js.br +0 -0
- package/dist/public/assets/{_BZe4BZ4G.js → _C9hmrTBV.js} +1 -1
- package/dist/public/assets/_C9hmrTBV.js.br +0 -0
- package/dist/public/assets/{_Dvsdxjs1.js → _CMGqtmQt.js} +1 -1
- package/dist/public/assets/_CMGqtmQt.js.br +0 -0
- package/dist/public/assets/{_lTcPBjyz2.js → _CNxYMMPa.js} +1 -1
- package/dist/public/assets/_CNxYMMPa.js.br +0 -0
- package/dist/public/assets/{_CMIAElmF.js → _CRmHsbsL.js} +1 -1
- package/dist/public/assets/_CRmHsbsL.js.br +0 -0
- package/dist/public/assets/{_BxlHpe2T.js → _CVQKEVHV.js} +1 -1
- package/dist/public/assets/_CVQKEVHV.js.br +0 -0
- package/dist/public/assets/{_BPiDffSK.js → _Cci4ZExC.js} +1 -1
- package/dist/public/assets/_Cci4ZExC.js.br +0 -0
- package/dist/public/assets/{_B3rIZBik.js → _CgnZDJPL.js} +1 -1
- package/dist/public/assets/_CgnZDJPL.js.br +0 -0
- package/dist/public/assets/{_BmH7JUGb2.js → _CkeutYnJ2.js} +1 -1
- package/dist/public/assets/_CkeutYnJ2.js.br +0 -0
- package/dist/public/assets/{_AG00U05V.js → _D0L-Bq8g.js} +1 -1
- package/dist/public/assets/_D0L-Bq8g.js.br +0 -0
- package/dist/public/assets/_D48HGWNS.js +1531 -0
- package/dist/public/assets/_D48HGWNS.js.br +0 -0
- package/dist/public/assets/{_CBF2sJFl.js → _D4J5RQqK.js} +1 -1
- package/dist/public/assets/_D4J5RQqK.js.br +0 -0
- package/dist/public/assets/{_Cawlufow.js → _D6xeqZLn.js} +1 -1
- package/dist/public/assets/_D6xeqZLn.js.br +0 -0
- package/dist/public/assets/{_DvqRc7vA2.js → _D7TvcnuF2.js} +1 -1
- package/dist/public/assets/_D7TvcnuF2.js.br +0 -0
- package/dist/public/assets/{_Cu3f85ax2.js → _D99Y49OA.js} +1 -1
- package/dist/public/assets/_D99Y49OA.js.br +0 -0
- package/dist/public/assets/{_BDIKDRj8.js → _D9jhO9rQ.js} +1 -1
- package/dist/public/assets/_D9jhO9rQ.js.br +0 -0
- package/dist/public/assets/{_BEEHMSv_.js → _DBzS4J_k.js} +1 -1
- package/dist/public/assets/_DBzS4J_k.js.br +0 -0
- package/dist/public/assets/{_DeCqhciO.js → _DDsFYxIq.js} +1 -1
- package/dist/public/assets/_DDsFYxIq.js.br +0 -0
- package/dist/public/assets/{_DTXvrAdN.js → _DIiEy_VP.js} +1 -1
- package/dist/public/assets/_DIiEy_VP.js.br +0 -0
- package/dist/public/assets/{_ji5qc8J4.js → _DImQNomk.js} +1 -1
- package/dist/public/assets/_DImQNomk.js.br +0 -0
- package/dist/public/assets/{_BHjsQD4C.js → _DRRQXGKH.js} +1 -1
- package/dist/public/assets/_DRRQXGKH.js.br +0 -0
- package/dist/public/assets/{_tKPNE6U52.js → _DZ0pRMJN2.js} +1 -1
- package/dist/public/assets/_DZ0pRMJN2.js.br +0 -0
- package/dist/public/assets/{_DJYs9cGt2.js → _DbkjWa7i2.js} +1 -1
- package/dist/public/assets/_DbkjWa7i2.js.br +0 -0
- package/dist/public/assets/{_BgDRYHYE.js → _DjKQr6mH.js} +1 -1
- package/dist/public/assets/_DjKQr6mH.js.br +0 -0
- package/dist/public/assets/{_ChIGZgCK2.js → _Dji7sUrK2.js} +1 -1
- package/dist/public/assets/_Dji7sUrK2.js.br +0 -0
- package/dist/public/assets/{_DPW4NADy2.js → _DkMIDB1P2.js} +1 -1
- package/dist/public/assets/_DkMIDB1P2.js.br +0 -0
- package/dist/public/assets/{_BzuTzxB9.js → _DlC4k_XP.js} +1 -1
- package/dist/public/assets/_DlC4k_XP.js.br +0 -0
- package/dist/public/assets/{_C3QGlxhv2.js → _DljpB8742.js} +1 -1
- package/dist/public/assets/_DljpB8742.js.br +0 -0
- package/dist/public/assets/{_T_hWiFRO.js → _DlsPVtFC.js} +1 -1
- package/dist/public/assets/_DlsPVtFC.js.br +0 -0
- package/dist/public/assets/{_ByQc1pkS.js → _Dmw0DArq.js} +1 -1
- package/dist/public/assets/_Dmw0DArq.js.br +0 -0
- package/dist/public/assets/{_CCXyJU0G.js → _DyNwE1Gc.js} +1 -1
- package/dist/public/assets/_DyNwE1Gc.js.br +0 -0
- package/dist/public/assets/{_CyDJr5hJ.js → _F3u8qQ9y.js} +1 -1
- package/dist/public/assets/_F3u8qQ9y.js.br +0 -0
- package/dist/public/assets/{_6fdNa05X2.js → _HH6t8aRM2.js} +1 -1
- package/dist/public/assets/_HH6t8aRM2.js.br +0 -0
- package/dist/public/assets/{_5pEZdV75.js → _JYBrvu87.js} +1 -1
- package/dist/public/assets/_JYBrvu87.js.br +0 -0
- package/dist/public/assets/{_FZ5aDFyS.js → _Kzpu52En.js} +1 -1
- package/dist/public/assets/_Kzpu52En.js.br +0 -0
- package/dist/public/assets/{_BGFm3dJ4.js → _UWZzN8Rg.js} +1 -1
- package/dist/public/assets/_UWZzN8Rg.js.br +0 -0
- package/dist/public/assets/{_nqBpAHq9.js → _YLPBpmu6.js} +1 -1
- package/dist/public/assets/_YLPBpmu6.js.br +0 -0
- package/dist/public/assets/{_fkktwOR8.js → _f4yPg-i-.js} +1 -1
- package/dist/public/assets/_f4yPg-i-.js.br +0 -0
- package/dist/public/assets/{_CfyASWBT2.js → _lBeubFtN2.js} +1 -1
- package/dist/public/assets/_lBeubFtN2.js.br +0 -0
- package/dist/public/assets/{_DZExUZ7A.js → _llnipctq2.js} +1 -1
- package/dist/public/assets/_llnipctq2.js.br +0 -0
- package/dist/public/assets/{_DFC22iAc.js → _sBNm9tCS.js} +1 -1
- package/dist/public/assets/_sBNm9tCS.js.br +0 -0
- package/dist/public/assets/{_BLvHtG5b.js → _u3et6kdz.js} +1 -1
- package/dist/public/assets/_u3et6kdz.js.br +0 -0
- package/dist/public/assets/{_DZyW50O5.js → _v4TxGuxE.js} +1 -1
- package/dist/public/assets/_v4TxGuxE.js.br +0 -0
- package/dist/public/assets/{_BPq9uIVf.js → _wvTh271a.js} +1 -1
- package/dist/public/assets/_wvTh271a.js.br +0 -0
- package/dist/public/assets/diff-view-CKEylX6w.css +1 -0
- package/dist/public/assets/diff-view-CKEylX6w.css.br +0 -0
- package/dist/public/assets/index-Bfh8nSee.js +85 -0
- package/dist/public/assets/index-Bfh8nSee.js.br +0 -0
- package/dist/public/assets/index-D41huIuZ.css +1 -0
- package/dist/public/assets/index-D41huIuZ.css.br +0 -0
- package/lib/setup/catalog.d.mts +22 -0
- package/lib/setup/catalog.mjs +72 -0
- package/lib/setup/doctor.d.mts +49 -0
- package/lib/setup/doctor.mjs +203 -0
- package/lib/setup/install.d.mts +14 -0
- package/lib/setup/install.mjs +135 -0
- package/package.json +2 -1
- package/dist/_CV5G1-Sr.js +0 -2
- package/dist/public/assets/_2_8X99jw.js.br +0 -0
- package/dist/public/assets/_5pEZdV75.js.br +0 -0
- package/dist/public/assets/_6fdNa05X2.js.br +0 -0
- package/dist/public/assets/_9CHuxVRu.js.br +0 -0
- package/dist/public/assets/_AG00U05V.js.br +0 -0
- package/dist/public/assets/_B2pxLNBO.js.br +0 -0
- package/dist/public/assets/_B3rIZBik.js.br +0 -0
- package/dist/public/assets/_B8PQyubX.js.br +0 -0
- package/dist/public/assets/_BDIKDRj8.js.br +0 -0
- package/dist/public/assets/_BEEHMSv_.js.br +0 -0
- package/dist/public/assets/_BGFm3dJ4.js.br +0 -0
- package/dist/public/assets/_BHjsQD4C.js.br +0 -0
- package/dist/public/assets/_BLibugcj.js +0 -1531
- package/dist/public/assets/_BLibugcj.js.br +0 -0
- package/dist/public/assets/_BLvHtG5b.js.br +0 -0
- package/dist/public/assets/_BMWhe7UA2.js.br +0 -0
- package/dist/public/assets/_BPiDffSK.js.br +0 -0
- package/dist/public/assets/_BPq9uIVf.js.br +0 -0
- package/dist/public/assets/_BRHBgjBP2.js.br +0 -0
- package/dist/public/assets/_BZe4BZ4G.js.br +0 -0
- package/dist/public/assets/_BgDRYHYE.js.br +0 -0
- package/dist/public/assets/_BmH7JUGb2.js.br +0 -0
- package/dist/public/assets/_BmtVFK052.js.br +0 -0
- package/dist/public/assets/_Btx74Q-k.js.br +0 -0
- package/dist/public/assets/_BxlHpe2T.js.br +0 -0
- package/dist/public/assets/_BxuGlOMJ.js.br +0 -0
- package/dist/public/assets/_By0S6RFm2.js.br +0 -0
- package/dist/public/assets/_ByQc1pkS.js.br +0 -0
- package/dist/public/assets/_BzuTzxB9.js.br +0 -0
- package/dist/public/assets/_C3QGlxhv2.js.br +0 -0
- package/dist/public/assets/_C7kYFLNM.js.br +0 -0
- package/dist/public/assets/_C9YvMapn.js.br +0 -0
- package/dist/public/assets/_CBF2sJFl.js.br +0 -0
- package/dist/public/assets/_CCXyJU0G.js.br +0 -0
- package/dist/public/assets/_CMIAElmF.js.br +0 -0
- package/dist/public/assets/_COmscE442.js.br +0 -0
- package/dist/public/assets/_CRF3psRH.js.br +0 -0
- package/dist/public/assets/_CRpvVy-g.js.br +0 -0
- package/dist/public/assets/_CYLr_2iE.js.br +0 -0
- package/dist/public/assets/_CYb-TtX12.js.br +0 -0
- package/dist/public/assets/_Cawlufow.js.br +0 -0
- package/dist/public/assets/_CfyASWBT2.js.br +0 -0
- package/dist/public/assets/_ChIGZgCK2.js.br +0 -0
- package/dist/public/assets/_ClduJgR5.js.br +0 -0
- package/dist/public/assets/_Cp2bkjzT2.js +0 -1
- package/dist/public/assets/_Cp2bkjzT2.js.br +0 -0
- package/dist/public/assets/_CpxRirGf.js.br +0 -0
- package/dist/public/assets/_CrvHv7e4.js.br +0 -0
- package/dist/public/assets/_Cu3f85ax2.js.br +0 -0
- package/dist/public/assets/_CyDJr5hJ.js.br +0 -0
- package/dist/public/assets/_D1Ecsx8-2.js.br +0 -0
- package/dist/public/assets/_D2tmOnaH.js +0 -1
- package/dist/public/assets/_D2tmOnaH.js.br +0 -0
- package/dist/public/assets/_D5DIKC5J2.js.br +0 -0
- package/dist/public/assets/_DFC22iAc.js.br +0 -0
- package/dist/public/assets/_DJYs9cGt2.js.br +0 -0
- package/dist/public/assets/_DPW4NADy2.js.br +0 -0
- package/dist/public/assets/_DTXvrAdN.js.br +0 -0
- package/dist/public/assets/_DU0F-fSc.js.br +0 -0
- package/dist/public/assets/_DZExUZ7A.js.br +0 -0
- package/dist/public/assets/_DZyW50O5.js.br +0 -0
- package/dist/public/assets/_DbkqHev42.js.br +0 -0
- package/dist/public/assets/_DeCqhciO.js.br +0 -0
- package/dist/public/assets/_DgucIXC9.js.br +0 -0
- package/dist/public/assets/_Dj0FqIsq2.js.br +0 -0
- package/dist/public/assets/_DvqRc7vA2.js.br +0 -0
- package/dist/public/assets/_Dvsdxjs1.js.br +0 -0
- package/dist/public/assets/_FZ5aDFyS.js.br +0 -0
- package/dist/public/assets/_QZ7jIJEp.js.br +0 -0
- package/dist/public/assets/_T_hWiFRO.js.br +0 -0
- package/dist/public/assets/_fkktwOR8.js.br +0 -0
- package/dist/public/assets/_ji5qc8J4.js.br +0 -0
- package/dist/public/assets/_lTcPBjyz2.js.br +0 -0
- package/dist/public/assets/_nqBpAHq9.js.br +0 -0
- package/dist/public/assets/_tKPNE6U52.js.br +0 -0
- package/dist/public/assets/_zkaPdW0C2.js.br +0 -0
- package/dist/public/assets/diff-view-AJeZtePd.css +0 -1
- package/dist/public/assets/diff-view-AJeZtePd.css.br +0 -0
- package/dist/public/assets/index-BG3uLJV6.js +0 -85
- package/dist/public/assets/index-BG3uLJV6.js.br +0 -0
- package/dist/public/assets/index-_5MkiydM.css +0 -1
- package/dist/public/assets/index-_5MkiydM.css.br +0 -0
- package/dist/public/assets/preload-helper-C1JvlFma.css +0 -1
- package/dist/public/assets/preload-helper-C1JvlFma.css.br +0 -0
- /package/dist/public/assets/{_B5W6OYN72.js → _B5W6OYN7.js} +0 -0
- /package/dist/public/assets/{_B5W6OYN72.js.br → _B5W6OYN7.js.br} +0 -0
- /package/dist/public/assets/{_DMoTqEGO2.js → _DMoTqEGO.js} +0 -0
- /package/dist/public/assets/{_DMoTqEGO2.js.br → _DMoTqEGO.js.br} +0 -0
- /package/dist/public/assets/{_DmIc4jLQ2.js → _DmIc4jLQ.js} +0 -0
- /package/dist/public/assets/{_DmIc4jLQ2.js.br → _DmIc4jLQ.js.br} +0 -0
- /package/dist/public/assets/{_DsUTQ-LC.js → _DsUTQ-LC2.js} +0 -0
- /package/dist/public/assets/{_DsUTQ-LC.js.br → _DsUTQ-LC2.js.br} +0 -0
- /package/dist/public/assets/{_VbXTXTou.js → _VbXTXTou2.js} +0 -0
- /package/dist/public/assets/{_VbXTXTou.js.br → _VbXTXTou2.js.br} +0 -0
- /package/dist/public/assets/{_iXnhIJG7.js → _iXnhIJG72.js} +0 -0
- /package/dist/public/assets/{_iXnhIJG7.js.br → _iXnhIJG72.js.br} +0 -0
- /package/dist/public/assets/{_vGVdxbeo.js → _vGVdxbeo2.js} +0 -0
- /package/dist/public/assets/{_vGVdxbeo.js.br → _vGVdxbeo2.js.br} +0 -0
|
@@ -4,21 +4,20 @@ import { t as require_safe_buffer } from "./_BmSjjJ2E.js";
|
|
|
4
4
|
import fs from "node:fs";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import os from "node:os";
|
|
7
|
-
import { DatabaseSync } from "node:sqlite";
|
|
8
7
|
import { execFile } from "node:child_process";
|
|
9
8
|
import { promisify } from "node:util";
|
|
9
|
+
import { DatabaseSync } from "node:sqlite";
|
|
10
10
|
//#region src/server/config.ts
|
|
11
|
-
var home = os.homedir();
|
|
11
|
+
var home$1 = os.homedir();
|
|
12
12
|
var config = {
|
|
13
13
|
/** Root directory containing all workspaces. */
|
|
14
|
-
workRoot: process.env.WORK_ROOT || path.join(home, "work"),
|
|
14
|
+
workRoot: process.env.WORK_ROOT || path.join(home$1, "work"),
|
|
15
15
|
/** Shared bare-repo cache, kept inside the work root. */
|
|
16
16
|
get cacheDir() {
|
|
17
17
|
return path.join(this.workRoot, ".cache");
|
|
18
18
|
},
|
|
19
19
|
/** Data directory for the sqlite db and other server state. */
|
|
20
|
-
dataDir: process.env.WORK_DATA_DIR || path.join(process.env.XDG_DATA_HOME || path.join(home, ".local", "share"), "work"),
|
|
21
|
-
gitHost: "github.com",
|
|
20
|
+
dataDir: process.env.WORK_DATA_DIR || path.join(process.env.XDG_DATA_HOME || path.join(home$1, ".local", "share"), "work"),
|
|
22
21
|
user: process.env.WORK_USER || os.userInfo().username,
|
|
23
22
|
host: process.env.WORK_HOST || os.hostname().split(".")[0],
|
|
24
23
|
/** Prefix every workspace branch starts with. Tooling finds a workspace's PRs
|
|
@@ -33,6 +32,31 @@ var config = {
|
|
|
33
32
|
};
|
|
34
33
|
fs.mkdirSync(config.dataDir, { recursive: true });
|
|
35
34
|
//#endregion
|
|
35
|
+
//#region src/server/exec.ts
|
|
36
|
+
/** Dedicated tmux server so we never touch another multiplexer's or the
|
|
37
|
+
* user's default tmux. */
|
|
38
|
+
var TMUX_SOCKET = "work";
|
|
39
|
+
var execFileAsync = promisify(execFile);
|
|
40
|
+
async function run$1(cmd, args, cwd, env) {
|
|
41
|
+
const { stdout } = await execFileAsync(cmd, args, {
|
|
42
|
+
cwd,
|
|
43
|
+
env,
|
|
44
|
+
maxBuffer: 67108864
|
|
45
|
+
});
|
|
46
|
+
return stdout.trim();
|
|
47
|
+
}
|
|
48
|
+
var git = (args, cwd) => run$1("git", args, cwd);
|
|
49
|
+
/** `gh` against one GitHub host — `GH_HOST` picks the stored credential. */
|
|
50
|
+
var gh = (args, host) => run$1("gh", args, void 0, host ? {
|
|
51
|
+
...process.env,
|
|
52
|
+
GH_HOST: host
|
|
53
|
+
} : void 0);
|
|
54
|
+
var tmux = (args, env) => run$1("tmux", [
|
|
55
|
+
"-L",
|
|
56
|
+
TMUX_SOCKET,
|
|
57
|
+
...args
|
|
58
|
+
], void 0, env);
|
|
59
|
+
//#endregion
|
|
36
60
|
//#region src/server/db.ts
|
|
37
61
|
var db = new DatabaseSync(path.join(config.dataDir, "work.db"));
|
|
38
62
|
db.exec("PRAGMA busy_timeout = 5000");
|
|
@@ -111,6 +135,448 @@ db.exec(`
|
|
|
111
135
|
);
|
|
112
136
|
`);
|
|
113
137
|
//#endregion
|
|
138
|
+
//#region lib/setup/catalog.mjs
|
|
139
|
+
/** Machine tools. `required` ones gate readiness; the rest are the utilities
|
|
140
|
+
* agents reach for constantly (mirrors DylanPiercey/start). Static binaries via
|
|
141
|
+
* mise, except the system packages the installer provides (git, tmux). */
|
|
142
|
+
var TOOLS = [
|
|
143
|
+
{
|
|
144
|
+
id: "git",
|
|
145
|
+
label: "git",
|
|
146
|
+
bin: "git",
|
|
147
|
+
required: true,
|
|
148
|
+
system: true
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
id: "tmux",
|
|
152
|
+
label: "tmux",
|
|
153
|
+
bin: "tmux",
|
|
154
|
+
required: true,
|
|
155
|
+
system: true,
|
|
156
|
+
mise: "tmux"
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
id: "node",
|
|
160
|
+
label: "Node.js",
|
|
161
|
+
bin: "node",
|
|
162
|
+
mise: "node",
|
|
163
|
+
required: true
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
id: "gh",
|
|
167
|
+
label: "GitHub CLI",
|
|
168
|
+
bin: "gh",
|
|
169
|
+
mise: "gh",
|
|
170
|
+
required: true
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
id: "ripgrep",
|
|
174
|
+
label: "ripgrep",
|
|
175
|
+
bin: "rg",
|
|
176
|
+
mise: "ripgrep"
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
id: "fd",
|
|
180
|
+
label: "fd",
|
|
181
|
+
bin: "fd",
|
|
182
|
+
mise: "fd"
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
id: "jq",
|
|
186
|
+
label: "jq",
|
|
187
|
+
bin: "jq",
|
|
188
|
+
mise: "jq"
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
id: "delta",
|
|
192
|
+
label: "delta",
|
|
193
|
+
bin: "delta",
|
|
194
|
+
mise: "delta"
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
id: "ast-grep",
|
|
198
|
+
label: "ast-grep",
|
|
199
|
+
bin: "ast-grep",
|
|
200
|
+
mise: "ast-grep"
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
id: "hyperfine",
|
|
204
|
+
label: "hyperfine",
|
|
205
|
+
bin: "hyperfine",
|
|
206
|
+
mise: "hyperfine"
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
id: "fzf",
|
|
210
|
+
label: "fzf",
|
|
211
|
+
bin: "fzf",
|
|
212
|
+
mise: "fzf"
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
id: "bottom",
|
|
216
|
+
label: "bottom",
|
|
217
|
+
bin: "btm",
|
|
218
|
+
mise: "bottom"
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
id: "pnpm",
|
|
222
|
+
label: "pnpm",
|
|
223
|
+
bin: "pnpm",
|
|
224
|
+
mise: "pnpm"
|
|
225
|
+
}
|
|
226
|
+
];
|
|
227
|
+
/** Coding agent CLIs. Installed via each vendor's own installer (not npm) so
|
|
228
|
+
* self-update works. `bins` lists the executable names a family answers to;
|
|
229
|
+
* numeric suffixes (`claude1`) are discovered on top of these. */
|
|
230
|
+
var AGENTS = [
|
|
231
|
+
{
|
|
232
|
+
id: "claude",
|
|
233
|
+
label: "Claude",
|
|
234
|
+
bins: ["claude"],
|
|
235
|
+
install: {
|
|
236
|
+
url: "https://claude.ai/install.sh",
|
|
237
|
+
shell: "bash"
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
id: "codex",
|
|
242
|
+
label: "Codex",
|
|
243
|
+
bins: ["codex"],
|
|
244
|
+
install: {
|
|
245
|
+
url: "https://chatgpt.com/codex/install.sh",
|
|
246
|
+
shell: "sh"
|
|
247
|
+
}
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
id: "copilot",
|
|
251
|
+
label: "Copilot",
|
|
252
|
+
bins: ["copilot"],
|
|
253
|
+
install: {
|
|
254
|
+
url: "https://gh.io/copilot-install",
|
|
255
|
+
shell: "bash"
|
|
256
|
+
}
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
id: "cursor",
|
|
260
|
+
label: "Cursor",
|
|
261
|
+
bins: ["cursor-agent"],
|
|
262
|
+
install: {
|
|
263
|
+
url: "https://cursor.com/install",
|
|
264
|
+
shell: "bash"
|
|
265
|
+
}
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
id: "grok",
|
|
269
|
+
label: "Grok",
|
|
270
|
+
bins: ["grok"],
|
|
271
|
+
install: {
|
|
272
|
+
url: "https://x.ai/cli/install.sh",
|
|
273
|
+
shell: "bash"
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
];
|
|
277
|
+
var DEFAULT_GITHUB_HOST = "github.com";
|
|
278
|
+
function toolById(id) {
|
|
279
|
+
return TOOLS.find((t) => t.id === id) || null;
|
|
280
|
+
}
|
|
281
|
+
function agentById(id) {
|
|
282
|
+
return AGENTS.find((a) => a.id === id) || null;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Agent *instances* are the family id plus an optional numeric suffix —
|
|
286
|
+
* `claude`, `claude1`, `claude2` — one per binary on PATH (`claude1`,
|
|
287
|
+
* `cursor-agent2`, …). This is the canonical id everywhere: sessions,
|
|
288
|
+
* settings, usage rows (`~/.claude-2` reports as `claude2`), icons.
|
|
289
|
+
*/
|
|
290
|
+
function parseAgentId(id) {
|
|
291
|
+
const m = /^([a-z]+?)(\d*)$/.exec(id || "");
|
|
292
|
+
const family = m && agentById(m[1]);
|
|
293
|
+
return family ? {
|
|
294
|
+
family,
|
|
295
|
+
suffix: m[2]
|
|
296
|
+
} : null;
|
|
297
|
+
}
|
|
298
|
+
/** argv0 an instance id launches — the family's binary plus the suffix. */
|
|
299
|
+
function agentCommand(id) {
|
|
300
|
+
const parsed = parseAgentId(id);
|
|
301
|
+
return parsed ? `${parsed.family.bins[0]}${parsed.suffix}` : null;
|
|
302
|
+
}
|
|
303
|
+
/** "Claude" / "Claude 2". */
|
|
304
|
+
function agentLabel(id) {
|
|
305
|
+
const parsed = parseAgentId(id);
|
|
306
|
+
return parsed ? `${parsed.family.label}${parsed.suffix ? ` ${parsed.suffix}` : ""}` : id;
|
|
307
|
+
}
|
|
308
|
+
//#endregion
|
|
309
|
+
//#region lib/setup/doctor.mjs
|
|
310
|
+
var home = os.homedir();
|
|
311
|
+
/** PATH the service runs with (no login shell) plus the current one, so a
|
|
312
|
+
* probe from the server sees the same binaries a probe from a terminal does. */
|
|
313
|
+
function setupPath(base = process.env.PATH || "") {
|
|
314
|
+
const extra = [
|
|
315
|
+
`${home}/.local/share/mise/shims`,
|
|
316
|
+
`${home}/.local/bin`,
|
|
317
|
+
"/opt/homebrew/bin",
|
|
318
|
+
"/usr/local/bin",
|
|
319
|
+
"/usr/bin",
|
|
320
|
+
"/bin"
|
|
321
|
+
];
|
|
322
|
+
const seen = /* @__PURE__ */ new Set();
|
|
323
|
+
return [...base.split(path.delimiter), ...extra].filter((p) => p && !seen.has(p) && seen.add(p)).join(path.delimiter);
|
|
324
|
+
}
|
|
325
|
+
/** `~/…` for anything under the home directory — every path here is for
|
|
326
|
+
* display (Settings rows, `work doctor`), never re-used to exec. */
|
|
327
|
+
function tilde(p) {
|
|
328
|
+
if (!p) return p;
|
|
329
|
+
return p === home ? "~" : p.startsWith(home + path.sep) ? "~" + p.slice(home.length) : p;
|
|
330
|
+
}
|
|
331
|
+
/** Absolute path of `bin` on setupPath(), or null. */
|
|
332
|
+
function which(bin) {
|
|
333
|
+
for (const dir of setupPath().split(path.delimiter)) {
|
|
334
|
+
const full = path.join(dir, bin);
|
|
335
|
+
try {
|
|
336
|
+
if (fs.statSync(full).isFile()) return full;
|
|
337
|
+
} catch {}
|
|
338
|
+
}
|
|
339
|
+
return null;
|
|
340
|
+
}
|
|
341
|
+
function run(cmd, args, { timeout = 15e3 } = {}) {
|
|
342
|
+
return new Promise((resolve) => {
|
|
343
|
+
execFile(cmd, args, {
|
|
344
|
+
env: {
|
|
345
|
+
...process.env,
|
|
346
|
+
PATH: setupPath()
|
|
347
|
+
},
|
|
348
|
+
timeout,
|
|
349
|
+
maxBuffer: 8 << 20
|
|
350
|
+
}, (err, stdout, stderr) => resolve({
|
|
351
|
+
ok: !err,
|
|
352
|
+
stdout: String(stdout || ""),
|
|
353
|
+
stderr: String(stderr || "")
|
|
354
|
+
}));
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
/** Versions of every mise-managed tool (global + any active config), keyed
|
|
358
|
+
* by short name. Local and fast; `mise outdated` (network) is a separate,
|
|
359
|
+
* on-demand call in the server. */
|
|
360
|
+
async function miseVersions() {
|
|
361
|
+
if (!which("mise")) return null;
|
|
362
|
+
const { ok, stdout } = await run("mise", ["ls", "--json"]);
|
|
363
|
+
if (!ok) return {};
|
|
364
|
+
const out = {};
|
|
365
|
+
try {
|
|
366
|
+
for (const [name, list] of Object.entries(JSON.parse(stdout))) {
|
|
367
|
+
const active = list.find((v) => v.installed && v.active) || list.find((v) => v.installed);
|
|
368
|
+
if (active) out[name] = active.version;
|
|
369
|
+
}
|
|
370
|
+
} catch {}
|
|
371
|
+
return out;
|
|
372
|
+
}
|
|
373
|
+
/** Hosts `gh` knows about (~/.config/gh/hosts.yml top-level keys) — the
|
|
374
|
+
* source of truth for "which GitHub hosts has this machine signed in to",
|
|
375
|
+
* merged with whatever the caller has configured. */
|
|
376
|
+
function ghKnownHosts() {
|
|
377
|
+
const file = path.join(process.env.GH_CONFIG_DIR || path.join(home, ".config", "gh"), "hosts.yml");
|
|
378
|
+
let text = "";
|
|
379
|
+
try {
|
|
380
|
+
text = fs.readFileSync(file, "utf8");
|
|
381
|
+
} catch {
|
|
382
|
+
return [];
|
|
383
|
+
}
|
|
384
|
+
return [...text.matchAll(/^([A-Za-z0-9.-]+):\s*$/gm)].map((m) => m[1]);
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Every agent CLI instance on PATH, per family: the plain binary and any
|
|
388
|
+
* numeric-suffixed siblings (`claude1`, `cursor-agent2`). Sync — a PATH
|
|
389
|
+
* scan is cheap and the boot handler needs it without awaiting. First hit
|
|
390
|
+
* on PATH wins per name, like the shell.
|
|
391
|
+
*/
|
|
392
|
+
function discoverAgents() {
|
|
393
|
+
const dirs = setupPath().split(path.delimiter);
|
|
394
|
+
const seen = /* @__PURE__ */ new Map();
|
|
395
|
+
for (const dir of dirs) {
|
|
396
|
+
let names;
|
|
397
|
+
try {
|
|
398
|
+
names = fs.readdirSync(dir);
|
|
399
|
+
} catch {
|
|
400
|
+
continue;
|
|
401
|
+
}
|
|
402
|
+
for (const name of names) {
|
|
403
|
+
const hit = AGENTS.find((a) => a.bins.some((b) => name === b || name.startsWith(b) && /^\d+$/.test(name.slice(b.length))));
|
|
404
|
+
if (!hit || seen.has(name)) continue;
|
|
405
|
+
const full = path.join(dir, name);
|
|
406
|
+
try {
|
|
407
|
+
if (!fs.statSync(full).isFile()) continue;
|
|
408
|
+
} catch {
|
|
409
|
+
continue;
|
|
410
|
+
}
|
|
411
|
+
const bin = hit.bins.find((b) => name.startsWith(b));
|
|
412
|
+
seen.set(name, {
|
|
413
|
+
family: hit,
|
|
414
|
+
id: `${hit.id}${name.slice(bin.length)}`,
|
|
415
|
+
command: name,
|
|
416
|
+
path: tilde(full)
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
return AGENTS.map((a) => {
|
|
421
|
+
const instances = [...seen.values()].filter((i) => i.family === a).map(({ id, command, path: p }) => ({
|
|
422
|
+
id,
|
|
423
|
+
command,
|
|
424
|
+
path: p,
|
|
425
|
+
suffix: id.slice(a.id.length)
|
|
426
|
+
})).sort((x, y) => x.suffix === "" ? -1 : y.suffix === "" ? 1 : Number(x.suffix) - Number(y.suffix));
|
|
427
|
+
return {
|
|
428
|
+
id: a.id,
|
|
429
|
+
label: a.label,
|
|
430
|
+
installed: instances.length > 0,
|
|
431
|
+
installable: true,
|
|
432
|
+
instances
|
|
433
|
+
};
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
/** Auth status for one host via gh (which owns the tokens). */
|
|
437
|
+
async function githubHostStatus(host) {
|
|
438
|
+
const isEnterprise = host !== DEFAULT_GITHUB_HOST;
|
|
439
|
+
if (!which("gh")) return {
|
|
440
|
+
host,
|
|
441
|
+
isEnterprise,
|
|
442
|
+
authed: false,
|
|
443
|
+
error: "gh not installed"
|
|
444
|
+
};
|
|
445
|
+
const { ok, stdout, stderr } = await run("gh", [
|
|
446
|
+
"auth",
|
|
447
|
+
"status",
|
|
448
|
+
"--hostname",
|
|
449
|
+
host
|
|
450
|
+
]);
|
|
451
|
+
const text = stdout + stderr;
|
|
452
|
+
const user = text.match(/account (\S+)/)?.[1] || text.match(/Logged in to \S+ as (\S+)/)?.[1];
|
|
453
|
+
return ok ? {
|
|
454
|
+
host,
|
|
455
|
+
isEnterprise,
|
|
456
|
+
authed: true,
|
|
457
|
+
user
|
|
458
|
+
} : {
|
|
459
|
+
host,
|
|
460
|
+
isEnterprise,
|
|
461
|
+
authed: false,
|
|
462
|
+
error: /not logged in/i.test(text) ? void 0 : text.trim().split("\n").pop()
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* Full readiness snapshot.
|
|
467
|
+
*
|
|
468
|
+
* @param {{ hosts?: string[] }} [opts] configured GitHub hosts (settings);
|
|
469
|
+
* github.com and any host gh is already signed in to are always included.
|
|
470
|
+
*/
|
|
471
|
+
async function doctor(opts = {}) {
|
|
472
|
+
const hostSet = /* @__PURE__ */ new Set([
|
|
473
|
+
DEFAULT_GITHUB_HOST,
|
|
474
|
+
...opts.hosts || [],
|
|
475
|
+
...ghKnownHosts()
|
|
476
|
+
]);
|
|
477
|
+
const [versions, github] = await Promise.all([miseVersions(), Promise.all([...hostSet].map(githubHostStatus))]);
|
|
478
|
+
const tools = TOOLS.map((t) => {
|
|
479
|
+
const found = which(t.bin);
|
|
480
|
+
return {
|
|
481
|
+
id: t.id,
|
|
482
|
+
label: t.label,
|
|
483
|
+
required: !!t.required,
|
|
484
|
+
installed: !!found,
|
|
485
|
+
path: tilde(found) || void 0,
|
|
486
|
+
version: t.mise && versions && versions[t.mise] || void 0,
|
|
487
|
+
installable: !!(t.mise && versions !== null),
|
|
488
|
+
mise: t.mise
|
|
489
|
+
};
|
|
490
|
+
});
|
|
491
|
+
const agents = discoverAgents();
|
|
492
|
+
const missing = [];
|
|
493
|
+
for (const t of tools) if (t.required && !t.installed) missing.push(t.id);
|
|
494
|
+
if (!github.some((h) => h.authed)) missing.push("github-auth");
|
|
495
|
+
if (!agents.some((a) => a.installed)) missing.push("agent");
|
|
496
|
+
return {
|
|
497
|
+
ready: missing.length === 0,
|
|
498
|
+
missing,
|
|
499
|
+
mise: {
|
|
500
|
+
installed: versions !== null,
|
|
501
|
+
path: tilde(which("mise")) || void 0
|
|
502
|
+
},
|
|
503
|
+
tools,
|
|
504
|
+
agents,
|
|
505
|
+
github
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
//#endregion
|
|
509
|
+
//#region src/server/settings.ts
|
|
510
|
+
function getSetting(key) {
|
|
511
|
+
return get("SELECT value FROM settings WHERE key = ?", key)?.value;
|
|
512
|
+
}
|
|
513
|
+
function setSetting(key, value) {
|
|
514
|
+
db.prepare("INSERT INTO settings (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value").run(key, value);
|
|
515
|
+
}
|
|
516
|
+
/** UI preferences (last workspace, tab per workspace, collapsed panes…)
|
|
517
|
+
* live in the settings table under a "ui." prefix — shared across every
|
|
518
|
+
* device rather than per-browser. */
|
|
519
|
+
function allPrefs() {
|
|
520
|
+
const rows = db.prepare("SELECT key, value FROM settings WHERE key LIKE 'ui.%'").all();
|
|
521
|
+
return Object.fromEntries(rows.map((r) => [r.key.slice(3), r.value]));
|
|
522
|
+
}
|
|
523
|
+
function setPref(key, value) {
|
|
524
|
+
if (value === null) db.prepare("DELETE FROM settings WHERE key = ?").run(`ui.${key}`);
|
|
525
|
+
else setSetting(`ui.${key}`, value);
|
|
526
|
+
}
|
|
527
|
+
/** Instance ids the user switched off in Settings (still installed). */
|
|
528
|
+
function disabledAgents() {
|
|
529
|
+
try {
|
|
530
|
+
return new Set(JSON.parse(getSetting("disabledAgents") || "[]"));
|
|
531
|
+
} catch {
|
|
532
|
+
return /* @__PURE__ */ new Set();
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
function setDisabledAgents(ids) {
|
|
536
|
+
setSetting("disabledAgents", JSON.stringify([...new Set(ids)]));
|
|
537
|
+
}
|
|
538
|
+
/** Every agent CLI instance installed on this machine (PATH scan) plus the
|
|
539
|
+
* built-in shell, with the user's enable/disable applied. Cheap and sync so
|
|
540
|
+
* the boot handler and session create can call it directly. */
|
|
541
|
+
function agentChoices() {
|
|
542
|
+
const off = disabledAgents();
|
|
543
|
+
const out = [];
|
|
544
|
+
for (const family of discoverAgents()) for (const inst of family.instances) out.push({
|
|
545
|
+
id: inst.id,
|
|
546
|
+
label: agentLabel(inst.id),
|
|
547
|
+
family: family.id,
|
|
548
|
+
command: inst.command,
|
|
549
|
+
enabled: !off.has(inst.id)
|
|
550
|
+
});
|
|
551
|
+
out.push({
|
|
552
|
+
id: "shell",
|
|
553
|
+
label: "Shell",
|
|
554
|
+
family: "shell",
|
|
555
|
+
command: "",
|
|
556
|
+
enabled: true
|
|
557
|
+
});
|
|
558
|
+
return out;
|
|
559
|
+
}
|
|
560
|
+
/** Ids the pickers offer: installed ∧ enabled. `shell` is not listed —
|
|
561
|
+
* every picker appends it itself as the always-there fallback. */
|
|
562
|
+
function enabledAgents() {
|
|
563
|
+
return agentChoices().filter((a) => a.enabled && a.id !== "shell").map((a) => a.id);
|
|
564
|
+
}
|
|
565
|
+
/** True for any id a session may be created with: a discovered instance,
|
|
566
|
+
* the shell, or a plausible instance id whose binary a login shell can find
|
|
567
|
+
* (PATH here and in the pane can differ). */
|
|
568
|
+
function isKnownAgent(id) {
|
|
569
|
+
return id === "shell" || !!parseAgentId(id);
|
|
570
|
+
}
|
|
571
|
+
/** Default agent for empty-session Start / auto-create. Falls back to the
|
|
572
|
+
* first enabled non-shell instance when the stored choice is gone. */
|
|
573
|
+
function preferredAgent() {
|
|
574
|
+
const stored = getSetting("preferredAgent");
|
|
575
|
+
const enabled = enabledAgents();
|
|
576
|
+
if (stored && enabled.includes(stored)) return stored;
|
|
577
|
+
return enabled.find((id) => id !== "shell") || stored || "claude";
|
|
578
|
+
}
|
|
579
|
+
//#endregion
|
|
114
580
|
//#region src/server/events.ts
|
|
115
581
|
var listeners = /* @__PURE__ */ new Set();
|
|
116
582
|
function publish(type, data) {
|
|
@@ -143,57 +609,6 @@ function subscriberCount() {
|
|
|
143
609
|
return listeners.size;
|
|
144
610
|
}
|
|
145
611
|
//#endregion
|
|
146
|
-
//#region src/server/exec.ts
|
|
147
|
-
/** Dedicated tmux server so we never touch another multiplexer's or the
|
|
148
|
-
* user's default tmux. */
|
|
149
|
-
var TMUX_SOCKET = "work";
|
|
150
|
-
var execFileAsync = promisify(execFile);
|
|
151
|
-
async function run(cmd, args, cwd, env) {
|
|
152
|
-
const { stdout } = await execFileAsync(cmd, args, {
|
|
153
|
-
cwd,
|
|
154
|
-
env,
|
|
155
|
-
maxBuffer: 67108864
|
|
156
|
-
});
|
|
157
|
-
return stdout.trim();
|
|
158
|
-
}
|
|
159
|
-
var git = (args, cwd) => run("git", args, cwd);
|
|
160
|
-
var gh = (args) => run("gh", args);
|
|
161
|
-
var tmux = (args, env) => run("tmux", [
|
|
162
|
-
"-L",
|
|
163
|
-
TMUX_SOCKET,
|
|
164
|
-
...args
|
|
165
|
-
], void 0, env);
|
|
166
|
-
//#endregion
|
|
167
|
-
//#region src/server/settings.ts
|
|
168
|
-
var AGENTS = [
|
|
169
|
-
"claude",
|
|
170
|
-
"codex",
|
|
171
|
-
"grok",
|
|
172
|
-
"copilot",
|
|
173
|
-
"cursor"
|
|
174
|
-
];
|
|
175
|
-
function getSetting(key) {
|
|
176
|
-
return get("SELECT value FROM settings WHERE key = ?", key)?.value;
|
|
177
|
-
}
|
|
178
|
-
function setSetting(key, value) {
|
|
179
|
-
db.prepare("INSERT INTO settings (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value").run(key, value);
|
|
180
|
-
}
|
|
181
|
-
/** UI preferences (last workspace, tab per workspace, collapsed panes…)
|
|
182
|
-
* live in the settings table under a "ui." prefix — shared across every
|
|
183
|
-
* device rather than per-browser. */
|
|
184
|
-
function allPrefs() {
|
|
185
|
-
const rows = db.prepare("SELECT key, value FROM settings WHERE key LIKE 'ui.%'").all();
|
|
186
|
-
return Object.fromEntries(rows.map((r) => [r.key.slice(3), r.value]));
|
|
187
|
-
}
|
|
188
|
-
function setPref(key, value) {
|
|
189
|
-
if (value === null) db.prepare("DELETE FROM settings WHERE key = ?").run(`ui.${key}`);
|
|
190
|
-
else setSetting(`ui.${key}`, value);
|
|
191
|
-
}
|
|
192
|
-
function preferredAgent() {
|
|
193
|
-
const value = getSetting("preferredAgent");
|
|
194
|
-
return AGENTS.includes(value) ? value : "claude";
|
|
195
|
-
}
|
|
196
|
-
//#endregion
|
|
197
612
|
//#region node_modules/.pnpm/bn.js@4.12.5/node_modules/bn.js/lib/bn.js
|
|
198
613
|
var require_bn = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
199
614
|
(function(module$1, exports$2) {
|
|
@@ -6013,7 +6428,7 @@ function publishChange(sessionId) {
|
|
|
6013
6428
|
const row = get("SELECT workspace_id FROM sessions WHERE id = ?", sessionId);
|
|
6014
6429
|
if (row?.workspace_id) {
|
|
6015
6430
|
const workspaceId = row.workspace_id;
|
|
6016
|
-
import("./
|
|
6431
|
+
import("./_B1U5NJd1.js").then((m) => m.notifySessionsChanged(workspaceId));
|
|
6017
6432
|
return;
|
|
6018
6433
|
}
|
|
6019
6434
|
publish("sessions.changed");
|
|
@@ -6037,11 +6452,17 @@ function stateCurl(state, reason) {
|
|
|
6037
6452
|
* believing the screen over that costs it the state its own hook just
|
|
6038
6453
|
* reported. */
|
|
6039
6454
|
function reportsWorking(agent) {
|
|
6040
|
-
return agent === "claude";
|
|
6455
|
+
return agentFamily(agent) === "claude";
|
|
6456
|
+
}
|
|
6457
|
+
/** Family of an instance id (`claude2` → `claude`); flags and hooks are
|
|
6458
|
+
* per family, every numbered copy behaves the same. */
|
|
6459
|
+
function agentFamily(agent) {
|
|
6460
|
+
return agent ? parseAgentId(agent)?.family.id : void 0;
|
|
6041
6461
|
}
|
|
6042
6462
|
/** Extra argv for an agent CLI so it reports working/waiting state. */
|
|
6043
6463
|
function agentLaunchFlags(agent) {
|
|
6044
|
-
|
|
6464
|
+
const family = agentFamily(agent);
|
|
6465
|
+
if (family === "claude") {
|
|
6045
6466
|
const hook = (state, reason) => [{ hooks: [{
|
|
6046
6467
|
type: "command",
|
|
6047
6468
|
command: stateCurl(state, reason)
|
|
@@ -6053,7 +6474,7 @@ function agentLaunchFlags(agent) {
|
|
|
6053
6474
|
Notification: hook("waiting", "attention")
|
|
6054
6475
|
} })];
|
|
6055
6476
|
}
|
|
6056
|
-
if (
|
|
6477
|
+
if (family === "codex") return ["-c", `notify=[${[
|
|
6057
6478
|
"sh",
|
|
6058
6479
|
"-c",
|
|
6059
6480
|
`[ -n "$WORK_SESSION_ID" ] && curl -sf -m 3 -X POST "http://127.0.0.1:\${WORK_APP_PORT:-${config.appPort}}/api/agent-state?session=$WORK_SESSION_ID&state=waiting&reason=done" -H 'content-type: application/json' --data "$1" >/dev/null 2>&1; exit 0`,
|
|
@@ -6070,7 +6491,7 @@ function getSession(id) {
|
|
|
6070
6491
|
return get("SELECT * FROM sessions WHERE id = ?", id);
|
|
6071
6492
|
}
|
|
6072
6493
|
function createSession(workspaceId, agent) {
|
|
6073
|
-
if (!(agent
|
|
6494
|
+
if (!isKnownAgent(agent)) throw new Error(`unknown session kind: ${agent}`);
|
|
6074
6495
|
const id = Math.random().toString(36).slice(2, 10);
|
|
6075
6496
|
db.prepare("INSERT INTO sessions (id, workspace_id, agent) VALUES (?, ?, ?)").run(id, workspaceId, agent);
|
|
6076
6497
|
notifySessionsChanged(workspaceId);
|
|
@@ -6152,7 +6573,7 @@ async function sendToSession(id, text, size) {
|
|
|
6152
6573
|
"-t",
|
|
6153
6574
|
name
|
|
6154
6575
|
], env).then(() => true, () => false)) {
|
|
6155
|
-
if (session.agent === "grok") {
|
|
6576
|
+
if (agentFamily(session.agent) === "grok") {
|
|
6156
6577
|
await tmux(newSessionArgs(session, wsPath, "-d", text, size), env);
|
|
6157
6578
|
markTmuxStarted(id);
|
|
6158
6579
|
return;
|
|
@@ -6226,7 +6647,7 @@ async function panePids() {
|
|
|
6226
6647
|
* (tmux exits when its last session closes). */
|
|
6227
6648
|
async function ensureTmuxServer() {
|
|
6228
6649
|
if (await tmux(["has-session"]).then(() => true, () => false)) return;
|
|
6229
|
-
await run("systemd-run", [
|
|
6650
|
+
await run$1("systemd-run", [
|
|
6230
6651
|
"--user",
|
|
6231
6652
|
"--unit=work-tmux",
|
|
6232
6653
|
"--service-type=forking",
|
|
@@ -6382,20 +6803,14 @@ function cleanEnv() {
|
|
|
6382
6803
|
}
|
|
6383
6804
|
var AGENT_BOOT_MS = 1500;
|
|
6384
6805
|
var PASTE_SETTLE_MS = 150;
|
|
6385
|
-
/**
|
|
6386
|
-
|
|
6387
|
-
|
|
6388
|
-
claude: ["claude"],
|
|
6389
|
-
codex: ["codex"],
|
|
6390
|
-
grok: ["grok"],
|
|
6391
|
-
copilot: ["copilot"],
|
|
6392
|
-
cursor: ["cursor-agent"]
|
|
6393
|
-
};
|
|
6394
|
-
/** Command for a session kind; `command.<agent>` in settings overrides (e.g. claude → claude1). */
|
|
6806
|
+
/** Command for a session kind: the instance's binary (`claude2`,
|
|
6807
|
+
* `cursor-agent`), nothing for `shell`; `command.<agent>` in settings still
|
|
6808
|
+
* overrides for one-off wrappers. */
|
|
6395
6809
|
function sessionCommand(agent) {
|
|
6396
6810
|
const override = getSetting(`command.${agent}`);
|
|
6397
6811
|
if (override) return override.split(/\s+/);
|
|
6398
|
-
|
|
6812
|
+
const command = agentCommand(agent);
|
|
6813
|
+
return command ? [command] : [];
|
|
6399
6814
|
}
|
|
6400
6815
|
/** tmux new-session env flags so the agent's hooks can report back which
|
|
6401
6816
|
* session they belong to. */
|
|
@@ -6414,4 +6829,4 @@ function sleep(ms) {
|
|
|
6414
6829
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
6415
6830
|
}
|
|
6416
6831
|
//#endregion
|
|
6417
|
-
export {
|
|
6832
|
+
export { get as $, subscribe as A, setPref as B, setScrapedPhase as C, pushPublicKey as D, deleteSubscription as E, disabledAgents as F, setupPath as G, doctor as H, enabledAgents as I, TOOLS as J, which as K, getSetting as L, subscriberJoins as M, agentChoices as N, saveSubscription as O, allPrefs as P, db as Q, preferredAgent as R, setAgentPhase as S, summaryFromHookPayload as T, ghKnownHosts as U, setSetting as V, miseVersions as W, toolById as X, agentById as Y, all as Z, tmuxName as _, ensureTmuxServer as a, tmux as at, clearAgentPhase as b, killWorkspaceSessions as c, newSessionArgs as d, workspacePath as et, notifySessionsChanged as f, sessionStates as g, sendToSession as h, disposeSessions as i, run$1 as it, subscriberCount as j, publish as k, listSessions as l, renameSession as m, clearTmuxStarted as n, gh as nt, getSession as o, config as ot, panePids as p, DEFAULT_GITHUB_HOST as q, createSession as r, git as rt, killSession as s, cleanEnv as t, TMUX_SOCKET as tt, markTmuxStarted as u, tmuxWasStarted as v, setSessionViewers as w, reasonFromHookPayload as x, reportsWorking as y, setDisabledAgents as z };
|