@dylanpiercey/work 0.0.223 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (521) hide show
  1. package/README.md +19 -32
  2. package/bin/work.mjs +259 -114
  3. package/dist/_D1C-XIqT.js +168 -0
  4. package/dist/{_CpANOzpd.js → _Dzz52ZtI.js} +488 -144
  5. package/dist/_HbAW5Cbt.js +2 -0
  6. package/dist/index.mjs +2634 -2786
  7. package/dist/public/assets/{_unfL8mz1.js → _-5UNb9-C.js} +1 -1
  8. package/dist/public/assets/_-5UNb9-C.js.br +0 -0
  9. package/dist/public/assets/_06rtP_SB.js +1 -0
  10. package/dist/public/assets/_14yhXek7.js +1 -0
  11. package/dist/public/assets/_14yhXek7.js.br +0 -0
  12. package/dist/public/assets/_1JXC9nFp.js +1 -0
  13. package/dist/public/assets/_1JXC9nFp.js.br +0 -0
  14. package/dist/public/assets/_1Yit_Y5R.js +1 -0
  15. package/dist/public/assets/_1ZPfR2B8.js +6 -0
  16. package/dist/public/assets/_1ZPfR2B8.js.br +0 -0
  17. package/dist/public/assets/{_BBpX-M4b.js → _1xOByopP.js} +1 -1
  18. package/dist/public/assets/_1xOByopP.js.br +0 -0
  19. package/dist/public/assets/{_BLTfQLdY.js → _3aBl7SEn.js} +1 -1
  20. package/dist/public/assets/_3aBl7SEn.js.br +0 -0
  21. package/dist/public/assets/_5aMLV2Vy.js +1 -0
  22. package/dist/public/assets/{_CX1wufuh.js → _7YrArFMB.js} +1 -1
  23. package/dist/public/assets/_7YrArFMB.js.br +0 -0
  24. package/dist/public/assets/{_mnBdD4YN.js → _B1-W0Sn2.js} +1 -1
  25. package/dist/public/assets/_B1-W0Sn2.js.br +0 -0
  26. package/dist/public/assets/{_BL9QMk_P.js → _B1D0PIz3.js} +1 -1
  27. package/dist/public/assets/_B1D0PIz3.js.br +0 -0
  28. package/dist/public/assets/_B1agoKUa.js +1 -0
  29. package/dist/public/assets/_B3NfNm8M.js +1591 -0
  30. package/dist/public/assets/_B3NfNm8M.js.br +0 -0
  31. package/dist/public/assets/{_DeCJ44Me.js → _B7VYILLZ.js} +1 -1
  32. package/dist/public/assets/_B7VYILLZ.js.br +0 -0
  33. package/dist/public/assets/_B7sPBy0J.js +1 -0
  34. package/dist/public/assets/_B81p6DSw.js +1 -0
  35. package/dist/public/assets/_BAkSKCkz.js +1 -0
  36. package/dist/public/assets/{_BUH04L5e.js → _BDUjU8Ev.js} +1 -1
  37. package/dist/public/assets/{_C6i9NP5A.js → _BHU5aikZ.js} +1 -1
  38. package/dist/public/assets/_BHZPTv1U.js +1 -0
  39. package/dist/public/assets/{_CttJbiei.js → _BKHtiW96.js} +1 -1
  40. package/dist/public/assets/_BKHtiW96.js.br +0 -0
  41. package/dist/public/assets/{_IWMmnVCy.js → _BKIx7IZP.js} +1 -1
  42. package/dist/public/assets/_BKIx7IZP.js.br +0 -0
  43. package/dist/public/assets/{_BCZpExov.js → _BLfzQY-3.js} +1 -1
  44. package/dist/public/assets/_BLfzQY-3.js.br +0 -0
  45. package/dist/public/assets/{_DhNuRs-V.js → _BPSTqkJn.js} +1 -1
  46. package/dist/public/assets/_BPSTqkJn.js.br +0 -0
  47. package/dist/public/assets/_BQZOimBB.js +1 -0
  48. package/dist/public/assets/{_vKQopDwG.js → _BRQ6iQ5p.js} +1 -1
  49. package/dist/public/assets/_BRQ6iQ5p.js.br +0 -0
  50. package/dist/public/assets/_BRVURc4u.js +1 -0
  51. package/dist/public/assets/{_eQK3EZCc.js → _BSFJEuJX.js} +1 -1
  52. package/dist/public/assets/_BSFJEuJX.js.br +0 -0
  53. package/dist/public/assets/{_B1RldJ0S.js → _BSWN-v3P.js} +1 -1
  54. package/dist/public/assets/_BSWN-v3P.js.br +0 -0
  55. package/dist/public/assets/_BTVAQr2c.js +1 -0
  56. package/dist/public/assets/_BUD1pBC0.js +1 -0
  57. package/dist/public/assets/_BVGzCczb.js +1 -0
  58. package/dist/public/assets/{_C1PmcEws.js → _BVQosHjY.js} +1 -1
  59. package/dist/public/assets/_BVQosHjY.js.br +0 -0
  60. package/dist/public/assets/{_DlpTErRA.js → _B_0C2_RO.js} +1 -1
  61. package/dist/public/assets/_B_0C2_RO.js.br +0 -0
  62. package/dist/public/assets/_BaA31ms5.js +1 -0
  63. package/dist/public/assets/_BgCHJGlO.js +1 -0
  64. package/dist/public/assets/_BhpRLDbL.js +1 -0
  65. package/dist/public/assets/_BhpRLDbL.js.br +0 -0
  66. package/dist/public/assets/_BkKcjMAC.js +1 -0
  67. package/dist/public/assets/{_BsimXDnm.js → _BkcPY2j0.js} +1 -1
  68. package/dist/public/assets/_BkcPY2j0.js.br +0 -0
  69. package/dist/public/assets/_BlTVd_3d.js +1 -0
  70. package/dist/public/assets/_BlqlLmEY.js +1 -0
  71. package/dist/public/assets/_BoNfxc9P.js +1 -0
  72. package/dist/public/assets/_BqswW9B9.js +1 -0
  73. package/dist/public/assets/_BricqzsO.js +1 -0
  74. package/dist/public/assets/_BrreckIa.js +1 -0
  75. package/dist/public/assets/{_CGLpCj_I.js → _BsJZPHmz.js} +1 -1
  76. package/dist/public/assets/_BsJZPHmz.js.br +0 -0
  77. package/dist/public/assets/_BtRYwaBb.js +1 -0
  78. package/dist/public/assets/{_CT3clsOQ.js → _BtZ2AatF.js} +1 -1
  79. package/dist/public/assets/_BvPBKjRP.js +1 -0
  80. package/dist/public/assets/_BvPBKjRP.js.br +0 -0
  81. package/dist/public/assets/_ByrrjMU9.js +1 -0
  82. package/dist/public/assets/{_s5Jez2mu.js → _BzGHediB.js} +1 -1
  83. package/dist/public/assets/_BzGHediB.js.br +0 -0
  84. package/dist/public/assets/_BzvTKm92.js +1 -0
  85. package/dist/public/assets/{_CnKYioYw.js → _C-EkQeP_.js} +1 -1
  86. package/dist/public/assets/_C-EkQeP_.js.br +0 -0
  87. package/dist/public/assets/{_BAHrOydH.js → _C0Ib7MZF.js} +1 -1
  88. package/dist/public/assets/_C0Ib7MZF.js.br +0 -0
  89. package/dist/public/assets/_C2p1Z5Lf.js +86 -0
  90. package/dist/public/assets/_C2p1Z5Lf.js.br +0 -0
  91. package/dist/public/assets/_C3iiOlxd.js +1 -0
  92. package/dist/public/assets/{_BdvO5Lqa.js → _C81nSl09.js} +1 -1
  93. package/dist/public/assets/_C81nSl09.js.br +0 -0
  94. package/dist/public/assets/{_BXT2bXMi.js → _C8bqYk4J.js} +1 -1
  95. package/dist/public/assets/_C8bqYk4J.js.br +0 -0
  96. package/dist/public/assets/_C98JZr09.js +1 -0
  97. package/dist/public/assets/_C98JZr09.js.br +0 -0
  98. package/dist/public/assets/_CB4VkmGZ.js +1 -0
  99. package/dist/public/assets/{_pUYwxsdF.js → _CCVkYcN5.js} +1 -1
  100. package/dist/public/assets/_CCVkYcN5.js.br +0 -0
  101. package/dist/public/assets/{_D-hK5uFn.js → _CDY0RpYX.js} +1 -1
  102. package/dist/public/assets/_CDY0RpYX.js.br +0 -0
  103. package/dist/public/assets/_CE2GEqMx.js +1 -0
  104. package/dist/public/assets/_CE2GEqMx.js.br +0 -0
  105. package/dist/public/assets/{_BeE9qDu0.js → _CFUREq1M.js} +1 -1
  106. package/dist/public/assets/_CFUREq1M.js.br +0 -0
  107. package/dist/public/assets/_CHdh6bII.js +1 -0
  108. package/dist/public/assets/{_CB31bp-W.js → _CHdpLB95.js} +1 -1
  109. package/dist/public/assets/_CHdpLB95.js.br +0 -0
  110. package/dist/public/assets/{_Fzbz4zvE.js → _CKLGAGKJ.js} +1 -1
  111. package/dist/public/assets/_CKLGAGKJ.js.br +0 -0
  112. package/dist/public/assets/_CMRt2lyQ.js +1 -0
  113. package/dist/public/assets/_CN1zW1AT.js +1 -0
  114. package/dist/public/assets/_CN1zW1AT.js.br +0 -0
  115. package/dist/public/assets/_CUILmj9R.js +1 -0
  116. package/dist/public/assets/_CUhP8KQ8.js +1 -0
  117. package/dist/public/assets/{_zKlxcAnQ.js → _CUsrMpdL.js} +1 -1
  118. package/dist/public/assets/_CUsrMpdL.js.br +0 -0
  119. package/dist/public/assets/_CVG0_w9T.js +1 -0
  120. package/dist/public/assets/{_CCCQMLw5.js → _CWG813ur.js} +1 -1
  121. package/dist/public/assets/_CWG813ur.js.br +0 -0
  122. package/dist/public/assets/{_C9OdJcx4.js → _CY87Y7QL.js} +1 -1
  123. package/dist/public/assets/_CY87Y7QL.js.br +0 -0
  124. package/dist/public/assets/_CYAsKva_.js +1 -0
  125. package/dist/public/assets/_CajKYNSY.js +1 -0
  126. package/dist/public/assets/{_gPFPzzPF.js → _Cb_k_JA_.js} +1 -1
  127. package/dist/public/assets/_Cb_k_JA_.js.br +0 -0
  128. package/dist/public/assets/_Ce8PlfMD.js +1 -0
  129. package/dist/public/assets/{_O70J1Mfv.js → _CfGEGt_k.js} +1 -1
  130. package/dist/public/assets/_CfGEGt_k.js.br +0 -0
  131. package/dist/public/assets/{_BLRpf6Uw.js → _CfdK8EeQ.js} +1 -1
  132. package/dist/public/assets/_CfdK8EeQ.js.br +0 -0
  133. package/dist/public/assets/_CgOKmAwr.js +1 -0
  134. package/dist/public/assets/{_C2ZpyiHV.js → _CiYQhf81.js} +1 -1
  135. package/dist/public/assets/_CiYQhf81.js.br +0 -0
  136. package/dist/public/assets/_Cj9DHPRL.js +1 -0
  137. package/dist/public/assets/{_BS4crAAm.js → _ClHPjF-1.js} +1 -1
  138. package/dist/public/assets/_ClHPjF-1.js.br +0 -0
  139. package/dist/public/assets/{_DmDSLxrw.js → _Cmmdd2e3.js} +1 -1
  140. package/dist/public/assets/_Cmmdd2e3.js.br +0 -0
  141. package/dist/public/assets/{_BsupnkWM.js → _Cn9Ia4SS.js} +1 -1
  142. package/dist/public/assets/_Cn9Ia4SS.js.br +0 -0
  143. package/dist/public/assets/_CnTzFbuG.js +1 -0
  144. package/dist/public/assets/{_DJ3UAR_s.js → _CqCenHOp.js} +1 -1
  145. package/dist/public/assets/_CqCenHOp.js.br +0 -0
  146. package/dist/public/assets/{_BRG_DBcC.js → _CtqGSS84.js} +1 -1
  147. package/dist/public/assets/_CtqGSS84.js.br +0 -0
  148. package/dist/public/assets/_CttfwM-c.js +1 -0
  149. package/dist/public/assets/{_DuXOUegE.js → _CxA3Yab0.js} +1 -1
  150. package/dist/public/assets/_CxA3Yab0.js.br +0 -0
  151. package/dist/public/assets/{_ifUb4WX7.js → _Cx_aJfDp.js} +1 -1
  152. package/dist/public/assets/_Cx_aJfDp.js.br +0 -0
  153. package/dist/public/assets/_D2L_ILOW.js +1 -0
  154. package/dist/public/assets/_D47lCu0c.js +1 -0
  155. package/dist/public/assets/_D5W-uGIK.js +1 -0
  156. package/dist/public/assets/_D6BbZLrc.js +1 -0
  157. package/dist/public/assets/_D6RVeCAn.js +1 -0
  158. package/dist/public/assets/_D75V4jV-.js +1 -0
  159. package/dist/public/assets/{_CwmzEsB4.js → _D9r_Fn0I.js} +1 -1
  160. package/dist/public/assets/_D9r_Fn0I.js.br +0 -0
  161. package/dist/public/assets/{_DoCtdMd2.js → _DBD57l1T.js} +1 -1
  162. package/dist/public/assets/_DBD57l1T.js.br +0 -0
  163. package/dist/public/assets/_DCWILZgL.js +1 -0
  164. package/dist/public/assets/{_DI0QHEXB.js → _DEOryr7w.js} +1 -1
  165. package/dist/public/assets/_DEOryr7w.js.br +0 -0
  166. package/dist/public/assets/_DF54Iz7o.js +1 -0
  167. package/dist/public/assets/_DFamU2Uj.js +2 -0
  168. package/dist/public/assets/_DFamU2Uj.js.br +0 -0
  169. package/dist/public/assets/_DHmBuyCO.js +1 -0
  170. package/dist/public/assets/_DHmBuyCO.js.br +0 -0
  171. package/dist/public/assets/{_BPcswKMK.js → _DJqEBkNd.js} +1 -1
  172. package/dist/public/assets/_DJqEBkNd.js.br +0 -0
  173. package/dist/public/assets/{_B_zyAtSJ.js → _DL3w8c_p.js} +1 -1
  174. package/dist/public/assets/_DL3w8c_p.js.br +0 -0
  175. package/dist/public/assets/_DLVL-4MP.js +1 -0
  176. package/dist/public/assets/{_BewXp5Y_.js → _DM60dKRs.js} +1 -1
  177. package/dist/public/assets/_DM60dKRs.js.br +0 -0
  178. package/dist/public/assets/{_BVp6r0fg.js → _DMJHTH74.js} +1 -1
  179. package/dist/public/assets/_DMJHTH74.js.br +0 -0
  180. package/dist/public/assets/_DMLv6KA6.js +1 -0
  181. package/dist/public/assets/_DQYpgyzr.js +1 -0
  182. package/dist/public/assets/_DQYpgyzr.js.br +0 -0
  183. package/dist/public/assets/{_BbiACo0Y.js → _DQyjuXTi.js} +1 -1
  184. package/dist/public/assets/_DQyjuXTi.js.br +0 -0
  185. package/dist/public/assets/{_C87NBm9i.js → _DRHCy0UF.js} +1 -1
  186. package/dist/public/assets/_DRHCy0UF.js.br +0 -0
  187. package/dist/public/assets/{_pvS44-AC.js → _DSUBv-Bl.js} +1 -1
  188. package/dist/public/assets/_DSUBv-Bl.js.br +0 -0
  189. package/dist/public/assets/{_BA8HFnO3.js → _DUFM9qLV.js} +1 -1
  190. package/dist/public/assets/_DUFM9qLV.js.br +0 -0
  191. package/dist/public/assets/{_D8u1YU9b.js → _DUs3ZGbj.js} +1 -1
  192. package/dist/public/assets/_DUs3ZGbj.js.br +0 -0
  193. package/dist/public/assets/{_CdgAsi3s.js → _DX5u6Wvm.js} +1 -1
  194. package/dist/public/assets/_DX5u6Wvm.js.br +0 -0
  195. package/dist/public/assets/{_BnyLUTdO.js → _DZvkgS3V.js} +1 -1
  196. package/dist/public/assets/_DZvkgS3V.js.br +0 -0
  197. package/dist/public/assets/{_CE5MhJWL.js → _Dbm6zAQS.js} +1 -1
  198. package/dist/public/assets/_Dbm6zAQS.js.br +0 -0
  199. package/dist/public/assets/{_DzrtBP-L.js → _DcOkTFth.js} +1 -1
  200. package/dist/public/assets/_Ddf1gumD.js +1 -0
  201. package/dist/public/assets/_De6E9M7R.js +1 -0
  202. package/dist/public/assets/{_C-6dImS5.js → _DgWKSW-Y.js} +1 -1
  203. package/dist/public/assets/_DgWKSW-Y.js.br +0 -0
  204. package/dist/public/assets/_DhEN6T4v.js +1 -0
  205. package/dist/public/assets/{_BxAl0m64.js → _Di1ccq_2.js} +1 -1
  206. package/dist/public/assets/_Di1ccq_2.js.br +0 -0
  207. package/dist/public/assets/{_CLerZOx-.js → _DifjKObE.js} +1 -1
  208. package/dist/public/assets/_DifjKObE.js.br +0 -0
  209. package/dist/public/assets/_Dn10ABa-.js +1 -0
  210. package/dist/public/assets/{_DuGmU4h0.js → _Do1ltY2a.js} +1 -1
  211. package/dist/public/assets/_Do1ltY2a.js.br +0 -0
  212. package/dist/public/assets/{_DeN4EY8L.js → _DomK7Scb.js} +1 -1
  213. package/dist/public/assets/_DomK7Scb.js.br +0 -0
  214. package/dist/public/assets/_DtWggCxt.js +1 -0
  215. package/dist/public/assets/_DtqqybyQ.js +1 -0
  216. package/dist/public/assets/{_CJ9j8N5Z.js → _DvKnakqk.js} +1 -1
  217. package/dist/public/assets/_DvKnakqk.js.br +0 -0
  218. package/dist/public/assets/_DxD_AC3a.js +1 -0
  219. package/dist/public/assets/_DxD_AC3a.js.br +0 -0
  220. package/dist/public/assets/_Dxo7m9cG.js +1 -0
  221. package/dist/public/assets/{_DhEdzMUw.js → _DzKW89Sx.js} +1 -1
  222. package/dist/public/assets/_DzKW89Sx.js.br +0 -0
  223. package/dist/public/assets/_DzTHCioH.js +1 -0
  224. package/dist/public/assets/{_CtyJUmXC.js → _EefWj858.js} +1 -1
  225. package/dist/public/assets/_EefWj858.js.br +0 -0
  226. package/dist/public/assets/{_Aq9oGnRu.js → _FlITqTCo.js} +1 -1
  227. package/dist/public/assets/_FlITqTCo.js.br +0 -0
  228. package/dist/public/assets/_GkEw2S0T.js +1 -0
  229. package/dist/public/assets/{__Oa255vo.js → _HM_QqtJi.js} +1 -1
  230. package/dist/public/assets/_HM_QqtJi.js.br +0 -0
  231. package/dist/public/assets/{_DuarImb7.js → _HmkI4Rfn.js} +1 -1
  232. package/dist/public/assets/_HmkI4Rfn.js.br +0 -0
  233. package/dist/public/assets/{_DaqT6m41.js → _JEvx8ub4.js} +1 -1
  234. package/dist/public/assets/_JEvx8ub4.js.br +0 -0
  235. package/dist/public/assets/_JOb8B3tz.js +1 -0
  236. package/dist/public/assets/_LEIhjFrO.js +1 -0
  237. package/dist/public/assets/_STJhwy7U.js +1 -0
  238. package/dist/public/assets/_TrcWRD8T.js +15 -0
  239. package/dist/public/assets/_TrcWRD8T.js.br +0 -0
  240. package/dist/public/assets/{_BO0OB-rz.js → _UaKPY71M.js} +1 -1
  241. package/dist/public/assets/_UaKPY71M.js.br +0 -0
  242. package/dist/public/assets/_UhK3lkm0.js +1 -0
  243. package/dist/public/assets/_VPLoEBTS.js +1 -0
  244. package/dist/public/assets/_Zeftz3t1.js +1 -0
  245. package/dist/public/assets/{_pP1W6w5v.js → __cyRVmTO.js} +1 -1
  246. package/dist/public/assets/__cyRVmTO.js.br +0 -0
  247. package/dist/public/assets/_awfYTHit.js +1 -0
  248. package/dist/public/assets/{_DiqV5bDH.js → _dsj7vMTW.js} +1 -1
  249. package/dist/public/assets/_dsj7vMTW.js.br +0 -0
  250. package/dist/public/assets/_eqpiOhSM.js +1 -0
  251. package/dist/public/assets/{_dr95P55a.js → _iutZ4EDe.js} +1 -1
  252. package/dist/public/assets/_iutZ4EDe.js.br +0 -0
  253. package/dist/public/assets/{_CZGS4T08.js → _kWQ0dtYZ.js} +1 -1
  254. package/dist/public/assets/_kWQ0dtYZ.js.br +0 -0
  255. package/dist/public/assets/_knvMqXQh.js +1 -0
  256. package/dist/public/assets/_lwC7sIgC.js +1 -0
  257. package/dist/public/assets/_m2tRa0jk.js +1 -0
  258. package/dist/public/assets/_m2tRa0jk.js.br +0 -0
  259. package/dist/public/assets/{_DwcoW-IU.js → _pXG8fRON.js} +1 -1
  260. package/dist/public/assets/_pXG8fRON.js.br +0 -0
  261. package/dist/public/assets/_r541ENtr.js +1 -0
  262. package/dist/public/assets/_rrUx1wn3.js +1 -0
  263. package/dist/public/assets/_tJvcu7sD.js +1 -0
  264. package/dist/public/assets/{_Cw_8WbwF.js → _vcLBrU2m.js} +1 -1
  265. package/dist/public/assets/_vcLBrU2m.js.br +0 -0
  266. package/dist/public/assets/_xZC4Vm70.js +1 -0
  267. package/dist/public/assets/_yAr5r-uL.js +1 -0
  268. package/dist/public/assets/{_DGTQBWy0.js → _yUmRJIJ6.js} +1 -1
  269. package/dist/public/assets/_yUmRJIJ6.js.br +0 -0
  270. package/dist/public/assets/app-shell-CVYlktwa.css +1 -0
  271. package/dist/public/assets/app-shell-CVYlktwa.css.br +0 -0
  272. package/dist/public/assets/files-view-CTadakLK.js +2 -0
  273. package/dist/public/assets/manage-workspace-HUAS6qjy.js +2 -0
  274. package/dist/public/assets/new-CirJkJFl.js +1 -0
  275. package/dist/public/assets/new-workspace-C3t1nA6z.js +2 -0
  276. package/dist/public/assets/review-view-DKPNtgmc.js +2 -0
  277. package/dist/public/assets/settings-CirJkJFl.js +1 -0
  278. package/dist/public/assets/settings-page-DH-9cN-8.js +2 -0
  279. package/dist/public/assets/styles-CIeNhVxC.css +1 -0
  280. package/dist/public/assets/styles-CIeNhVxC.css.br +0 -0
  281. package/dist/public/assets/w-CirJkJFl.js +1 -0
  282. package/dist/public/assets/w._-BnShhzdq.js +1 -0
  283. package/dist/public/assets/w._-CirJkJFl.js +1 -0
  284. package/dist/public/assets/w._-aCTYfruH.js +1 -0
  285. package/lib/review/markdown.mjs +5 -5
  286. package/lib/setup/bridge.d.mts +10 -0
  287. package/lib/setup/bridge.mjs +84 -0
  288. package/lib/setup/doctor.d.mts +17 -1
  289. package/lib/setup/doctor.mjs +97 -8
  290. package/lib/setup/install.d.mts +1 -0
  291. package/lib/setup/install.mjs +21 -1
  292. package/lib/setup/listen.mjs +2 -2
  293. package/lib/setup/tailscale.d.mts +53 -0
  294. package/lib/setup/tailscale.mjs +179 -0
  295. package/lib/share/manifest.mjs +2 -1
  296. package/package.json +2 -3
  297. package/dist/_LF2Fo5WE.js +0 -2
  298. package/dist/public/assets/_--tE4Gxz.js +0 -2
  299. package/dist/public/assets/_--tE4Gxz.js.br +0 -0
  300. package/dist/public/assets/_1OL9vXM-.js +0 -1
  301. package/dist/public/assets/_2mnAZf6B.js +0 -1
  302. package/dist/public/assets/_2mnAZf6B.js.br +0 -0
  303. package/dist/public/assets/_5f9fMvWJ.js +0 -1
  304. package/dist/public/assets/_5y69OR6M.js +0 -1
  305. package/dist/public/assets/_Aq9oGnRu.js.br +0 -0
  306. package/dist/public/assets/_B0uJCjmk.js +0 -1
  307. package/dist/public/assets/_B1RldJ0S.js.br +0 -0
  308. package/dist/public/assets/_B5TpOQCZ.js +0 -1
  309. package/dist/public/assets/_B6UdulKa.js +0 -1
  310. package/dist/public/assets/_BA8HFnO3.js.br +0 -0
  311. package/dist/public/assets/_BAHrOydH.js.br +0 -0
  312. package/dist/public/assets/_BBpX-M4b.js.br +0 -0
  313. package/dist/public/assets/_BCZpExov.js.br +0 -0
  314. package/dist/public/assets/_BFZHNauV.js +0 -1
  315. package/dist/public/assets/_BJRSndB4.js +0 -6
  316. package/dist/public/assets/_BJRSndB4.js.br +0 -0
  317. package/dist/public/assets/_BL9QMk_P.js.br +0 -0
  318. package/dist/public/assets/_BLNEzyb5.js +0 -1
  319. package/dist/public/assets/_BLRpf6Uw.js.br +0 -0
  320. package/dist/public/assets/_BLTfQLdY.js.br +0 -0
  321. package/dist/public/assets/_BO0OB-rz.js.br +0 -0
  322. package/dist/public/assets/_BPcswKMK.js.br +0 -0
  323. package/dist/public/assets/_BPhXWliU.js +0 -1
  324. package/dist/public/assets/_BQXTv9Cr.js +0 -1
  325. package/dist/public/assets/_BRG_DBcC.js.br +0 -0
  326. package/dist/public/assets/_BS4crAAm.js.br +0 -0
  327. package/dist/public/assets/_BVp6r0fg.js.br +0 -0
  328. package/dist/public/assets/_BXT2bXMi.js.br +0 -0
  329. package/dist/public/assets/_B_zyAtSJ.js.br +0 -0
  330. package/dist/public/assets/_BaXKdIeb.js +0 -1
  331. package/dist/public/assets/_BbiACo0Y.js.br +0 -0
  332. package/dist/public/assets/_BdvO5Lqa.js.br +0 -0
  333. package/dist/public/assets/_BeE9qDu0.js.br +0 -0
  334. package/dist/public/assets/_BewXp5Y_.js.br +0 -0
  335. package/dist/public/assets/_BfOOLKo5.js +0 -1
  336. package/dist/public/assets/_BhS8bTnr.js +0 -1
  337. package/dist/public/assets/_BhZ3ZoG0.js +0 -1
  338. package/dist/public/assets/_Bi3_ZsOQ.js +0 -1
  339. package/dist/public/assets/_Bj_Lfa8B.js +0 -1
  340. package/dist/public/assets/_BlN_x04q.js +0 -1
  341. package/dist/public/assets/_Bn5nsnie.js +0 -1
  342. package/dist/public/assets/_BnOOD6nr.js +0 -15
  343. package/dist/public/assets/_BnOOD6nr.js.br +0 -0
  344. package/dist/public/assets/_BnyLUTdO.js.br +0 -0
  345. package/dist/public/assets/_Bp_WT09q.js +0 -1
  346. package/dist/public/assets/_Bp_WT09q.js.br +0 -0
  347. package/dist/public/assets/_BsimXDnm.js.br +0 -0
  348. package/dist/public/assets/_BsupnkWM.js.br +0 -0
  349. package/dist/public/assets/_BxAl0m64.js.br +0 -0
  350. package/dist/public/assets/_C-6dImS5.js.br +0 -0
  351. package/dist/public/assets/_C18Torhh.js +0 -1
  352. package/dist/public/assets/_C1PmcEws.js.br +0 -0
  353. package/dist/public/assets/_C2ZpyiHV.js.br +0 -0
  354. package/dist/public/assets/_C3P1VHUI.js +0 -1
  355. package/dist/public/assets/_C6xwTKke.js +0 -1
  356. package/dist/public/assets/_C6yqlRfl.js +0 -1
  357. package/dist/public/assets/_C75D8bH2.js +0 -1
  358. package/dist/public/assets/_C87NBm9i.js.br +0 -0
  359. package/dist/public/assets/_C8Vc_vBH.js +0 -1
  360. package/dist/public/assets/_C9OdJcx4.js.br +0 -0
  361. package/dist/public/assets/_C9eoo0sE.js +0 -1
  362. package/dist/public/assets/_C9qO_dny.js +0 -1
  363. package/dist/public/assets/_C9qO_dny.js.br +0 -0
  364. package/dist/public/assets/_CB31bp-W.js.br +0 -0
  365. package/dist/public/assets/_CCCQMLw5.js.br +0 -0
  366. package/dist/public/assets/_CCie36pi.js +0 -1
  367. package/dist/public/assets/_CDD9N34p.js +0 -1
  368. package/dist/public/assets/_CE5MhJWL.js.br +0 -0
  369. package/dist/public/assets/_CGLpCj_I.js.br +0 -0
  370. package/dist/public/assets/_CJ9j8N5Z.js.br +0 -0
  371. package/dist/public/assets/_CLDmR3jR.js +0 -1
  372. package/dist/public/assets/_CLDmR3jR.js.br +0 -0
  373. package/dist/public/assets/_CLerZOx-.js.br +0 -0
  374. package/dist/public/assets/_CM5GtJb2.js +0 -1
  375. package/dist/public/assets/_COECwOVb.js +0 -1
  376. package/dist/public/assets/_CSQE9nMN.js +0 -1
  377. package/dist/public/assets/_CSXMgHLQ.js +0 -1
  378. package/dist/public/assets/_CVRiByCT.js +0 -1
  379. package/dist/public/assets/_CVSrm4Pl.js +0 -1
  380. package/dist/public/assets/_CX1wufuh.js.br +0 -0
  381. package/dist/public/assets/_CYNAhnRH.js +0 -1591
  382. package/dist/public/assets/_CYNAhnRH.js.br +0 -0
  383. package/dist/public/assets/_CZGS4T08.js.br +0 -0
  384. package/dist/public/assets/_C_L7l9Mg.js +0 -1
  385. package/dist/public/assets/_CaMrYy1W.js +0 -1
  386. package/dist/public/assets/_CdgAsi3s.js.br +0 -0
  387. package/dist/public/assets/_Ce-E7sJE.js +0 -1
  388. package/dist/public/assets/_Cg3S760D.js +0 -1
  389. package/dist/public/assets/_ChpYg41R.js +0 -1
  390. package/dist/public/assets/_CicyY7KP.js +0 -1
  391. package/dist/public/assets/_Ck0YOw_7.js +0 -1
  392. package/dist/public/assets/_CmHlTZSs.js +0 -1
  393. package/dist/public/assets/_CnECYh66.js +0 -1
  394. package/dist/public/assets/_CnKYioYw.js.br +0 -0
  395. package/dist/public/assets/_CnUVvVPd.js +0 -1
  396. package/dist/public/assets/_CqSgGCGC.js +0 -1
  397. package/dist/public/assets/_CttJbiei.js.br +0 -0
  398. package/dist/public/assets/_CtyJUmXC.js.br +0 -0
  399. package/dist/public/assets/_Cw_8WbwF.js.br +0 -0
  400. package/dist/public/assets/_CwmzEsB4.js.br +0 -0
  401. package/dist/public/assets/_CzETFsJs.js +0 -1
  402. package/dist/public/assets/_D-S9H-tX.js +0 -1
  403. package/dist/public/assets/_D-hK5uFn.js.br +0 -0
  404. package/dist/public/assets/_D5fTwHXK.js +0 -1
  405. package/dist/public/assets/_D8u1YU9b.js.br +0 -0
  406. package/dist/public/assets/_DAH8evhA.js +0 -1
  407. package/dist/public/assets/_DAemmoHI.js +0 -1
  408. package/dist/public/assets/_DEMYxWZf.js +0 -1
  409. package/dist/public/assets/_DGTQBWy0.js.br +0 -0
  410. package/dist/public/assets/_DHhv0pCA.js +0 -1
  411. package/dist/public/assets/_DI0QHEXB.js.br +0 -0
  412. package/dist/public/assets/_DJ3UAR_s.js.br +0 -0
  413. package/dist/public/assets/_DKu6UxI7.js +0 -1
  414. package/dist/public/assets/_DNC-9RBN.js +0 -1
  415. package/dist/public/assets/_DP-Bu7ET.js +0 -1
  416. package/dist/public/assets/_DYmmPBcq.js +0 -1
  417. package/dist/public/assets/_Da2Dmt_d.js +0 -1
  418. package/dist/public/assets/_Da2Dmt_d.js.br +0 -0
  419. package/dist/public/assets/_DaqT6m41.js.br +0 -0
  420. package/dist/public/assets/_DbVyutEZ.js +0 -1
  421. package/dist/public/assets/_DcBvO2Si.js +0 -1
  422. package/dist/public/assets/_DeCJ44Me.js.br +0 -0
  423. package/dist/public/assets/_DeN4EY8L.js.br +0 -0
  424. package/dist/public/assets/_DhEdzMUw.js.br +0 -0
  425. package/dist/public/assets/_DhNuRs-V.js.br +0 -0
  426. package/dist/public/assets/_DiqV5bDH.js.br +0 -0
  427. package/dist/public/assets/_Diqt_yCf.js +0 -1
  428. package/dist/public/assets/_DlpTErRA.js.br +0 -0
  429. package/dist/public/assets/_DmDSLxrw.js.br +0 -0
  430. package/dist/public/assets/_DoC0qbSD.js +0 -1
  431. package/dist/public/assets/_DoCtdMd2.js.br +0 -0
  432. package/dist/public/assets/_DpqWFkMg.js +0 -1
  433. package/dist/public/assets/_Dr0Bkgso.js +0 -1
  434. package/dist/public/assets/_Dt-n9FaQ.js +0 -1
  435. package/dist/public/assets/_DtOzdwHm.js +0 -1
  436. package/dist/public/assets/_DtOzdwHm.js.br +0 -0
  437. package/dist/public/assets/_DuGmU4h0.js.br +0 -0
  438. package/dist/public/assets/_DuXOUegE.js.br +0 -0
  439. package/dist/public/assets/_DuaocJd1.js +0 -1
  440. package/dist/public/assets/_DuarImb7.js.br +0 -0
  441. package/dist/public/assets/_DwcoW-IU.js.br +0 -0
  442. package/dist/public/assets/_DxVt7Zuk.js +0 -86
  443. package/dist/public/assets/_DxVt7Zuk.js.br +0 -0
  444. package/dist/public/assets/_Fzbz4zvE.js.br +0 -0
  445. package/dist/public/assets/_I5oX-lGP.js +0 -1
  446. package/dist/public/assets/_IWMmnVCy.js.br +0 -0
  447. package/dist/public/assets/_O70J1Mfv.js.br +0 -0
  448. package/dist/public/assets/_SwbsOoi9.js +0 -1
  449. package/dist/public/assets/_SwbsOoi9.js.br +0 -0
  450. package/dist/public/assets/_Yy39CykK.js +0 -1
  451. package/dist/public/assets/__Oa255vo.js.br +0 -0
  452. package/dist/public/assets/_bPze7k1x.js +0 -1
  453. package/dist/public/assets/_bU1KcT1I.js +0 -1
  454. package/dist/public/assets/_dr95P55a.js.br +0 -0
  455. package/dist/public/assets/_eQK3EZCc.js.br +0 -0
  456. package/dist/public/assets/_gPFPzzPF.js.br +0 -0
  457. package/dist/public/assets/_hzpOPZUB.js +0 -1
  458. package/dist/public/assets/_ifUb4WX7.js.br +0 -0
  459. package/dist/public/assets/_kQ7LiSim.js +0 -1
  460. package/dist/public/assets/_lOAW1VLM.js +0 -1
  461. package/dist/public/assets/_mnBdD4YN.js.br +0 -0
  462. package/dist/public/assets/_odBcV1kc.js +0 -1
  463. package/dist/public/assets/_pP1W6w5v.js.br +0 -0
  464. package/dist/public/assets/_pUYwxsdF.js.br +0 -0
  465. package/dist/public/assets/_pvS44-AC.js.br +0 -0
  466. package/dist/public/assets/_qJTL2ooe.js +0 -1
  467. package/dist/public/assets/_qJTL2ooe.js.br +0 -0
  468. package/dist/public/assets/_s5Jez2mu.js.br +0 -0
  469. package/dist/public/assets/_unfL8mz1.js.br +0 -0
  470. package/dist/public/assets/_unwtcXFQ.js +0 -1
  471. package/dist/public/assets/_unwtcXFQ.js.br +0 -0
  472. package/dist/public/assets/_vKQopDwG.js.br +0 -0
  473. package/dist/public/assets/_w1aegGdT.js +0 -1
  474. package/dist/public/assets/_xdrkfok5.js +0 -1
  475. package/dist/public/assets/_xdrkfok5.js.br +0 -0
  476. package/dist/public/assets/_y-lm36fI.js +0 -1
  477. package/dist/public/assets/_zKlxcAnQ.js.br +0 -0
  478. package/dist/public/assets/app-shell-CpPCwWPW.css +0 -1
  479. package/dist/public/assets/app-shell-CpPCwWPW.css.br +0 -0
  480. package/dist/public/assets/files-view-BfCdcfXX.js +0 -2
  481. package/dist/public/assets/files-view-DtI7JE-f.css +0 -1
  482. package/dist/public/assets/files-view-DtI7JE-f.css.br +0 -0
  483. package/dist/public/assets/group.css.ts-SeaNz7WZ.css +0 -1
  484. package/dist/public/assets/group.css.ts-SeaNz7WZ.css.br +0 -0
  485. package/dist/public/assets/icon-folder-DHVc-REl.css +0 -1
  486. package/dist/public/assets/icon-folder-DHVc-REl.css.br +0 -0
  487. package/dist/public/assets/icon-search-DAtjHWFL.css +0 -1
  488. package/dist/public/assets/icon-search-DAtjHWFL.css.br +0 -0
  489. package/dist/public/assets/manage-workspace-6i6Zeai7.css +0 -1
  490. package/dist/public/assets/manage-workspace-CixeMkdt.js +0 -2
  491. package/dist/public/assets/modal-view-D0qnmuJE.css +0 -1
  492. package/dist/public/assets/modal-view-D0qnmuJE.css.br +0 -0
  493. package/dist/public/assets/new-DxhaKmbF.js +0 -1
  494. package/dist/public/assets/new-workspace-BXjDRbqF.css +0 -1
  495. package/dist/public/assets/new-workspace-BXjDRbqF.css.br +0 -0
  496. package/dist/public/assets/new-workspace-DG693v2S.js +0 -2
  497. package/dist/public/assets/port-chip-Lz3mVJWb.css +0 -1
  498. package/dist/public/assets/port-chip-Lz3mVJWb.css.br +0 -0
  499. package/dist/public/assets/prompt-dialog-vhnae1-x.css +0 -1
  500. package/dist/public/assets/prompt-dialog-vhnae1-x.css.br +0 -0
  501. package/dist/public/assets/quick-open-DVqzk3-g.css +0 -1
  502. package/dist/public/assets/quick-open-DVqzk3-g.css.br +0 -0
  503. package/dist/public/assets/repo-picker-K5RYsEge.css +0 -1
  504. package/dist/public/assets/repo-picker-K5RYsEge.css.br +0 -0
  505. package/dist/public/assets/review-view-DqMrB4Ny.css +0 -1
  506. package/dist/public/assets/review-view-DqMrB4Ny.css.br +0 -0
  507. package/dist/public/assets/review-view-TdLbCgEg.js +0 -2
  508. package/dist/public/assets/section-2MyJSq5D.css +0 -1
  509. package/dist/public/assets/section-2MyJSq5D.css.br +0 -0
  510. package/dist/public/assets/settings-DxhaKmbF.js +0 -1
  511. package/dist/public/assets/settings-page-BBAG94Vh.js +0 -2
  512. package/dist/public/assets/settings-page-DUefc32x.css +0 -1
  513. package/dist/public/assets/settings-page-DUefc32x.css.br +0 -0
  514. package/dist/public/assets/skill-row-BeOk8NK8.css +0 -1
  515. package/dist/public/assets/sso-auth-CU3fGJ4U.css +0 -1
  516. package/dist/public/assets/sso-auth-CU3fGJ4U.css.br +0 -0
  517. package/dist/public/assets/w-DxhaKmbF.js +0 -1
  518. package/dist/public/assets/w._-C6JVdFgi.js +0 -1
  519. package/dist/public/assets/w._-DxhaKmbF.js +0 -1
  520. package/dist/public/assets/w._-rfvcDGPk.js +0 -1
  521. package/scripts/migrate.mjs +0 -682
