@sma1lboy/rove 0.9.238 → 0.9.240

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 (237) hide show
  1. package/README.md +2 -2
  2. package/dist/cli/chunk-0mj358p5.js +3 -0
  3. package/dist/cli/{chunk-nntg9d85.js → chunk-0y4qgnby.js} +1 -1
  4. package/dist/cli/chunk-1brfxbvg.js +4 -0
  5. package/dist/cli/chunk-21fm5tks.js +2 -0
  6. package/dist/cli/{chunk-bkbmqec2.js → chunk-28zg6p31.js} +1 -1
  7. package/dist/cli/chunk-2andp9gs.js +2 -0
  8. package/dist/cli/{chunk-r2pztgm6.js → chunk-2bgmby1d.js} +1 -1
  9. package/dist/cli/chunk-2vgc5cyj.js +2 -0
  10. package/dist/cli/chunk-2x9yc5nx.js +2 -0
  11. package/dist/cli/chunk-30kjq5m7.js +2 -0
  12. package/dist/cli/{chunk-b503z32q.js → chunk-31y92jm8.js} +3 -3
  13. package/dist/cli/{chunk-mkksdcsw.js → chunk-3342qzve.js} +1 -1
  14. package/dist/cli/{chunk-0wgheepg.js → chunk-34261s0m.js} +3 -3
  15. package/dist/cli/chunk-3aqhytyy.js +3 -0
  16. package/dist/cli/chunk-3c58659p.js +2 -0
  17. package/dist/cli/chunk-3d1hjrq0.js +2 -0
  18. package/dist/cli/{chunk-pzbrj3gd.js → chunk-3vyk7bzb.js} +1 -1
  19. package/dist/cli/chunk-41x1hrqe.js +3 -0
  20. package/dist/cli/chunk-4dv0mgan.js +2 -0
  21. package/dist/cli/{chunk-mhg40es1.js → chunk-4hestsjp.js} +1 -1
  22. package/dist/cli/{chunk-77w83wgh.js → chunk-4tx2kayk.js} +1 -1
  23. package/dist/cli/{chunk-aj7fkrha.js → chunk-4xj52nx1.js} +1 -1
  24. package/dist/cli/{chunk-s1p650mm.js → chunk-53cyns0f.js} +1 -1
  25. package/dist/cli/chunk-576r5nht.js +5 -0
  26. package/dist/cli/{chunk-1bm6sryf.js → chunk-5nsvp4h7.js} +1 -1
  27. package/dist/cli/{chunk-zyd6k6ak.js → chunk-7q43tysm.js} +1 -1
  28. package/dist/cli/chunk-801h8bze.js +4 -0
  29. package/dist/cli/chunk-80ydqr3s.js +3 -0
  30. package/dist/cli/{chunk-cv1kaq8a.js → chunk-85zr7kph.js} +5 -5
  31. package/dist/cli/{chunk-zwgns5ce.js → chunk-8tadwbx9.js} +1 -1
  32. package/dist/cli/chunk-96cjpssp.js +3 -0
  33. package/dist/cli/{chunk-bs7v83x0.js → chunk-9aydqazr.js} +1 -1
  34. package/dist/cli/{chunk-7txq91d9.js → chunk-9jsm6h5y.js} +1 -1
  35. package/dist/cli/{chunk-pz907kve.js → chunk-9w5g7frx.js} +1 -1
  36. package/dist/cli/chunk-a0ave3g6.js +3 -0
  37. package/dist/cli/{chunk-vnpqemb0.js → chunk-a7kq09ke.js} +1 -1
  38. package/dist/cli/chunk-abyk3w2j.js +2 -0
  39. package/dist/cli/chunk-adkva3ep.js +6 -0
  40. package/dist/cli/{chunk-nvqdmx7q.js → chunk-ag3txfg2.js} +1 -1
  41. package/dist/cli/{chunk-2rg6aw59.js → chunk-atmaakwp.js} +1 -1
  42. package/dist/cli/chunk-axsm0gn5.js +3 -0
  43. package/dist/cli/chunk-b0ssvpht.js +3 -0
  44. package/dist/cli/chunk-b39sdtt0.js +3 -0
  45. package/dist/cli/{chunk-grt1e2s8.js → chunk-bb5zqmea.js} +2 -2
  46. package/dist/cli/{chunk-g56km26e.js → chunk-bn73kd6z.js} +1 -1
  47. package/dist/cli/chunk-c2m55b72.js +4 -0
  48. package/dist/cli/{chunk-ch0ehc06.js → chunk-cbc1h345.js} +1 -1
  49. package/dist/cli/{chunk-dnbh8hsm.js → chunk-cbjh43yc.js} +1 -1
  50. package/dist/cli/chunk-cst86kt3.js +2 -0
  51. package/dist/cli/chunk-des00203.js +2 -0
  52. package/dist/cli/chunk-dgs0m8r4.js +3 -0
  53. package/dist/cli/chunk-dkgxz9hf.js +5 -0
  54. package/dist/cli/{chunk-mb1e73jm.js → chunk-ekd274v3.js} +2 -2
  55. package/dist/cli/{chunk-gqphk56d.js → chunk-ekg3h5z3.js} +7 -7
  56. package/dist/cli/chunk-f1nf99hj.js +2 -0
  57. package/dist/cli/chunk-fert44x2.js +2 -0
  58. package/dist/cli/chunk-ff1h2qxd.js +2 -0
  59. package/dist/cli/{chunk-cv6r89jp.js → chunk-ffs26p85.js} +1 -1
  60. package/dist/cli/{chunk-hp32tbes.js → chunk-fg62y5fm.js} +1 -1
  61. package/dist/cli/{chunk-s9a974w9.js → chunk-fvmee0tr.js} +1 -1
  62. package/dist/cli/{chunk-8h0khkap.js → chunk-fwqd5ta2.js} +2 -2
  63. package/dist/cli/{chunk-acw32w13.js → chunk-g0eygcnq.js} +6 -5
  64. package/dist/cli/chunk-g4c4ffqp.js +20 -0
  65. package/dist/cli/{chunk-k7g060qr.js → chunk-g4j41mky.js} +2 -2
  66. package/dist/cli/{chunk-j6kataan.js → chunk-g5c5jytr.js} +1 -1
  67. package/dist/cli/{chunk-dqndd97s.js → chunk-gkdfct7t.js} +2 -2
  68. package/dist/cli/chunk-gvrtrvnz.js +96 -0
  69. package/dist/cli/chunk-h2m7em1e.js +3 -0
  70. package/dist/cli/chunk-h33m6cc6.js +8 -0
  71. package/dist/cli/{chunk-ynbfqbn9.js → chunk-h3fckxn3.js} +1 -1
  72. package/dist/cli/chunk-h7y9v8k1.js +4 -0
  73. package/dist/cli/{chunk-32mv1yy6.js → chunk-h9cg0j3a.js} +1 -1
  74. package/dist/cli/{chunk-h4qv19v8.js → chunk-hbn1t161.js} +1 -1
  75. package/dist/cli/{chunk-3es6spp4.js → chunk-hq9tbzqa.js} +2 -2
  76. package/dist/cli/{chunk-snjte1rd.js → chunk-hr2xky15.js} +1 -1
  77. package/dist/cli/chunk-jxqs4y9j.js +10 -0
  78. package/dist/cli/{chunk-s0snbj93.js → chunk-kb6xw0fw.js} +1 -1
  79. package/dist/cli/{chunk-vyb5a2rh.js → chunk-kg9kmwt9.js} +1 -1
  80. package/dist/cli/chunk-ktzbg4jg.js +2 -0
  81. package/dist/cli/chunk-kz4txj2e.js +8 -0
  82. package/dist/cli/{chunk-bhqracn8.js → chunk-m19q29wk.js} +1 -1
  83. package/dist/cli/chunk-m1ekbqyz.js +2 -0
  84. package/dist/cli/chunk-m4f5h05c.js +10 -0
  85. package/dist/cli/chunk-m5gx53yr.js +3 -0
  86. package/dist/cli/chunk-m6q44xc0.js +2 -0
  87. package/dist/cli/{chunk-hq2n27y1.js → chunk-mw0ysrpd.js} +1 -1
  88. package/dist/cli/{chunk-2cwb64fj.js → chunk-n5dea05t.js} +1 -1
  89. package/dist/cli/chunk-nc46gddg.js +3 -0
  90. package/dist/cli/{chunk-jhbc9nx2.js → chunk-nckmga7j.js} +1 -1
  91. package/dist/cli/chunk-nem2x959.js +2 -0
  92. package/dist/cli/chunk-ng12dprz.js +2 -0
  93. package/dist/cli/chunk-npwzmmv9.js +3 -0
  94. package/dist/cli/chunk-nzh30nty.js +4 -0
  95. package/dist/cli/{chunk-gqrh2gp1.js → chunk-p024scd4.js} +1 -1
  96. package/dist/cli/chunk-p18ehv9y.js +7 -0
  97. package/dist/cli/{chunk-3sg5v7cg.js → chunk-p83wf4zw.js} +2 -2
  98. package/dist/cli/{chunk-s278gjet.js → chunk-pdvyfz3n.js} +1 -1
  99. package/dist/cli/chunk-pe6wnsww.js +2 -0
  100. package/dist/cli/chunk-prqeddy7.js +3 -0
  101. package/dist/cli/chunk-pvm3fc44.js +2 -0
  102. package/dist/cli/{chunk-2yd128k1.js → chunk-q5eee34y.js} +6 -6
  103. package/dist/cli/{chunk-z5fnv7nk.js → chunk-q7zzycy7.js} +25 -23
  104. package/dist/cli/chunk-qvfdqrbf.js +3 -0
  105. package/dist/cli/{chunk-2xsem13q.js → chunk-qzsahxd9.js} +1 -1
  106. package/dist/cli/chunk-rqyaf0dw.js +4 -0
  107. package/dist/cli/chunk-s57vy3k3.js +2 -0
  108. package/dist/cli/{chunk-g2advs8t.js → chunk-sak1tphp.js} +1 -1
  109. package/dist/cli/{chunk-vdcn6h48.js → chunk-snhcvjdb.js} +1 -1
  110. package/dist/cli/{chunk-bav389wj.js → chunk-svm809bx.js} +1 -1
  111. package/dist/cli/chunk-szrfp0jq.js +2 -0
  112. package/dist/cli/chunk-t8v9rpdx.js +2 -0
  113. package/dist/cli/{chunk-j4xfsn9g.js → chunk-tbrkck2f.js} +1 -1
  114. package/dist/cli/chunk-tdhk4dz8.js +4 -0
  115. package/dist/cli/chunk-thsmzarw.js +3 -0
  116. package/dist/cli/{chunk-t3wwsz29.js → chunk-tvk46rfs.js} +1 -1
  117. package/dist/cli/{chunk-4d54zgc7.js → chunk-twyda1p8.js} +2 -2
  118. package/dist/cli/{chunk-s1e0e9hc.js → chunk-vej49hnt.js} +2 -2
  119. package/dist/cli/chunk-w2sp489k.js +3 -0
  120. package/dist/cli/{chunk-0wh2ff77.js → chunk-whbm14qr.js} +2 -2
  121. package/dist/cli/chunk-wp9bygh4.js +2 -0
  122. package/dist/cli/{chunk-ww4fbx8h.js → chunk-wtb8cycx.js} +2 -2
  123. package/dist/cli/chunk-x9s14ppv.js +4 -0
  124. package/dist/cli/{chunk-hk8mc43r.js → chunk-xckpezd9.js} +5 -5
  125. package/dist/cli/{chunk-dq2mh3b3.js → chunk-xv8fhxxm.js} +1 -1
  126. package/dist/cli/{chunk-85pk7c74.js → chunk-xx166cdv.js} +1 -1
  127. package/dist/cli/{chunk-ssfj9td0.js → chunk-y8tysjc2.js} +15 -13
  128. package/dist/cli/{chunk-y3k1accw.js → chunk-yexx8nec.js} +1 -1
  129. package/dist/cli/{chunk-9prawccj.js → chunk-yt15y085.js} +1 -1
  130. package/dist/cli/{chunk-n0mg67wn.js → chunk-ytxk6zqc.js} +1 -1
  131. package/dist/cli/chunk-yvjgwnb9.js +2 -0
  132. package/dist/cli/{chunk-n24dmy2r.js → chunk-yxt1y0n3.js} +9 -9
  133. package/dist/cli/chunk-ze0htjr5.js +2 -0
  134. package/dist/cli/chunk-zeb0sttx.js +2 -0
  135. package/dist/cli/chunk-znjcesdr.js +5 -0
  136. package/dist/cli/chunk-zsfyj36g.js +3 -0
  137. package/dist/cli/chunk-zt49bbg9.js +3 -0
  138. package/dist/cli/chunk-zt7wfnva.js +3 -0
  139. package/dist/cli/{chunk-6rvzzrd7.js → chunk-zx2n95qe.js} +1 -1
  140. package/dist/cli/index.js +12 -10
  141. package/dist/cli/pty-host-node.mjs +880 -169
  142. package/dist/cli/rove-run.js +1 -1
  143. package/dist/cli/rove.js +6 -6
  144. package/dist/skills/rove/SKILL.md +1 -1
  145. package/dist/skills/rove/references/api-flags.md +5 -5
  146. package/dist/web-ui/assets/{harness-CQ-1WI4q.js → harness-BHiciz5A.js} +2 -2
  147. package/dist/web-ui/assets/{index-_ttAn6pY.js → index-BkxJISAI.js} +2 -2
  148. package/dist/web-ui/assets/{index-C4dLQEqf.css → index-nMJ42IGm.css} +1 -1
  149. package/dist/web-ui/index.html +2 -2
  150. package/dist/web-ui/origin-policy.mjs +1 -1
  151. package/dist/web-ui/pty-server.mjs +24 -10
  152. package/dist/web-ui/pty-session-lifecycle.mjs +9 -13
  153. package/package.json +6 -8
  154. package/dist/cli/chunk-05jej26n.js +0 -3
  155. package/dist/cli/chunk-079cyb2e.js +0 -4
  156. package/dist/cli/chunk-1265fmzk.js +0 -3
  157. package/dist/cli/chunk-1da3bqjc.js +0 -4
  158. package/dist/cli/chunk-1tx1s5v6.js +0 -2
  159. package/dist/cli/chunk-507zn8rs.js +0 -3
  160. package/dist/cli/chunk-53afdybj.js +0 -3
  161. package/dist/cli/chunk-544bwsss.js +0 -4
  162. package/dist/cli/chunk-67ev8k22.js +0 -2
  163. package/dist/cli/chunk-6s5mev2n.js +0 -4
  164. package/dist/cli/chunk-6x5vzzpx.js +0 -3
  165. package/dist/cli/chunk-7s1kx9ez.js +0 -2
  166. package/dist/cli/chunk-85mk6j0s.js +0 -3
  167. package/dist/cli/chunk-8hbtca1g.js +0 -3
  168. package/dist/cli/chunk-8pa1ph1s.js +0 -7
  169. package/dist/cli/chunk-9ek7xm94.js +0 -8
  170. package/dist/cli/chunk-9k47xr7m.js +0 -2
  171. package/dist/cli/chunk-9mtxxsb3.js +0 -2
  172. package/dist/cli/chunk-a1k2z44b.js +0 -2
  173. package/dist/cli/chunk-a3yyrabb.js +0 -2
  174. package/dist/cli/chunk-ahnk6zx3.js +0 -2
  175. package/dist/cli/chunk-bc18gat5.js +0 -4
  176. package/dist/cli/chunk-be757xzj.js +0 -3
  177. package/dist/cli/chunk-bw73t1zw.js +0 -5
  178. package/dist/cli/chunk-c2tevj9f.js +0 -2
  179. package/dist/cli/chunk-d1agt94n.js +0 -8
  180. package/dist/cli/chunk-dc31fzrm.js +0 -2
  181. package/dist/cli/chunk-dw853n4w.js +0 -3
  182. package/dist/cli/chunk-eawt4n4g.js +0 -2
  183. package/dist/cli/chunk-egx76ah2.js +0 -5
  184. package/dist/cli/chunk-ex1a2djb.js +0 -2
  185. package/dist/cli/chunk-f5e3dcxe.js +0 -2
  186. package/dist/cli/chunk-fwb72vzc.js +0 -2
  187. package/dist/cli/chunk-fxs82dsx.js +0 -4
  188. package/dist/cli/chunk-g3r1dwy9.js +0 -3
  189. package/dist/cli/chunk-ge30p4s5.js +0 -3
  190. package/dist/cli/chunk-gmgsxdrf.js +0 -10
  191. package/dist/cli/chunk-he76emdm.js +0 -2
  192. package/dist/cli/chunk-hgx20x94.js +0 -2
  193. package/dist/cli/chunk-hnfp317x.js +0 -2
  194. package/dist/cli/chunk-hq4b3fca.js +0 -3
  195. package/dist/cli/chunk-janvvpv5.js +0 -8
  196. package/dist/cli/chunk-jvxh93nz.js +0 -3
  197. package/dist/cli/chunk-k6nxyxyh.js +0 -3
  198. package/dist/cli/chunk-k8tspshr.js +0 -2
  199. package/dist/cli/chunk-md8k7c5w.js +0 -2
  200. package/dist/cli/chunk-mppda1wq.js +0 -3
  201. package/dist/cli/chunk-ppwpjm39.js +0 -3
  202. package/dist/cli/chunk-pvw2y93q.js +0 -25
  203. package/dist/cli/chunk-pw6yfj10.js +0 -3
  204. package/dist/cli/chunk-q4nehkj9.js +0 -2
  205. package/dist/cli/chunk-qagek3wg.js +0 -5
  206. package/dist/cli/chunk-r8xqvg26.js +0 -2
  207. package/dist/cli/chunk-rz8zs7j8.js +0 -3
  208. package/dist/cli/chunk-sb0ns0c7.js +0 -3
  209. package/dist/cli/chunk-tcj36cqg.js +0 -2
  210. package/dist/cli/chunk-vejgnmcp.js +0 -2
  211. package/dist/cli/chunk-vzqrj32e.js +0 -2
  212. package/dist/cli/chunk-wpsbyq4s.js +0 -2
  213. package/dist/cli/chunk-wtqxv2rv.js +0 -39
  214. package/dist/cli/chunk-y05d79az.js +0 -2
  215. package/dist/cli/chunk-y4048296.js +0 -4
  216. package/dist/cli/chunk-y8fqdnh3.js +0 -3
  217. package/dist/cli/chunk-ygd572ee.js +0 -4
  218. package/dist/cli/chunk-yj5pjxx2.js +0 -2
  219. package/dist/cli/chunk-zja9chrd.js +0 -4
  220. package/dist/cli/chunk-zwej00t0.js +0 -5
  221. package/dist/cli/kobe-run.js +0 -3
  222. package/dist/cli/kobe.js +0 -7
  223. package/dist/completions/kobe.bash +0 -25
  224. package/dist/completions/kobe.fish +0 -27
  225. package/dist/completions/kobe.zsh +0 -35
  226. /package/dist/cli/{chunk-hqbmzz4t.js → chunk-0422g8ac.js} +0 -0
  227. /package/dist/cli/{chunk-khj0apc7.js → chunk-2tfnscxk.js} +0 -0
  228. /package/dist/cli/{chunk-7q67dz4c.js → chunk-4250pw6r.js} +0 -0
  229. /package/dist/cli/{chunk-xsrcwcjc.js → chunk-5mhvjytn.js} +0 -0
  230. /package/dist/cli/{chunk-ef39ym8f.js → chunk-7bgbansg.js} +0 -0
  231. /package/dist/cli/{chunk-nh4wvyz3.js → chunk-atn06ncf.js} +0 -0
  232. /package/dist/cli/{chunk-h4n8ffqy.js → chunk-dmzg9zdc.js} +0 -0
  233. /package/dist/cli/{chunk-w25b7xxz.js → chunk-etfh8f4z.js} +0 -0
  234. /package/dist/cli/{chunk-hape5vwj.js → chunk-hpay0ax8.js} +0 -0
  235. /package/dist/cli/{chunk-f10n6063.js → chunk-pn5ygqn6.js} +0 -0
  236. /package/dist/cli/{chunk-rcyasw34.js → chunk-rxqdw6s5.js} +0 -0
  237. /package/dist/cli/{chunk-exfyqsdd.js → chunk-vjvkkrzc.js} +0 -0
package/README.md CHANGED
@@ -18,11 +18,11 @@ rove add /path/to/repo
18
18
  rove