@@ -1,41 +1,15 @@
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";
7
8
  import fs$1 from "node:fs/promises";
8
9
  import os from "node:os";
9
10
  import { promisify } from "node:util";
10
11
  import { DatabaseSync } from "node:sqlite";
11
12
  import { createHash } from "node:crypto";
12
- //#region src/server/http.ts
13
- /** Who may frame the app's own responses: the app alone (the review's PDF
14
- * preview). A page elsewhere that frames it can dress a click on it as a
15
- * click on something of its own. A route that sends a
16
- * Content-Security-Policy of its own replaces this one, so it names
17
- * `FRAME_ANCESTORS` too. */
18
- var FRAME_ANCESTORS = "frame-ancestors 'self'";
19
- var FRAME_HEADERS = {
20
- "content-security-policy": FRAME_ANCESTORS,
21
- "x-frame-options": "SAMEORIGIN"
22
- };
23
- /** Error whose `status` the API error-boundary middleware uses for the response. */
24
- function httpError(status, message) {
25
- return Object.assign(new Error(message), { status });
26
- }
27
- /** The value of a Standard Schema `[value, issues]` pair, or a thrown 400
28
- * built from the issues. */
29
- function checked(result, what = "request") {
30
- const [value, issues] = result;
31
- if (issues) throw httpError(400, `invalid ${what}: ${issues.map((issue) => issue.message).join("; ")}`);
32
- return value;
33
- }
34
- /** Validated request body, or a thrown 400 built from the valibot issues. */
35
- async function readBody(ctx) {
36
- return checked(await ctx.body, "request body");
37
- }
38
- //#endregion
39
13
  //#region src/server/cache.ts
40
14
  /** Keyed stale-while-revalidate cache: a cached value is served immediately
41
15
  * (revalidating in the background when older than `ttlMs`); loads are deduped
@@ -312,11 +286,291 @@ function utf8Locale(env) {
312
286
  for (const [key, value] of Object.entries(env)) if (value !== void 0) out[key] = value;
313
287
  return forceUtf8Locale(out);
314
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
+ {
352
+ version: 1,
353
+ name: "baseline",
354
+ up(db) {
355
+ db.exec(`
356
+ CREATE TABLE workspaces (
357
+ id TEXT PRIMARY KEY,
358
+ name TEXT NOT NULL,
359
+ path TEXT NOT NULL UNIQUE,
360
+ branch TEXT NOT NULL,
361
+ status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'archived')),
362
+ created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
363
+ materialized INTEGER NOT NULL DEFAULT 1,
364
+ origin_branch TEXT,
365
+ imported_at TEXT
366
+ );
367
+
368
+ CREATE TABLE repos (
369
+ workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
370
+ full_name TEXT NOT NULL,
371
+ worktree TEXT NOT NULL,
372
+ base_branch TEXT NOT NULL,
373
+ default_branch TEXT NOT NULL,
374
+ PRIMARY KEY (workspace_id, full_name)
375
+ );
376
+
377
+ CREATE TABLE sessions (
378
+ id TEXT PRIMARY KEY,
379
+ workspace_id TEXT REFERENCES workspaces(id) ON DELETE SET NULL,
380
+ agent TEXT NOT NULL,
381
+ title TEXT,
382
+ created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
383
+ );
384
+
385
+ CREATE TABLE settings (
386
+ key TEXT PRIMARY KEY,
387
+ value TEXT NOT NULL
388
+ );
389
+
390
+ CREATE TABLE review_comments (
391
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
392
+ workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
393
+ worktree TEXT NOT NULL,
394
+ path TEXT NOT NULL,
395
+ side TEXT NOT NULL DEFAULT 'additions',
396
+ line_start INTEGER NOT NULL,
397
+ line_end INTEGER NOT NULL,
398
+ text TEXT NOT NULL,
399
+ created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
400
+ head TEXT,
401
+ snippet TEXT
402
+ );
403
+
404
+ CREATE TABLE push_subscriptions (
405
+ endpoint TEXT PRIMARY KEY,
406
+ data TEXT NOT NULL
407
+ );
408
+
409
+ CREATE TABLE dismissed_prs (
410
+ workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
411
+ full_name TEXT NOT NULL,
412
+ number INTEGER NOT NULL,
413
+ PRIMARY KEY (workspace_id, full_name, number)
414
+ );
415
+
416
+ CREATE TABLE review_marks (
417
+ workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
418
+ worktree TEXT NOT NULL,
419
+ branch TEXT NOT NULL,
420
+ path TEXT NOT NULL,
421
+ fingerprint TEXT NOT NULL,
422
+ PRIMARY KEY (workspace_id, worktree, branch, path)
423
+ );
424
+ `);
425
+ }
426
+ },
427
+ {
428
+ version: 2,
429
+ name: "drop what 0.0.x kept for its upgrades",
430
+ up(db) {
431
+ db.exec(`
432
+ DELETE FROM review_marks WHERE path = '';
433
+ DELETE FROM settings
434
+ WHERE key IN ('review-cleared-diff-v2', 'ui.diff-uncommitted', 'diff-uncommitted')
435
+ OR key GLOB 'review.seen:*';
436
+ `);
437
+ for (const name of [
438
+ "tab",
439
+ "diff-filter",
440
+ "diff-folded",
441
+ "diff-collapsed",
442
+ "diff-focus",
443
+ "diff-pos",
444
+ "files-recent"
445
+ ]) {
446
+ const prefix = `ui.${name}:`;
447
+ db.prepare("DELETE FROM settings WHERE key GLOB ? AND substr(key, ?) NOT IN (SELECT id FROM workspaces)").run(`${prefix}*`, prefix.length + 1);
448
+ }
449
+ const pref = (key) => db.prepare("SELECT value FROM settings WHERE key = ?").get(key)?.value;
450
+ const parse = (text) => {
451
+ try {
452
+ return text === void 0 ? void 0 : JSON.parse(text);
453
+ } catch {
454
+ return;
455
+ }
456
+ };
457
+ const font = parse(pref("ui.term-font"));
458
+ if (font && typeof font === "object") {
459
+ 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]));
460
+ }
461
+ db.exec("DELETE FROM settings WHERE key = 'ui.term-font'");
462
+ const keys = parse(pref("ui.phone-keys"));
463
+ if (Array.isArray(keys)) db.prepare("UPDATE settings SET value = ? WHERE key = 'ui.phone-keys'").run(JSON.stringify({
464
+ base: [],
465
+ extra: keys
466
+ }));
467
+ }
468
+ },
469
+ {
470
+ version: 3,
471
+ name: "drop the typing-prediction pref",
472
+ up(db) {
473
+ db.exec("DELETE FROM settings WHERE key = 'ui.term-predict'");
474
+ }
475
+ }
476
+ ];
477
+ var LATEST = STEPS.at(-1).version;
478
+ /** The database at `file`, at the latest version: an empty one is built by
479
+ * every step, an existing one gets those it lacks — each in a transaction
480
+ * of its own with its version stamp inside it, after a copy of the whole
481
+ * file (`work.db.v<from>.bak` beside it, the newest two kept). One from
482
+ * before the baseline is handed to `bridge` first, when given (the
483
+ * server's: lib/setup/bridge.mjs). Throws, with what to do in its message,
484
+ * for a database this code cannot open: one still from before the
485
+ * baseline, one from a newer release, or one a step failed on (rolled back
486
+ * to the step before). */
487
+ function openDatabase(file, { bridge } = {}) {
488
+ if (bridge && needsBridge(file)) bridge(path.dirname(file));
489
+ const db = new DatabaseSync(file);
490
+ try {
491
+ db.exec("PRAGMA busy_timeout = 5000");
492
+ db.exec("PRAGMA journal_mode = WAL");
493
+ migrate(db, file);
494
+ db.exec("PRAGMA foreign_keys = ON");
495
+ return db;
496
+ } catch (err) {
497
+ db.close();
498
+ throw err;
499
+ }
500
+ }
501
+ function versionOf(db) {
502
+ return db.prepare("PRAGMA user_version").get().user_version;
503
+ }
504
+ function migrate(db, file) {
505
+ const from = versionOf(db);
506
+ const empty = !db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table'").get();
507
+ 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 ")}`);
508
+ if (from > LATEST) {
509
+ const backup = newestBackup(file, LATEST);
510
+ 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` : ""}.`);
511
+ }
512
+ const pending = STEPS.filter((s) => s.version > from);
513
+ if (!pending.length) return;
514
+ const backup = empty ? null : snapshot(db, file, from);
515
+ for (const step of pending) {
516
+ db.exec("BEGIN IMMEDIATE");
517
+ try {
518
+ if (versionOf(db) >= step.version) {
519
+ db.exec("ROLLBACK");
520
+ continue;
521
+ }
522
+ step.up(db);
523
+ db.exec(`PRAGMA user_version = ${step.version}`);
524
+ db.exec("COMMIT");
525
+ } catch (err) {
526
+ try {
527
+ db.exec("ROLLBACK");
528
+ } catch {}
529
+ 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}` : ""}`);
530
+ }
531
+ }
532
+ }
533
+ var backupName = (file, version) => `${path.basename(file)}.v${version}.bak`;
534
+ /** The file's backups, newest version first. */
535
+ function backups(file) {
536
+ const dir = path.dirname(file);
537
+ const re = new RegExp(`^${path.basename(file).replace(/\./g, "\\.")}\\.v(\\d+)\\.bak$`);
538
+ let names = [];
539
+ try {
540
+ names = fs.readdirSync(dir);
541
+ } catch {}
542
+ return names.map((name) => re.exec(name)).filter((m) => !!m).map((m) => ({
543
+ file: path.join(dir, m[0]),
544
+ version: Number(m[1])
545
+ })).sort((a, b) => b.version - a.version);
546
+ }
547
+ function newestBackup(file, atMost) {
548
+ return backups(file).find((b) => b.version <= atMost)?.file ?? null;
549
+ }
550
+ /** A copy of the whole database as it is before an upgrade from `version`,
551
+ * which a release that knows `version` can open. */
552
+ function snapshot(db, file, version) {
553
+ const dest = path.join(path.dirname(file), backupName(file, version));
554
+ fs.rmSync(dest, { force: true });
555
+ db.prepare("VACUUM INTO ?").run(dest);
556
+ for (const old of backups(file).slice(2)) fs.rmSync(old.file, { force: true });
557
+ return dest;
558
+ }
315
559
  //#endregion