19
19
  ```
20
20
 
21
- The CLI runs on the Bun runtime. The published `rove` / `kobe` bins are node
21
+ The CLI runs on the Bun runtime. The published `rove` / `rove` bins are node
22
22
  launchers that re-exec through Bun, so an `npm install -g` or `npx` on a
23
23
  machine without Bun still ends up with a working Rove.
24
24
 
25
- The package also keeps `kobe` as a compatibility alias. Both executable names
25
+ The package also keeps `rove` as a compatibility alias. Both executable names
26
26
  copy supported legacy state into `~/.rove` and `~/.config/rove` without deleting
27
27
  or overwriting the old files; daemon-owned stores wait until the legacy writer
28
28
  has stopped.
@@ -0,0 +1,3 @@
1
+ // @bun
2
+ class ClientWriter{socket;highWaterMark;onOverflow;queue=new Map;snapshots=new Map;sequence=0;queuedBytes=0;paused=!1;droppedFrames=0;overflowed=!1;constructor(socket,options={}){this.socket=socket;this.highWaterMark=options.highWaterMark??8388608,this.onOverflow=options.onOverflow??(()=>socket.destroy())}get isPaused(){return this.paused}get pendingBytes(){return this.queuedBytes}get pendingCount(){return this.queue.size}get dropped(){return this.droppedFrames}write(line,replaceKey=null){if(this.overflowed)return;if(!this.paused){if(!this.safeWrite(line))this.pause();return}if(replaceKey!==null){let previous=this.snapshots.get(replaceKey);if(previous!==void 0)this.dequeue(previous),this.droppedFrames++}let id=this.sequence++,frame={line,bytes:Buffer.byteLength(line),replaceKey};if(this.queue.set(id,frame),replaceKey!==null)this.snapshots.set(replaceKey,id);if(this.queuedBytes+=frame.bytes,this.queuedBytes<=this.highWaterMark)return;this.overflowed=!0,this.queue.clear(),this.snapshots.clear(),this.queuedBytes=0,this.onOverflow()}dequeue(id){let frame=this.queue.get(id);if(!frame)return;if(this.queue.delete(id),this.queuedBytes-=frame.bytes,frame.replaceKey!==null)this.snapshots.delete(frame.replaceKey)}pause(){this.paused=!0,this.socket.once("drain",()=>{if(this.paused=!1,this.overflowed)return;for(let[id,frame]of this.queue)if(this.dequeue(id),!this.safeWrite(frame.line)){this.pause();return}})}safeWrite(line){try{return this.socket.write(line)}catch{return!0}}}function objectPayload(payload){if(!payload||typeof payload!=="object"||Array.isArray(payload))return{};return payload}function requireString(payload,key){let value=payload[key];if(typeof value!=="string"||value.length===0)throw Error(`${key} is required`);return value}function optionalString(payload,key){let value=payload[key];if(value===void 0||value===null||value==="")return;if(typeof value!=="string")throw Error(`${key} must be a string`);return value}function optionalBoolean(payload,key){let value=payload[key];if(value===void 0||value===null)return;if(typeof value!=="boolean")throw Error(`${key} must be a boolean`);return value}function requireNumber(payload,key){let value=payload[key];if(typeof value!=="number"||!Number.isFinite(value))throw Error(`${key} must be a finite number`);return value}function optionalNumber(payload,key){let value=payload[key];if(value===void 0||value===null)return;if(typeof value!=="number"||!Number.isFinite(value))throw Error(`${key} must be a finite number`);return value}function optionalVendor(payload,key){let value=optionalString(payload,key);return value&&value.trim().length>0?value:void 0}function optionalActivityDetail(payload){let raw=payload.detail;if(!raw||typeof raw!=="object"||Array.isArray(raw))return;let d=raw,out={};if(d.failure==="rate_limit"||d.failure==="billing"||d.failure==="other")out.failure=d.failure;if(d.waiting==="permission"||d.waiting==="input")out.waiting=d.waiting;if(typeof d.note==="string")out.note=d.note;let tool=d.tool;if(tool&&typeof tool==="object"&&!Array.isArray(tool))out.tool={...typeof tool.name==="string"?{name:tool.name}:{},...typeof tool.id==="string"?{id:tool.id}:{}};let compact=d.compact;if(compact&&typeof compact==="object"&&!Array.isArray(compact))out.compact=compact.trigger==="manual"||compact.trigger==="auto"?{trigger:compact.trigger}:{};let subagent=d.subagent;if(subagent&&typeof subagent==="object"&&!Array.isArray(subagent))out.subagent={...typeof subagent.type==="string"?{type:subagent.type}:{},...typeof subagent.id==="string"?{id:subagent.id}:{}};return Object.keys(out).length>0?out:void 0}class LineReceiver{maxBytes;storage=Buffer.alloc(0);length=0;failed=!1;constructor(maxBytes=8388608){this.maxBytes=maxBytes}get pendingBytes(){return this.length}push(chunk,onLine){if(this.failed)return!1;let start=0;while(start<chunk.length){let newline=chunk.indexOf(10,start),end=newline===-1?chunk.length:newline,size=this.length+end-start;if(size>this.maxBytes)return this.failed=!0,this.storage=Buffer.alloc(0),this.length=0,!1;if(size>this.storage.length){let capacity=Math.min(this.maxBytes,Math.max(size,this.storage.length*2,1024)),grown=Buffer.allocUnsafe(capacity);this.storage.copy(grown,0,0,this.length),this.storage=grown}if(chunk.copy(this.storage,this.length,start,end),this.length=size,newline===-1)return!0;let line=this.storage.toString("utf8",0,this.length);this.length=0,onLine(line),start=newline+1}return!0}}
3
+ export{ClientWriter,objectPayload,requireString,optionalString,optionalBoolean,requireNumber,optionalNumber,optionalVendor,optionalActivityDetail,LineReceiver};
@@ -1,3 +1,3 @@
1
1
  // @bun
2
- import{DEFAULT_TERMINAL_COLORS}from"./chunk-7q67dz4c.js";import{OWNER_ONLY_DIR_MODE,OWNER_ONLY_FILE_MODE,tightenDirPermissionsSync,tightenFilePermissionsSync}from"./chunk-9prawccj.js";import{defaultPtyFreezeDir}from"./chunk-y8fqdnh3.js";import{randomUUID}from"crypto";import{mkdirSync,readFileSync,readdirSync,renameSync,rmSync,statSync,writeFileSync}from"fs";import{join}from"path";import{StringDecoder}from"string_decoder";var DEFAULT_MODES={applicationCursorKeys:!1,applicationKeypad:!1,origin:!1,wraparound:!0,reverseWraparound:!1,cursorBlink:!1,cursorVisible:!0,insertMode:!1,sendFocus:!1,bracketedPaste:!1,synchronizedOutput:!1,altScreen:!1,mouseProtocol:"none",mouseEncoding:"default"},MOUSE_PROTOCOLS={9:"x10",1000:"vt200",1002:"drag",1003:"any"},MOUSE_ENCODINGS={1006:"sgr",1016:"sgr-pixels"};function freshModeTrack(modes={...DEFAULT_MODES}){return{modes,carry:""}}function normalizeTerminalModes(raw){let modes={...DEFAULT_MODES};if(typeof raw!=="object"||raw===null)return modes;let record=raw;for(let key of Object.keys(DEFAULT_MODES))if(typeof record[key]==="boolean"&&typeof modes[key]==="boolean")modes[key]=record[key];if(Object.values(MOUSE_PROTOCOLS).includes(record.mouseProtocol))modes.mouseProtocol=record.mouseProtocol;if(Object.values(MOUSE_ENCODINGS).includes(record.mouseEncoding))modes.mouseEncoding=record.mouseEncoding;return modes}function scanTerminalModes(track,chunk){let text=track.carry+chunk;track.carry="";let replies=[],i=text.indexOf("\x1B");while(i!==-1){if(i+1>=text.length){track.carry="\x1B";break}let next=text.charCodeAt(i+1);if(next===91){let end=csiEnd(text,i+2);if(end===-1){if(text.length-i<=64)track.carry=text.slice(i);break}if(end>=0)applyCsi(track.modes,text.slice(i+2,end),text[end],replies);i=text.indexOf("\x1B",end>=0?end+1:i+2);continue}if(next===61)track.modes.applicationKeypad=!0;else if(next===62)track.modes.applicationKeypad=!1;else if(next===99)track.modes={...DEFAULT_MODES};i=text.indexOf("\x1B",i+1)}return replies}function terminalModePreamble(modes){let set=[],reset=[];if(modes.applicationCursorKeys)set.push(1);if(modes.origin)set.push(6);if(!modes.wraparound)reset.push(7);if(modes.cursorBlink)set.push(12);if(!modes.cursorVisible)reset.push(25);if(modes.reverseWraparound)set.push(45);for(let[mode,protocol]of Object.entries(MOUSE_PROTOCOLS))if(modes.mouseProtocol===protocol)set.push(+mode);for(let[mode,encoding]of Object.entries(MOUSE_ENCODINGS))if(modes.mouseEncoding===encoding)set.push(+mode);if(modes.sendFocus)set.push(1004);if(modes.bracketedPaste)set.push(2004);let out=modes.altScreen?"\x1B[?1049h":"";if(set.length>0)out+=`\x1B[?${set.join(";")}h`;if(reset.length>0)out+=`\x1B[?${reset.join(";")}l`;if(modes.applicationKeypad)out+="\x1B=";if(modes.insertMode)out+="\x1B[4h";return out}function csiEnd(text,from){for(let j=from;j<text.length;j++){let c=text.charCodeAt(j);if(c>=64&&c<=126)return j;if(c<32||c>63)return-2}return-1}function applyCsi(modes,body,final,replies){let start=0,prefix="",first=body.charCodeAt(0);if(first>=60&&first<=63)prefix=body[0],start=1;let end=body.length;while(end>start&&body.charCodeAt(end-1)<=47)end--;let intermediates=body.slice(end),params=body.slice(start,end).split(";").map((param)=>Number.parseInt(param.split(":")[0]??"",10)||0);if(intermediates===""&&(final==="h"||final==="l")){let on=final==="h";if(prefix==="?")for(let mode of params)setPrivateMode(modes,mode,on);else if(prefix===""&&params.includes(4))modes.insertMode=on}else if(intermediates==="$"&&final==="p"&&(prefix==="?"||prefix==="")){let mode=params[0]??0,value=prefix==="?"?privateModeValue(modes,mode):ansiModeValue(modes,mode);replies.push(`\x1B[${prefix}${mode};${value}$y`)}else if(intermediates==="!"&&final==="p"&&prefix==="")softReset(modes);else if(intermediates===""&&final==="c"&&prefix===""&&(params[0]??0)===0)replies.push("\x1B[?1;2c")}function setPrivateMode(modes,mode,on){if(mode in MOUSE_PROTOCOLS){modes.mouseProtocol=on?MOUSE_PROTOCOLS[mode]:"none";return}if(mode in MOUSE_ENCODINGS){modes.mouseEncoding=on?MOUSE_ENCODINGS[mode]:"default";return}switch(mode){case 1:modes.applicationCursorKeys=on;break;case 6:modes.origin=on;break;case 7:modes.wraparound=on;break;case 12:modes.cursorBlink=on;break;case 25:modes.cursorVisible=on;break;case 45:modes.reverseWraparound=on;break;case 66:modes.applicationKeypad=on;break;case 1004:modes.sendFocus=on;break;case 47:case 1047:case 1049:modes.altScreen=on;break;case 2004:modes.bracketedPaste=on;break;case 2026:modes.synchronizedOutput=on;break}}function softReset(modes){Object.assign(modes,{applicationCursorKeys:!1,applicationKeypad:!1,origin:!1,wraparound:!0,reverseWraparound:!1,cursorVisible:!0,insertMode:!1,sendFocus:!1,bracketedPaste:!1,synchronizedOutput:!1})}var NOT_RECOGNIZED=0,SET=1,RESET=2,PERMANENTLY_SET=3,PERMANENTLY_RESET=4,flag=(on)=>on?SET:RESET;function privateModeValue(modes,mode){if(mode in MOUSE_PROTOCOLS)return flag(modes.mouseProtocol===MOUSE_PROTOCOLS[mode]);if(mode in MOUSE_ENCODINGS)return flag(modes.mouseEncoding===MOUSE_ENCODINGS[mode]);switch(mode){case 1:return flag(modes.applicationCursorKeys);case 6:return flag(modes.origin);case 7:return flag(modes.wraparound);case 8:return PERMANENTLY_SET;case 12:return flag(modes.cursorBlink);case 25:return flag(modes.cursorVisible);case 45:return flag(modes.reverseWraparound);case 66:return flag(modes.applicationKeypad);case 67:case 1005:case 1015:return PERMANENTLY_RESET;case 1004:return flag(modes.sendFocus);case 1048:return SET;case 47:case 1047:case 1049:return flag(modes.altScreen);case 2004:return flag(modes.bracketedPaste);case 2026:return flag(modes.synchronizedOutput);default:return NOT_RECOGNIZED}}function ansiModeValue(modes,mode){switch(mode){case 2:return PERMANENTLY_RESET;case 4:return flag(modes.insertMode);case 12:return PERMANENTLY_SET;case 20:return RESET;default:return NOT_RECOGNIZED}}var FREEZE_VERSION=1;function freezeSession(session,now=new Date){return{v:FREEZE_VERSION,key:session.key,cwd:session.cwd,command:[...session.command],cols:session.cols,rows:session.rows,title:session.title,totalBytes:session.totalBytes,exit:session.exit,ringB64:Buffer.concat(session.chunks).toString("base64"),...session.ringModes?{ringModes:session.ringModes.modes}:{},updatedAt:now.toISOString()}}function thawRing(record,cap){let ring;try{ring=Buffer.from(record.ringB64,"base64")}catch{return null}let cut=Math.max(0,ring.byteLength-cap),trimmed=ring.subarray(cut),ringModes=freshModeTrack(normalizeTerminalModes(record.ringModes));if(cut>0)scanTerminalModes(ringModes,ring.subarray(0,cut).toString("latin1"));return{chunks:trimmed.byteLength>0?[trimmed]:[],bytes:trimmed.byteLength,ringModes}}function thawSession(record,cap){let ring=thawRing(record,cap);if(!ring)return null;let modes=freshModeTrack({...ring.ringModes.modes});for(let chunk of ring.chunks)scanTerminalModes(modes,chunk.toString("latin1"));return{key:record.key,generation:randomUUID(),cwd:record.cwd,proc:null,alive:!1,chunks:[...ring.chunks],bytes:ring.bytes,totalBytes:Math.max(record.totalBytes,ring.bytes),cols:record.cols,rows:record.rows,command:record.command,title:record.title,titleCarry:"",titleDecoder:new StringDecoder("utf8"),colorQueryCarry:"",defaultColors:DEFAULT_TERMINAL_COLORS,modes,ringModes:ring.ringModes,sinks:new Map,emulatorSinks:new Set,parked:!1,parkedScreenBytes:0,exit:record.exit,restored:!0,lastFreezeAtMs:0}}function recordFile(dir,key){return join(dir,`${encodeURIComponent(key)}.json`)}function parseRecord(raw){try{let parsed=JSON.parse(raw);if(parsed?.v!==FREEZE_VERSION)return null;if(typeof parsed.key!=="string"||parsed.key.length===0)return null;if(parsed.key.startsWith("::"))return null;if(typeof parsed.cwd!=="string"||!Array.isArray(parsed.command))return null;if(typeof parsed.ringB64!=="string"||typeof parsed.totalBytes!=="number")return null;return parsed}catch{return null}}var FREEZE_TTL_MS=1209600000,FREEZE_RESTORE_MAX_BYTES=67108864;function updatedAtMs(record){let t=Date.parse(record.updatedAt);return Number.isFinite(t)?t:0}function loadFrozenSessions(dir=defaultPtyFreezeDir(),now=Date.now(),report){let names;try{names=readdirSync(dir)}catch{return[]}let entries=[];for(let name of names){if(!name.endsWith(".json"))continue;try{let st=statSync(join(dir,name));entries.push({name,size:st.size,mtimeMs:st.mtimeMs})}catch{}}entries.sort((a,b)=>b.mtimeMs-a.mtimeMs);let kept=[],stale=[],bytesRead=0,deferred=0,unreadable=0;for(let entry of entries){if(now-entry.mtimeMs>FREEZE_TTL_MS){stale.push(entry.name);continue}if(bytesRead+entry.size>FREEZE_RESTORE_MAX_BYTES&&kept.length>0){deferred++;continue}let record=null;try{record=parseRecord(readFileSync(join(dir,entry.name),"utf8"))}catch{}if(bytesRead+=entry.size,!record){unreadable++;continue}if(now-updatedAtMs(record)>FREEZE_TTL_MS)stale.push(entry.name);else kept.push(record)}for(let name of stale)try{rmSync(join(dir,name),{force:!0})}catch{}return kept.sort((a,b)=>updatedAtMs(b)-updatedAtMs(a)),report?.({restored:kept.length,bytesRead,deferred,expired:stale.length,unreadable}),kept}function tightenExistingPermissions(dir){tightenDirPermissionsSync(dir);let names;try{names=readdirSync(dir)}catch{return}for(let name of names)if(name.endsWith(".json"))tightenFilePermissionsSync(join(dir,name))}function fileFreezeSink(dir=defaultPtyFreezeDir()){return tightenExistingPermissions(dir),{save(record){try{mkdirSync(dir,{recursive:!0,mode:OWNER_ONLY_DIR_MODE});let target=recordFile(dir,record.key),staging=`${target}.${process.pid}.tmp`;writeFileSync(staging,JSON.stringify(record),{encoding:"utf8",mode:OWNER_ONLY_FILE_MODE}),renameSync(staging,target)}catch{}},drop(key){try{rmSync(recordFile(dir,key),{force:!0})}catch{}}}}function clearFrozenSessions(dir=defaultPtyFreezeDir()){try{rmSync(dir,{recursive:!0,force:!0})}catch{}}
2
+ import{DEFAULT_TERMINAL_COLORS}from"./chunk-4250pw6r.js";import{OWNER_ONLY_DIR_MODE,OWNER_ONLY_FILE_MODE,tightenDirPermissionsSync,tightenFilePermissionsSync}from"./chunk-yt15y085.js";import{defaultPtyFreezeDir}from"./chunk-npwzmmv9.js";import{randomUUID}from"crypto";import{mkdirSync,readFileSync,readdirSync,renameSync,rmSync,statSync,writeFileSync}from"fs";import{join}from"path";import{StringDecoder}from"string_decoder";var DEFAULT_MODES={applicationCursorKeys:!1,applicationKeypad:!1,origin:!1,wraparound:!0,reverseWraparound:!1,cursorBlink:!1,cursorVisible:!0,insertMode:!1,sendFocus:!1,bracketedPaste:!1,synchronizedOutput:!1,altScreen:!1,mouseProtocol:"none",mouseEncoding:"default"},MOUSE_PROTOCOLS={9:"x10",1000:"vt200",1002:"drag",1003:"any"},MOUSE_ENCODINGS={1006:"sgr",1016:"sgr-pixels"};function freshModeTrack(modes={...DEFAULT_MODES}){return{modes,carry:""}}function normalizeTerminalModes(raw){let modes={...DEFAULT_MODES};if(typeof raw!=="object"||raw===null)return modes;let record=raw;for(let key of Object.keys(DEFAULT_MODES))if(typeof record[key]==="boolean"&&typeof modes[key]==="boolean")modes[key]=record[key];if(Object.values(MOUSE_PROTOCOLS).includes(record.mouseProtocol))modes.mouseProtocol=record.mouseProtocol;if(Object.values(MOUSE_ENCODINGS).includes(record.mouseEncoding))modes.mouseEncoding=record.mouseEncoding;return modes}function scanTerminalModes(track,chunk){let text=track.carry+chunk;track.carry="";let replies=[],i=text.indexOf("\x1B");while(i!==-1){if(i+1>=text.length){track.carry="\x1B";break}let next=text.charCodeAt(i+1);if(next===91){let end=csiEnd(text,i+2);if(end===-1){if(text.length-i<=64)track.carry=text.slice(i);break}if(end>=0)applyCsi(track.modes,text.slice(i+2,end),text[end],replies);i=text.indexOf("\x1B",end>=0?end+1:i+2);continue}if(next===61)track.modes.applicationKeypad=!0;else if(next===62)track.modes.applicationKeypad=!1;else if(next===99)track.modes={...DEFAULT_MODES};i=text.indexOf("\x1B",i+1)}return replies}function terminalModePreamble(modes){let set=[],reset=[];if(modes.applicationCursorKeys)set.push(1);if(modes.origin)set.push(6);if(!modes.wraparound)reset.push(7);if(modes.cursorBlink)set.push(12);if(!modes.cursorVisible)reset.push(25);if(modes.reverseWraparound)set.push(45);for(let[mode,protocol]of Object.entries(MOUSE_PROTOCOLS))if(modes.mouseProtocol===protocol)set.push(+mode);for(let[mode,encoding]of Object.entries(MOUSE_ENCODINGS))if(modes.mouseEncoding===encoding)set.push(+mode);if(modes.sendFocus)set.push(1004);if(modes.bracketedPaste)set.push(2004);let out=modes.altScreen?"\x1B[?1049h":"";if(set.length>0)out+=`\x1B[?${set.join(";")}h`;if(reset.length>0)out+=`\x1B[?${reset.join(";")}l`;if(modes.applicationKeypad)out+="\x1B=";if(modes.insertMode)out+="\x1B[4h";return out}function csiEnd(text,from){for(let j=from;j<text.length;j++){let c=text.charCodeAt(j);if(c>=64&&c<=126)return j;if(c<32||c>63)return-2}return-1}function applyCsi(modes,body,final,replies){let start=0,prefix="",first=body.charCodeAt(0);if(first>=60&&first<=63)prefix=body[0],start=1;let end=body.length;while(end>start&&body.charCodeAt(end-1)<=47)end--;let intermediates=body.slice(end),params=body.slice(start,end).split(";").map((param)=>Number.parseInt(param.split(":")[0]??"",10)||0);if(intermediates===""&&(final==="h"||final==="l")){let on=final==="h";if(prefix==="?")for(let mode of params)setPrivateMode(modes,mode,on);else if(prefix===""&&params.includes(4))modes.insertMode=on}else if(intermediates==="$"&&final==="p"&&(prefix==="?"||prefix==="")){let mode=params[0]??0,value=prefix==="?"?privateModeValue(modes,mode):ansiModeValue(modes,mode);replies.push(`\x1B[${prefix}${mode};${value}$y`)}else if(intermediates==="!"&&final==="p"&&prefix==="")softReset(modes);else if(intermediates===""&&final==="c"&&prefix===""&&(params[0]??0)===0)replies.push("\x1B[?1;2c")}function setPrivateMode(modes,mode,on){if(mode in MOUSE_PROTOCOLS){modes.mouseProtocol=on?MOUSE_PROTOCOLS[mode]:"none";return}if(mode in MOUSE_ENCODINGS){modes.mouseEncoding=on?MOUSE_ENCODINGS[mode]:"default";return}switch(mode){case 1:modes.applicationCursorKeys=on;break;case 6:modes.origin=on;break;case 7:modes.wraparound=on;break;case 12:modes.cursorBlink=on;break;case 25:modes.cursorVisible=on;break;case 45:modes.reverseWraparound=on;break;case 66:modes.applicationKeypad=on;break;case 1004:modes.sendFocus=on;break;case 47:case 1047:case 1049:modes.altScreen=on;break;case 2004:modes.bracketedPaste=on;break;case 2026:modes.synchronizedOutput=on;break}}function softReset(modes){Object.assign(modes,{applicationCursorKeys:!1,applicationKeypad:!1,origin:!1,wraparound:!0,reverseWraparound:!1,cursorVisible:!0,insertMode:!1,sendFocus:!1,bracketedPaste:!1,synchronizedOutput:!1})}var NOT_RECOGNIZED=0,SET=1,RESET=2,PERMANENTLY_SET=3,PERMANENTLY_RESET=4,flag=(on)=>on?SET:RESET;function privateModeValue(modes,mode){if(mode in MOUSE_PROTOCOLS)return flag(modes.mouseProtocol===MOUSE_PROTOCOLS[mode]);if(mode in MOUSE_ENCODINGS)return flag(modes.mouseEncoding===MOUSE_ENCODINGS[mode]);switch(mode){case 1:return flag(modes.applicationCursorKeys);case 6:return flag(modes.origin);case 7:return flag(modes.wraparound);case 8:return PERMANENTLY_SET;case 12:return flag(modes.cursorBlink);case 25:return flag(modes.cursorVisible);case 45:return flag(modes.reverseWraparound);case 66:return flag(modes.applicationKeypad);case 67:case 1005:case 1015:return PERMANENTLY_RESET;case 1004:return flag(modes.sendFocus);case 1048:return SET;case 47:case 1047:case 1049:return flag(modes.altScreen);case 2004:return flag(modes.bracketedPaste);case 2026:return flag(modes.synchronizedOutput);default:return NOT_RECOGNIZED}}function ansiModeValue(modes,mode){switch(mode){case 2:return PERMANENTLY_RESET;case 4:return flag(modes.insertMode);case 12:return PERMANENTLY_SET;case 20:return RESET;default:return NOT_RECOGNIZED}}var FREEZE_VERSION=1;function freezeSession(session,now=new Date){return{v:FREEZE_VERSION,key:session.key,cwd:session.cwd,command:[...session.command],cols:session.cols,rows:session.rows,title:session.title,totalBytes:session.totalBytes,exit:session.exit,ringB64:Buffer.concat(session.chunks).toString("base64"),...session.ringModes?{ringModes:session.ringModes.modes}:{},updatedAt:now.toISOString()}}function thawRing(record,cap){let ring;try{ring=Buffer.from(record.ringB64,"base64")}catch{return null}let cut=Math.max(0,ring.byteLength-cap),trimmed=ring.subarray(cut),ringModes=freshModeTrack(normalizeTerminalModes(record.ringModes));if(cut>0)scanTerminalModes(ringModes,ring.subarray(0,cut).toString("latin1"));return{chunks:trimmed.byteLength>0?[trimmed]:[],bytes:trimmed.byteLength,ringModes}}function thawSession(record,cap){let ring=thawRing(record,cap);if(!ring)return null;let modes=freshModeTrack({...ring.ringModes.modes});for(let chunk of ring.chunks)scanTerminalModes(modes,chunk.toString("latin1"));return{key:record.key,generation:randomUUID(),cwd:record.cwd,proc:null,alive:!1,chunks:[...ring.chunks],bytes:ring.bytes,totalBytes:Math.max(record.totalBytes,ring.bytes),cols:record.cols,rows:record.rows,command:record.command,title:record.title,titleCarry:"",titleDecoder:new StringDecoder("utf8"),colorQueryCarry:"",defaultColors:DEFAULT_TERMINAL_COLORS,modes,ringModes:ring.ringModes,sinks:new Map,emulatorSinks:new Set,parked:!1,parkedScreenBytes:0,exit:record.exit,restored:!0,lastFreezeAtMs:0}}function recordFile(dir,key){return join(dir,`${encodeURIComponent(key)}.json`)}function parseRecord(raw){try{let parsed=JSON.parse(raw);if(parsed?.v!==FREEZE_VERSION)return null;if(typeof parsed.key!=="string"||parsed.key.length===0)return null;if(parsed.key.startsWith("::"))return null;if(typeof parsed.cwd!=="string"||!Array.isArray(parsed.command))return null;if(typeof parsed.ringB64!=="string"||typeof parsed.totalBytes!=="number")return null;return parsed}catch{return null}}var FREEZE_TTL_MS=1209600000,FREEZE_RESTORE_MAX_BYTES=67108864;function updatedAtMs(record){let t=Date.parse(record.updatedAt);return Number.isFinite(t)?t:0}function loadFrozenSessions(dir=defaultPtyFreezeDir(),now=Date.now(),report){let names;try{names=readdirSync(dir)}catch{return[]}let entries=[];for(let name of names){if(!name.endsWith(".json"))continue;try{let st=statSync(join(dir,name));entries.push({name,size:st.size,mtimeMs:st.mtimeMs})}catch{}}entries.sort((a,b)=>b.mtimeMs-a.mtimeMs);let kept=[],stale=[],bytesRead=0,deferred=0,unreadable=0;for(let entry of entries){if(now-entry.mtimeMs>FREEZE_TTL_MS){stale.push(entry.name);continue}if(bytesRead+entry.size>FREEZE_RESTORE_MAX_BYTES&&kept.length>0){deferred++;continue}let record=null;try{record=parseRecord(readFileSync(join(dir,entry.name),"utf8"))}catch{}if(bytesRead+=entry.size,!record){unreadable++;continue}if(now-updatedAtMs(record)>FREEZE_TTL_MS)stale.push(entry.name);else kept.push(record)}for(let name of stale)try{rmSync(join(dir,name),{force:!0})}catch{}return kept.sort((a,b)=>updatedAtMs(b)-updatedAtMs(a)),report?.({restored:kept.length,bytesRead,deferred,expired:stale.length,unreadable}),kept}function tightenExistingPermissions(dir){tightenDirPermissionsSync(dir);let names;try{names=readdirSync(dir)}catch{return}for(let name of names)if(name.endsWith(".json"))tightenFilePermissionsSync(join(dir,name))}function fileFreezeSink(dir=defaultPtyFreezeDir()){return tightenExistingPermissions(dir),{save(record){try{mkdirSync(dir,{recursive:!0,mode:OWNER_ONLY_DIR_MODE});let target=recordFile(dir,record.key),staging=`${target}.${process.pid}.tmp`;writeFileSync(staging,JSON.stringify(record),{encoding:"utf8",mode:OWNER_ONLY_FILE_MODE}),renameSync(staging,target)}catch{}},drop(key){try{rmSync(recordFile(dir,key),{force:!0})}catch{}}}}function clearFrozenSessions(dir=defaultPtyFreezeDir()){try{rmSync(dir,{recursive:!0,force:!0})}catch{}}
3
3
  export{freshModeTrack,scanTerminalModes,terminalModePreamble,freezeSession,thawSession,FREEZE_TTL_MS,FREEZE_RESTORE_MAX_BYTES,loadFrozenSessions,fileFreezeSink,clearFrozenSessions};
@@ -0,0 +1,4 @@
1
+ // @bun
2
+ import{ROVE_PRODUCT_NAME}from"./chunk-zt7wfnva.js";var SEARCH_TIMEOUT_MS=5000,CLI_NAME=ROVE_PRODUCT_NAME,FIRST_PARTY=[{ref:"Sma1lboy/rove-plugins/notify",desc:"Desktop/ntfy notifications when an agent finishes or needs input"},{ref:"Sma1lboy/rove-plugins/github-start",desc:"Start a Rove task from a GitHub issue or PR"},{ref:"Sma1lboy/rove-plugins/worktree-include",desc:"Copy .worktreeinclude-matched files into new worktrees"},{ref:"Sma1lboy/rove-plugins/linear-start",desc:"Pick a Linear issue (fzf) and start a task on its branch"},{ref:"Sma1lboy/rove-plugins/lazygit",desc:"lazygit on the task worktree, as a pane tab"},{ref:"Sma1lboy/rove-plugins/browser",desc:"Chromium rendered as terminal cells (carbonyl) in a pane tab"}];async function fetchTopic(topic,query){let q=encodeURIComponent(`topic:${topic}${query?` ${query}`:""}`),ctrl=new AbortController,timer=setTimeout(()=>ctrl.abort(),SEARCH_TIMEOUT_MS);try{let res=await fetch(`https://api.github.com/search/repositories?q=${q}&sort=stars&order=desc&per_page=50`,{signal:ctrl.signal,headers:{accept:"application/vnd.github+json"}});if(!res.ok)return null;let body=await res.json();if(!Array.isArray(body.items))return null;return body.items.filter((r)=>typeof r.full_name==="string").map((r)=>({ref:r.full_name,desc:r.description??"",stars:r.stargazers_count}))}catch{return null}finally{clearTimeout(timer)}}async function fetchMarketplace(query){let topicResults=await Promise.all([fetchTopic("rove-plugin",query)]),lower=query?.toLowerCase(),seeds=FIRST_PARTY.filter((s)=>!lower||`${s.ref} ${s.desc}`.toLowerCase().includes(lower)).map((s)=>({...s,firstParty:!0}));return{entries:dedupeEntries([...seeds,...topicResults.flatMap((result)=>result??[])]),offline:topicResults.every((result)=>result===null)}}async function searchMarketplace(query){let{entries,offline}=await fetchMarketplace(query);if(offline)console.error("(GitHub search unreachable \u2014 showing first-party plugins only)");if(entries.length===0){console.log(query?`no plugins match \`${query}\``:"no plugins found");return}let width=Math.min(48,Math.max(...entries.map((e)=>e.ref.length))+2);for(let e of entries){let stars=e.stars!==void 0?`\u2605${e.stars}`:e.firstParty?"first-party":"";console.log(`${e.ref.padEnd(width)}${stars.padEnd(12)}${e.desc}`)}console.log(`
3
+ install: ${CLI_NAME} plugin install <owner/repo[/subdir]> \u2014 browse: https://rove.run/plugins`)}function dedupeEntries(entries){let seen=new Set;return entries.filter((entry)=>{let key=entry.ref.toLowerCase();if(seen.has(key))return!1;return seen.add(key),!0})}
4
+ export{fetchMarketplace,searchMarketplace};
@@ -0,0 +1,2 @@
1
+ // @bun
2
+ import{ensureForwards}from"./chunk-9jsm6h5y.js";import{dedupeMachines,listMachines,localDaemonSocketPath}from"./chunk-9aydqazr.js";import{ApiError}from"./chunk-f7zjggfv.js";import"./chunk-7q43tysm.js";import"./chunk-mw0ysrpd.js";import"./chunk-a7kq09ke.js";import"./chunk-prqeddy7.js";import"./chunk-zt7wfnva.js";import"./chunk-yt15y085.js";import{RoveDaemonClient}from"./chunk-adkva3ep.js";import"./chunk-0422g8ac.js";import"./chunk-hq9tbzqa.js";import"./chunk-pn5ygqn6.js";import"./chunk-npwzmmv9.js";import"./chunk-b39sdtt0.js";import"./chunk-nc46gddg.js";import"./chunk-wqfp8d9w.js";function remoteTaskUnsupported(taskId,machineId){return new ApiError(`task ${taskId} lives on machine "${machineId}". Rove can list it, but acting on a remote task is not supported yet.`,"NOT_YET_SUPPORTED_REMOTE",{taskId,machineId,hint:`run the command on ${machineId} itself; remote writes arrive in a later release`,nextCommandArgs:["machine","list"]})}async function machineTasks(entry){let socketPath=localDaemonSocketPath(entry.alias),direct=await tasksOf(socketPath);if(direct)return direct;if(!entry.sockets)return null;return await ensureForwards({alias:entry.alias,config:entry,remoteDaemonSocket:entry.sockets.daemon,remotePtySocket:entry.sockets.pty})?await tasksOf(socketPath):null}async function tasksOf(socketPath){let client=new RoveDaemonClient(socketPath);try{return await client.request("hello",{}),(await client.request("task.list")).tasks??[]}catch{return null}finally{client.close()}}async function mergeTaskList(local){let machines=dedupeMachines(listMachines());if(machines.length===0)return local;let tasks=(local.tasks??[]).map((task)=>({...task,origin:{machineId:"local",hostLabel:"local"}}));for(let entry of machines){let remote=await machineTasks(entry);if(!remote)continue;let hostLabel=entry.alias;for(let task of remote)tasks.push({...task,origin:{machineId:entry.alias,hostLabel}})}return{tasks}}async function assertLocalTask(taskId){if(!taskId)return;let machines=dedupeMachines(listMachines());if(machines.length===0)return;for(let entry of machines){let remote=await machineTasks(entry);if(!remote)continue;if(remote.some((task)=>task.id===taskId))throw remoteTaskUnsupported(taskId,entry.alias)}}export{mergeTaskList,assertLocalTask};
@@ -1,2 +1,2 @@
1
1
  // @bun
2
- import{currentLang,intlLocale,localeState,setLocaleLang,t,tKeys}from"./chunk-vdcn6h48.js";import"./chunk-ge30p4s5.js";import"./chunk-nhakrm1f.js";import"./chunk-wqfp8d9w.js";export{tKeys,t,setLocaleLang,localeState,intlLocale,currentLang};
2
+ import{currentLang,intlLocale,localeState,setLocaleLang,t,tKeys}from"./chunk-snhcvjdb.js";import"./chunk-zt49bbg9.js";import"./chunk-nhakrm1f.js";import"./chunk-wqfp8d9w.js";export{tKeys,t,setLocaleLang,localeState,intlLocale,currentLang};
@@ -0,0 +1,2 @@
1
+ // @bun
2
+ import{describeRepoInitSources,missingDependenciesCoda,resolveEngineLaunchInit,resolveRepoInit}from"./chunk-dkgxz9hf.js";import"./chunk-hpay0ax8.js";import"./chunk-h9cg0j3a.js";import"./chunk-40dgv828.js";import"./chunk-3342qzve.js";import"./chunk-7q43tysm.js";import"./chunk-mw0ysrpd.js";import"./chunk-a7kq09ke.js";import"./chunk-prqeddy7.js";import"./chunk-zt7wfnva.js";import"./chunk-yt15y085.js";import"./chunk-pn5ygqn6.js";import"./chunk-npwzmmv9.js";import"./chunk-b39sdtt0.js";import"./chunk-nc46gddg.js";import"./chunk-wqfp8d9w.js";export{resolveRepoInit,resolveEngineLaunchInit,missingDependenciesCoda,describeRepoInitSources};
@@ -1,3 +1,3 @@
1
1
  // @bun
2
- function reduceActivity(previous,kind,detail){switch(kind){case"session-start":case"session-end":case"turn-interrupted":return"idle";case"turn-start":return"running";case"turn-complete":return previous==="running"||previous==="permission_needed"||previous===void 0?"turn_complete":previous;case"turn-failed":return detail?.failure==="rate_limit"||detail?.failure==="billing"?"rate_limited":"error";case"awaiting-input":return"permission_needed";default:return previous??"idle"}}var DEFAULT_ENGINE_STATE_TTL_MS=600000,STICKY_STATES=new Set(["turn_complete","permission_needed","error","rate_limited","dead"]);function resolveEngineStateTtlMs(){let raw=process.env.KOBE_ENGINE_STATE_TTL_MS;if(raw===void 0)return DEFAULT_ENGINE_STATE_TTL_MS;let n=Number(raw);return Number.isFinite(n)&&n>0?n:DEFAULT_ENGINE_STATE_TTL_MS}function activityStillWorking(live,at,now,staleMs){if(!live)return!1;if(live.unknown)return!0;if(live.completedAt!==void 0&&live.completedAt>=at)return!1;return live.mtimeMs!==void 0&&live.mtimeMs>now-staleMs}
2
+ function reduceActivity(previous,kind,detail){switch(kind){case"session-start":case"session-end":case"turn-interrupted":return"idle";case"turn-start":return"running";case"turn-complete":return previous==="running"||previous==="permission_needed"||previous===void 0?"turn_complete":previous;case"turn-failed":return detail?.failure==="rate_limit"||detail?.failure==="billing"?"rate_limited":"error";case"awaiting-input":return"permission_needed";default:return previous??"idle"}}var DEFAULT_ENGINE_STATE_TTL_MS=600000,STICKY_STATES=new Set(["turn_complete","permission_needed","error","rate_limited","dead"]);function resolveEngineStateTtlMs(){let raw=process.env.ROVE_ENGINE_STATE_TTL_MS;if(raw===void 0)return DEFAULT_ENGINE_STATE_TTL_MS;let n=Number(raw);return Number.isFinite(n)&&n>0?n:DEFAULT_ENGINE_STATE_TTL_MS}function activityStillWorking(live,at,now,staleMs){if(!live)return!1;if(live.unknown)return!0;if(live.completedAt!==void 0&&live.completedAt>=at)return!1;return live.mtimeMs!==void 0&&live.mtimeMs>now-staleMs}
3
3
  export{reduceActivity,STICKY_STATES,resolveEngineStateTtlMs,activityStillWorking};
@@ -0,0 +1,2 @@
1
+ // @bun
2
+ import{pathRejection,projectRejection,rejectionReason}from"./chunk-3342qzve.js";import"./chunk-prqeddy7.js";import"./chunk-zt7wfnva.js";import"./chunk-pn5ygqn6.js";import"./chunk-b39sdtt0.js";import"./chunk-nc46gddg.js";import"./chunk-wqfp8d9w.js";export{rejectionReason,projectRejection,pathRejection};
@@ -0,0 +1,2 @@
1
+ // @bun
2
+ import{ensureGlobalRoveHooks,readStdinText,readTextWithTimeout,runHookSubcommand}from"./chunk-h33m6cc6.js";import"./chunk-17e2tgyg.js";import"./chunk-2bgmby1d.js";import"./chunk-rqyaf0dw.js";import"./chunk-y8tysjc2.js";import"./chunk-576r5nht.js";import"./chunk-w7zv47mp.js";import"./chunk-2tfnscxk.js";import"./chunk-zsfyj36g.js";import"./chunk-96cjpssp.js";import"./chunk-9w5g7frx.js";import"./chunk-gvrtrvnz.js";import"./chunk-2brn8e1y.js";import"./chunk-yexx8nec.js";import"./chunk-znjcesdr.js";import"./chunk-7kysxgbq.js";import"./chunk-qzsahxd9.js";import"./chunk-xy8be792.js";import"./chunk-h2m7em1e.js";import"./chunk-tdhk4dz8.js";import"./chunk-h9cg0j3a.js";import"./chunk-40dgv828.js";import"./chunk-3342qzve.js";import"./chunk-7q43tysm.js";import"./chunk-mw0ysrpd.js";import"./chunk-a7kq09ke.js";import"./chunk-prqeddy7.js";import"./chunk-zt7wfnva.js";import"./chunk-yt15y085.js";import"./chunk-adkva3ep.js";import"./chunk-0422g8ac.js";import"./chunk-hq9tbzqa.js";import"./chunk-pn5ygqn6.js";import"./chunk-npwzmmv9.js";import"./chunk-b39sdtt0.js";import"./chunk-nc46gddg.js";import"./chunk-wqfp8d9w.js";export{runHookSubcommand,readTextWithTimeout,readStdinText,ensureGlobalRoveHooks};
@@ -0,0 +1,2 @@
1
+ // @bun
2
+ import{ENGINE_NOT_OBSERVED_REASON,ENGINE_START_POLL_MS,ENGINE_START_PROBE_MS,deliverHostedPrompt,deliverToKey,ensurePtyHost,findEngineKey,isTaskKey,killTaskSessions,listSessions,listSessionsOrNull,openPtyHost,outcomeFields,taskKeys}from"./chunk-zx2n95qe.js";import"./chunk-bn73kd6z.js";import"./chunk-yxt1y0n3.js";import"./chunk-cbjh43yc.js";import"./chunk-2apszxn2.js";import"./chunk-sak1tphp.js";import"./chunk-x9s14ppv.js";import"./chunk-rxqdw6s5.js";import"./chunk-4250pw6r.js";import"./chunk-nckmga7j.js";import"./chunk-vjvkkrzc.js";import"./chunk-pdvyfz3n.js";import"./chunk-dkgxz9hf.js";import"./chunk-hpay0ax8.js";import"./chunk-g5c5jytr.js";import"./chunk-y8tysjc2.js";import"./chunk-576r5nht.js";import"./chunk-w7zv47mp.js";import"./chunk-2tfnscxk.js";import"./chunk-etfh8f4z.js";import"./chunk-f7zjggfv.js";import"./chunk-zsfyj36g.js";import"./chunk-96cjpssp.js";import"./chunk-9w5g7frx.js";import"./chunk-gvrtrvnz.js";import"./chunk-ag3txfg2.js";import"./chunk-2brn8e1y.js";import"./chunk-yexx8nec.js";import"./chunk-znjcesdr.js";import"./chunk-7kysxgbq.js";import"./chunk-qzsahxd9.js";import"./chunk-xy8be792.js";import"./chunk-h2m7em1e.js";import"./chunk-tdhk4dz8.js";import"./chunk-h9cg0j3a.js";import"./chunk-40dgv828.js";import"./chunk-3342qzve.js";import"./chunk-7q43tysm.js";import"./chunk-mw0ysrpd.js";import"./chunk-a7kq09ke.js";import"./chunk-prqeddy7.js";import"./chunk-zt7wfnva.js";import"./chunk-yt15y085.js";import"./chunk-snhcvjdb.js";import"./chunk-zt49bbg9.js";import"./chunk-nhakrm1f.js";import"./chunk-pxk2c2vj.js";import"./chunk-adkva3ep.js";import"./chunk-0422g8ac.js";import"./chunk-hq9tbzqa.js";import"./chunk-pn5ygqn6.js";import"./chunk-npwzmmv9.js";import"./chunk-b39sdtt0.js";import"./chunk-nc46gddg.js";import"./chunk-wqfp8d9w.js";export{taskKeys,outcomeFields,openPtyHost,listSessionsOrNull,listSessions,killTaskSessions,isTaskKey,findEngineKey,ensurePtyHost,deliverToKey,deliverHostedPrompt,ENGINE_START_PROBE_MS,ENGINE_START_POLL_MS,ENGINE_NOT_OBSERVED_REASON};
@@ -1,9 +1,9 @@
1
1
  // @bun
2
- import{deliverPromptToLiveEngineAdapter,deliverPromptToLiveEngineDetailedAdapter,deliverPromptToLiveEngineTabDetailedAdapter,deriveTitleFromSession,ensureTaskSessionAdapter,startTaskSessionWithPromptAdapter,tearDownTaskSessionAdapter}from"./chunk-hp32tbes.js";import{resolvePluginBinPath}from"./chunk-6x5vzzpx.js";import{Orchestrator}from"./chunk-6s5mev2n.js";import{GH_PR_VIEW_FIELDS,classifyGhFailure,mapGhPrView,nextPrPoll,samePrStatus}from"./chunk-t3wwsz29.js";import{GitWorktreeManager,parseDirtyPaths}from"./chunk-gmgsxdrf.js";import"./chunk-2cwb64fj.js";import{auditDeletionBranchKept,auditDeletionResidue,auditDeletionSalvaged,auditWorktreeResidue,auditWorktreeSalvaged,parseAheadBehind,startDaemonServer}from"./chunk-gqphk56d.js";import"./chunk-85pk7c74.js";import"./chunk-53afdybj.js";import"./chunk-rz8zs7j8.js";import{affectsActivityState,isEngineActivityKind}from"./chunk-17e2tgyg.js";import{PLACEHOLDER_TASK_TITLE}from"./chunk-ch0ehc06.js";import"./chunk-mppda1wq.js";import"./chunk-mhg40es1.js";import"./chunk-r2pztgm6.js";import"./chunk-1da3bqjc.js";import"./chunk-85mk6j0s.js";import"./chunk-xsrcwcjc.js";import"./chunk-nh4wvyz3.js";import{TaskIndexStore}from"./chunk-zja9chrd.js";import"./chunk-qkehg2c1.js";import{autoStatusEnabled}from"./chunk-n24dmy2r.js";import{execHostForWorktreePath}from"./chunk-dnbh8hsm.js";import"./chunk-2apszxn2.js";import"./chunk-g2advs8t.js";import{GENERIC_PROTOCOL,engineDisplayName,engineProtocolKey,getEngineProtocol,kobeApiInvocation,protocolEntry,resolveCommandProtocol,sessionProtocol}from"./chunk-ygd572ee.js";import{installDaemonCrashHandlers,logDaemonInfo}from"./chunk-rcyasw34.js";import"./chunk-7q67dz4c.js";import"./chunk-jhbc9nx2.js";import"./chunk-exfyqsdd.js";import"./chunk-s278gjet.js";import"./chunk-egx76ah2.js";import"./chunk-hape5vwj.js";import{foregroundEngineIn,parsePsSnapshot,psSnapshot}from"./chunk-j6kataan.js";import{createEngineTurnDetector,engineEntry,engineTitleTurnHint,vendorsWithQuotaProbe}from"./chunk-ssfj9td0.js";import{availableEngineIds}from"./chunk-zwej00t0.js";import"./chunk-w7zv47mp.js";import{spawnCapture}from"./chunk-khj0apc7.js";import"./chunk-g3r1dwy9.js";import"./chunk-w25b7xxz.js";import"./chunk-dq2mh3b3.js";import{parsePorcelain}from"./chunk-k6nxyxyh.js";import"./chunk-h4n8ffqy.js";import{DEFAULT_BASE_REF_CANDIDATES,readHeadSha,readRefSha,resolveGitDirs}from"./chunk-vyb5a2rh.js";import{readOnlyGitProcessEnv}from"./chunk-6xppe9bj.js";import"./chunk-jvxh93nz.js";import{connectOrStartDaemon,daemonSpawnReason}from"./chunk-wtqxv2rv.js";import{stopDaemonProcess}from"./chunk-pz907kve.js";import"./chunk-2brn8e1y.js";import"./chunk-y3k1accw.js";import"./chunk-bw73t1zw.js";import"./chunk-7kysxgbq.js";import"./chunk-2xsem13q.js";import{DEFAULT_TASK_VENDOR,isTaskStatus}from"./chunk-xy8be792.js";import{BUILTIN_VENDORS,isBuiltinVendor}from"./chunk-05jej26n.js";import{SUBCOMMAND_VERBS}from"./chunk-fhch0x0q.js";import{CURRENT_VERSION,checkLatestVersion}from"./chunk-be757xzj.js";import{backfillSavedReposFromProjects,getCustomEngineIds,getPersistedString,getRemoteRepoConfig,getSavedRepos,setPersistedString}from"./chunk-32mv1yy6.js";import"./chunk-40dgv828.js";import"./chunk-mkksdcsw.js";import{activeCliName}from"./chunk-ppwpjm39.js";import{migrateRoveDaemonStateLayout}from"./chunk-fxs82dsx.js";import"./chunk-zyd6k6ak.js";import"./chunk-8hbtca1g.js";import{releaseSync}from"./chunk-hq2n27y1.js";import"./chunk-sb0ns0c7.js";import{isProcessAlive,readPidFile}from"./chunk-vnpqemb0.js";import"./chunk-9prawccj.js";import"./chunk-ge30p4s5.js";import"./chunk-nhakrm1f.js";import"./chunk-pxk2c2vj.js";import{KobeDaemonClient}from"./chunk-qagek3wg.js";import"./chunk-544bwsss.js";import"./chunk-hqbmzz4t.js";import"./chunk-3es6spp4.js";import{rotateLogIfNeeded}from"./chunk-pw6yfj10.js";import"./chunk-f10n6063.js";import{defaultDaemonLogPath,defaultDaemonPidPath,defaultDaemonSocketPath}from"./chunk-y8fqdnh3.js";import{readRoveHomeDirEnv}from"./chunk-hq4b3fca.js";import"./chunk-wqfp8d9w.js";function sniffProtocolFromTitle(title){let trimmed=title?.trim();if(!trimmed)return null;let owners=new Map;for(let vendor of BUILTIN_VENDORS)for(let glyph of engineEntry(vendor).terminalTitle?.statusPrefixes??[])owners.set(glyph,[...owners.get(glyph)??[],vendor]);for(let glyph of[...owners.keys()].sort((a,b)=>b.length-a.length)){if(!trimmed.startsWith(glyph))continue;if(trimmed.slice(glyph.length).trim().length===0)continue;let vendors=owners.get(glyph)??[];if(vendors.length===1)return vendors[0];return null}return null}function protocolUpgradeFromLiveSession(task,evidence){let command=task.command?.trim();if(!command)return null;if(task.vendor&&isBuiltinVendor(task.vendor))return null;if(resolveCommandProtocol(command)!==GENERIC_PROTOCOL)return null;let walk=evidence.walkVendor,vendor=walk!==null&&isBuiltinVendor(walk)?walk:sniffProtocolFromTitle(evidence.title);return vendor?{command,vendor}:null}function protocolWriteBackFromLiveSession(task,evidence,customEngineIds){let id=task.vendor?.trim();if(!id)return null;if(getEngineProtocol(id)!==void 0)return null;if(!customEngineIds.includes(id))return null;let walk=evidence.walkVendor;return walk!==null&&isBuiltinVendor(walk)?{id,protocol:walk}:null}async function latestTranscriptMtime(vendor,worktree){if(!worktree)return 0;return protocolEntry(vendor).history.latestTranscriptMtimeForWorktree(worktree)}async function maybeAutoStart(orch,taskId,enabled=autoStatusEnabled){if(!enabled())return"skipped";let task=orch.getTask(taskId);if(!task)return"skipped";if((task.kind??"task")==="main")return"skipped";if(task.status!=="backlog")return"skipped";return await orch.setStatus(taskId,"in_progress"),"moved"}var SYNC_TIMEOUT_MS=60000,SYNC_CONFLICT="SYNC_CONFLICT",SYNC_DIRTY="SYNC_WORKTREE_DIRTY";async function git(cwd,args,signal,write=!1){return spawnCapture("git",args,{cwd,env:write?process.env:readOnlyGitProcessEnv(),signal})}function parseConflictedPaths(stdout){return stdout.split(`
2
+ import{deliverPromptToLiveEngineAdapter,deliverPromptToLiveEngineDetailedAdapter,deliverPromptToLiveEngineTabDetailedAdapter,deriveTitleFromSession,ensureTaskSessionAdapter,startTaskSessionWithPromptAdapter,tearDownTaskSessionAdapter}from"./chunk-fg62y5fm.js";import{resolvePluginBinPath}from"./chunk-b0ssvpht.js";import{Orchestrator}from"./chunk-nzh30nty.js";import{GH_PR_VIEW_FIELDS,classifyGhFailure,mapGhPrView,nextPrPoll,samePrStatus}from"./chunk-tvk46rfs.js";import{GitWorktreeManager,parseDirtyPaths}from"./chunk-m4f5h05c.js";import"./chunk-n5dea05t.js";import{auditDeletionBranchKept,auditDeletionResidue,auditDeletionSalvaged,auditWorktreeResidue,auditWorktreeSalvaged,parseAheadBehind,startDaemonServer}from"./chunk-ekg3h5z3.js";import"./chunk-xx166cdv.js";import"./chunk-axsm0gn5.js";import"./chunk-0mj358p5.js";import{TaskIndexStore}from"./chunk-h7y9v8k1.js";import{affectsActivityState,isEngineActivityKind}from"./chunk-17e2tgyg.js";import{PLACEHOLDER_TASK_TITLE}from"./chunk-cbc1h345.js";import"./chunk-qvfdqrbf.js";import"./chunk-4hestsjp.js";import"./chunk-2bgmby1d.js";import"./chunk-rqyaf0dw.js";import"./chunk-41x1hrqe.js";import"./chunk-5mhvjytn.js";import"./chunk-atn06ncf.js";import"./chunk-qkehg2c1.js";import{autoStatusEnabled}from"./chunk-yxt1y0n3.js";import{execHostForWorktreePath}from"./chunk-cbjh43yc.js";import"./chunk-2apszxn2.js";import"./chunk-sak1tphp.js";import{GENERIC_PROTOCOL,engineDisplayName,engineProtocolKey,getEngineProtocol,protocolEntry,resolveCommandProtocol,roveApiInvocation,sessionProtocol}from"./chunk-x9s14ppv.js";import{installDaemonCrashHandlers,logDaemonInfo}from"./chunk-rxqdw6s5.js";import"./chunk-4250pw6r.js";import"./chunk-nckmga7j.js";import"./chunk-vjvkkrzc.js";import"./chunk-pdvyfz3n.js";import"./chunk-dkgxz9hf.js";import"./chunk-hpay0ax8.js";import{foregroundEngineIn,parsePsSnapshot,psSnapshot}from"./chunk-g5c5jytr.js";import{createEngineTurnDetector,engineEntry,engineTitleTurnHint,vendorsWithQuotaProbe}from"./chunk-y8tysjc2.js";import{availableEngineIds}from"./chunk-576r5nht.js";import"./chunk-w7zv47mp.js";import{spawnCapture}from"./chunk-2tfnscxk.js";import"./chunk-w2sp489k.js";import"./chunk-etfh8f4z.js";import"./chunk-xv8fhxxm.js";import{parsePorcelain}from"./chunk-dgs0m8r4.js";import"./chunk-dmzg9zdc.js";import{DEFAULT_BASE_REF_CANDIDATES,readHeadSha,readRefSha,resolveGitDirs}from"./chunk-kg9kmwt9.js";import{readOnlyGitProcessEnv}from"./chunk-6xppe9bj.js";import"./chunk-zsfyj36g.js";import{connectOrStartDaemon,daemonSpawnReason}from"./chunk-96cjpssp.js";import{stopDaemonProcess}from"./chunk-9w5g7frx.js";import"./chunk-gvrtrvnz.js";import"./chunk-2brn8e1y.js";import"./chunk-yexx8nec.js";import"./chunk-znjcesdr.js";import"./chunk-7kysxgbq.js";import"./chunk-qzsahxd9.js";import{DEFAULT_TASK_VENDOR,isTaskStatus}from"./chunk-xy8be792.js";import{BUILTIN_VENDORS,isBuiltinVendor}from"./chunk-h2m7em1e.js";import{migrateRoveDaemonStateLayout}from"./chunk-tdhk4dz8.js";import{SUBCOMMAND_VERBS}from"./chunk-fhch0x0q.js";import{CURRENT_VERSION,checkLatestVersion}from"./chunk-a0ave3g6.js";import{backfillSavedReposFromProjects,getCustomEngineIds,getPersistedString,getRemoteRepoConfig,getSavedRepos,setPersistedString}from"./chunk-h9cg0j3a.js";import"./chunk-40dgv828.js";import"./chunk-3342qzve.js";import"./chunk-7q43tysm.js";import{releaseSync}from"./chunk-mw0ysrpd.js";import{isProcessAlive,readPidFile}from"./chunk-a7kq09ke.js";import"./chunk-prqeddy7.js";import{ROVE_PRODUCT_NAME}from"./chunk-zt7wfnva.js";import"./chunk-yt15y085.js";import"./chunk-zt49bbg9.js";import"./chunk-nhakrm1f.js";import"./chunk-pxk2c2vj.js";import{RoveDaemonClient}from"./chunk-adkva3ep.js";import"./chunk-0422g8ac.js";import{rotateLogIfNeeded}from"./chunk-hq9tbzqa.js";import"./chunk-pn5ygqn6.js";import{defaultDaemonLogPath,defaultDaemonPidPath,defaultDaemonSocketPath}from"./chunk-npwzmmv9.js";import"./chunk-b39sdtt0.js";import{readRoveHomeDirEnv}from"./chunk-nc46gddg.js";import"./chunk-wqfp8d9w.js";function sniffProtocolFromTitle(title){let trimmed=title?.trim();if(!trimmed)return null;let owners=new Map;for(let vendor of BUILTIN_VENDORS)for(let glyph of engineEntry(vendor).terminalTitle?.statusPrefixes??[])owners.set(glyph,[...owners.get(glyph)??[],vendor]);for(let glyph of[...owners.keys()].sort((a,b)=>b.length-a.length)){if(!trimmed.startsWith(glyph))continue;if(trimmed.slice(glyph.length).trim().length===0)continue;let vendors=owners.get(glyph)??[];if(vendors.length===1)return vendors[0];return null}return null}function protocolUpgradeFromLiveSession(task,evidence){let command=task.command?.trim();if(!command)return null;if(task.vendor&&isBuiltinVendor(task.vendor))return null;if(resolveCommandProtocol(command)!==GENERIC_PROTOCOL)return null;let walk=evidence.walkVendor,vendor=walk!==null&&isBuiltinVendor(walk)?walk:sniffProtocolFromTitle(evidence.title);return vendor?{command,vendor}:null}function protocolWriteBackFromLiveSession(task,evidence,customEngineIds){let id=task.vendor?.trim();if(!id)return null;if(getEngineProtocol(id)!==void 0)return null;if(!customEngineIds.includes(id))return null;let walk=evidence.walkVendor;return walk!==null&&isBuiltinVendor(walk)?{id,protocol:walk}:null}async function latestTranscriptMtime(vendor,worktree){if(!worktree)return 0;return protocolEntry(vendor).history.latestTranscriptMtimeForWorktree(worktree)}async function maybeAutoStart(orch,taskId,enabled=autoStatusEnabled){if(!enabled())return"skipped";let task=orch.getTask(taskId);if(!task)return"skipped";if((task.kind??"task")==="main")return"skipped";if(task.status!=="backlog")return"skipped";return await orch.setStatus(taskId,"in_progress"),"moved"}var SYNC_TIMEOUT_MS=60000,SYNC_CONFLICT="SYNC_CONFLICT",SYNC_DIRTY="SYNC_WORKTREE_DIRTY";async function git(cwd,args,signal,write=!1){return spawnCapture("git",args,{cwd,env:write?process.env:readOnlyGitProcessEnv(),signal})}function parseConflictedPaths(stdout){return stdout.split(`
3
3
  `).map((line)=>line.trim()).filter((line)=>line.length>0)}async function syncWorktreeWithBase(worktreePath,baseRef,signal){let status=await git(worktreePath,["status","--porcelain=v1"],signal);if(status.status!==0)throw Error("git status failed");let dirty=parseDirtyPaths(status.stdout);if(dirty.length>0)throw Error(`${SYNC_DIRTY}: ${dirty.join(", ")}`);let before=await git(worktreePath,["rev-parse","HEAD"],signal),merge=await git(worktreePath,["merge","--no-edit",baseRef],signal,!0);if(merge.status!==0){let conflicted=await git(worktreePath,["diff","--name-only","--diff-filter=U"],signal),paths=parseConflictedPaths(conflicted.stdout);if(paths.length>0)throw Error(`${SYNC_CONFLICT}: ${paths.join(", ")}`);let detail=merge.stderr?.trim();throw Error(detail?`git merge ${baseRef} failed \u2014 ${detail}`:`git merge ${baseRef} failed`)}let after=await git(worktreePath,["rev-parse","HEAD"],signal);return{baseRef,alreadyCurrent:before.status===0&&before.stdout.trim()===after.stdout.trim()}}import{readFileSync}from"fs";import{join}from"path";var BASE_REF_TTL_MS=300000,cache=new Map;async function git2(worktreePath,args,signal){return await spawnCapture("git",[...args],{cwd:worktreePath,env:readOnlyGitProcessEnv(),signal})}async function refExists(worktreePath,ref,signal){return(await git2(worktreePath,["rev-parse","--verify","--quiet",ref],signal)).status===0}async function sharesHistory(worktreePath,ref,signal){return(await git2(worktreePath,["merge-base",ref,"HEAD"],signal)).status===0}async function baseCheckoutBranchFromGit(worktreePath,signal){let out=await git2(worktreePath,["worktree","list","--porcelain"],signal);if(out.status!==0)return null;return(out.stdout.split(`
4
4
 
5
5
  `,1)[0]??"").split(`
6
- `).find((l)=>l.startsWith("branch "))?.slice(7).trim().replace(/^refs\/heads\//,"")||null}function readRefSymbolic(dirs,ref){for(let dir of[dirs.gitDir,dirs.commonDir])try{let target=readFileSync(join(dir,ref),"utf8").trim().match(/^ref:\s*(.+)$/)?.[1]?.trim();if(target)return target}catch{}return null}function ladderFromFiles(worktreePath){let dirs=resolveGitDirs(worktreePath);if(!dirs)return;let originHead=readRefSymbolic(dirs,"refs/remotes/origin/HEAD")?.replace(/^refs\/remotes\//,""),baseCheckout=readRefSymbolic({gitDir:dirs.commonDir,commonDir:dirs.commonDir},"HEAD")?.replace(/^refs\/heads\//,""),names=[],head=readHeadSha(dirs),parts=[`HEAD=${head}`];for(let guess of[...originHead?[originHead]:[],...DEFAULT_BASE_REF_CANDIDATES,...baseCheckout?[baseCheckout]:[]]){if(names.includes(guess))continue;let sha=readRefSha(dirs,guess);if(sha===null)continue;names.push(guess),parts.push(`${guess}=${sha}`)}return{names,fingerprint:head===null?null:parts.join(",")}}async function ladderFromGit(worktreePath,signal){let head=await git2(worktreePath,["symbolic-ref","--short","refs/remotes/origin/HEAD"],signal),originHead=head.status===0?head.stdout.trim():"",baseCheckout=await baseCheckoutBranchFromGit(worktreePath,signal),names=[],candidates=[...originHead?[originHead]:[],...DEFAULT_BASE_REF_CANDIDATES,...baseCheckout?[baseCheckout]:[]];for(let guess of candidates){if(names.includes(guess))continue;if(await refExists(worktreePath,guess,signal))names.push(guess)}return{names,fingerprint:null}}async function resolveBaseRefCached(worktreePath,recordedBaseRef,signal,now=Date.now()){if(recordedBaseRef){let dirs=resolveGitDirs(worktreePath);if(dirs&&readRefSha(dirs,recordedBaseRef)!==null)return recordedBaseRef;if(await refExists(worktreePath,recordedBaseRef,signal))return recordedBaseRef}let hit=cache.get(worktreePath);if(hit&&now-hit.at<BASE_REF_TTL_MS)return hit.ref;let ladder=ladderFromFiles(worktreePath)??await ladderFromGit(worktreePath,signal);if(hit&&ladder.fingerprint!==null&&hit.fingerprint===ladder.fingerprint)return cache.set(worktreePath,{...hit,at:now}),hit.ref;let ref=null;for(let candidate of ladder.names)if(await sharesHistory(worktreePath,candidate,signal)){ref=candidate;break}return cache.set(worktreePath,{ref,at:now,fingerprint:ladder.fingerprint}),ref}var cache2=new Map;function readShas(worktreePath,baseRef){let dirs=resolveGitDirs(worktreePath);if(!dirs)return null;let head=readHeadSha(dirs),base=readRefSha(dirs,baseRef);return head&&base?{head,base}:null}async function driftCached(worktreePath,baseRef,compute){let shas=readShas(worktreePath,baseRef),hit=shas?cache2.get(worktreePath):void 0;if(shas&&hit&&hit.head===shas.head&&hit.base===shas.base)return hit.value;let value=await compute();if(shas&&value!==null)cache2.set(worktreePath,{...shas,value});return value}import{statSync}from"fs";function judgeWorktree(signals,nowMs){if(signals.dirty)return{verdict:"active",reason:"dirty"};if(signals.prState==="open")return{verdict:"active",reason:"prOpen"};if(signals.prState==="merged")return{verdict:"merged",reason:"prMerged"};if(signals.aheadOfDefault===0)return{verdict:"merged",reason:"inMain"};if(signals.prState==="closed")return{verdict:"stale",reason:"prClosed"};if(signals.lastActivityMs>0&&nowMs-signals.lastActivityMs>1209600000)return{verdict:"stale",reason:"idle"};return{verdict:"fresh",reason:"fresh"}}function parseGhPrList(stdout){let entries;try{entries=JSON.parse(stdout)}catch{return null}if(!Array.isArray(entries))return null;let rank={open:3,merged:2,closed:1},map=new Map;for(let entry of entries){let branch=entry?.headRefName,rawState=entry?.state;if(typeof branch!=="string"||typeof rawState!=="string")continue;let state=rawState.toLowerCase();if(state!=="open"&&state!=="merged"&&state!=="closed")continue;let cur=map.get(branch);if(!cur||rank[state]>rank[cur])map.set(branch,state)}return map}var TIMEOUT_MS=4000,manager=new GitWorktreeManager;function createdAt(path){try{let stat=statSync(path);return stat.birthtimeMs||stat.mtimeMs}catch{return 0}}async function run(path,argv){return execHostForWorktreePath(path).run(argv,{cwd:path,signal:AbortSignal.timeout(TIMEOUT_MS)})}async function branchOnRemote(path,branch){try{let out=await run(path,["git","ls-remote","--exit-code","--heads","origin",branch]);return out.exitCode===0?!0:out.exitCode===2?!1:null}catch{return null}}async function defaultRef(repo){try{let out=await run(repo,["git","symbolic-ref","--short","refs/remotes/origin/HEAD"]);if(out.exitCode===0&&out.stdout.trim())return out.stdout.trim()}catch{}for(let guess of["origin/main","origin/master"])try{if((await run(repo,["git","rev-parse","--verify","--quiet",guess])).exitCode===0)return guess}catch{}return null}async function prStates(repo){try{let origin=await run(repo,["git","remote","get-url","origin"]);if(origin.exitCode!==0||!origin.stdout.includes("github.com"))return null;let out=await run(repo,["gh","pr","list","--state","all","--limit","200","--json","headRefName,state"]);return out.exitCode===0?parseGhPrList(out.stdout):null}catch{return null}}async function ahead(path,ref){if(!ref)return null;try{let out=await run(path,["git","rev-list","--count",`${ref}..HEAD`]),value=Number.parseInt(out.stdout.trim(),10);return out.exitCode===0&&!Number.isNaN(value)?value:null}catch{return null}}async function listWorktreeProjectsAdapter(network){let repos=getSavedRepos().filter((repo)=>!getRemoteRepoConfig(repo)),now=Date.now();return Promise.all(repos.map(async(repo)=>{let[worktrees,states,ref]=await Promise.all([manager.listAll(repo),network?prStates(repo):null,defaultRef(repo)]),rows=await Promise.all(worktrees.map(async(worktree)=>{let[remote,aheadBy]=await Promise.all([network?branchOnRemote(worktree.path,worktree.branch):null,ahead(worktree.path,ref)]),judgement=judgeWorktree({dirty:worktree.dirty===!0,prState:states?.get(worktree.branch)??null,aheadOfDefault:aheadBy,lastActivityMs:worktree.lastActivityMs},now);return{...worktree,repo,createdAtMs:createdAt(worktree.path),branchOnRemote:remote,verdict:judgement.verdict,verdictReason:judgement.reason}}));return{repo,worktrees:rows}}))}async function listUnreadableWorktreesAdapter(repo){return manager.listUnreadableWorktrees(repo)}async function removeWorktreeAdapter(path,force){let residue=null;return await manager.remove(path,{force,onSalvage:(record)=>{if(record)auditWorktreeSalvaged(path,record.ref,record.commit,record.uncaptured)},onResidue:(r)=>{residue={path:r.path,reason:r.reason},auditWorktreeResidue(r.path,r.reason)}}),residue}function resolveProtocolUpgradeAndLearnPreset(task,evidence){let preset=protocolWriteBackFromLiveSession(task,evidence,getCustomEngineIds());if(preset)setPersistedString(engineProtocolKey(preset.id),preset.protocol);return protocolUpgradeFromLiveSession(task,evidence)}var daemonRuntime={currentVersion:CURRENT_VERSION,defaultTaskVendor:DEFAULT_TASK_VENDOR,placeholderTaskTitle:PLACEHOLDER_TASK_TITLE,isTaskStatus,isEngineActivityKind,affectsActivityState,async foregroundEngines(pids){let rows=parsePsSnapshot(await psSnapshot([...pids])),out=new Map;for(let pid of pids){let found=foregroundEngineIn(rows,pid);out.set(pid,found?{vendor:found.vendor,pid:found.pid}:null)}return out},titleTurnHint:(vendor,title)=>engineTitleTurnHint(sessionProtocol(vendor),title),resolveProtocolUpgrade:resolveProtocolUpgradeAndLearnPreset,readEngineTurns:async(vendor,transcriptPath)=>await protocolEntry(vendor).readTurns?.(transcriptPath)??[],checkLatestVersion,latestTranscriptMtime,deriveTitleFromSession,createEngineTurnDetector:(vendor)=>createEngineTurnDetector(sessionProtocol(vendor)),async runWorktreeStatus(worktreePath,signal,baseRef){let result=await spawnCapture("git",["status","--porcelain=v1"],{cwd:worktreePath,env:readOnlyGitProcessEnv(),signal});if(result.status!==0)throw Error("git status failed");let counts=parsePorcelain(result.stdout),base=await resolveBaseRefCached(worktreePath,baseRef,signal);if(!base)return counts;let drift=await driftCached(worktreePath,base,async()=>{let out=await spawnCapture("git",["rev-list","--left-right","--count",`${base}...HEAD`],{cwd:worktreePath,env:readOnlyGitProcessEnv(),signal});return out.status===0?parseAheadBehind(out.stdout):null});return drift===null?counts:{...counts,...drift}},maybeAutoStart:(orch,taskId)=>maybeAutoStart(orch,taskId),listWorktreeProjects:listWorktreeProjectsAdapter,listUnreadableWorktrees:listUnreadableWorktreesAdapter,removeWorktree:removeWorktreeAdapter,async syncWorktreeWithBase(worktreePath,recordedBaseRef){let controller=new AbortController,timer=setTimeout(()=>controller.abort(),SYNC_TIMEOUT_MS);try{let baseRef=await resolveBaseRefCached(worktreePath,recordedBaseRef,controller.signal);if(!baseRef)throw Error("no base ref resolves for this worktree");return await syncWorktreeWithBase(worktreePath,baseRef,controller.signal)}finally{clearTimeout(timer)}},availableEngineIds,engineDisplayName,kobeApiInvocation,engineEntry,ensureTaskSession:ensureTaskSessionAdapter,startTaskSessionWithPrompt:startTaskSessionWithPromptAdapter,tearDownTaskSession:tearDownTaskSessionAdapter,async readEngineContextUsage(vendor,sessionId){let read=protocolEntry(vendor).history.readUsageSnapshot;if(!read)return null;let snapshot=await read(sessionId);if(snapshot?.context_tokens===void 0)return null;return{contextTokens:snapshot.context_tokens,...snapshot.context_window_tokens===void 0?{}:{contextWindowTokens:snapshot.context_window_tokens},...snapshot.context_tokens_approximate?{approximate:!0}:{},...snapshot.input_tokens===void 0?{}:{inputTokens:snapshot.input_tokens},...snapshot.output_tokens===void 0?{}:{outputTokens:snapshot.output_tokens},...snapshot.cache_read_input_tokens===void 0?{}:{cacheReadTokens:snapshot.cache_read_input_tokens},...snapshot.cache_creation_input_tokens===void 0?{}:{cacheCreationTokens:snapshot.cache_creation_input_tokens}}},quotaUsage:(vendor)=>engineEntry(vendor).quotaUsage?.()??Promise.resolve(null),vendorsWithQuotaProbe,deliverPromptToLiveEngine:deliverPromptToLiveEngineAdapter,deliverPromptToLiveEngineDetailed:deliverPromptToLiveEngineDetailedAdapter,deliverPromptToLiveEngineTabDetailed:deliverPromptToLiveEngineTabDetailedAdapter,getPersistedString,setPersistedString,getSavedRepos:()=>[...getSavedRepos()],prStatus:{viewFields:GH_PR_VIEW_FIELDS,mapView:(view,at)=>mapGhPrView(view,at),sameStatus:samePrStatus,nextPoll:(outcome,failures,now,config,random)=>nextPrPoll(outcome,failures,now,config,random),classify:classifyGhFailure}};import{homedir}from"os";async function createKobeCore(options={}){let homeDir=options.homeDir??readRoveHomeDirEnv()??homedir(),store=new TaskIndexStore({homeDir});await store.load();let worktrees=new GitWorktreeManager,orchestrator=new Orchestrator({store,worktrees,onSalvage:(taskId,salvage)=>auditDeletionSalvaged(String(taskId),salvage.ref,salvage.commit,store.get(taskId)?.repo,salvage.uncaptured),onWorktreeResidue:(taskId,residue)=>auditDeletionResidue(String(taskId),residue.path,residue.reason),onBranchKept:(taskId,kept)=>auditDeletionBranchKept(String(taskId),kept.branch,kept.reason),tearDownSession:(taskId)=>tearDownTaskSessionAdapter(String(taskId))}),backfilled=backfillSavedReposFromProjects(store.list().filter((task)=>task.kind==="main").map((task)=>task.repo));if(backfilled.length>0)console.error(`[rove] added ${backfilled.length} existing project(s) to the new-task picker`);return{homeDir,orchestrator,store,worktrees,async close(){orchestrator.dispose()}}}import{existsSync,readFileSync as readFileSync2,readdirSync,statSync as statSync2,unlinkSync}from"fs";import{join as join2}from"path";var TMP_MAX_AGE_MS=300000;function sweepIndexLeftovers(stateDir,now=Date.now()){let tmp=[],tmpBytes=0,entries;try{entries=readdirSync(stateDir)}catch{return{tmp,tmpBytes,lock:!1}}for(let name of entries){if(!name.startsWith("tasks.json.")||!name.endsWith(".tmp"))continue;let path=join2(stateDir,name);try{let stat=statSync2(path);if(now-stat.mtimeMs<TMP_MAX_AGE_MS)continue;unlinkSync(path),tmp.push(path),tmpBytes+=stat.size}catch{}}return{tmp,tmpBytes,lock:clearStaleLock(join2(stateDir,"tasks.json.lock"))}}function clearStaleLock(lockPath){let holder;try{holder=readFileSync2(lockPath,"utf8").trim()}catch{return!1}let pid=Number.parseInt(holder,10);if(Number.isFinite(pid)&&pid>0&&isProcessAlive(pid))return!1;return releaseSync(lockPath,holder),!existsSync(lockPath)}var CLI_NAME=activeCliName();function printDaemonUsage(out){out.write([`Usage: ${CLI_NAME} daemon <command>`,"","Commands:"," status Print the running daemon's status JSON (default)"," start Run the daemon in the foreground (this process becomes it)"," stop Ask the running daemon to shut down"," restart Stop the daemon (graceful \u2192 SIGTERM \u2192 SIGKILL) and respawn it",""].join(`
6
+ `).find((l)=>l.startsWith("branch "))?.slice(7).trim().replace(/^refs\/heads\//,"")||null}function readRefSymbolic(dirs,ref){for(let dir of[dirs.gitDir,dirs.commonDir])try{let target=readFileSync(join(dir,ref),"utf8").trim().match(/^ref:\s*(.+)$/)?.[1]?.trim();if(target)return target}catch{}return null}function ladderFromFiles(worktreePath){let dirs=resolveGitDirs(worktreePath);if(!dirs)return;let originHead=readRefSymbolic(dirs,"refs/remotes/origin/HEAD")?.replace(/^refs\/remotes\//,""),baseCheckout=readRefSymbolic({gitDir:dirs.commonDir,commonDir:dirs.commonDir},"HEAD")?.replace(/^refs\/heads\//,""),names=[],head=readHeadSha(dirs),parts=[`HEAD=${head}`];for(let guess of[...originHead?[originHead]:[],...DEFAULT_BASE_REF_CANDIDATES,...baseCheckout?[baseCheckout]:[]]){if(names.includes(guess))continue;let sha=readRefSha(dirs,guess);if(sha===null)continue;names.push(guess),parts.push(`${guess}=${sha}`)}return{names,fingerprint:head===null?null:parts.join(",")}}async function ladderFromGit(worktreePath,signal){let head=await git2(worktreePath,["symbolic-ref","--short","refs/remotes/origin/HEAD"],signal),originHead=head.status===0?head.stdout.trim():"",baseCheckout=await baseCheckoutBranchFromGit(worktreePath,signal),names=[],candidates=[...originHead?[originHead]:[],...DEFAULT_BASE_REF_CANDIDATES,...baseCheckout?[baseCheckout]:[]];for(let guess of candidates){if(names.includes(guess))continue;if(await refExists(worktreePath,guess,signal))names.push(guess)}return{names,fingerprint:null}}async function resolveBaseRefCached(worktreePath,recordedBaseRef,signal,now=Date.now()){if(recordedBaseRef){let dirs=resolveGitDirs(worktreePath);if(dirs&&readRefSha(dirs,recordedBaseRef)!==null)return recordedBaseRef;if(await refExists(worktreePath,recordedBaseRef,signal))return recordedBaseRef}let hit=cache.get(worktreePath);if(hit&&now-hit.at<BASE_REF_TTL_MS)return hit.ref;let ladder=ladderFromFiles(worktreePath)??await ladderFromGit(worktreePath,signal);if(hit&&ladder.fingerprint!==null&&hit.fingerprint===ladder.fingerprint)return cache.set(worktreePath,{...hit,at:now}),hit.ref;let ref=null;for(let candidate of ladder.names)if(await sharesHistory(worktreePath,candidate,signal)){ref=candidate;break}return cache.set(worktreePath,{ref,at:now,fingerprint:ladder.fingerprint}),ref}var cache2=new Map;function readShas(worktreePath,baseRef){let dirs=resolveGitDirs(worktreePath);if(!dirs)return null;let head=readHeadSha(dirs),base=readRefSha(dirs,baseRef);return head&&base?{head,base}:null}async function driftCached(worktreePath,baseRef,compute){let shas=readShas(worktreePath,baseRef),hit=shas?cache2.get(worktreePath):void 0;if(shas&&hit&&hit.head===shas.head&&hit.base===shas.base)return hit.value;let value=await compute();if(shas&&value!==null)cache2.set(worktreePath,{...shas,value});return value}import{statSync}from"fs";function judgeWorktree(signals,nowMs){if(signals.dirty)return{verdict:"active",reason:"dirty"};if(signals.prState==="open")return{verdict:"active",reason:"prOpen"};if(signals.prState==="merged")return{verdict:"merged",reason:"prMerged"};if(signals.aheadOfDefault===0)return{verdict:"merged",reason:"inMain"};if(signals.prState==="closed")return{verdict:"stale",reason:"prClosed"};if(signals.lastActivityMs>0&&nowMs-signals.lastActivityMs>1209600000)return{verdict:"stale",reason:"idle"};return{verdict:"fresh",reason:"fresh"}}function parseGhPrList(stdout){let entries;try{entries=JSON.parse(stdout)}catch{return null}if(!Array.isArray(entries))return null;let rank={open:3,merged:2,closed:1},map=new Map;for(let entry of entries){let branch=entry?.headRefName,rawState=entry?.state;if(typeof branch!=="string"||typeof rawState!=="string")continue;let state=rawState.toLowerCase();if(state!=="open"&&state!=="merged"&&state!=="closed")continue;let cur=map.get(branch);if(!cur||rank[state]>rank[cur])map.set(branch,state)}return map}var TIMEOUT_MS=4000,manager=new GitWorktreeManager;function createdAt(path){try{let stat=statSync(path);return stat.birthtimeMs||stat.mtimeMs}catch{return 0}}async function run(path,argv){return execHostForWorktreePath(path).run(argv,{cwd:path,signal:AbortSignal.timeout(TIMEOUT_MS)})}async function branchOnRemote(path,branch){try{let out=await run(path,["git","ls-remote","--exit-code","--heads","origin",branch]);return out.exitCode===0?!0:out.exitCode===2?!1:null}catch{return null}}async function defaultRef(repo){try{let out=await run(repo,["git","symbolic-ref","--short","refs/remotes/origin/HEAD"]);if(out.exitCode===0&&out.stdout.trim())return out.stdout.trim()}catch{}for(let guess of["origin/main","origin/master"])try{if((await run(repo,["git","rev-parse","--verify","--quiet",guess])).exitCode===0)return guess}catch{}return null}async function prStates(repo){try{let origin=await run(repo,["git","remote","get-url","origin"]);if(origin.exitCode!==0||!origin.stdout.includes("github.com"))return null;let out=await run(repo,["gh","pr","list","--state","all","--limit","200","--json","headRefName,state"]);return out.exitCode===0?parseGhPrList(out.stdout):null}catch{return null}}async function ahead(path,ref){if(!ref)return null;try{let out=await run(path,["git","rev-list","--count",`${ref}..HEAD`]),value=Number.parseInt(out.stdout.trim(),10);return out.exitCode===0&&!Number.isNaN(value)?value:null}catch{return null}}async function listWorktreeProjectsAdapter(network){let repos=getSavedRepos().filter((repo)=>!getRemoteRepoConfig(repo)),now=Date.now();return Promise.all(repos.map(async(repo)=>{let[worktrees,states,ref]=await Promise.all([manager.listAll(repo),network?prStates(repo):null,defaultRef(repo)]),rows=await Promise.all(worktrees.map(async(worktree)=>{let[remote,aheadBy]=await Promise.all([network?branchOnRemote(worktree.path,worktree.branch):null,ahead(worktree.path,ref)]),judgement=judgeWorktree({dirty:worktree.dirty===!0,prState:states?.get(worktree.branch)??null,aheadOfDefault:aheadBy,lastActivityMs:worktree.lastActivityMs},now);return{...worktree,repo,createdAtMs:createdAt(worktree.path),branchOnRemote:remote,verdict:judgement.verdict,verdictReason:judgement.reason}}));return{repo,worktrees:rows}}))}async function listUnreadableWorktreesAdapter(repo){return manager.listUnreadableWorktrees(repo)}async function removeWorktreeAdapter(path,force){let residue=null;return await manager.remove(path,{force,onSalvage:(record)=>{if(record)auditWorktreeSalvaged(path,record.ref,record.commit,record.uncaptured)},onResidue:(r)=>{residue={path:r.path,reason:r.reason},auditWorktreeResidue(r.path,r.reason)}}),residue}function resolveProtocolUpgradeAndLearnPreset(task,evidence){let preset=protocolWriteBackFromLiveSession(task,evidence,getCustomEngineIds());if(preset)setPersistedString(engineProtocolKey(preset.id),preset.protocol);return protocolUpgradeFromLiveSession(task,evidence)}var daemonRuntime={currentVersion:CURRENT_VERSION,defaultTaskVendor:DEFAULT_TASK_VENDOR,placeholderTaskTitle:PLACEHOLDER_TASK_TITLE,isTaskStatus,isEngineActivityKind,affectsActivityState,async foregroundEngines(pids){let rows=parsePsSnapshot(await psSnapshot([...pids])),out=new Map;for(let pid of pids){let found=foregroundEngineIn(rows,pid);out.set(pid,found?{vendor:found.vendor,pid:found.pid}:null)}return out},titleTurnHint:(vendor,title)=>engineTitleTurnHint(sessionProtocol(vendor),title),resolveProtocolUpgrade:resolveProtocolUpgradeAndLearnPreset,readEngineTurns:async(vendor,transcriptPath)=>await protocolEntry(vendor).readTurns?.(transcriptPath)??[],checkLatestVersion,latestTranscriptMtime,deriveTitleFromSession,createEngineTurnDetector:(vendor)=>createEngineTurnDetector(sessionProtocol(vendor)),async runWorktreeStatus(worktreePath,signal,baseRef){let result=await spawnCapture("git",["status","--porcelain=v1"],{cwd:worktreePath,env:readOnlyGitProcessEnv(),signal});if(result.status!==0)throw Error("git status failed");let counts=parsePorcelain(result.stdout),base=await resolveBaseRefCached(worktreePath,baseRef,signal);if(!base)return counts;let drift=await driftCached(worktreePath,base,async()=>{let out=await spawnCapture("git",["rev-list","--left-right","--count",`${base}...HEAD`],{cwd:worktreePath,env:readOnlyGitProcessEnv(),signal});return out.status===0?parseAheadBehind(out.stdout):null});return drift===null?counts:{...counts,...drift}},maybeAutoStart:(orch,taskId)=>maybeAutoStart(orch,taskId),listWorktreeProjects:listWorktreeProjectsAdapter,listUnreadableWorktrees:listUnreadableWorktreesAdapter,removeWorktree:removeWorktreeAdapter,async syncWorktreeWithBase(worktreePath,recordedBaseRef){let controller=new AbortController,timer=setTimeout(()=>controller.abort(),SYNC_TIMEOUT_MS);try{let baseRef=await resolveBaseRefCached(worktreePath,recordedBaseRef,controller.signal);if(!baseRef)throw Error("no base ref resolves for this worktree");return await syncWorktreeWithBase(worktreePath,baseRef,controller.signal)}finally{clearTimeout(timer)}},availableEngineIds,engineDisplayName,roveApiInvocation,engineEntry,ensureTaskSession:ensureTaskSessionAdapter,startTaskSessionWithPrompt:startTaskSessionWithPromptAdapter,tearDownTaskSession:tearDownTaskSessionAdapter,async readEngineContextUsage(vendor,sessionId){let read=protocolEntry(vendor).history.readUsageSnapshot;if(!read)return null;let snapshot=await read(sessionId);if(snapshot?.context_tokens===void 0)return null;return{contextTokens:snapshot.context_tokens,...snapshot.context_window_tokens===void 0?{}:{contextWindowTokens:snapshot.context_window_tokens},...snapshot.context_tokens_approximate?{approximate:!0}:{},...snapshot.input_tokens===void 0?{}:{inputTokens:snapshot.input_tokens},...snapshot.output_tokens===void 0?{}:{outputTokens:snapshot.output_tokens},...snapshot.cache_read_input_tokens===void 0?{}:{cacheReadTokens:snapshot.cache_read_input_tokens},...snapshot.cache_creation_input_tokens===void 0?{}:{cacheCreationTokens:snapshot.cache_creation_input_tokens}}},quotaUsage:(vendor)=>engineEntry(vendor).quotaUsage?.()??Promise.resolve(null),vendorsWithQuotaProbe,deliverPromptToLiveEngine:deliverPromptToLiveEngineAdapter,deliverPromptToLiveEngineDetailed:deliverPromptToLiveEngineDetailedAdapter,deliverPromptToLiveEngineTabDetailed:deliverPromptToLiveEngineTabDetailedAdapter,getPersistedString,setPersistedString,getSavedRepos:()=>[...getSavedRepos()],prStatus:{viewFields:GH_PR_VIEW_FIELDS,mapView:(view,at)=>mapGhPrView(view,at),sameStatus:samePrStatus,nextPoll:(outcome,failures,now,config,random)=>nextPrPoll(outcome,failures,now,config,random),classify:classifyGhFailure}};import{homedir}from"os";async function createRoveCore(options={}){let homeDir=options.homeDir??readRoveHomeDirEnv()??homedir(),store=new TaskIndexStore({homeDir});await store.load();let worktrees=new GitWorktreeManager,orchestrator=new Orchestrator({store,worktrees,onSalvage:(taskId,salvage)=>auditDeletionSalvaged(String(taskId),salvage.ref,salvage.commit,store.get(taskId)?.repo,salvage.uncaptured),onWorktreeResidue:(taskId,residue)=>auditDeletionResidue(String(taskId),residue.path,residue.reason),onBranchKept:(taskId,kept)=>auditDeletionBranchKept(String(taskId),kept.branch,kept.reason),tearDownSession:(taskId)=>tearDownTaskSessionAdapter(String(taskId))}),backfilled=backfillSavedReposFromProjects(store.list().filter((task)=>task.kind==="main").map((task)=>task.repo));if(backfilled.length>0)console.error(`[rove] added ${backfilled.length} existing project(s) to the new-task picker`);return{homeDir,orchestrator,store,worktrees,async close(){orchestrator.dispose()}}}import{existsSync,readFileSync as readFileSync2,readdirSync,statSync as statSync2,unlinkSync}from"fs";import{join as join2}from"path";var TMP_MAX_AGE_MS=300000;function sweepIndexLeftovers(stateDir,now=Date.now()){let tmp=[],tmpBytes=0,entries;try{entries=readdirSync(stateDir)}catch{return{tmp,tmpBytes,lock:!1}}for(let name of entries){if(!name.startsWith("tasks.json.")||!name.endsWith(".tmp"))continue;let path=join2(stateDir,name);try{let stat=statSync2(path);if(now-stat.mtimeMs<TMP_MAX_AGE_MS)continue;unlinkSync(path),tmp.push(path),tmpBytes+=stat.size}catch{}}return{tmp,tmpBytes,lock:clearStaleLock(join2(stateDir,"tasks.json.lock"))}}function clearStaleLock(lockPath){let holder;try{holder=readFileSync2(lockPath,"utf8").trim()}catch{return!1}let pid=Number.parseInt(holder,10);if(Number.isFinite(pid)&&pid>0&&isProcessAlive(pid))return!1;return releaseSync(lockPath,holder),!existsSync(lockPath)}var CLI_NAME=ROVE_PRODUCT_NAME;function printDaemonUsage(out){out.write([`Usage: ${CLI_NAME} daemon <command>`,"","Commands:"," status Print the running daemon's status JSON (default)"," start Run the daemon in the foreground (this process becomes it)"," stop Ask the running daemon to shut down"," restart Stop the daemon (graceful \u2192 SIGTERM \u2192 SIGKILL) and respawn it",""].join(`
7
7
  `))}async function runDaemonSubcommand(argv){let[command="status"]=argv,socketPath=defaultDaemonSocketPath(),pidPath=defaultDaemonPidPath();if(command==="--help"||command==="-h"||command==="help"){printDaemonUsage(process.stdout);return}if(!SUBCOMMAND_VERBS.daemon.includes(command))process.stderr.write(`${CLI_NAME} daemon: unknown command "${command}"
8
8
 
9
- `),printDaemonUsage(process.stderr),process.exit(2);if(command==="status"){let client=new KobeDaemonClient(socketPath);try{let status=await client.request("daemon.status");console.log(JSON.stringify(status,null,2))}catch{let pid=await readPidFile(pidPath);if(pid)console.log(`${CLI_NAME} daemon: no daemon socket at ${socketPath} (stale pidfile pid=${pid})`);else console.log(`${CLI_NAME} daemon: no daemon running at ${socketPath}`);process.exitCode=1}finally{client.close()}return}if(command==="stop"){let client=new KobeDaemonClient(socketPath);try{await client.request("daemon.stop"),console.log(`${CLI_NAME} daemon: stop requested`)}catch{console.log(`${CLI_NAME} daemon: no daemon running at ${socketPath}`)}finally{client.close()}return}if(command==="restart"){await stopDaemonProcess(socketPath,pidPath,{reason:"restart"}),(await connectOrStartDaemon("explicit-restart")).close(),console.log(`${CLI_NAME} daemon: restarted, listening on ${socketPath}`);return}rotateLogIfNeeded(defaultDaemonLogPath()),installDaemonCrashHandlers(),logDaemonInfo("boot",`daemon starting \u2014 ${daemonSpawnReason()} (pid ${process.pid}, v${CURRENT_VERSION})`);let core,server=await startDaemonServer(async()=>{let migration=migrateRoveDaemonStateLayout();for(let warning of migration.warnings)console.error(`[rove] daemon state migration will retry: ${warning}`);core=await createKobeCore();let swept=sweepIndexLeftovers(core.store.stateDir);if(swept.lock||swept.tmp.length>0)console.error(`[rove] swept crash leftovers in ${core.store.stateDir}: ${swept.tmp.length} orphaned staging file(s) (${swept.tmpBytes} bytes)${swept.lock?", stale task-index lockfile":""}`);return core.orchestrator},{runtime:daemonRuntime,socketPath,pidPath,plugins:{binPath:resolvePluginBinPath()},onStop:async()=>{await core?.close()}});console.log(`${CLI_NAME} daemon: listening on ${server.socketPath}`);let shutdown=async()=>{await server.close(),process.exit(0)};process.once("SIGINT",()=>void shutdown()),process.once("SIGTERM",()=>void shutdown())}export{runDaemonSubcommand};
9
+ `),printDaemonUsage(process.stderr),process.exit(2);if(command==="status"){let client=new RoveDaemonClient(socketPath);try{let status=await client.request("daemon.status");console.log(JSON.stringify(status,null,2))}catch{let pid=await readPidFile(pidPath);if(pid)console.log(`${CLI_NAME} daemon: no daemon socket at ${socketPath} (stale pidfile pid=${pid})`);else console.log(`${CLI_NAME} daemon: no daemon running at ${socketPath}`);process.exitCode=1}finally{client.close()}return}if(command==="stop"){let client=new RoveDaemonClient(socketPath);try{await client.request("daemon.stop"),console.log(`${CLI_NAME} daemon: stop requested`)}catch{console.log(`${CLI_NAME} daemon: no daemon running at ${socketPath}`)}finally{client.close()}return}if(command==="restart"){await stopDaemonProcess(socketPath,pidPath,{reason:"restart"}),(await connectOrStartDaemon("explicit-restart")).close(),console.log(`${CLI_NAME} daemon: restarted, listening on ${socketPath}`);return}rotateLogIfNeeded(defaultDaemonLogPath()),installDaemonCrashHandlers(),logDaemonInfo("boot",`daemon starting \u2014 ${daemonSpawnReason()} (pid ${process.pid}, v${CURRENT_VERSION})`);let core,server=await startDaemonServer(async()=>{let migration=migrateRoveDaemonStateLayout();for(let warning of migration.warnings)console.error(`[rove] daemon state migration will retry: ${warning}`);core=await createRoveCore();let swept=sweepIndexLeftovers(core.store.stateDir);if(swept.lock||swept.tmp.length>0)console.error(`[rove] swept crash leftovers in ${core.store.stateDir}: ${swept.tmp.length} orphaned staging file(s) (${swept.tmpBytes} bytes)${swept.lock?", stale task-index lockfile":""}`);return core.orchestrator},{runtime:daemonRuntime,socketPath,pidPath,plugins:{binPath:resolvePluginBinPath()},onStop:async()=>{await core?.close()}});console.log(`${CLI_NAME} daemon: listening on ${server.socketPath}`);let shutdown=async()=>{await server.close(),process.exit(0)};process.once("SIGINT",()=>void shutdown()),process.once("SIGTERM",()=>void shutdown())}export{runDaemonSubcommand};
@@ -1,3 +1,3 @@
1
1
  // @bun
2
- import{homeDir,legacyKobeStateDir,roveStateDir}from"./chunk-8hbtca1g.js";import{pathSyntax,pathWithin}from"./chunk-f10n6063.js";import{tmpdir}from"os";import{join}from"path";var THROWAWAY_SEGMENTS=new Set([".dev-sandbox",".scratch"]);function isRemoteKey(key){return key.startsWith("ssh://")}function isInside(candidate,root){return pathWithin(root,candidate)!==null}function roveInternalRoots(){return[roveStateDir(),legacyKobeStateDir(),join(homeDir(),".config","rove")]}function pathRejection(absPath,intent="derived"){let raw=absPath.trim();if(!raw)return"notAbsolute";if(isRemoteKey(raw))return null;let syntax=pathSyntax(raw);if(!syntax.isAbsolute(raw))return"notAbsolute";if(syntax.normalize(raw).split(syntax.sep).some((s)=>THROWAWAY_SEGMENTS.has(s)))return"insideSandbox";for(let root of roveInternalRoots())if(isInside(raw,root))return"roveInternal";if(intent==="derived"&&(isInside(raw,tmpdir())||isInside(raw,"/tmp")||isInside(raw,"/private/tmp")))return"temporary";return null}function projectRejection(absPath,isRepo,intent="derived"){let shape=pathRejection(absPath,intent);if(shape)return shape;let raw=absPath.trim();if(isRemoteKey(raw))return null;if(isRepo&&!isRepo(raw))return"notGitRepo";return null}function rejectionReason(rejection){switch(rejection){case"notAbsolute":return"not an absolute path";case"notGitRepo":return"not a git repository";case"temporary":return"inside a temporary directory";case"roveInternal":return"inside Rove's own state directory";case"insideSandbox":return"inside a sandbox or scratch directory"}}
2
+ import{homeDir,legacyRoveStateDir,roveStateDir}from"./chunk-prqeddy7.js";import{pathSyntax,pathWithin}from"./chunk-pn5ygqn6.js";import{tmpdir}from"os";import{join}from"path";var THROWAWAY_SEGMENTS=new Set([".dev-sandbox",".scratch"]);function isRemoteKey(key){return key.startsWith("ssh://")}function isInside(candidate,root){return pathWithin(root,candidate)!==null}function roveInternalRoots(){return[roveStateDir(),legacyRoveStateDir(),join(homeDir(),".config","rove")]}function pathRejection(absPath,intent="derived"){let raw=absPath.trim();if(!raw)return"notAbsolute";if(isRemoteKey(raw))return null;let syntax=pathSyntax(raw);if(!syntax.isAbsolute(raw))return"notAbsolute";if(syntax.normalize(raw).split(syntax.sep).some((s)=>THROWAWAY_SEGMENTS.has(s)))return"insideSandbox";for(let root of roveInternalRoots())if(isInside(raw,root))return"roveInternal";if(intent==="derived"&&(isInside(raw,tmpdir())||isInside(raw,"/tmp")||isInside(raw,"/private/tmp")))return"temporary";return null}function projectRejection(absPath,isRepo,intent="derived"){let shape=pathRejection(absPath,intent);if(shape)return shape;let raw=absPath.trim();if(isRemoteKey(raw))return null;if(isRepo&&!isRepo(raw))return"notGitRepo";return null}function rejectionReason(rejection){switch(rejection){case"notAbsolute":return"not an absolute path";case"notGitRepo":return"not a git repository";case"temporary":return"inside a temporary directory";case"roveInternal":return"inside Rove's own state directory";case"insideSandbox":return"inside a sandbox or scratch directory"}}
3
3
  export{pathRejection,projectRejection,rejectionReason};
@@ -1,4 +1,4 @@
1
1
  // @bun
2
- import{buildPaneArgv}from"./chunk-cv6r89jp.js";import{PluginCliError,installPlugin,linkPlugin}from"./chunk-pzbrj3gd.js";import{resolvePluginBinPath}from"./chunk-6x5vzzpx.js";import{buildPluginEnv}from"./chunk-53afdybj.js";import{currentPluginPlatform,loadPluginRegistry,pluginCheckoutDir,pluginConfigDir,pluginLogPath,qualifiedActionId,readPluginManifest,removePluginEntry,savePluginRegistry,supportsPlatform}from"./chunk-1da3bqjc.js";import"./chunk-exfyqsdd.js";import"./chunk-w7zv47mp.js";import{flagValue}from"./chunk-jvxh93nz.js";import{errorMessage}from"./chunk-2brn8e1y.js";import{SUBCOMMAND_VERBS}from"./chunk-fhch0x0q.js";import"./chunk-be757xzj.js";import{activeCliName}from"./chunk-ppwpjm39.js";import"./chunk-fxs82dsx.js";import"./chunk-zyd6k6ak.js";import"./chunk-8hbtca1g.js";import"./chunk-hq2n27y1.js";import"./chunk-sb0ns0c7.js";import"./chunk-vnpqemb0.js";import"./chunk-9prawccj.js";import"./chunk-hqbmzz4t.js";import{defaultDaemonSocketPath}from"./chunk-y8fqdnh3.js";import"./chunk-hq4b3fca.js";import{__require}from"./chunk-wqfp8d9w.js";import{spawnSync}from"child_process";import{readFileSync,rmSync}from"fs";var CLI_NAME=activeCliName();function printUsage(out){out.write([`usage: ${CLI_NAME} plugin <command>`,""," install <owner/repo[/subdir]> [--yes] [--ref <rev>] clone from GitHub, preview, build, register"," link <dir> register a local plugin directory (dev)"," list installed + linked plugins"," search [query] browse the marketplace (GitHub topic rove-plugin)"," outdated check GitHub-installed plugins against upstream"," update <id\u2026> | --all [--yes] reinstall stale plugins from GitHub"," enable <id> | disable <id> toggle a plugin without unregistering it"," unlink <id> unregister a linked plugin (files untouched)"," uninstall <id-or-spec> unregister + remove the managed checkout"," config-dir <id> print the plugin's config directory"," log <id> [-n <count>] tail the plugin's command-run log"," action list [--plugin <id>] declared actions"," action invoke <plugin-id.action-id> run an action now"," pane open <plugin-id.pane-id> [--task <task-id>] open a plugin pane as a terminal tab (JSON:"," clients \u2014 0 = no attached UI performed the split)","","Marketplace: https://github.com/topics/rove-plugin (legacy kobe-plugin is included)",""].join(`
3
- `))}function loadAll(){return loadPluginRegistry().plugins.map((entry)=>{try{return{entry,manifest:readPluginManifest(entry.root).manifest}}catch{return{entry,manifest:void 0}}})}function requireEntry(id){let entry=loadPluginRegistry().plugins.find((p)=>p.id===id);if(!entry)throw new PluginCliError(`no plugin registered as \`${id}\`; see \`${CLI_NAME} plugin list\``);return entry}function listPlugins(){let all=loadAll();if(all.length===0){console.log(`no plugins installed. Try: ${CLI_NAME} plugin install <owner/repo> \u2014 browse the \`rove-plugin\` GitHub topic.`);return}for(let{entry,manifest}of all){let state=entry.enabled?"enabled":"disabled",kind=entry.source.kind==="link"?`linked ${entry.root}`:entry.source.spec,broken=manifest?"":" [manifest unreadable]";console.log(`${entry.id} v${entry.version} ${state} (${kind})${broken}`)}}function setEnabled(id,enabled){let entry=requireEntry(id),registry=loadPluginRegistry();savePluginRegistry({plugins:registry.plugins.map((p)=>p.id===id?{...entry,enabled}:p)}),console.log(`${enabled?"enabled":"disabled"} ${id}`)}function unlink(id){let entry=requireEntry(id);if(entry.source.kind!=="link")throw new PluginCliError(`\`${id}\` is a GitHub install; use uninstall`);savePluginRegistry(removePluginEntry(loadPluginRegistry(),id)),console.log(`unlinked ${id} (files untouched at ${entry.root})`)}function uninstall(idOrSpec){let registry=loadPluginRegistry(),entry=registry.plugins.find((p)=>p.id===idOrSpec||p.source.kind==="github"&&p.source.spec===idOrSpec);if(!entry)throw new PluginCliError(`no plugin registered as \`${idOrSpec}\``);if(entry.source.kind==="link")throw new PluginCliError(`\`${entry.id}\` is linked; use unlink`);savePluginRegistry(removePluginEntry(registry,entry.id)),rmSync(pluginCheckoutDir(entry.id),{recursive:!0,force:!0}),console.log(`uninstalled ${entry.id} (config/state kept under ~/.rove/plugins/${entry.id}/)`)}function listActions(pluginFilter){for(let{entry,manifest}of loadAll()){if(!manifest||pluginFilter&&entry.id!==pluginFilter)continue;for(let action of manifest.actions)console.log(`${qualifiedActionId(entry.id,action.id)} ${action.title}`)}}function findByLongestPluginPrefix(qualified,options,findItem){for(let{entry,manifest}of loadAll().filter(({entry:entry2,manifest:manifest2})=>Boolean(manifest2&&(!options.enabledOnly||entry2.enabled)&&qualified.startsWith(`${entry2.id}.`))).sort((a,b)=>b.entry.id.length-a.entry.id.length)){let item=findItem(manifest,qualified.slice(entry.id.length+1));if(item!==void 0)return{entry,manifest,item}}return}function assertPlatformSupported(label,item,manifest){if(supportsPlatform(item,manifest,currentPluginPlatform()))return;let declared=(item.platforms??manifest.platforms??[]).join(", ");throw new PluginCliError(`\`${label}\` is not supported on this platform (declares ${declared})`)}function invokeAction(qualified,extraArgs){let hit=findByLongestPluginPrefix(qualified,{enabledOnly:!0},(manifest,actionId)=>manifest.actions.find((a)=>a.id===actionId));if(!hit)throw new PluginCliError(`no action \`${qualified}\`; see \`${CLI_NAME} plugin action list\``);assertPlatformSupported(qualified,hit.item,hit.manifest);let action=hit.item,[cmd,...args]=[...action.command,...extraArgs],res=spawnSync(cmd,args,{cwd:hit.entry.root,stdio:"inherit",env:buildPluginEnv({socketPath:defaultDaemonSocketPath(),binPath:resolvePluginBinPath(),pluginId:hit.entry.id,pluginRoot:hit.entry.root,extra:{ROVE_PLUGIN_ACTION_ID:action.id,ROVE_PLUGIN_INVOKE_CWD:process.cwd()}})});process.exit(res.status??1)}function resolvePaneQualified(qualified){let hit=findByLongestPluginPrefix(qualified,{enabledOnly:!1},(manifest,entrypoint)=>manifest.panes.find((p)=>p.id===entrypoint));if(!hit)throw new PluginCliError(`no pane \`${qualified}\`; see \`${CLI_NAME} plugin list\``);return{pluginId:hit.entry.id,entrypoint:hit.item.id}}async function openPane(pluginId,entrypoint,taskFlag){let loaded=loadAll().find(({entry})=>entry.id===pluginId);if(!loaded?.manifest)throw new PluginCliError(`no plugin \`${pluginId}\` (or its manifest is unreadable)`);if(!loaded.entry.enabled)throw new PluginCliError(`\`${pluginId}\` is disabled`);let pane=loaded.manifest.panes.find((p)=>p.id===entrypoint);if(!pane)throw new PluginCliError(`no pane \`${entrypoint}\` in \`${pluginId}\`; declare it under [[panes]]`);assertPlatformSupported(`${pluginId}.${pane.id}`,pane,loaded.manifest);let{openDaemonSession,resolveActiveTaskId}=await import("./chunk-f5e3dcxe.js"),session=await openDaemonSession({mode:"start"});try{let taskId=taskFlag??await resolveActiveTaskId(session.client);if(!taskId)throw new PluginCliError("no active task; pass --task <id>");let argv=buildPaneArgv(loaded.entry.id,loaded.entry.root,pane,{socketPath:defaultDaemonSocketPath(),binPath:resolvePluginBinPath(),taskId}),reply=await session.client.request("tab.open",{taskId,argv,title:pane.title,placement:pane.placement});console.log(JSON.stringify({...reply,ok:!0,pane:`${pluginId}.${pane.id}`,taskId,title:pane.title}))}finally{session.close()}}function tailLog(id,count){requireEntry(id);let text;try{text=readFileSync(pluginLogPath(id),"utf8")}catch{console.log("(no runs logged yet)");return}let lines=text.trimEnd().split(`
4
- `);for(let line of lines.slice(-count))console.log(line)}async function runPluginSubcommand(rest){let[command,...args]=rest;if(command!==void 0&&!SUBCOMMAND_VERBS.plugin.includes(command)){let isHelp=command==="help"||command==="--help"||command==="-h";if(printUsage(isHelp?process.stdout:process.stderr),!isHelp)process.exit(2);return}try{switch(command){case"install":{let spec=args.find((a)=>!a.startsWith("-"));if(!spec)throw new PluginCliError("install needs <owner/repo[/subdir]>");await installPlugin(spec,{yes:args.includes("--yes"),ref:flagValue(args,"--ref")});return}case"link":{if(!args[0])throw new PluginCliError("link needs a directory");linkPlugin(args[0]);return}case"list":listPlugins();return;case"search":{let{searchMarketplace}=await import("./chunk-ahnk6zx3.js");await searchMarketplace(args.find((a)=>!a.startsWith("-")));return}case"outdated":{let{printOutdated}=await import("./chunk-r8xqvg26.js");printOutdated();return}case"update":{let{updatePlugins}=await import("./chunk-r8xqvg26.js");await updatePlugins(args.filter((a)=>!a.startsWith("-")),{all:args.includes("--all"),yes:args.includes("--yes")});return}case"enable":case"disable":{if(!args[0])throw new PluginCliError(`${command} needs a plugin id`);setEnabled(args[0],command==="enable");return}case"unlink":{if(!args[0])throw new PluginCliError("unlink needs a plugin id");unlink(args[0]);return}case"uninstall":{if(!args[0])throw new PluginCliError("uninstall needs a plugin id or owner/repo spec");uninstall(args[0]);return}case"config-dir":{if(!args[0])throw new PluginCliError("config-dir needs a plugin id");requireEntry(args[0]),console.log(pluginConfigDir(args[0]));return}case"log":{if(!args[0])throw new PluginCliError("log needs a plugin id");tailLog(args[0],Number.parseInt(flagValue(args,"-n")??"20",10)||20);return}case"pane":{let[sub,...paneArgs]=args;if(sub==="open"){let positional=paneArgs.find((a)=>!a.startsWith("-")&&a!==flagValue(paneArgs,"--task")),pluginId=flagValue(paneArgs,"--plugin"),entrypoint=flagValue(paneArgs,"--entrypoint");if(!pluginId||!entrypoint){if(!positional)throw new PluginCliError("pane open needs <plugin-id.pane-id> (or --plugin <id> --entrypoint <pane-id>) [--task <task-id>]");({pluginId,entrypoint}=resolvePaneQualified(positional))}await openPane(pluginId,entrypoint,flagValue(paneArgs,"--task"));return}printUsage(process.stderr),process.exit(2);return}case"action":{let[sub,...actionArgs]=args;if(sub==="list"){listActions(flagValue(actionArgs,"--plugin"));return}if(sub==="invoke"){if(!actionArgs[0])throw new PluginCliError("action invoke needs <plugin-id.action-id>");invokeAction(actionArgs[0],actionArgs.slice(1));return}printUsage(process.stderr),process.exit(2);return}default:{let isHelp=command===void 0||command==="help"||command==="--help"||command==="-h";if(printUsage(isHelp?process.stdout:process.stderr),!isHelp)process.exit(2);return}}}catch(err){if(err instanceof PluginCliError)console.error(`${CLI_NAME} plugin: ${err.message}`),process.exit(1);console.error(`${CLI_NAME} plugin: ${errorMessage(err)}`),process.exit(1)}}export{runPluginSubcommand};
2
+ import{buildPaneArgv}from"./chunk-ffs26p85.js";import{PluginCliError,installPlugin,linkPlugin}from"./chunk-3vyk7bzb.js";import{resolvePluginBinPath}from"./chunk-b0ssvpht.js";import{buildPluginEnv}from"./chunk-axsm0gn5.js";import{currentPluginPlatform,loadPluginRegistry,pluginCheckoutDir,pluginConfigDir,pluginLogPath,qualifiedActionId,readPluginManifest,removePluginEntry,savePluginRegistry,supportsPlatform}from"./chunk-rqyaf0dw.js";import"./chunk-vjvkkrzc.js";import"./chunk-w7zv47mp.js";import{flagValue}from"./chunk-zsfyj36g.js";import{errorMessage}from"./chunk-2brn8e1y.js";import{SUBCOMMAND_VERBS}from"./chunk-fhch0x0q.js";import"./chunk-a0ave3g6.js";import"./chunk-prqeddy7.js";import{ROVE_PRODUCT_NAME}from"./chunk-zt7wfnva.js";import"./chunk-yt15y085.js";import"./chunk-0422g8ac.js";import{defaultDaemonSocketPath}from"./chunk-npwzmmv9.js";import"./chunk-b39sdtt0.js";import"./chunk-nc46gddg.js";import{__require}from"./chunk-wqfp8d9w.js";import{spawnSync}from"child_process";import{readFileSync,rmSync}from"fs";var CLI_NAME=ROVE_PRODUCT_NAME;function printUsage(out){out.write([`usage: ${CLI_NAME} plugin <command>`,""," install <owner/repo[/subdir]> [--yes] [--ref <rev>] clone from GitHub, preview, build, register"," link <dir> register a local plugin directory (dev)"," list installed + linked plugins"," search [query] browse the marketplace (GitHub topic rove-plugin)"," outdated check GitHub-installed plugins against upstream"," update <id\u2026> | --all [--yes] reinstall stale plugins from GitHub"," enable <id> | disable <id> toggle a plugin without unregistering it"," unlink <id> unregister a linked plugin (files untouched)"," uninstall <id-or-spec> unregister + remove the managed checkout"," config-dir <id> print the plugin's config directory"," log <id> [-n <count>] tail the plugin's command-run log"," action list [--plugin <id>] declared actions"," action invoke <plugin-id.action-id> run an action now"," pane open <plugin-id.pane-id> [--task <task-id>] open a plugin pane as a terminal tab (JSON:"," clients \u2014 0 = no attached UI performed the split)","","Marketplace: https://github.com/topics/rove-plugin",""].join(`
3
+ `))}function loadAll(){return loadPluginRegistry().plugins.map((entry)=>{try{return{entry,manifest:readPluginManifest(entry.root).manifest}}catch{return{entry,manifest:void 0}}})}function requireEntry(id){let entry=loadPluginRegistry().plugins.find((p)=>p.id===id);if(!entry)throw new PluginCliError(`no plugin registered as \`${id}\`; see \`${CLI_NAME} plugin list\``);return entry}function listPlugins(){let all=loadAll();if(all.length===0){console.log(`no plugins installed. Try: ${CLI_NAME} plugin install <owner/repo> \u2014 browse the \`rove-plugin\` GitHub topic.`);return}for(let{entry,manifest}of all){let state=entry.enabled?"enabled":"disabled",kind=entry.source.kind==="link"?`linked ${entry.root}`:entry.source.spec,broken=manifest?"":" [manifest unreadable]";console.log(`${entry.id} v${entry.version} ${state} (${kind})${broken}`)}}function setEnabled(id,enabled){let entry=requireEntry(id),registry=loadPluginRegistry();savePluginRegistry({plugins:registry.plugins.map((p)=>p.id===id?{...entry,enabled}:p)}),console.log(`${enabled?"enabled":"disabled"} ${id}`)}function unlink(id){let entry=requireEntry(id);if(entry.source.kind!=="link")throw new PluginCliError(`\`${id}\` is a GitHub install; use uninstall`);savePluginRegistry(removePluginEntry(loadPluginRegistry(),id)),console.log(`unlinked ${id} (files untouched at ${entry.root})`)}function uninstall(idOrSpec){let registry=loadPluginRegistry(),entry=registry.plugins.find((p)=>p.id===idOrSpec||p.source.kind==="github"&&p.source.spec===idOrSpec);if(!entry)throw new PluginCliError(`no plugin registered as \`${idOrSpec}\``);if(entry.source.kind==="link")throw new PluginCliError(`\`${entry.id}\` is linked; use unlink`);savePluginRegistry(removePluginEntry(registry,entry.id)),rmSync(pluginCheckoutDir(entry.id),{recursive:!0,force:!0}),console.log(`uninstalled ${entry.id} (config/state kept under ~/.rove/plugins/${entry.id}/)`)}function listActions(pluginFilter){for(let{entry,manifest}of loadAll()){if(!manifest||pluginFilter&&entry.id!==pluginFilter)continue;for(let action of manifest.actions)console.log(`${qualifiedActionId(entry.id,action.id)} ${action.title}`)}}function findByLongestPluginPrefix(qualified,options,findItem){for(let{entry,manifest}of loadAll().filter(({entry:entry2,manifest:manifest2})=>Boolean(manifest2&&(!options.enabledOnly||entry2.enabled)&&qualified.startsWith(`${entry2.id}.`))).sort((a,b)=>b.entry.id.length-a.entry.id.length)){let item=findItem(manifest,qualified.slice(entry.id.length+1));if(item!==void 0)return{entry,manifest,item}}return}function assertPlatformSupported(label,item,manifest){if(supportsPlatform(item,manifest,currentPluginPlatform()))return;let declared=(item.platforms??manifest.platforms??[]).join(", ");throw new PluginCliError(`\`${label}\` is not supported on this platform (declares ${declared})`)}function invokeAction(qualified,extraArgs){let hit=findByLongestPluginPrefix(qualified,{enabledOnly:!0},(manifest,actionId)=>manifest.actions.find((a)=>a.id===actionId));if(!hit)throw new PluginCliError(`no action \`${qualified}\`; see \`${CLI_NAME} plugin action list\``);assertPlatformSupported(qualified,hit.item,hit.manifest);let action=hit.item,[cmd,...args]=[...action.command,...extraArgs],res=spawnSync(cmd,args,{cwd:hit.entry.root,stdio:"inherit",env:buildPluginEnv({socketPath:defaultDaemonSocketPath(),binPath:resolvePluginBinPath(),pluginId:hit.entry.id,pluginRoot:hit.entry.root,extra:{ROVE_PLUGIN_ACTION_ID:action.id,ROVE_PLUGIN_INVOKE_CWD:process.cwd()}})});process.exit(res.status??1)}function resolvePaneQualified(qualified){let hit=findByLongestPluginPrefix(qualified,{enabledOnly:!1},(manifest,entrypoint)=>manifest.panes.find((p)=>p.id===entrypoint));if(!hit)throw new PluginCliError(`no pane \`${qualified}\`; see \`${CLI_NAME} plugin list\``);return{pluginId:hit.entry.id,entrypoint:hit.item.id}}async function openPane(pluginId,entrypoint,taskFlag){let loaded=loadAll().find(({entry})=>entry.id===pluginId);if(!loaded?.manifest)throw new PluginCliError(`no plugin \`${pluginId}\` (or its manifest is unreadable)`);if(!loaded.entry.enabled)throw new PluginCliError(`\`${pluginId}\` is disabled`);let pane=loaded.manifest.panes.find((p)=>p.id===entrypoint);if(!pane)throw new PluginCliError(`no pane \`${entrypoint}\` in \`${pluginId}\`; declare it under [[panes]]`);assertPlatformSupported(`${pluginId}.${pane.id}`,pane,loaded.manifest);let{openDaemonSession,resolveActiveTaskId}=await import("./chunk-yvjgwnb9.js"),session=await openDaemonSession({mode:"start"});try{let taskId=taskFlag??await resolveActiveTaskId(session.client);if(!taskId)throw new PluginCliError("no active task; pass --task <id>");let argv=buildPaneArgv(loaded.entry.id,loaded.entry.root,pane,{socketPath:defaultDaemonSocketPath(),binPath:resolvePluginBinPath(),taskId}),reply=await session.client.request("tab.open",{taskId,argv,title:pane.title,placement:pane.placement});console.log(JSON.stringify({...reply,ok:!0,pane:`${pluginId}.${pane.id}`,taskId,title:pane.title}))}finally{session.close()}}function tailLog(id,count){requireEntry(id);let text;try{text=readFileSync(pluginLogPath(id),"utf8")}catch{console.log("(no runs logged yet)");return}let lines=text.trimEnd().split(`
4
+ `);for(let line of lines.slice(-count))console.log(line)}async function runPluginSubcommand(rest){let[command,...args]=rest;if(command!==void 0&&!SUBCOMMAND_VERBS.plugin.includes(command)){let isHelp=command==="help"||command==="--help"||command==="-h";if(printUsage(isHelp?process.stdout:process.stderr),!isHelp)process.exit(2);return}try{switch(command){case"install":{let spec=args.find((a)=>!a.startsWith("-"));if(!spec)throw new PluginCliError("install needs <owner/repo[/subdir]>");await installPlugin(spec,{yes:args.includes("--yes"),ref:flagValue(args,"--ref")});return}case"link":{if(!args[0])throw new PluginCliError("link needs a directory");linkPlugin(args[0]);return}case"list":listPlugins();return;case"search":{let{searchMarketplace}=await import("./chunk-nem2x959.js");await searchMarketplace(args.find((a)=>!a.startsWith("-")));return}case"outdated":{let{printOutdated}=await import("./chunk-szrfp0jq.js");printOutdated();return}case"update":{let{updatePlugins}=await import("./chunk-szrfp0jq.js");await updatePlugins(args.filter((a)=>!a.startsWith("-")),{all:args.includes("--all"),yes:args.includes("--yes")});return}case"enable":case"disable":{if(!args[0])throw new PluginCliError(`${command} needs a plugin id`);setEnabled(args[0],command==="enable");return}case"unlink":{if(!args[0])throw new PluginCliError("unlink needs a plugin id");unlink(args[0]);return}case"uninstall":{if(!args[0])throw new PluginCliError("uninstall needs a plugin id or owner/repo spec");uninstall(args[0]);return}case"config-dir":{if(!args[0])throw new PluginCliError("config-dir needs a plugin id");requireEntry(args[0]),console.log(pluginConfigDir(args[0]));return}case"log":{if(!args[0])throw new PluginCliError("log needs a plugin id");tailLog(args[0],Number.parseInt(flagValue(args,"-n")??"20",10)||20);return}case"pane":{let[sub,...paneArgs]=args;if(sub==="open"){let positional=paneArgs.find((a)=>!a.startsWith("-")&&a!==flagValue(paneArgs,"--task")),pluginId=flagValue(paneArgs,"--plugin"),entrypoint=flagValue(paneArgs,"--entrypoint");if(!pluginId||!entrypoint){if(!positional)throw new PluginCliError("pane open needs <plugin-id.pane-id> (or --plugin <id> --entrypoint <pane-id>) [--task <task-id>]");({pluginId,entrypoint}=resolvePaneQualified(positional))}await openPane(pluginId,entrypoint,flagValue(paneArgs,"--task"));return}printUsage(process.stderr),process.exit(2);return}case"action":{let[sub,...actionArgs]=args;if(sub==="list"){listActions(flagValue(actionArgs,"--plugin"));return}if(sub==="invoke"){if(!actionArgs[0])throw new PluginCliError("action invoke needs <plugin-id.action-id>");invokeAction(actionArgs[0],actionArgs.slice(1));return}printUsage(process.stderr),process.exit(2);return}default:{let isHelp=command===void 0||command==="help"||command==="--help"||command==="-h";if(printUsage(isHelp?process.stdout:process.stderr),!isHelp)process.exit(2);return}}}catch(err){if(err instanceof PluginCliError)console.error(`${CLI_NAME} plugin: ${err.message}`),process.exit(1);console.error(`${CLI_NAME} plugin: ${errorMessage(err)}`),process.exit(1)}}export{runPluginSubcommand};
@@ -0,0 +1,3 @@
1
+ // @bun
2
+ var ROVE_TERMINAL_TITLE_SEQUENCE="\x1B]0;rove\x07";function publishRoveTerminalTitle(output=process.stdout){if(!output.isTTY)return!1;return output.write("\x1B]0;rove\x07"),!0}
3
+ export{ROVE_TERMINAL_TITLE_SEQUENCE,publishRoveTerminalTitle};
@@ -0,0 +1,2 @@
1
+ // @bun
2
+ import{ensureForwards,startTunnel}from"./chunk-9jsm6h5y.js";import"./chunk-9aydqazr.js";import"./chunk-7q43tysm.js";import"./chunk-mw0ysrpd.js";import"./chunk-a7kq09ke.js";import"./chunk-prqeddy7.js";import"./chunk-zt7wfnva.js";import"./chunk-yt15y085.js";import"./chunk-npwzmmv9.js";import"./chunk-b39sdtt0.js";import"./chunk-nc46gddg.js";import"./chunk-wqfp8d9w.js";export{startTunnel,ensureForwards};
@@ -0,0 +1,2 @@
1
+ // @bun
2
+ import{NoopHookAdapter,activityHookAdapters,createEngineHookAdapter}from"./chunk-y8tysjc2.js";import"./chunk-576r5nht.js";import"./chunk-w7zv47mp.js";import"./chunk-2tfnscxk.js";import"./chunk-2brn8e1y.js";import"./chunk-yexx8nec.js";import"./chunk-znjcesdr.js";import"./chunk-7kysxgbq.js";import"./chunk-qzsahxd9.js";import"./chunk-xy8be792.js";import"./chunk-h2m7em1e.js";import"./chunk-tdhk4dz8.js";import"./chunk-h9cg0j3a.js";import"./chunk-40dgv828.js";import"./chunk-3342qzve.js";import"./chunk-7q43tysm.js";import"./chunk-mw0ysrpd.js";import"./chunk-a7kq09ke.js";import"./chunk-prqeddy7.js";import"./chunk-zt7wfnva.js";import"./chunk-yt15y085.js";import"./chunk-hq9tbzqa.js";import"./chunk-pn5ygqn6.js";import"./chunk-npwzmmv9.js";import"./chunk-b39sdtt0.js";import"./chunk-nc46gddg.js";import"./chunk-wqfp8d9w.js";export{createEngineHookAdapter,activityHookAdapters,NoopHookAdapter};
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- import{PLUGIN_MANIFEST_FILENAMES,currentPluginPlatform,loadPluginRegistry,parsePluginManifest,pluginCheckoutDir,pluginConfigDir,pluginManifestPath,pluginStateDir,pluginsRootDir,savePluginRegistry,supportsPlatform,upsertPluginEntry}from"./chunk-1da3bqjc.js";import{CURRENT_VERSION,compareSemver}from"./chunk-be757xzj.js";import{spawn}from"child_process";import{cpSync,existsSync,mkdirSync,readFileSync,renameSync,rmSync}from"fs";import{mkdtempSync}from"fs";import{basename,join,resolve}from"path";import{createInterface}from"readline/promises";var GITHUB_SPEC_RE=/^([A-Za-z0-9-]+)\/([A-Za-z0-9._-]+)(\/.+)?$/;class PluginCliError extends Error{}function fail(message){throw new PluginCliError(message)}function readManifestAt(root){let path=pluginManifestPath(root);if(!path)fail(`no ${PLUGIN_MANIFEST_FILENAMES.join(" or ")} found at ${root}`);let source=readFileSync(path,"utf8");return{...parsePluginManifest(source,basename(path)),manifestPath:path,manifestSource:source}}function checkVersionGate(parsed){let min=parsed.manifest.minKobeVersion;if(compareSemver(CURRENT_VERSION,min)<0)fail(`plugin requires Rove >= ${min} (this is ${CURRENT_VERSION}); update Rove first`)}function commandLines(parsed){let m=parsed.manifest,lines=[];for(let c of m.build)lines.push(`build: ${c.command.join(" ")}`);for(let c of m.startup)lines.push(`startup: ${c.command.join(" ")}`);for(let a of m.actions)lines.push(`action ${a.id}: ${a.command.join(" ")}`);for(let e of m.events)lines.push(`on ${e.on}: ${e.command.join(" ")}`);return lines}var CAPTURE_TAIL_BYTES=4096;function run(cmd,args,opts){return new Promise((resolve2)=>{let child=spawn(cmd,args,{cwd:opts.cwd,stdio:opts.inherit?["ignore","inherit","inherit"]:["ignore","pipe","pipe"]}),output="",collect=(chunk)=>{output=`${output}${String(chunk)}`.slice(-CAPTURE_TAIL_BYTES)};child.stdout?.on("data",collect),child.stderr?.on("data",collect),child.on("error",(err)=>resolve2({code:null,output:`${output}${err.message}`})),child.on("close",(code)=>resolve2({code,output}))})}function outputTail(output){let trimmed=output.trim();return trimmed?`: ${trimmed.split(`
2
+ import{PLUGIN_MANIFEST_FILENAMES,currentPluginPlatform,loadPluginRegistry,parsePluginManifest,pluginCheckoutDir,pluginConfigDir,pluginManifestPath,pluginStateDir,pluginsRootDir,savePluginRegistry,supportsPlatform,upsertPluginEntry}from"./chunk-rqyaf0dw.js";import{CURRENT_VERSION,compareSemver}from"./chunk-a0ave3g6.js";import{spawn}from"child_process";import{cpSync,existsSync,mkdirSync,readFileSync,renameSync,rmSync}from"fs";import{mkdtempSync}from"fs";import{basename,join,resolve}from"path";import{createInterface}from"readline/promises";var GITHUB_SPEC_RE=/^([A-Za-z0-9-]+)\/([A-Za-z0-9._-]+)(\/.+)?$/;class PluginCliError extends Error{}function fail(message){throw new PluginCliError(message)}function readManifestAt(root){let path=pluginManifestPath(root);if(!path)fail(`no ${PLUGIN_MANIFEST_FILENAMES.join(" or ")} found at ${root}`);let source=readFileSync(path,"utf8");return{...parsePluginManifest(source,basename(path)),manifestPath:path,manifestSource:source}}function checkVersionGate(parsed){let min=parsed.manifest.minRoveVersion;if(compareSemver(CURRENT_VERSION,min)<0)fail(`plugin requires Rove >= ${min} (this is ${CURRENT_VERSION}); update Rove first`)}function commandLines(parsed){let m=parsed.manifest,lines=[];for(let c of m.build)lines.push(`build: ${c.command.join(" ")}`);for(let c of m.startup)lines.push(`startup: ${c.command.join(" ")}`);for(let a of m.actions)lines.push(`action ${a.id}: ${a.command.join(" ")}`);for(let e of m.events)lines.push(`on ${e.on}: ${e.command.join(" ")}`);return lines}var CAPTURE_TAIL_BYTES=4096;function run(cmd,args,opts){return new Promise((resolve2)=>{let child=spawn(cmd,args,{cwd:opts.cwd,stdio:opts.inherit?["ignore","inherit","inherit"]:["ignore","pipe","pipe"]}),output="",collect=(chunk)=>{output=`${output}${String(chunk)}`.slice(-CAPTURE_TAIL_BYTES)};child.stdout?.on("data",collect),child.stderr?.on("data",collect),child.on("error",(err)=>resolve2({code:null,output:`${output}${err.message}`})),child.on("close",(code)=>resolve2({code,output}))})}function outputTail(output){let trimmed=output.trim();return trimmed?`: ${trimmed.split(`
3
3
  `).slice(-3).join(" / ")}`:""}async function git(args,opts){let{code,output}=await run("git",args,opts);if(code!==0)fail(`git ${args[0]} failed${outputTail(output)}`)}async function runBuildCommands(parsed,root,opts){let platform=currentPluginPlatform();for(let[i,step]of parsed.manifest.build.entries()){if(!supportsPlatform(step,parsed.manifest,platform))continue;let[cmd,...args]=step.command;if(opts.inherit)console.log(`build[${i}]: ${step.command.join(" ")}`);let{code,output}=await run(cmd,args,{cwd:root,inherit:opts.inherit});if(code!==0)fail(`build[${i}] failed (exit ${code??"spawn error"}); plugin not registered${outputTail(output)}`)}}function makeStagingDir(){let root=pluginsRootDir();return mkdirSync(root,{recursive:!0}),mkdtempSync(join(root,".staging-"))}function movePluginTree(from,to){try{renameSync(from,to)}catch(err){if(err.code!=="EXDEV")throw err;cpSync(from,to,{recursive:!0,verbatimSymlinks:!0}),rmSync(from,{recursive:!0,force:!0})}}function register(entry){savePluginRegistry(upsertPluginEntry(loadPluginRegistry(),entry)),mkdirSync(pluginConfigDir(entry.id),{recursive:!0,mode:448}),mkdirSync(pluginStateDir(entry.id),{recursive:!0,mode:448})}async function preparePluginInstall(spec,opts={}){let match=spec.match(GITHUB_SPEC_RE);if(!match)fail(`install takes GitHub shorthand (owner/repo[/subdir]), got \`${spec}\``);let[,owner,repo,subdirRaw]=match,subdir=subdirRaw?.replace(/^\//,""),inherit=opts.inherit??!1,tmp=makeStagingDir();try{let url=`https://github.com/${owner}/${repo}.git`;if(inherit)console.log(`cloning ${url}${opts.ref?` @ ${opts.ref}`:""}`);if(opts.ref)await git(["clone","--quiet",url,tmp],{inherit}),await git(["checkout","--quiet",opts.ref],{cwd:tmp,inherit});else await git(["clone","--quiet","--depth","1",url,tmp],{inherit});let rootInClone=subdir?join(tmp,subdir):tmp,parsed=readManifestAt(rootInClone);checkVersionGate(parsed);let id=parsed.manifest.id,existing=loadPluginRegistry().plugins.find((p)=>p.id===id);if(existing?.source.kind==="link")fail(`\`${id}\` is locally linked at ${existing.root}; unlink it first`);if(!supportsPlatform({},parsed.manifest,currentPluginPlatform()))fail(`plugin declares platforms [${parsed.manifest.platforms?.join(", ")}]; this machine is unsupported`);return{preview:{id,name:parsed.manifest.name,version:parsed.manifest.version,description:parsed.manifest.description??null,source:`github.com/${owner}/${repo}${subdir?`/${subdir}`:""}`,commands:commandLines(parsed),warnings:parsed.warnings},commit:async()=>{try{await runBuildCommands(parsed,rootInClone,{inherit});let manifestPath=pluginManifestPath(rootInClone);if(!manifestPath)fail("manifest disappeared during build; aborting");if(manifestPath!==parsed.manifestPath)fail("manifest changed during build; aborting");if(readFileSync(manifestPath,"utf8")!==parsed.manifestSource)fail("manifest changed during build; aborting");let checkout=pluginCheckoutDir(id);return rmSync(checkout,{recursive:!0,force:!0}),mkdirSync(join(checkout,".."),{recursive:!0}),movePluginTree(tmp,checkout),register({id,source:{kind:"github",spec},root:subdir?join(checkout,subdir):checkout,enabled:!0,version:parsed.manifest.version,installedAt:Date.now()}),id}finally{rmSync(tmp,{recursive:!0,force:!0})}},discard:()=>rmSync(tmp,{recursive:!0,force:!0})}}catch(err){throw rmSync(tmp,{recursive:!0,force:!0}),err}}function printPreview(preview){console.log(`
4
4
  ${preview.name} (${preview.id}) v${preview.version} \u2014 ${preview.description??"no description"}`),console.log(`source: ${preview.source}`);for(let line of preview.commands)console.log(` ${line}`);for(let w of preview.warnings)console.log(` warning: ${w}`);console.log("")}async function confirmOrBail(yes){if(yes)return;if(!process.stdin.isTTY)fail("refusing to install without confirmation in a non-interactive terminal; pass --yes");let rl=createInterface({input:process.stdin,output:process.stdout}),answer=(await rl.question("Install this plugin and run its build commands? [y/N] ")).trim().toLowerCase();if(rl.close(),answer!=="y"&&answer!=="yes")fail("aborted")}async function installPlugin(spec,opts){let prepared=await preparePluginInstall(spec,{ref:opts.ref,inherit:!0});printPreview(prepared.preview);try{await confirmOrBail(opts.yes)}catch(err){throw prepared.discard(),err}let id=await prepared.commit();return console.log(`installed ${id} v${prepared.preview.version}`),id}function linkPlugin(dir){let root=resolve(dir);if(!existsSync(root))fail(`no such directory: ${root}`);let parsed=readManifestAt(root);checkVersionGate(parsed);let id=parsed.manifest.id;if(loadPluginRegistry().plugins.find((p)=>p.id===id)?.source.kind==="github")fail(`\`${id}\` is installed from GitHub; uninstall it before linking a local copy`);for(let w of parsed.warnings)console.log(`warning: ${w}`);if(!supportsPlatform({},parsed.manifest,currentPluginPlatform()))console.log(`warning: declares platforms [${parsed.manifest.platforms?.join(", ")}]; nothing will run on this machine`);register({id,source:{kind:"link"},root,enabled:!0,version:parsed.manifest.version,installedAt:Date.now()}),console.log(`linked ${id} v${parsed.manifest.version} \u2192 ${root}`)}
5
5
  export{PluginCliError,preparePluginInstall,installPlugin,linkPlugin};
@@ -0,0 +1,3 @@
1
+ // @bun
2
+ import{defaultUiPrefsStatePath,resolveProductHomeDir}from"./chunk-prqeddy7.js";import{preRenameStateDir}from"./chunk-b39sdtt0.js";import{ROVE_STATE_DIR_BASENAME}from"./chunk-nc46gddg.js";import{createHash}from"crypto";import{readFileSync}from"fs";import path from"path";var WORKTREE_ROOT_DIR="worktrees",REPO_LOCAL_ROVE_WORKTREE_ROOT_SUBPATH=".rove/worktrees",LEGACY_ROVE_WORKTREE_ROOT_SUBPATH=".claude/worktrees",REPO_LOCAL_MANAGED_WORKTREE_ROOT_SUBPATHS=[REPO_LOCAL_ROVE_WORKTREE_ROOT_SUBPATH,LEGACY_ROVE_WORKTREE_ROOT_SUBPATH],WORKTREE_BASE_KEY="worktree.basePath",PROJECT_DIR_TOKEN="$project_dir";function repoWorktreeDirName(repo){let safeBase=(path.basename(repo)||"repo").replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")||"repo",hash=createHash("sha1").update(path.resolve(repo)).digest("hex").slice(0,12);return`${safeBase}-${hash}`}function hasProjectDirToken(raw){let trimmed=raw.trim();return trimmed===PROJECT_DIR_TOKEN||trimmed.startsWith(`${PROJECT_DIR_TOKEN}/`)||process.platform==="win32"&&trimmed.startsWith(`${PROJECT_DIR_TOKEN}\\`)}function normalizeWorktreeBase(raw,projectDir){if(typeof raw!=="string")return null;let trimmed=raw.trim();if(!trimmed)return null;if(hasProjectDirToken(trimmed)){if(!projectDir)return null;let rest=trimmed.slice(PROJECT_DIR_TOKEN.length).replace(process.platform==="win32"?/^[/\\]+/:/^\/+/,"");return path.resolve(projectDir,rest)}let home=resolveProductHomeDir();if(trimmed==="~")return home;let expanded=trimmed.startsWith("~/")||process.platform==="win32"&&trimmed.startsWith("~\\")?path.join(home,trimmed.slice(2)):trimmed;return path.isAbsolute(expanded)?expanded:path.resolve(home,expanded)}function readWorktreeBaseOverride(projectDir){try{let raw=JSON.parse(readFileSync(defaultUiPrefsStatePath(),"utf8"));if(!raw||typeof raw!=="object"||Array.isArray(raw))return null;let value=raw[WORKTREE_BASE_KEY];return normalizeWorktreeBase(typeof value==="string"?value:null,projectDir)}catch{return null}}function defaultLocalWorktreesRoot(){return path.join(resolveProductHomeDir(),ROVE_STATE_DIR_BASENAME,WORKTREE_ROOT_DIR)}function legacyLocalWorktreesRoot(){return path.join(preRenameStateDir(resolveProductHomeDir()),WORKTREE_ROOT_DIR)}function worktreeRootFor(repo,override){if(!path.isAbsolute(repo))throw Error(`worktreeRootFor: repo must be an absolute path, got: ${repo}`);return path.join(override??defaultLocalWorktreesRoot(),repoWorktreeDirName(repo))}function managedWorktreeRootsFor(repo,override){if(!path.isAbsolute(repo))throw Error(`managedWorktreeRootsFor: repo must be an absolute path, got: ${repo}`);let dirName=repoWorktreeDirName(repo);return[...new Set([worktreeRootFor(repo,override),path.join(defaultLocalWorktreesRoot(),dirName),path.join(legacyLocalWorktreesRoot(),dirName),...REPO_LOCAL_MANAGED_WORKTREE_ROOT_SUBPATHS.map((subpath)=>path.join(repo,subpath))])]}
3
+ export{WORKTREE_BASE_KEY,PROJECT_DIR_TOKEN,hasProjectDirToken,normalizeWorktreeBase,readWorktreeBaseOverride,defaultLocalWorktreesRoot,legacyLocalWorktreesRoot,worktreeRootFor,managedWorktreeRootsFor};
@@ -0,0 +1,2 @@
1
+ // @bun
2
+ import{launchTui,trackWelcomeWrite}from"./chunk-m5gx53yr.js";import"./chunk-wqfp8d9w.js";export{trackWelcomeWrite,launchTui};
@@ -1,3 +1,3 @@
1
1
  // @bun
2
- import{serialized,writeJsonAtomic}from"./chunk-xsrcwcjc.js";import{logDaemonError}from"./chunk-rcyasw34.js";import{ROVE_STATE_DIR_BASENAME,readRoveHomeDirEnv}from"./chunk-hq4b3fca.js";import{readFile}from"fs/promises";import{homedir}from"os";import{join,resolve as resolve2}from"path";import{execFile}from"child_process";import{realpath,stat}from"fs/promises";import{isAbsolute,resolve}from"path";import{promisify}from"util";var execFileAsync=promisify(execFile);async function gitCommonDir(path){let{stdout}=await execFileAsync("git",["-C",path,"rev-parse","--git-common-dir"]),dir=stdout.trim();return realpath(isAbsolute(dir)?dir:resolve(path,dir))}async function gitMainWorktree(path){let{stdout}=await execFileAsync("git",["-C",path,"worktree","list","--porcelain"]),first=stdout.split(/\r?\n/).find((line)=>line.startsWith("worktree "))?.slice(9).trim();return first?await realpath(first):null}async function gitTopLevel(path){let{stdout}=await execFileAsync("git",["-C",path,"rev-parse","--show-toplevel"]);return stdout.trim()}async function resolveRepoRoot(raw){let absolute=resolve(raw);if(!(await stat(absolute).catch(()=>null))?.isDirectory())throw Error("repoRoot does not exist");let[repoRoot,repoKey]=await Promise.all([gitMainWorktree(absolute),gitCommonDir(absolute)]);return{repoRoot,repoKey}}var ISSUE_STATUSES=["open","doing","hold","done"],ISSUE_NOT_FOUND_CODE="ISSUE_NOT_FOUND",ISSUE_STORE_UNREADABLE_CODE="ISSUE_STORE_UNREADABLE";function isGitNotRepositoryError(err){return(err instanceof Error?err.message:String(err)).includes("not a git repository")}function defaultIssuesStorePath(homeDir=readRoveHomeDirEnv()??homedir()){return join(homeDir,ROVE_STATE_DIR_BASENAME,"issues.json")}function isValidStatus(value){return typeof value==="string"&&ISSUE_STATUSES.includes(value)}function normalizeIssue(entry){if(entry===null||typeof entry!=="object"||Array.isArray(entry))return null;let raw=entry;if(typeof raw.id!=="number")return null;return{id:raw.id,title:typeof raw.title==="string"?raw.title:"(untitled)",status:isValidStatus(raw.status)?raw.status:"open",created:typeof raw.created==="string"?raw.created:"",body:typeof raw.body==="string"?raw.body:"",taskId:typeof raw.taskId==="string"?raw.taskId:void 0}}function emptyStore(){return{version:1,repos:{}}}function nextIdFallback(entries){let max=0;for(let entry of entries){let id=Number(entry?.id);if(Number.isFinite(id)&&id>max)max=Math.trunc(id)}return max+1}function todayStamp(){let pinned=process.env.KOBE_ISSUES_TODAY;if(pinned&&/^\d{4}-\d{2}-\d{2}$/.test(pinned))return pinned;let d=new Date,mm=String(d.getMonth()+1).padStart(2,"0"),dd=String(d.getDate()).padStart(2,"0");return`${d.getFullYear()}-${mm}-${dd}`}async function resolveRepo(raw){if(typeof raw!=="string"||raw.length===0)throw Error("repoRoot is required");try{let{repoRoot,repoKey}=await resolveRepoRoot(raw);return{repoRoot:repoRoot??await gitTopLevel(resolve2(raw)),repoKey}}catch(err){if(isGitNotRepositoryError(err))throw Error("repoRoot is not a git repository");throw err}}function unreadableCount(raw){if(raw!==null&&typeof raw==="object"&&!Array.isArray(raw))return Math.max(1,Object.keys(raw).length);return 1}function readRecord(value){let record=value,base={repoRoot:typeof record.repoRoot==="string"?record.repoRoot:"",nextId:typeof record.nextId==="number"?record.nextId:1};if(record.issues!==void 0&&!Array.isArray(record.issues))return{record:{...base,issues:[],unusable:[],unreadable:{raw:value}},dropped:unreadableCount(record.issues)};let entries=Array.isArray(record.issues)?record.issues:[],issues=entries.map(normalizeIssue).filter((issue)=>issue!==null),unusable=entries.filter((entry)=>normalizeIssue(entry)===null);return{record:{repoRoot:base.repoRoot,nextId:typeof record.nextId==="number"?record.nextId:nextIdFallback(entries),issues,unusable},dropped:unusable.length}}async function readStore(path){try{let raw=JSON.parse(await readFile(path,"utf8")),repos={},skipped=new Map;if(raw.repos&&typeof raw.repos==="object")for(let[key,value]of Object.entries(raw.repos)){if(!value||typeof value!=="object")continue;let{record,dropped}=readRecord(value);if(dropped>0){skipped.set(key,dropped);let why=record.unreadable?'"issues" is not an array':"id is not a number";logDaemonError("issues-store-read",Error(`${key}: dropped ${dropped} unreadable issue entr${dropped===1?"y":"ies"} (${why})`))}repos[key]=record}return{file:{version:1,repos},skipped}}catch(err){if(err.code==="ENOENT")return{file:emptyStore(),skipped:new Map};throw Error(`${path}: ${err instanceof Error?err.message:String(err)}`)}}function serializeRecord(record){if(record.unreadable)return record.unreadable.raw;return{repoRoot:record.repoRoot,nextId:record.nextId,issues:[...record.issues,...record.unusable]}}async function writeStore(path,store){let repos={};for(let[key,record]of Object.entries(store.repos))repos[key]=serializeRecord(record);await writeJsonAtomic(path,{version:store.version,repos})}function response(repoRoot,record,skipped=0){return{repoRoot,exists:record!==null,nextId:record?.nextId??1,issues:record?.issues??[],skipped}}class IssuesStore{path;constructor(path=defaultIssuesStorePath()){this.path=path}async list(repo){let{repoRoot,repoKey}=await resolveRepo(repo);return serialized(this.path,async()=>{let{file:store,skipped}=await readStore(this.path),record=store.repos[repoKey]??null;if(record&&!record.unreadable&&record.repoRoot!==repoRoot)record.repoRoot=repoRoot,await writeStore(this.path,store);return response(repoRoot,record,skipped.get(repoKey)??0)})}async repos(){return serialized(this.path,async()=>{let{file}=await readStore(this.path);return Object.values(file.repos).map((record)=>record.repoRoot).filter((root)=>root.length>0)})}async mirrorTaskDone(repo,taskId){let{repoRoot,repoKey}=await resolveRepo(repo);if(!taskId)return null;return serialized(this.path,async()=>{let{file:store,skipped}=await readStore(this.path),record=store.repos[repoKey];if(!record)return null;let issue=record.issues.find((i)=>i.taskId===taskId);if(!issue||issue.status==="done")return null;return issue.status="done",record.repoRoot=repoRoot,await writeStore(this.path,store),response(repoRoot,record,skipped.get(repoKey)??0)})}async unlinkTask(repo,taskId){let{repoRoot,repoKey}=await resolveRepo(repo);if(!taskId)return null;return serialized(this.path,async()=>{let{file:store,skipped}=await readStore(this.path),record=store.repos[repoKey];if(!record)return null;let issue=record.issues.find((i)=>i.taskId===taskId);if(!issue)return null;return issue.taskId=void 0,record.repoRoot=repoRoot,await writeStore(this.path,store),response(repoRoot,record,skipped.get(repoKey)??0)})}async mutate(repo,op){let{repoRoot,repoKey}=await resolveRepo(repo);if(!op||typeof op!=="object"||Array.isArray(op)||typeof op.type!=="string")throw Error("missing op");return serialized(this.path,async()=>{let{file:store,skipped}=await readStore(this.path),record=store.repos[repoKey];if(!record)record={repoRoot,nextId:1,issues:[],unusable:[]},store.repos[repoKey]=record;if(record.unreadable)throw Error(`${ISSUE_STORE_UNREADABLE_CODE}: ${repoRoot}'s record in ${this.path} has a non-array "issues" \u2014 refusing to write over stories this build cannot read`);record.repoRoot=repoRoot;let typed=op;if(typed.type==="create"){if(typeof typed.title!=="string"||typed.title.trim().length===0)throw Error("create requires a non-empty title");if(typed.body!==void 0&&typeof typed.body!=="string")throw Error("body must be a string");record.issues=[{id:record.nextId,title:typed.title,status:"open",created:todayStamp(),body:typeof typed.body==="string"?typed.body:""},...record.issues],record.nextId+=1}else if(typed.type==="setStatus"){if(typeof typed.id!=="number")throw Error("setStatus requires a numeric id");if(!isValidStatus(typed.status))throw Error(`invalid status: must be one of ${ISSUE_STATUSES.join(", ")}`);let issue=record.issues.find((i)=>i.id===typed.id);if(!issue)throw Error(`${ISSUE_NOT_FOUND_CODE}: no issue #${typed.id}`);issue.status=typed.status}else if(typed.type==="update"){if(typeof typed.id!=="number")throw Error("update requires a numeric id");if(typed.title!==void 0&&(typeof typed.title!=="string"||typed.title.trim().length===0))throw Error("title must be a non-empty string");if(typed.body!==void 0&&typeof typed.body!=="string")throw Error("body must be a string");if(typed.taskId!==void 0&&typed.taskId!==null&&(typeof typed.taskId!=="string"||typed.taskId.length===0))throw Error("taskId must be a non-empty string or null");let issue=record.issues.find((i)=>i.id===typed.id);if(!issue)throw Error(`${ISSUE_NOT_FOUND_CODE}: no issue #${typed.id}`);if(typeof typed.title==="string")issue.title=typed.title;if(typeof typed.body==="string")issue.body=typed.body;if(typed.taskId!==void 0)issue.taskId=typed.taskId===null?void 0:typed.taskId}else if(typed.type==="link"){if(typeof typed.id!=="number")throw Error("link requires a numeric id");if(typeof typed.taskId!=="string"||typed.taskId.length===0)throw Error("link requires a non-empty taskId");let issue=record.issues.find((i)=>i.id===typed.id);if(!issue)throw Error(`${ISSUE_NOT_FOUND_CODE}: no issue #${typed.id}`);issue.taskId=typed.taskId}else if(typed.type==="unlink"){if(typeof typed.id!=="number")throw Error("unlink requires a numeric id");let issue=record.issues.find((i)=>i.id===typed.id);if(!issue)throw Error(`${ISSUE_NOT_FOUND_CODE}: no issue #${typed.id}`);issue.taskId=void 0}else if(typed.type==="delete"){if(typeof typed.id!=="number")throw Error("delete requires a numeric id");let nextIssues=record.issues.filter((i)=>i.id!==typed.id);if(nextIssues.length===record.issues.length)throw Error(`${ISSUE_NOT_FOUND_CODE}: no issue #${typed.id}`);record.issues=nextIssues}else throw Error(`unknown op type: ${typed.type}`);return await writeStore(this.path,store),response(repoRoot,record,skipped.get(repoKey)??0)})}}
2
+ import{serialized,writeJsonAtomic}from"./chunk-5mhvjytn.js";import{logDaemonError}from"./chunk-rxqdw6s5.js";import{ROVE_STATE_DIR_BASENAME,readRoveHomeDirEnv}from"./chunk-nc46gddg.js";import{readFile}from"fs/promises";import{homedir}from"os";import{join,resolve as resolve2}from"path";import{execFile}from"child_process";import{realpath,stat}from"fs/promises";import{isAbsolute,resolve}from"path";import{promisify}from"util";var execFileAsync=promisify(execFile);async function gitCommonDir(path){let{stdout}=await execFileAsync("git",["-C",path,"rev-parse","--git-common-dir"]),dir=stdout.trim();return realpath(isAbsolute(dir)?dir:resolve(path,dir))}async function gitMainWorktree(path){let{stdout}=await execFileAsync("git",["-C",path,"worktree","list","--porcelain"]),first=stdout.split(/\r?\n/).find((line)=>line.startsWith("worktree "))?.slice(9).trim();return first?await realpath(first):null}async function gitTopLevel(path){let{stdout}=await execFileAsync("git",["-C",path,"rev-parse","--show-toplevel"]);return stdout.trim()}async function resolveRepoRoot(raw){let absolute=resolve(raw);if(!(await stat(absolute).catch(()=>null))?.isDirectory())throw Error("repoRoot does not exist");let[repoRoot,repoKey]=await Promise.all([gitMainWorktree(absolute),gitCommonDir(absolute)]);return{repoRoot,repoKey}}var ISSUE_STATUSES=["open","doing","hold","done"],ISSUE_NOT_FOUND_CODE="ISSUE_NOT_FOUND",ISSUE_STORE_UNREADABLE_CODE="ISSUE_STORE_UNREADABLE";function isGitNotRepositoryError(err){return(err instanceof Error?err.message:String(err)).includes("not a git repository")}function defaultIssuesStorePath(homeDir=readRoveHomeDirEnv()??homedir()){return join(homeDir,ROVE_STATE_DIR_BASENAME,"issues.json")}function isValidStatus(value){return typeof value==="string"&&ISSUE_STATUSES.includes(value)}function normalizeIssue(entry){if(entry===null||typeof entry!=="object"||Array.isArray(entry))return null;let raw=entry;if(typeof raw.id!=="number")return null;return{id:raw.id,title:typeof raw.title==="string"?raw.title:"(untitled)",status:isValidStatus(raw.status)?raw.status:"open",created:typeof raw.created==="string"?raw.created:"",body:typeof raw.body==="string"?raw.body:"",taskId:typeof raw.taskId==="string"?raw.taskId:void 0}}function emptyStore(){return{version:1,repos:{}}}function nextIdFallback(entries){let max=0;for(let entry of entries){let id=Number(entry?.id);if(Number.isFinite(id)&&id>max)max=Math.trunc(id)}return max+1}function todayStamp(){let pinned=process.env.ROVE_ISSUES_TODAY;if(pinned&&/^\d{4}-\d{2}-\d{2}$/.test(pinned))return pinned;let d=new Date,mm=String(d.getMonth()+1).padStart(2,"0"),dd=String(d.getDate()).padStart(2,"0");return`${d.getFullYear()}-${mm}-${dd}`}async function resolveRepo(raw){if(typeof raw!=="string"||raw.length===0)throw Error("repoRoot is required");try{let{repoRoot,repoKey}=await resolveRepoRoot(raw);return{repoRoot:repoRoot??await gitTopLevel(resolve2(raw)),repoKey}}catch(err){if(isGitNotRepositoryError(err))throw Error("repoRoot is not a git repository");throw err}}function unreadableCount(raw){if(raw!==null&&typeof raw==="object"&&!Array.isArray(raw))return Math.max(1,Object.keys(raw).length);return 1}function readRecord(value){let record=value,base={repoRoot:typeof record.repoRoot==="string"?record.repoRoot:"",nextId:typeof record.nextId==="number"?record.nextId:1};if(record.issues!==void 0&&!Array.isArray(record.issues))return{record:{...base,issues:[],unusable:[],unreadable:{raw:value}},dropped:unreadableCount(record.issues)};let entries=Array.isArray(record.issues)?record.issues:[],issues=entries.map(normalizeIssue).filter((issue)=>issue!==null),unusable=entries.filter((entry)=>normalizeIssue(entry)===null);return{record:{repoRoot:base.repoRoot,nextId:typeof record.nextId==="number"?record.nextId:nextIdFallback(entries),issues,unusable},dropped:unusable.length}}async function readStore(path){try{let raw=JSON.parse(await readFile(path,"utf8")),repos={},skipped=new Map;if(raw.repos&&typeof raw.repos==="object")for(let[key,value]of Object.entries(raw.repos)){if(!value||typeof value!=="object")continue;let{record,dropped}=readRecord(value);if(dropped>0){skipped.set(key,dropped);let why=record.unreadable?'"issues" is not an array':"id is not a number";logDaemonError("issues-store-read",Error(`${key}: dropped ${dropped} unreadable issue entr${dropped===1?"y":"ies"} (${why})`))}repos[key]=record}return{file:{version:1,repos},skipped}}catch(err){if(err.code==="ENOENT")return{file:emptyStore(),skipped:new Map};throw Error(`${path}: ${err instanceof Error?err.message:String(err)}`)}}function serializeRecord(record){if(record.unreadable)return record.unreadable.raw;return{repoRoot:record.repoRoot,nextId:record.nextId,issues:[...record.issues,...record.unusable]}}async function writeStore(path,store){let repos={};for(let[key,record]of Object.entries(store.repos))repos[key]=serializeRecord(record);await writeJsonAtomic(path,{version:store.version,repos})}function response(repoRoot,record,skipped=0){return{repoRoot,exists:record!==null,nextId:record?.nextId??1,issues:record?.issues??[],skipped}}class IssuesStore{path;constructor(path=defaultIssuesStorePath()){this.path=path}async list(repo){let{repoRoot,repoKey}=await resolveRepo(repo);return serialized(this.path,async()=>{let{file:store,skipped}=await readStore(this.path),record=store.repos[repoKey]??null;if(record&&!record.unreadable&&record.repoRoot!==repoRoot)record.repoRoot=repoRoot,await writeStore(this.path,store);return response(repoRoot,record,skipped.get(repoKey)??0)})}async repos(){return serialized(this.path,async()=>{let{file}=await readStore(this.path);return Object.values(file.repos).map((record)=>record.repoRoot).filter((root)=>root.length>0)})}async mirrorTaskDone(repo,taskId){let{repoRoot,repoKey}=await resolveRepo(repo);if(!taskId)return null;return serialized(this.path,async()=>{let{file:store,skipped}=await readStore(this.path),record=store.repos[repoKey];if(!record)return null;let issue=record.issues.find((i)=>i.taskId===taskId);if(!issue||issue.status==="done")return null;return issue.status="done",record.repoRoot=repoRoot,await writeStore(this.path,store),response(repoRoot,record,skipped.get(repoKey)??0)})}async unlinkTask(repo,taskId){let{repoRoot,repoKey}=await resolveRepo(repo);if(!taskId)return null;return serialized(this.path,async()=>{let{file:store,skipped}=await readStore(this.path),record=store.repos[repoKey];if(!record)return null;let issue=record.issues.find((i)=>i.taskId===taskId);if(!issue)return null;return issue.taskId=void 0,record.repoRoot=repoRoot,await writeStore(this.path,store),response(repoRoot,record,skipped.get(repoKey)??0)})}async mutate(repo,op){let{repoRoot,repoKey}=await resolveRepo(repo);if(!op||typeof op!=="object"||Array.isArray(op)||typeof op.type!=="string")throw Error("missing op");return serialized(this.path,async()=>{let{file:store,skipped}=await readStore(this.path),record=store.repos[repoKey];if(!record)record={repoRoot,nextId:1,issues:[],unusable:[]},store.repos[repoKey]=record;if(record.unreadable)throw Error(`${ISSUE_STORE_UNREADABLE_CODE}: ${repoRoot}'s record in ${this.path} has a non-array "issues" \u2014 refusing to write over stories this build cannot read`);record.repoRoot=repoRoot;let typed=op;if(typed.type==="create"){if(typeof typed.title!=="string"||typed.title.trim().length===0)throw Error("create requires a non-empty title");if(typed.body!==void 0&&typeof typed.body!=="string")throw Error("body must be a string");record.issues=[{id:record.nextId,title:typed.title,status:"open",created:todayStamp(),body:typeof typed.body==="string"?typed.body:""},...record.issues],record.nextId+=1}else if(typed.type==="setStatus"){if(typeof typed.id!=="number")throw Error("setStatus requires a numeric id");if(!isValidStatus(typed.status))throw Error(`invalid status: must be one of ${ISSUE_STATUSES.join(", ")}`);let issue=record.issues.find((i)=>i.id===typed.id);if(!issue)throw Error(`${ISSUE_NOT_FOUND_CODE}: no issue #${typed.id}`);issue.status=typed.status}else if(typed.type==="update"){if(typeof typed.id!=="number")throw Error("update requires a numeric id");if(typed.title!==void 0&&(typeof typed.title!=="string"||typed.title.trim().length===0))throw Error("title must be a non-empty string");if(typed.body!==void 0&&typeof typed.body!=="string")throw Error("body must be a string");if(typed.taskId!==void 0&&typed.taskId!==null&&(typeof typed.taskId!=="string"||typed.taskId.length===0))throw Error("taskId must be a non-empty string or null");let issue=record.issues.find((i)=>i.id===typed.id);if(!issue)throw Error(`${ISSUE_NOT_FOUND_CODE}: no issue #${typed.id}`);if(typeof typed.title==="string")issue.title=typed.title;if(typeof typed.body==="string")issue.body=typed.body;if(typed.taskId!==void 0)issue.taskId=typed.taskId===null?void 0:typed.taskId}else if(typed.type==="link"){if(typeof typed.id!=="number")throw Error("link requires a numeric id");if(typeof typed.taskId!=="string"||typed.taskId.length===0)throw Error("link requires a non-empty taskId");let issue=record.issues.find((i)=>i.id===typed.id);if(!issue)throw Error(`${ISSUE_NOT_FOUND_CODE}: no issue #${typed.id}`);issue.taskId=typed.taskId}else if(typed.type==="unlink"){if(typeof typed.id!=="number")throw Error("unlink requires a numeric id");let issue=record.issues.find((i)=>i.id===typed.id);if(!issue)throw Error(`${ISSUE_NOT_FOUND_CODE}: no issue #${typed.id}`);issue.taskId=void 0}else if(typed.type==="delete"){if(typeof typed.id!=="number")throw Error("delete requires a numeric id");let nextIssues=record.issues.filter((i)=>i.id!==typed.id);if(nextIssues.length===record.issues.length)throw Error(`${ISSUE_NOT_FOUND_CODE}: no issue #${typed.id}`);record.issues=nextIssues}else throw Error(`unknown op type: ${typed.type}`);return await writeStore(this.path,store),response(repoRoot,record,skipped.get(repoKey)??0)})}}
3
3
  export{resolveRepoRoot,ISSUE_STATUSES,defaultIssuesStorePath,IssuesStore};
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- import{CURRENT_VERSION,repoSlug}from"./chunk-be757xzj.js";import{spawnSync}from"child_process";var DEFAULT_FEEDBACK_CATEGORY_SLUG="feedback",DISCUSSION_CATEGORY_QUERY=`
2
+ import{CURRENT_VERSION,repoSlug}from"./chunk-a0ave3g6.js";import{spawnSync}from"child_process";var DEFAULT_FEEDBACK_CATEGORY_SLUG="feedback",DISCUSSION_CATEGORY_QUERY=`
3
3
  query($owner: String!, $name: String!) {
4
4
  repository(owner: $owner, name: $name) {
5
5
  id
@@ -1,4 +1,4 @@
1
1
  // @bun
2
- import{resolveLoginShell}from"./chunk-exfyqsdd.js";import{recommendedGlobalInstallCommand}from"./chunk-be757xzj.js";function updaterShell(deps={}){let platform=deps.platform??process.platform;if(platform!=="win32")return"sh";return resolveLoginShell({fallback:"/bin/sh",platform,env:deps.env,exists:deps.exists})}function updaterShellFailureHint(deps={}){if((deps.platform??process.platform)!=="win32")return null;return["The update script is POSIX shell. Rove runs it through Git for Windows'","bash \u2014 the same shell every engine and terminal tab launches through.","Install Git for Windows (https://git-scm.com/download/win), or update","by hand:",` ${recommendedGlobalInstallCommand()}`,""].join(`
2
+ import{resolveLoginShell}from"./chunk-vjvkkrzc.js";import{recommendedGlobalInstallCommand}from"./chunk-a0ave3g6.js";function updaterShell(deps={}){let platform=deps.platform??process.platform;if(platform!=="win32")return"sh";return resolveLoginShell({fallback:"/bin/sh",platform,env:deps.env,exists:deps.exists})}function updaterShellFailureHint(deps={}){if((deps.platform??process.platform)!=="win32")return null;return["The update script is POSIX shell. Rove runs it through Git for Windows'","bash \u2014 the same shell every engine and terminal tab launches through.","Install Git for Windows (https://git-scm.com/download/win), or update","by hand:",` ${recommendedGlobalInstallCommand()}`,""].join(`
3
3
  `)}
4
4
  export{updaterShell,updaterShellFailureHint};
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- import{RemoteExecHost}from"./chunk-2apszxn2.js";import{getKeychainPassword,isKeychainSupported,remoteKeychainRef,setKeychainPassword}from"./chunk-g2advs8t.js";import{errorMessage}from"./chunk-2brn8e1y.js";import"./chunk-7kysxgbq.js";import{addRemoteRepo,isRemoteProjectsEnabled}from"./chunk-32mv1yy6.js";import"./chunk-40dgv828.js";import"./chunk-mkksdcsw.js";import{activeCliName}from"./chunk-ppwpjm39.js";import"./chunk-fxs82dsx.js";import"./chunk-zyd6k6ak.js";import{remoteControlSocketPath}from"./chunk-8hbtca1g.js";import"./chunk-hq2n27y1.js";import"./chunk-sb0ns0c7.js";import"./chunk-vnpqemb0.js";import"./chunk-9prawccj.js";import"./chunk-f10n6063.js";import"./chunk-y8fqdnh3.js";import"./chunk-hq4b3fca.js";import"./chunk-wqfp8d9w.js";import{createInterface}from"readline";var CLI_NAME=activeCliName(),USAGE=`Usage: ${CLI_NAME} add --remote --host <host> --user <user> --path <basePath>
2
+ import{RemoteExecHost}from"./chunk-2apszxn2.js";import{getKeychainPassword,isKeychainSupported,remoteKeychainRef,setKeychainPassword}from"./chunk-sak1tphp.js";import{errorMessage}from"./chunk-2brn8e1y.js";import"./chunk-7kysxgbq.js";import{addRemoteRepo,isRemoteProjectsEnabled}from"./chunk-h9cg0j3a.js";import"./chunk-40dgv828.js";import"./chunk-3342qzve.js";import"./chunk-7q43tysm.js";import"./chunk-mw0ysrpd.js";import"./chunk-a7kq09ke.js";import{remoteControlSocketPath}from"./chunk-prqeddy7.js";import{ROVE_PRODUCT_NAME}from"./chunk-zt7wfnva.js";import"./chunk-yt15y085.js";import"./chunk-pn5ygqn6.js";import"./chunk-npwzmmv9.js";import"./chunk-b39sdtt0.js";import"./chunk-nc46gddg.js";import"./chunk-wqfp8d9w.js";import{createInterface}from"readline";var CLI_NAME=ROVE_PRODUCT_NAME,USAGE=`Usage: ${CLI_NAME} add --remote --host <host> --user <user> --path <basePath>
3
3
  [--port N] [--key [path] | --password]
4
4
 
5
5
  Register an experimental SSH-backed project. Worktrees are created on <host>