316
560
  //#region src/server/db.ts
317
561
  if (!path.isAbsolute(config.dataDir)) throw new Error(`data dir must be absolute, got "${config.dataDir}" — check WORK_DATA_DIR and $HOME`);
318
- var db = new DatabaseSync(path.join(config.dataDir, "work.db"));
319
- db.exec("PRAGMA busy_timeout = 5000");
562
+ /** The app's database, at the latest schema version before anything reads
563
+ * it (server/migrations.ts), one from before 0.1 bridged first. One this
564
+ * release cannot open stops the server here, saying what to do: a stack
565
+ * trace would bury that under itself. */
566
+ var db = (() => {
567
+ try {
568
+ return openDatabase(path.join(config.dataDir, "work.db"), { bridge: bridgeForServer });
569
+ } catch (err) {
570
+ console.error(`[work] ${err.message}`);
571
+ process.exit(1);
572
+ }
573
+ })();
320
574
  /** Prepared statements, kept by their SQL: preparing is most of a small
321
575
  * query's cost (10 µs against 4), and a status build runs hundreds. The
322
576
  * texts are the call sites' own, so the set is small; the cap covers any
@@ -340,91 +594,33 @@ function get(sql, ...params) {
340
594
  function workspacePath(id) {
341
595
  return get("SELECT path FROM workspaces WHERE id = ?", id)?.path;
342
596
  }
343
- var fresh = !db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table'").get();
344
- var freshReview = !db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'review_comments'").get();
345
- db.exec(`
346
- PRAGMA journal_mode = WAL;
347
- PRAGMA foreign_keys = ON;
348
-
349
- CREATE TABLE IF NOT EXISTS workspaces (
350
- id TEXT PRIMARY KEY,
351
- name TEXT NOT NULL,
352
- path TEXT NOT NULL UNIQUE,
353
- branch TEXT NOT NULL,
354
- status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'archived')),
355
- created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
356
- );
357
-
358
- CREATE TABLE IF NOT EXISTS repos (
359
- workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
360
- full_name TEXT NOT NULL,
361
- worktree TEXT NOT NULL,
362
- base_branch TEXT NOT NULL,
363
- default_branch TEXT NOT NULL,
364
- PRIMARY KEY (workspace_id, full_name)
365
- );
366
-
367
- CREATE TABLE IF NOT EXISTS sessions (
368
- id TEXT PRIMARY KEY,
369
- workspace_id TEXT REFERENCES workspaces(id) ON DELETE SET NULL,
370
- agent TEXT NOT NULL,
371
- title TEXT,
372
- created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
373
- );
374
-
375
- CREATE TABLE IF NOT EXISTS settings (
376
- key TEXT PRIMARY KEY,
377
- value TEXT NOT NULL
378
- );
379
-
380
- CREATE TABLE IF NOT EXISTS review_comments (
381
- id INTEGER PRIMARY KEY AUTOINCREMENT,
382
- workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
383
- worktree TEXT NOT NULL,
384
- path TEXT NOT NULL,
385
- side TEXT NOT NULL DEFAULT 'additions',
386
- line_start INTEGER NOT NULL,
387
- line_end INTEGER NOT NULL,
388
- text TEXT NOT NULL,
389
- created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
390
- );
391
-
392
- CREATE TABLE IF NOT EXISTS push_subscriptions (
393
- endpoint TEXT PRIMARY KEY,
394
- data TEXT NOT NULL
395
- );
396
-
397
- CREATE TABLE IF NOT EXISTS dismissed_prs (
398
- workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
399
- full_name TEXT NOT NULL,
400
- number INTEGER NOT NULL,
401
- PRIMARY KEY (workspace_id, full_name, number)
402
- );
403
-
404
- -- Viewed marks (server/viewed.ts): a file of a branch, and its change
405
- -- as it was when marked.
406
- CREATE TABLE IF NOT EXISTS review_marks (
407
- workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
408
- worktree TEXT NOT NULL,
409
- branch TEXT NOT NULL,
410
- path TEXT NOT NULL,
411
- fingerprint TEXT NOT NULL,
412
- PRIMARY KEY (workspace_id, worktree, branch, path)
413
- );
414
- `);
415
- if (freshReview) db.prepare("INSERT OR IGNORE INTO settings (key, value) VALUES ('review-cleared-diff-v2', '1')").run();
416
- /** Additive schema changes: `CREATE TABLE IF NOT EXISTS` never revisits a
417
- * table that already exists, so a column added after a release has to be
418
- * bolted on here for databases created before it. */
419
- function ensureColumn(table, column, decl) {
420
- if (!db.prepare(`PRAGMA table_info(${table})`).all().some((c) => c.name === column)) db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${decl}`);
421
- }
422
- ensureColumn("review_comments", "head", "TEXT");
423
- ensureColumn("review_comments", "snippet", "TEXT");
424
- ensureColumn("workspaces", "materialized", "INTEGER NOT NULL DEFAULT 1");
425
- ensureColumn("workspaces", "origin_branch", "TEXT");
426
- ensureColumn("workspaces", "imported_at", "TEXT");
427
- if (fresh) db.exec("PRAGMA user_version = 1");
597
+ //#endregion
598
+ //#region src/server/http.ts
599
+ /** Who may frame the app's own responses: the app alone (the review's PDF
600
+ * preview). A page elsewhere that frames it can dress a click on it as a
601
+ * click on something of its own. A route that sends a
602
+ * Content-Security-Policy of its own replaces this one, so it names
603
+ * `FRAME_ANCESTORS` too. */
604
+ var FRAME_ANCESTORS = "frame-ancestors 'self'";
605
+ var FRAME_HEADERS = {
606
+ "content-security-policy": FRAME_ANCESTORS,
607
+ "x-frame-options": "SAMEORIGIN"
608
+ };
609
+ /** Error whose `status` the API error-boundary middleware uses for the response. */
610
+ function httpError(status, message) {
611
+ return Object.assign(new Error(message), { status });
612
+ }
613
+ /** The value of a Standard Schema `[value, issues]` pair, or a thrown 400
614
+ * built from the issues. */
615
+ function checked(result, what = "request") {
616
+ const [value, issues] = result;
617
+ if (issues) throw httpError(400, `invalid ${what}: ${issues.map((issue) => issue.message).join("; ")}`);
618
+ return value;
619
+ }
620
+ /** Validated request body, or a thrown 400 built from the valibot issues. */
621
+ async function readBody(ctx) {
622
+ return checked(await ctx.body, "request body");
623
+ }
428
624
  //#endregion
429
625
  //#region src/client/pref-change.ts
430
626
  /** The stored text after `change`, or null when nothing is left. A value
@@ -793,6 +989,94 @@ function agentLabel$1(id) {
793
989
  const parsed = parseAgentId(id);
794
990
  return parsed ? `${parsed.family.label}${parsed.suffix ? ` ${parsed.suffix}` : ""}` : id;
795
991
  }
992
+ /** `tailscale version` prints the short version first (`1.76.1`, or
993
+ * `1.77.30` on an unstable track), then commit lines. */
994
+ function parseVersion(text) {
995
+ return /\b(\d+)\.(\d+)\.(\d+)\b/.exec(text || "")?.[0] ?? null;
996
+ }
997
+ function atLeast(version, min) {
998
+ const a = version.split(".").map(Number);
999
+ const b = min.split(".").map(Number);
1000
+ for (let i = 0; i < 3; i++) if (a[i] !== b[i]) return a[i] > b[i];
1001
+ return true;
1002
+ }
1003
+ /** The target the CLI writes (`http://127.0.0.1:7171`) or one a hand-made
1004
+ * or older config holds (`localhost:7171`, `http://[::1]:7171`, `7171`),
1005
+ * when it is work's port on this machine. */
1006
+ function targetsPort(proxy, port) {
1007
+ if (/^\d+$/.test(proxy)) return proxy === String(port);
1008
+ let url;
1009
+ try {
1010
+ url = new URL(proxy.includes("://") ? proxy : `http://${proxy}`);
1011
+ } catch {
1012
+ return false;
1013
+ }
1014
+ return url.protocol === "http:" && [
1015
+ "127.0.0.1",
1016
+ "localhost",
1017
+ "[::1]"
1018
+ ].includes(url.hostname) && url.port === String(port);
1019
+ }
1020
+ /** The URL a `Web` entry (`<name>:<port>`) is opened at: https unless its
1021
+ * port is served as plain HTTP (`--http=<port>`). */
1022
+ function webUrl(config, hostPort) {
1023
+ const i = hostPort.lastIndexOf(":");
1024
+ const host = hostPort.slice(0, i);
1025
+ const port = hostPort.slice(i + 1);
1026
+ const tls = !config.TCP?.[port]?.HTTP;
1027
+ return `${tls ? "https" : "http"}://${host}${port === (tls ? "443" : "80") ? "" : `:${port}`}/`;
1028
+ }
1029
+ /** Where `tailscale serve status --json` (an ipn.ServeConfig; `{}` or
1030
+ * `null` when empty) serves work's port, and whether Funnel publishes that
1031
+ * to the internet — or null. Only a handler at `/` counts: work serves
1032
+ * every page, asset and websocket from the root. */
1033
+ function serveOf(config, port) {
1034
+ for (const [hostPort, web] of Object.entries(config?.Web || {})) {
1035
+ const proxy = web?.Handlers?.["/"]?.Proxy;
1036
+ if (!proxy || !targetsPort(proxy, port)) continue;
1037
+ const url = webUrl(config, hostPort);
1038
+ return {
1039
+ url,
1040
+ host: new URL(url).hostname,
1041
+ funnel: !!config.AllowFunnel?.[hostPort]
1042
+ };
1043
+ }
1044
+ return null;
1045
+ }
1046
+ function hosts(value) {
1047
+ return (value || "").split(",").map((s) => s.trim()).filter(Boolean);
1048
+ }
1049
+ /**
1050
+ * The probe `work doctor` and `work setup` read, from the CLI's output:
1051
+ * `version` (`tailscale version`), `status` (`tailscale status --json`,
1052
+ * null when tailscaled did not answer) and `serve` (`tailscale serve
1053
+ * status --json`). `allowedHosts` is the WORK_ALLOWED_HOSTS the service
1054
+ * runs with.
1055
+ */
1056
+ function readTailscale({ path, version: versionText, status, serve }, { port, allowedHosts }) {
1057
+ const version = parseVersion(versionText);
1058
+ const name = String(status?.Self?.DNSName || "").replace(/\.$/, "").toLowerCase() || null;
1059
+ const certs = status?.CertDomains;
1060
+ const https = Array.isArray(certs) ? certs.some((d) => d.toLowerCase() === name) : status && "CertDomains" in status ? false : null;
1061
+ const served = serveOf(serve, port);
1062
+ const root = name ? serve?.Web?.[`${name}:443`]?.Handlers?.["/"] : null;
1063
+ return {
1064
+ installed: true,
1065
+ path,
1066
+ version,
1067
+ serveCli: !!version && atLeast(version, "1.52.0"),
1068
+ state: status?.BackendState ?? null,
1069
+ running: status?.BackendState === "Running" && !!name,
1070
+ name,
1071
+ https,
1072
+ port: String(port),
1073
+ serve: served && {
1074
+ ...served,
1075
+ allowed: hosts(allowedHosts).some((h) => h.toLowerCase() === served.host)
1076
+ },
1077
+ rootTaken: !served && root ? root.Proxy || root.Path || root.Redirect || "text" : null
1078
+ };
1079
+ }
796
1080
  //#endregion
797
1081
  //#region lib/setup/doctor.mjs
798
1082
  var home = os.homedir();
@@ -904,6 +1188,40 @@ async function readMiseInstalls() {
904
1188
  } catch {}
905
1189
  return out;
906
1190
  }
1191
+ /** A path owned by one release of a version manager — mise/asdf
1192
+ * `installs`, homebrew's `Cellar`, nvm's `versions` — which that tool
1193
+ * deletes on its next update. */
1194
+ var VERSIONED_PATH = /\/(installs|Cellar|versions|toolchains)\//;
1195
+ /** The gh for git to run as a credential helper: the launcher on PATH
1196
+ * (mise's shim, /usr/bin/gh), when it is not itself one release's. Still an
1197
+ * absolute path, so it works for GUI clients and cron jobs that never
1198
+ * sourced a shell profile, but one that follows upgrades. */
1199
+ function stableGh() {
1200
+ const gh = which("gh");
1201
+ return gh && !VERSIONED_PATH.test(gh) ? gh : null;
1202
+ }
1203
+ /** Credential helpers in ~/.gitconfig that run a gh which is gone, by
1204
+ * config key. `gh auth setup-git` writes the absolute path of the gh that
1205
+ * ran it, and git runs that string literally: once a version manager's
1206
+ * upgrade deletes it, every https push fails with "could not read
1207
+ * Username" while `gh` itself still works. Listed only when there is a
1208
+ * stable gh to point them at, which `work setup` does. */
1209
+ async function staleGhHelpers() {
1210
+ if (!stableGh()) return [];
1211
+ const { stdout } = await run("git", [
1212
+ "config",
1213
+ "--global",
1214
+ "--get-regexp",
1215
+ String.raw`^credential\..*\.helper$`
1216
+ ]);
1217
+ const keys = /* @__PURE__ */ new Set();
1218
+ for (const line of stdout.split("\n")) {
1219
+ const sp = line.indexOf(" ");
1220
+ const bin = /^!(\S+) auth git-credential$/.exec(line.slice(sp + 1))?.[1];
1221
+ if (sp > 0 && bin && !fs.existsSync(bin)) keys.add(line.slice(0, sp));
1222
+ }
1223
+ return [...keys];
1224
+ }
907
1225
  /** Hosts `gh` knows about (~/.config/gh/hosts.yml top-level keys) — the
908
1226
  * source of truth for "which GitHub hosts has this machine signed in to",
909
1227
  * merged with whatever the caller has configured. */
@@ -1062,11 +1380,50 @@ async function ghExtensions() {
1062
1380
  }
1063
1381
  return out;
1064
1382
  }
1383
+ function parseJson(text) {
1384
+ try {
1385
+ return JSON.parse(text);
1386
+ } catch {
1387
+ return null;
1388
+ }
1389
+ }
1390
+ /** Tailscale here and what its serve config does with work's port
1391
+ * (lib/setup/tailscale.mjs), from read-only commands. `port` and
1392
+ * `allowedHosts` default to this process's own, which are the server's
1393
+ * when the server asks. */
1394
+ async function tailscaleProbe({ port, allowedHosts } = {}) {
1395
+ const bin = which("tailscale");
1396
+ if (!bin) return { installed: false };
1397
+ const [version, status, serve] = await Promise.all([
1398
+ run(bin, ["version"], { timeout: 5e3 }),
1399
+ run(bin, [
1400
+ "status",
1401
+ "--json",
1402
+ "--peers=false"
1403
+ ], { timeout: 5e3 }),
1404
+ run(bin, [
1405
+ "serve",
1406
+ "status",
1407
+ "--json"
1408
+ ], { timeout: 5e3 })
1409
+ ]);
1410
+ return readTailscale({
1411
+ path: tilde(bin),
1412
+ version: version.stdout,
1413
+ status: status.ok ? parseJson(status.stdout) : null,
1414
+ serve: serve.ok ? parseJson(serve.stdout) : null
1415
+ }, {
1416
+ port: port || process.env.PORT || process.env.WORK_APP_PORT || "7171",
1417
+ allowedHosts: allowedHosts ?? process.env.WORK_ALLOWED_HOSTS
1418
+ });
1419
+ }
1065
1420
  /**
1066
1421
  * Full readiness snapshot.
1067
1422
  *
1068
- * @param {{ hosts?: string[] }} [opts] configured GitHub hosts (settings);
1069
- * github.com and any host gh is already signed in to are always included.
1423
+ * @param {{ hosts?: string[], port?: string, allowedHosts?: string }} [opts]
1424
+ * configured GitHub hosts (settings); github.com and any host gh is
1425
+ * already signed in to are always included. `port` and `allowedHosts`
1426
+ * are the service's, for the Tailscale probe.
1070
1427
  */
1071
1428
  async function doctor(opts = {}) {
1072
1429
  const hostSet = /* @__PURE__ */ new Set([
@@ -1074,11 +1431,13 @@ async function doctor(opts = {}) {
1074
1431
  ...opts.hosts || [],
1075
1432
  ...ghKnownHosts()
1076
1433
  ]);
1077
- const [versions, github, awake, extensions] = await Promise.all([
1434
+ const [versions, github, awake, extensions, helpers, tailscale] = await Promise.all([
1078
1435
  miseVersions(),
1079
1436
  Promise.all([...hostSet].map(githubHostStatus)),
1080
1437
  canStayAwake(),
1081
- ghExtensions()
1438
+ ghExtensions(),
1439
+ staleGhHelpers(),
1440
+ tailscaleProbe(opts)
1082
1441
  ]);
1083
1442
  const tools = TOOLS.map((t) => {
1084
1443
  if (t.ghExtension) {
@@ -1119,7 +1478,9 @@ async function doctor(opts = {}) {
1119
1478
  tools,
1120
1479
  agents,
1121
1480
  github,
1122
- awake
1481
+ awake,
1482
+ staleGhHelpers: helpers,
1483
+ tailscale
1123
1484
  };
1124
1485
  }
1125
1486
  //#endregion
@@ -1142,8 +1503,7 @@ var PREF_MAX = 4096;
1142
1503
  /** The prefs kept per workspace, keyed `<name>:<workspace id>`. They ride
1143
1504
  * every page's HTML, so they go with the workspace (`deleteWorkspacePrefs`)
1144
1505
  * and /api/prefs refuses them for one that is gone; one missing here
1145
- * outlives its workspace for good. `scripts/migrate.mjs` prunes orphans of
1146
- * the same list. */
1506
+ * outlives its workspace for good. */
1147
1507
  var WORKSPACE_PREFS = [
1148
1508
  "tab",
1149
1509
  "diff-filter",
@@ -5641,7 +6001,7 @@ var require_vapid_helper = /* @__PURE__ */ __commonJSMin(((exports, module) => {
5641
6001
  var crypto$3 = __require("crypto");
5642
6002
  var asn1 = require_asn1();
5643
6003
  var jws = require_jws();
5644
- var { URL } = __require("url");
6004
+ var { URL: URL$1 } = __require("url");
5645
6005
  var WebPushConstants = require_web_push_constants();
5646
6006
  var urlBase64Helper = require_urlsafe_base64_helper();
5647
6007
  /**
@@ -5692,7 +6052,7 @@ var require_vapid_helper = /* @__PURE__ */ __commonJSMin(((exports, module) => {
5692
6052
  if (typeof subject !== "string" || subject.length === 0) throw new Error("The subject value must be a string containing an https: URL or mailto: address. " + subject);
5693
6053
  let subjectParseResult = null;
5694
6054
  try {
5695
- subjectParseResult = new URL(subject);
6055
+ subjectParseResult = new URL$1(subject);
5696
6056
  } catch (err) {
5697
6057
  throw new Error("Vapid subject is not a valid URL. " + subject);
5698
6058
  }
@@ -5754,7 +6114,7 @@ var require_vapid_helper = /* @__PURE__ */ __commonJSMin(((exports, module) => {
5754
6114
  if (!audience) throw new Error("No audience could be generated for VAPID.");
5755
6115
  if (typeof audience !== "string" || audience.length === 0) throw new Error("The audience value must be a string containing the origin of a push service. " + audience);
5756
6116
  try {
5757
- new URL(audience);
6117
+ new URL$1(audience);
5758
6118
  } catch (err) {
5759
6119
  throw new Error("VAPID audience is not a url. " + audience);
5760
6120
  }
@@ -7385,7 +7745,7 @@ function publishChange(sessionId) {
7385
7745
  const row = get("SELECT workspace_id FROM sessions WHERE id = ?", sessionId);
7386
7746
  if (row?.workspace_id) {
7387
7747
  const workspaceId = row.workspace_id;
7388
- import("./_LF2Fo5WE.js").then((m) => m.notifySessionsChanged(workspaceId));
7748
+ import("./_HbAW5Cbt.js").then((m) => m.notifySessionsChanged(workspaceId));
7389
7749
  return;
7390
7750
  }
7391
7751
  publish("sessions.changed");
@@ -9616,28 +9976,12 @@ async function listPanesNow() {
9616
9976
  };
9617
9977
  return panes;
9618
9978
  }
9619
- /** Cleared once per process — boot already runs this, and a server we
9620
- * create below never has PORT set, so re-running on every attach only
9621
- * unsets something already unset. */
9622
- var portCleared = false;
9623
9979
  /** Start the tmux server in its own systemd user unit so it escapes this
9624
9980
  * service's cgroup — otherwise `systemctl restart work` kills every
9625
9981
  * session with it. A hidden "work-keeper" session pins the server alive
9626
9982
  * (tmux exits when its last session closes). */
9627
9983
  async function ensureTmuxServer() {
9628
- if (await tmux(["has-session"]).then(() => true, () => false)) {
9629
- if (!portCleared) {
9630
- await tmux([
9631
- "set-environment",
9632
- "-g",
9633
- "-u",
9634
- "PORT"
9635
- ]).catch(() => {});
9636
- portCleared = true;
9637
- }
9638
- return;
9639
- }
9640
- portCleared = true;
9984
+ if (await tmux(["has-session"]).then(() => true, () => false)) return;
9641
9985
  await run$1("systemd-run", [
9642
9986
  "--user",
9643
9987
  `--unit=${TMUX_SOCKET === "work" ? "work-tmux" : `work-tmux-${TMUX_SOCKET.replace(/[^\w.:-]/g, "_")}`}`,
@@ -9910,4 +10254,4 @@ function sleep(ms) {
9910
10254
  return new Promise((resolve) => setTimeout(resolve, ms));
9911
10255
  }
9912
10256
  //#endregion
9913
- export { saveSubscription as $, readBody as $t, clearAgentPhase as A, agentById as At, agentBadge as B, gh as Bt, readHookPayload as C, miseVersions as Ct, realInsideSync as D, DEFAULT_GITHUB_HOST as Dt, realInside as E, which as Et, onPhaseChange as F, all as Ft, ACCENT_RE as G, config as Gt, agentFromCommand as H, gitEnv as Ht, setAgentPhase as I, db as It, manifest as J, withLock as Jt, getInstance as K, shared as Kt, setScrapedPhase as L, get as Lt, hookReportedAt as M, catalogPin as Mt, noteBackground as N, toolById as Nt, blankRow as O, PROJECT_TOOLS as Ot, noteUserAnswered as P, applyPrefChange as Pt, pushPublicKey as Q, httpError as Qt, setSessionViewers as R, workspacePath as Rt, AGENTS as S, miseInstalls as St, inside as T, tilde as Tt, agentLabel as U, run$1 as Ut, agentFamily as V, git as Vt, agentMeta as W, tmux as Wt, setInstance as X, FRAME_HEADERS as Xt, normalizeAccent as Y, FRAME_ANCESTORS as Yt, deleteSubscription as Z, checked 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, 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, agentLabel$1 as jt, agentPhase as k, 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, swr 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, TMUX_SOCKET as zt };
10257
+ 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 };