@sma1lboy/rove 0.9.274 → 0.9.277-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (236) hide show
  1. package/dist/cli/{chunk-kgs56yns.js → chunk-0a65j1zj.js} +1 -1
  2. package/dist/cli/{chunk-55ajzrj6.js → chunk-0r1jf8m9.js} +1 -1
  3. package/dist/cli/{chunk-q6septaj.js → chunk-0rvydb9q.js} +1 -1
  4. package/dist/cli/chunk-1g6vhgfe.js +14 -0
  5. package/dist/cli/{chunk-mmq6922s.js → chunk-1vxtd8rh.js} +2 -2
  6. package/dist/cli/chunk-1wwqf6kx.js +3 -0
  7. package/dist/cli/{chunk-8h437k1q.js → chunk-2kbzb24j.js} +1 -1
  8. package/dist/cli/chunk-2kt0mfvf.js +2 -0
  9. package/dist/cli/{chunk-m4dvx7bd.js → chunk-2vph030z.js} +3 -3
  10. package/dist/cli/chunk-2xsxcdp6.js +3 -0
  11. package/dist/cli/{chunk-fexzfgd1.js → chunk-2y70y8na.js} +1 -1
  12. package/dist/cli/{chunk-tw9w8pzg.js → chunk-36eyrv4r.js} +3 -3
  13. package/dist/cli/chunk-37fas9aj.js +2 -0
  14. package/dist/cli/chunk-3dhv5n19.js +2 -0
  15. package/dist/cli/{chunk-kx53jjee.js → chunk-3x5g06mw.js} +8 -6
  16. package/dist/cli/{chunk-8sggyn8y.js → chunk-3y0z478f.js} +1 -1
  17. package/dist/cli/chunk-4dt1gfb3.js +3 -0
  18. package/dist/cli/chunk-4w4tpsqx.js +2 -0
  19. package/dist/cli/chunk-5apxck3d.js +97 -0
  20. package/dist/cli/chunk-5vrg6h71.js +3 -0
  21. package/dist/cli/chunk-5xpvd182.js +2 -0
  22. package/dist/cli/chunk-5yfffvqe.js +2 -0
  23. package/dist/cli/{chunk-gryq2vgw.js → chunk-5yh5trgy.js} +1 -1
  24. package/dist/cli/chunk-61cn88e7.js +15 -0
  25. package/dist/cli/{chunk-g9yba5vh.js → chunk-671ak750.js} +2 -2
  26. package/dist/cli/chunk-676f3tva.js +5 -0
  27. package/dist/cli/chunk-6hcyvg0m.js +3 -0
  28. package/dist/cli/chunk-6mg5zp8y.js +2 -0
  29. package/dist/cli/chunk-6q4br0pt.js +2 -0
  30. package/dist/cli/chunk-6wfhq8xd.js +4 -0
  31. package/dist/cli/{chunk-ypd337d0.js → chunk-748656h7.js} +3 -3
  32. package/dist/cli/chunk-7bakcyes.js +5 -0
  33. package/dist/cli/{chunk-hfdk7j28.js → chunk-7kgcy89w.js} +1 -1
  34. package/dist/cli/chunk-8qkyd589.js +5 -0
  35. package/dist/cli/chunk-9ckvdy0j.js +3 -0
  36. package/dist/cli/{chunk-egpcaxwb.js → chunk-9fdy8vne.js} +1 -1
  37. package/dist/cli/{chunk-h8t4xg1p.js → chunk-9rj2fx6v.js} +1 -1
  38. package/dist/cli/chunk-9x2xd1rz.js +2 -0
  39. package/dist/cli/{chunk-r77pfw4m.js → chunk-9zswhjkv.js} +1 -1
  40. package/dist/cli/{chunk-p6jw0zcd.js → chunk-agvtzads.js} +1 -1
  41. package/dist/cli/chunk-aq4j8ar4.js +2 -0
  42. package/dist/cli/{chunk-ecrw211n.js → chunk-aqwckba5.js} +1 -1
  43. package/dist/cli/{chunk-rzef6szc.js → chunk-atg13xab.js} +1 -1
  44. package/dist/cli/{chunk-ez438kn3.js → chunk-b95q6zhk.js} +1 -1
  45. package/dist/cli/chunk-bagwgxsg.js +2 -0
  46. package/dist/cli/{chunk-4hnz77xf.js → chunk-bcyex84w.js} +1 -1
  47. package/dist/cli/chunk-bv050ssb.js +8 -0
  48. package/dist/cli/chunk-bykqhbvy.js +2 -0
  49. package/dist/cli/{chunk-29s67j3k.js → chunk-ca4x8s96.js} +4 -4
  50. package/dist/cli/chunk-cakyme4s.js +2 -0
  51. package/dist/cli/{chunk-16ttm9x6.js → chunk-ccmke5sx.js} +1 -1
  52. package/dist/cli/chunk-cf3vpsm5.js +3 -0
  53. package/dist/cli/chunk-d552cvb2.js +2 -0
  54. package/dist/cli/{chunk-gcg5h667.js → chunk-dsdtq087.js} +1 -1
  55. package/dist/cli/{chunk-387ecqb8.js → chunk-e58kj4gm.js} +1 -1
  56. package/dist/cli/chunk-ee314raa.js +2 -0
  57. package/dist/cli/{chunk-0rrmz6k6.js → chunk-eege1x0a.js} +1 -1
  58. package/dist/cli/{chunk-m6yy3qc1.js → chunk-fgtc1xq9.js} +1 -1
  59. package/dist/cli/{chunk-5dd7trgf.js → chunk-fq2pefc5.js} +1 -1
  60. package/dist/cli/chunk-g4p5znv1.js +2 -0
  61. package/dist/cli/chunk-g9ba25q5.js +3 -0
  62. package/dist/cli/{chunk-qe7xb4rm.js → chunk-g9xknhjq.js} +2 -2
  63. package/dist/cli/chunk-gbd5j3dv.js +2 -0
  64. package/dist/cli/{chunk-ycd28edp.js → chunk-ggjmcqpt.js} +3 -4
  65. package/dist/cli/chunk-hv79ys32.js +1 -1
  66. package/dist/cli/chunk-hz1x3hak.js +3 -0
  67. package/dist/cli/{chunk-03rbg95q.js → chunk-hzz020xx.js} +5 -5
  68. package/dist/cli/chunk-j1qy79fd.js +3 -0
  69. package/dist/cli/chunk-j9tsdn1d.js +2 -0
  70. package/dist/cli/chunk-jejmt4k0.js +140 -0
  71. package/dist/cli/chunk-jj5f4n51.js +1 -1
  72. package/dist/cli/{chunk-nzbq51h9.js → chunk-k225696b.js} +1 -1
  73. package/dist/cli/{chunk-by6fjf7m.js → chunk-kag7cfbr.js} +1 -1
  74. package/dist/cli/{chunk-jwedmkm8.js → chunk-kdnk8m5j.js} +1 -1
  75. package/dist/cli/{chunk-yzkhwn31.js → chunk-kxp04jnp.js} +1 -1
  76. package/dist/cli/chunk-m4z6kepz.js +3 -0
  77. package/dist/cli/chunk-mdc7b01e.js +3 -0
  78. package/dist/cli/{chunk-bj6sa371.js → chunk-mjyhy152.js} +1 -1
  79. package/dist/cli/chunk-mqfvzdpr.js +3 -0
  80. package/dist/cli/chunk-mqvkd2g1.js +2 -0
  81. package/dist/cli/chunk-mvtqstte.js +4 -0
  82. package/dist/cli/{chunk-qs1r0tqr.js → chunk-mxx0y791.js} +1 -1
  83. package/dist/cli/{chunk-1rjq808h.js → chunk-n0rdn2fn.js} +1 -1
  84. package/dist/cli/{chunk-3v9s3bcz.js → chunk-n2zgej1a.js} +1 -1
  85. package/dist/cli/chunk-n94vzkbe.js +3 -0
  86. package/dist/cli/chunk-njncqdwf.js +2 -0
  87. package/dist/cli/{chunk-6jk2khme.js → chunk-nw092jak.js} +1 -1
  88. package/dist/cli/{chunk-22d4fjjb.js → chunk-pfagrkt6.js} +1 -1
  89. package/dist/cli/{chunk-sa48rtjz.js → chunk-pnrftncm.js} +1 -1
  90. package/dist/cli/{chunk-mxgtz5vz.js → chunk-pqr6td4z.js} +1 -1
  91. package/dist/cli/chunk-q8ffd1pc.js +3 -0
  92. package/dist/cli/{chunk-snqa07h6.js → chunk-qcjkactr.js} +1 -1
  93. package/dist/cli/{chunk-tjj9bt7n.js → chunk-qqr4tfhk.js} +1 -1
  94. package/dist/cli/chunk-qs359899.js +3 -0
  95. package/dist/cli/{chunk-sza3tyhs.js → chunk-qzzmd63x.js} +2 -3
  96. package/dist/cli/{chunk-xkmdxcjg.js → chunk-r2bb8b11.js} +1 -1
  97. package/dist/cli/{chunk-rtpa8hg3.js → chunk-rjfdzjhj.js} +1 -1
  98. package/dist/cli/chunk-rjy900p4.js +4 -0
  99. package/dist/cli/chunk-rmsdybs3.js +20 -0
  100. package/dist/cli/{chunk-y5axx6ev.js → chunk-rztqccs3.js} +1 -1
  101. package/dist/cli/chunk-s1308b3d.js +63 -0
  102. package/dist/cli/{chunk-b492aee1.js → chunk-se00fc8v.js} +1 -1
  103. package/dist/cli/chunk-shtm72c0.js +3 -0
  104. package/dist/cli/{chunk-dpq60qph.js → chunk-t9vjj8sy.js} +1 -1
  105. package/dist/cli/chunk-ta1p2nwa.js +6 -0
  106. package/dist/cli/chunk-teh40faw.js +1 -1
  107. package/dist/cli/{chunk-gqh6atvp.js → chunk-tjhw09bz.js} +1 -1
  108. package/dist/cli/chunk-tnatqcy7.js +2 -0
  109. package/dist/cli/chunk-tq0h3vy6.js +3 -0
  110. package/dist/cli/{chunk-9er68n24.js → chunk-tt58819p.js} +1 -1
  111. package/dist/cli/chunk-tw9tfs1d.js +3 -0
  112. package/dist/cli/chunk-v6dz59gy.js +2 -0
  113. package/dist/cli/chunk-v6v272b3.js +3 -0
  114. package/dist/cli/chunk-vkv1v3xn.js +56 -0
  115. package/dist/cli/chunk-vkz6kkmm.js +24 -0
  116. package/dist/cli/chunk-vp29jgbt.js +4 -0
  117. package/dist/cli/chunk-vpsarakj.js +2 -0
  118. package/dist/cli/{chunk-xbwq4bc0.js → chunk-vr2r2ncm.js} +1 -1
  119. package/dist/cli/{chunk-qvnr8c18.js → chunk-vvqwgcge.js} +1 -1
  120. package/dist/cli/{chunk-5gzpq34w.js → chunk-vwpf55cr.js} +3 -3
  121. package/dist/cli/{chunk-zaw71cf4.js → chunk-vytrhm50.js} +1 -1
  122. package/dist/cli/chunk-w77s2df8.js +3 -0
  123. package/dist/cli/{chunk-bexnp6g4.js → chunk-w7v71t7e.js} +1 -1
  124. package/dist/cli/chunk-wfgrn8p2.js +4 -0
  125. package/dist/cli/chunk-wzss4pzh.js +3 -0
  126. package/dist/cli/chunk-x1ghdmp1.js +2 -0
  127. package/dist/cli/chunk-x1jxxmtc.js +3 -0
  128. package/dist/cli/{chunk-edrxs4cy.js → chunk-x83xbzjd.js} +5 -5
  129. package/dist/cli/{chunk-9trbc3kj.js → chunk-x85rcep5.js} +2 -2
  130. package/dist/cli/{chunk-jd7p0y5x.js → chunk-x89zw7br.js} +1 -1
  131. package/dist/cli/chunk-xg42e2ff.js +19 -0
  132. package/dist/cli/{chunk-sbds7zx4.js → chunk-xte4phd1.js} +1 -1
  133. package/dist/cli/chunk-y8b2p44q.js +1 -1
  134. package/dist/cli/chunk-ys6v36ph.js +2 -0
  135. package/dist/cli/chunk-yzdrhytj.js +10 -0
  136. package/dist/cli/{chunk-39sfhppm.js → chunk-z3qz6enf.js} +1 -1
  137. package/dist/cli/chunk-z3wrbtcq.js +22 -0
  138. package/dist/cli/chunk-z43e08kw.js +4 -0
  139. package/dist/cli/{chunk-t34kjg5y.js → chunk-zpwvjt14.js} +7 -4
  140. package/dist/cli/chunk-zrf93zrx.js +2 -0
  141. package/dist/cli/index.js +9 -12
  142. package/dist/cli/pty-host-node.mjs +259 -32
  143. package/dist/cli/rove-run.js +1 -1
  144. package/dist/cli/rove.js +1 -1
  145. package/dist/completions/rove.bash +2 -2
  146. package/dist/completions/rove.fish +2 -2
  147. package/dist/completions/rove.zsh +2 -2
  148. package/dist/skills/rove/SKILL.md +25 -10
  149. package/dist/skills/rove/references/api-flags.md +30 -14
  150. package/dist/web/assets/index-BVQbpUea.css +1 -0
  151. package/dist/web/assets/index-Cn_7vMHX.js +152 -0
  152. package/dist/web/assets/jetbrains-mono-cyrillic-500-normal-DJqRU3vO.woff +0 -0
  153. package/dist/web/assets/jetbrains-mono-cyrillic-500-normal-DmUKJPL_.woff2 +0 -0
  154. package/dist/web/assets/jetbrains-mono-cyrillic-600-normal-8K4wrrwR.woff +0 -0
  155. package/dist/web/assets/jetbrains-mono-cyrillic-600-normal-EVf6-Yzo.woff2 +0 -0
  156. package/dist/web/assets/jetbrains-mono-greek-500-normal-D7SFKleX.woff +0 -0
  157. package/dist/web/assets/jetbrains-mono-greek-500-normal-JpySY46c.woff2 +0 -0
  158. package/dist/web/assets/jetbrains-mono-greek-600-normal-H7WoG9Et.woff2 +0 -0
  159. package/dist/web/assets/jetbrains-mono-greek-600-normal-mc2nkWzM.woff +0 -0
  160. package/dist/web/assets/jetbrains-mono-latin-500-normal-BWZEU5yA.woff2 +0 -0
  161. package/dist/web/assets/jetbrains-mono-latin-500-normal-CJOVTJB7.woff +0 -0
  162. package/dist/web/assets/jetbrains-mono-latin-600-normal-BfsvjouI.woff +0 -0
  163. package/dist/web/assets/jetbrains-mono-latin-600-normal-C8RAYTDA.woff2 +0 -0
  164. package/dist/web/assets/jetbrains-mono-latin-ext-500-normal-Cut-4mMH.woff2 +0 -0
  165. package/dist/web/assets/jetbrains-mono-latin-ext-500-normal-ckzbgY84.woff +0 -0
  166. package/dist/web/assets/jetbrains-mono-latin-ext-600-normal-BfB_LPfz.woff2 +0 -0
  167. package/dist/web/assets/jetbrains-mono-latin-ext-600-normal-DObL3zCW.woff +0 -0
  168. package/dist/web/assets/jetbrains-mono-vietnamese-500-normal-DNRqzVM1.woff +0 -0
  169. package/dist/web/assets/jetbrains-mono-vietnamese-600-normal-OWROknRo.woff +0 -0
  170. package/dist/web/index.html +2 -2
  171. package/dist/web/relay/index.html +34 -0
  172. package/dist/web/sw.js +52 -0
  173. package/dist/web-ui/assets/{harness-pEyVtWV4.js → harness-C7ciHx2w.js} +2 -2
  174. package/dist/web-ui/assets/{index-Dyg-qcgB.js → index-B1FLht5L.js} +2 -2
  175. package/dist/web-ui/assets/{index-Bsn8NuKa.css → index-BDIkPexK.css} +1 -1
  176. package/dist/web-ui/index.html +2 -2
  177. package/package.json +3 -3
  178. package/dist/cli/chunk-033k4ap7.js +0 -2
  179. package/dist/cli/chunk-0g3sjn8z.js +0 -3
  180. package/dist/cli/chunk-0ppkvphp.js +0 -2
  181. package/dist/cli/chunk-11wyec8z.js +0 -2
  182. package/dist/cli/chunk-15fp4p9v.js +0 -15
  183. package/dist/cli/chunk-1exwrmjd.js +0 -3
  184. package/dist/cli/chunk-1ffqacz9.js +0 -3
  185. package/dist/cli/chunk-2v68zaaa.js +0 -2
  186. package/dist/cli/chunk-2y29zrm1.js +0 -2
  187. package/dist/cli/chunk-4d1v6066.js +0 -3
  188. package/dist/cli/chunk-4dxc29mm.js +0 -2
  189. package/dist/cli/chunk-5zsdjrgz.js +0 -4
  190. package/dist/cli/chunk-68wpp5y8.js +0 -20
  191. package/dist/cli/chunk-6h4qdckd.js +0 -3
  192. package/dist/cli/chunk-6jj82bej.js +0 -2
  193. package/dist/cli/chunk-783d1ba0.js +0 -3
  194. package/dist/cli/chunk-78v1q5mz.js +0 -2
  195. package/dist/cli/chunk-7z463zkx.js +0 -3
  196. package/dist/cli/chunk-97m9nyw7.js +0 -2
  197. package/dist/cli/chunk-9bae7f3m.js +0 -4
  198. package/dist/cli/chunk-b5c7p22a.js +0 -2
  199. package/dist/cli/chunk-b5pytfgm.js +0 -2
  200. package/dist/cli/chunk-b68dd36h.js +0 -3
  201. package/dist/cli/chunk-bbksmb5a.js +0 -3
  202. package/dist/cli/chunk-cpf78z3x.js +0 -4
  203. package/dist/cli/chunk-cyzp2btw.js +0 -63
  204. package/dist/cli/chunk-d9e4ssy7.js +0 -12
  205. package/dist/cli/chunk-e01321zn.js +0 -5
  206. package/dist/cli/chunk-ec7f3wcm.js +0 -3
  207. package/dist/cli/chunk-erx7x9xg.js +0 -97
  208. package/dist/cli/chunk-ewqqwtrj.js +0 -2
  209. package/dist/cli/chunk-fmbv4m3y.js +0 -25
  210. package/dist/cli/chunk-fs51wx31.js +0 -3
  211. package/dist/cli/chunk-fvvb0072.js +0 -3
  212. package/dist/cli/chunk-g263457v.js +0 -2
  213. package/dist/cli/chunk-g3tv8kht.js +0 -2
  214. package/dist/cli/chunk-g53yqr82.js +0 -78
  215. package/dist/cli/chunk-k67vbszb.js +0 -3
  216. package/dist/cli/chunk-kyt9ytz2.js +0 -20
  217. package/dist/cli/chunk-n2ejvjrd.js +0 -3
  218. package/dist/cli/chunk-p4s826r2.js +0 -96
  219. package/dist/cli/chunk-p6334e7v.js +0 -2
  220. package/dist/cli/chunk-q9zgj6kw.js +0 -3
  221. package/dist/cli/chunk-qfe1wf5c.js +0 -2
  222. package/dist/cli/chunk-r40aj7z6.js +0 -2
  223. package/dist/cli/chunk-sqxdfzdq.js +0 -5
  224. package/dist/cli/chunk-sz2xs0a2.js +0 -4
  225. package/dist/cli/chunk-t5y8k772.js +0 -2
  226. package/dist/cli/chunk-vht2e44j.js +0 -10
  227. package/dist/cli/chunk-vjp7drne.js +0 -2
  228. package/dist/cli/chunk-vm551pxs.js +0 -2
  229. package/dist/cli/chunk-w09356fj.js +0 -20
  230. package/dist/cli/chunk-w9cdc97q.js +0 -3
  231. package/dist/cli/chunk-x20bs6bs.js +0 -3
  232. package/dist/cli/chunk-xmqv1zx6.js +0 -2
  233. package/dist/cli/chunk-xn7bk4f9.js +0 -3
  234. package/dist/cli/chunk-zybjm7d5.js +0 -2
  235. package/dist/web/assets/index-C9vaSoIJ.js +0 -113
  236. package/dist/web/assets/index-sA2EEQJw.css +0 -1
@@ -494,7 +494,7 @@ function formatPtyHostLine(event, message, now = new Date) {
494
494
  }
495
495
 
496
496
  // ../rove-daemon/src/daemon/pty-server.ts
497
- import { readFileSync as readFileSync4 } from "node:fs";
497
+ import { readFileSync as readFileSync5 } from "node:fs";
498
498
  import { mkdir as mkdir4, unlink } from "node:fs/promises";
499
499
  import { createServer } from "node:net";
500
500
  import { dirname as dirname8 } from "node:path";
@@ -707,9 +707,6 @@ function ensureOwnerOnlyStateDir(homeDir) {
707
707
  return ensureOwnerOnlyDir(join5(homeDir, ROVE_STATE_DIR_BASENAME));
708
708
  }
709
709
 
710
- // ../rove-daemon/src/repo-id.ts
711
- var memo = new Map;
712
-
713
710
  // ../rove-daemon/src/daemon/automation-contracts.ts
714
711
  var ROUTINE_RESPONSE_WINDOW_MS = 2 * 60 * 60000;
715
712
  // ../rove-daemon/src/daemon/delivery-contracts.ts
@@ -768,15 +765,20 @@ var BLOCKING_RPCS = new Set([
768
765
  "task.land",
769
766
  "workitem.start",
770
767
  "automation.runNow",
768
+ "task.startScheduledNow",
771
769
  "pr.rerunFailedChecks",
772
770
  "pr.reviewComments",
773
771
  "task.ensureWorktree",
774
772
  "task.spawn",
775
773
  "task.ensureMain",
774
+ "task.moveToProject",
776
775
  "worktree.discoverAdoptable",
777
776
  "worktree.adopt",
778
777
  "worktree.list",
779
- "worktree.remove"
778
+ "worktree.remove",
779
+ "task.checkpoint",
780
+ "task.rewind",
781
+ "task.exportBranch"
780
782
  ]);
781
783
  var PTY_STOP_REFUSED = "PtyStopRefused";
782
784
  function frameToLine(frame) {
@@ -939,6 +941,152 @@ import { mkdirSync as mkdirSync4, readFileSync as readFileSync3, readdirSync, re
939
941
  import { join as join7 } from "node:path";
940
942
  import { StringDecoder } from "node:string_decoder";
941
943
 
944
+ // ../rove-daemon/src/daemon/kitty-transmits.ts
945
+ var MAX_IMAGES = 8;
946
+ var MAX_BYTES = 16 * 1024 * 1024;
947
+ var ESC = 27;
948
+ var OPEN = Buffer.from("\x1B_");
949
+ var CLOSE = Buffer.from("\x1B\\");
950
+ function parseKeys(control) {
951
+ const keys = new Map;
952
+ for (const pair of control.split(",")) {
953
+ const eq = pair.indexOf("=");
954
+ if (eq > 0)
955
+ keys.set(pair.slice(0, eq), pair.slice(eq + 1));
956
+ }
957
+ return keys;
958
+ }
959
+
960
+ class KittyTransmits {
961
+ images = new Map;
962
+ bytes = 0;
963
+ apc = null;
964
+ apcBytes = 0;
965
+ escPending = false;
966
+ upload = null;
967
+ push(buf) {
968
+ let i = 0;
969
+ if (this.escPending && buf.length > 0) {
970
+ this.escPending = false;
971
+ if (this.apc && buf[0] === 92) {
972
+ this.finish();
973
+ i = 1;
974
+ } else {
975
+ this.apc = null;
976
+ if (buf[0] === 95)
977
+ this.open();
978
+ if (buf[0] === 95 || buf[0] === 99)
979
+ i = 1;
980
+ if (buf[0] === 99)
981
+ this.clear();
982
+ }
983
+ }
984
+ while (i < buf.length) {
985
+ if (this.apc) {
986
+ const esc2 = buf.indexOf(ESC, i);
987
+ if (esc2 === -1) {
988
+ this.append(buf.subarray(i));
989
+ return;
990
+ }
991
+ this.append(buf.subarray(i, esc2));
992
+ if (esc2 + 1 >= buf.length) {
993
+ this.escPending = true;
994
+ return;
995
+ }
996
+ if (buf[esc2 + 1] === 92)
997
+ this.finish();
998
+ else
999
+ this.apc = null;
1000
+ i = esc2 + 2;
1001
+ continue;
1002
+ }
1003
+ const esc = buf.indexOf(ESC, i);
1004
+ if (esc === -1)
1005
+ return;
1006
+ if (esc + 1 >= buf.length) {
1007
+ this.escPending = true;
1008
+ return;
1009
+ }
1010
+ const next = buf[esc + 1];
1011
+ if (next === 95)
1012
+ this.open();
1013
+ else if (next === 99)
1014
+ this.clear();
1015
+ i = esc + 2;
1016
+ }
1017
+ }
1018
+ replay() {
1019
+ return Buffer.concat([...this.images.values()]);
1020
+ }
1021
+ open() {
1022
+ this.apc = [];
1023
+ this.apcBytes = 0;
1024
+ }
1025
+ append(part) {
1026
+ if (!this.apc || part.length === 0)
1027
+ return;
1028
+ this.apcBytes += part.length;
1029
+ if (this.apcBytes > MAX_BYTES)
1030
+ this.apc = null;
1031
+ else
1032
+ this.apc.push(Buffer.from(part));
1033
+ }
1034
+ finish() {
1035
+ const body = this.apc ? Buffer.concat(this.apc) : null;
1036
+ this.apc = null;
1037
+ if (!body || body[0] !== 71)
1038
+ return;
1039
+ const semi = body.indexOf(59);
1040
+ const keys = parseKeys(body.subarray(1, semi === -1 ? body.length : semi).toString("latin1"));
1041
+ const raw = Buffer.concat([OPEN, body, CLOSE]);
1042
+ if (this.upload && [...keys.keys()].every((k) => k === "m" || k === "q")) {
1043
+ this.upload.parts.push(raw);
1044
+ this.upload.bytes += raw.length;
1045
+ if (this.upload.bytes > MAX_BYTES)
1046
+ this.upload = null;
1047
+ else if (keys.get("m") !== "1") {
1048
+ const { id: id2, parts } = this.upload;
1049
+ this.upload = null;
1050
+ this.keep(id2, Buffer.concat(parts));
1051
+ }
1052
+ return;
1053
+ }
1054
+ this.upload = null;
1055
+ const action = keys.get("a") ?? "t";
1056
+ const id = Number(keys.get("i"));
1057
+ if ((action === "t" || action === "T") && (keys.get("t") ?? "d") === "d" && id > 0) {
1058
+ if (keys.get("m") === "1")
1059
+ this.upload = { id, parts: [raw], bytes: raw.length };
1060
+ else
1061
+ this.keep(id, raw);
1062
+ } else if (action === "d" && (keys.get("d") === "i" || keys.get("d") === "I"))
1063
+ this.drop(id);
1064
+ }
1065
+ keep(id, raw) {
1066
+ this.drop(id);
1067
+ this.images.set(id, raw);
1068
+ this.bytes += raw.length;
1069
+ for (const [old, kept] of this.images) {
1070
+ if (this.images.size <= MAX_IMAGES && this.bytes <= MAX_BYTES)
1071
+ break;
1072
+ this.images.delete(old);
1073
+ this.bytes -= kept.length;
1074
+ }
1075
+ }
1076
+ drop(id) {
1077
+ const kept = this.images.get(id);
1078
+ if (!kept)
1079
+ return;
1080
+ this.images.delete(id);
1081
+ this.bytes -= kept.length;
1082
+ }
1083
+ clear() {
1084
+ this.images.clear();
1085
+ this.bytes = 0;
1086
+ this.upload = null;
1087
+ }
1088
+ }
1089
+
942
1090
  // ../rove-daemon/src/daemon/terminal-colors.ts
943
1091
  var DEFAULT_TERMINAL_COLORS = {
944
1092
  foreground: "#eae7df",
@@ -1010,7 +1158,7 @@ var MOUSE_ENCODINGS = { 1006: "sgr", 1016: "sgr-pixels" };
1010
1158
  var MAX_CARRY = 64;
1011
1159
  var DA1_REPLY = "\x1B[?1;2c";
1012
1160
  function freshModeTrack(modes = { ...DEFAULT_MODES }) {
1013
- return { modes, carry: "" };
1161
+ return { modes, carry: "", inString: null };
1014
1162
  }
1015
1163
  function normalizeTerminalModes(raw) {
1016
1164
  const modes = { ...DEFAULT_MODES };
@@ -1031,7 +1179,18 @@ function scanTerminalModes(track, chunk) {
1031
1179
  const text = track.carry + chunk;
1032
1180
  track.carry = "";
1033
1181
  const replies = [];
1034
- let i = text.indexOf("\x1B");
1182
+ let i = 0;
1183
+ if (track.inString) {
1184
+ const end = stringEnd(text, 0, track.inString);
1185
+ if (end < 0) {
1186
+ if (text.endsWith("\x1B"))
1187
+ track.carry = "\x1B";
1188
+ return replies;
1189
+ }
1190
+ track.inString = null;
1191
+ i = end;
1192
+ }
1193
+ i = text.indexOf("\x1B", i);
1035
1194
  while (i !== -1) {
1036
1195
  if (i + 1 >= text.length) {
1037
1196
  track.carry = "\x1B";
@@ -1050,6 +1209,18 @@ function scanTerminalModes(track, chunk) {
1050
1209
  i = text.indexOf("\x1B", end >= 0 ? end + 1 : i + 2);
1051
1210
  continue;
1052
1211
  }
1212
+ const kind = STRING_INTRODUCERS[text[i + 1]];
1213
+ if (kind) {
1214
+ const end = stringEnd(text, i + 2, kind);
1215
+ if (end < 0) {
1216
+ track.inString = kind;
1217
+ if (text.endsWith("\x1B"))
1218
+ track.carry = "\x1B";
1219
+ break;
1220
+ }
1221
+ i = text.indexOf("\x1B", end);
1222
+ continue;
1223
+ }
1053
1224
  if (next === 61)
1054
1225
  track.modes.applicationKeypad = true;
1055
1226
  else if (next === 62)
@@ -1096,6 +1267,23 @@ function terminalModePreamble(modes) {
1096
1267
  out += "\x1B[4h";
1097
1268
  return out;
1098
1269
  }
1270
+ function replayStart(track, ring) {
1271
+ if (!track.inString)
1272
+ return 0;
1273
+ const text = track.carry + ring.toString("latin1");
1274
+ const end = stringEnd(text, 0, track.inString);
1275
+ return end < 0 ? ring.byteLength : Math.max(0, end - track.carry.length);
1276
+ }
1277
+ var STRING_INTRODUCERS = { _: "st", P: "st", "^": "st", X: "st", "]": "osc" };
1278
+ function stringEnd(text, from, kind) {
1279
+ const esc = text.indexOf("\x1B", from);
1280
+ const bel = kind === "osc" ? text.indexOf("\x07", from) : -1;
1281
+ if (bel !== -1 && (esc === -1 || bel < esc))
1282
+ return bel + 1;
1283
+ if (esc === -1 || esc + 1 >= text.length)
1284
+ return -1;
1285
+ return text[esc + 1] === "\\" ? esc + 2 : esc;
1286
+ }
1099
1287
  function csiEnd(text, from) {
1100
1288
  for (let j = from;j < text.length; j++) {
1101
1289
  const c = text.charCodeAt(j);
@@ -1263,6 +1451,7 @@ function ansiModeValue(modes, mode) {
1263
1451
  // ../rove-daemon/src/daemon/pty-freeze-store.ts
1264
1452
  var FREEZE_VERSION = 1;
1265
1453
  function freezeSession(session, now = new Date) {
1454
+ const ring = Buffer.concat(session.chunks);
1266
1455
  return {
1267
1456
  v: FREEZE_VERSION,
1268
1457
  key: session.key,
@@ -1273,7 +1462,7 @@ function freezeSession(session, now = new Date) {
1273
1462
  title: session.title,
1274
1463
  totalBytes: session.totalBytes,
1275
1464
  exit: session.exit,
1276
- ringB64: Buffer.concat(session.chunks).toString("base64"),
1465
+ ringB64: ring.subarray(session.ringModes ? replayStart(session.ringModes, ring) : 0).toString("base64"),
1277
1466
  ...session.ringModes ? { ringModes: session.ringModes.modes } : {},
1278
1467
  updatedAt: now.toISOString()
1279
1468
  };
@@ -1318,12 +1507,13 @@ function thawSession(record, cap) {
1318
1507
  defaultColors: DEFAULT_TERMINAL_COLORS,
1319
1508
  modes,
1320
1509
  ringModes: ring.ringModes,
1510
+ kitty: new KittyTransmits,
1321
1511
  sinks: new Map,
1322
1512
  emulatorSinks: new Set,
1323
1513
  parked: false,
1324
1514
  parkedScreenBytes: 0,
1325
1515
  exit: record.exit,
1326
- restored: true,
1516
+ restored: record.exit === null,
1327
1517
  lastFreezeAtMs: 0
1328
1518
  };
1329
1519
  }
@@ -1606,7 +1796,10 @@ function scanOscSignals(signals, bytes, now = Date.now(), onRootChange) {
1606
1796
  }
1607
1797
 
1608
1798
  // ../rove-daemon/src/daemon/pty-child-controller.ts
1799
+ import { spawn } from "node:child_process";
1609
1800
  import { randomUUID as randomUUID6 } from "node:crypto";
1801
+ import { readFileSync as readFileSync4 } from "node:fs";
1802
+ import path from "node:path";
1610
1803
 
1611
1804
  // ../rove-daemon/src/daemon/platform-shell.js
1612
1805
  import { existsSync as existsSync6 } from "node:fs";
@@ -1693,6 +1886,7 @@ function embeddedTerminalEnv(base, overrides = {}) {
1693
1886
  // ../rove-daemon/src/daemon/pty-host-types.ts
1694
1887
  import { randomUUID as randomUUID5 } from "node:crypto";
1695
1888
  import { StringDecoder as StringDecoder3 } from "node:string_decoder";
1889
+ var LAUNCH_PREFIX_FILE = ".rove-launch.json";
1696
1890
  function freshSessionState(key, spec, argv) {
1697
1891
  return {
1698
1892
  key,
@@ -1713,6 +1907,7 @@ function freshSessionState(key, spec, argv) {
1713
1907
  defaultColors: parseTerminalDefaultColors(spec.defaultColors) ?? DEFAULT_TERMINAL_COLORS,
1714
1908
  modes: freshModeTrack(),
1715
1909
  ringModes: freshModeTrack(),
1910
+ kitty: new KittyTransmits,
1716
1911
  sinks: new Map,
1717
1912
  emulatorSinks: new Set,
1718
1913
  parked: false,
@@ -1895,8 +2090,9 @@ class PtyChildController {
1895
2090
  session.programStatusEvent = undefined;
1896
2091
  this.reportStatus(session, null);
1897
2092
  try {
2093
+ const launch = launchWrapper(session.cwd, session.generation);
1898
2094
  session.proc = (this.deps.driver ?? bunTerminalDriver())({
1899
- argv: [...session.command],
2095
+ argv: [...launch.prefix, ...session.command],
1900
2096
  cwd: session.cwd,
1901
2097
  env: embeddedTerminalEnv(process.env, {
1902
2098
  TERM: "xterm-256color",
@@ -1911,7 +2107,11 @@ class PtyChildController {
1911
2107
  onData: (data) => this.onData(session, data)
1912
2108
  });
1913
2109
  session.alive = true;
1914
- session.proc.exited.then((exit) => this.markExited(session, exit), () => this.markExited(session));
2110
+ const reap = launch.reap;
2111
+ session.proc.exited.then((exit) => this.markExited(session, exit), () => this.markExited(session)).then(() => {
2112
+ if (reap.length > 0)
2113
+ spawn(reap[0], reap.slice(1), { detached: true, stdio: "ignore" }).unref();
2114
+ });
1915
2115
  } catch (err) {
1916
2116
  session.alive = false;
1917
2117
  this.deps.log?.("pty", `spawn failed for ${session.key}: ${err instanceof Error ? err.message : String(err)}`);
@@ -1978,6 +2178,7 @@ class PtyChildController {
1978
2178
  } catch {}
1979
2179
  }
1980
2180
  scanOscTitle(session, buf);
2181
+ session.kitty.push(buf);
1981
2182
  session.chunks.push(buf);
1982
2183
  session.bytes += buf.byteLength;
1983
2184
  session.totalBytes += buf.byteLength;
@@ -1991,6 +2192,24 @@ class PtyChildController {
1991
2192
  this.deps.onOutput?.(session, buf);
1992
2193
  }
1993
2194
  }
2195
+ function launchWrapper(cwd, id) {
2196
+ let raw;
2197
+ try {
2198
+ raw = readFileSync4(path.join(cwd, LAUNCH_PREFIX_FILE), "utf8");
2199
+ } catch {
2200
+ return { prefix: [], reap: [] };
2201
+ }
2202
+ const file = JSON.parse(raw);
2203
+ const argv = (field, name) => {
2204
+ if (field === undefined && name === "reap")
2205
+ return [];
2206
+ if (!Array.isArray(field) || !field.every((a) => typeof a === "string")) {
2207
+ throw new Error(`${LAUNCH_PREFIX_FILE} in ${cwd}: "${name}" is not a string array`);
2208
+ }
2209
+ return field.map((a) => a.replaceAll("{launch}", id));
2210
+ };
2211
+ return { prefix: argv(file.prefix, "prefix"), reap: argv(file.reap, "reap") };
2212
+ }
1994
2213
 
1995
2214
  // ../rove-daemon/src/daemon/pty-freeze-policy.ts
1996
2215
  var FREEZE_INTERVAL_MS = 5000;
@@ -2063,11 +2282,19 @@ class WarmSpare {
2063
2282
  var LOGGED_WRITE_BYTES = 1024;
2064
2283
  var DEFAULT_SCROLLBACK_CAP = 512 * 1024;
2065
2284
  var EXIT_TAIL_BYTES = 16 * 1024;
2285
+ function fullReplay(session, ring) {
2286
+ return Buffer.concat([
2287
+ Buffer.from(terminalModePreamble(session.ringModes.modes), "latin1"),
2288
+ session.kitty.replay(),
2289
+ ring.subarray(replayStart(session.ringModes, ring))
2290
+ ]);
2291
+ }
2066
2292
 
2067
2293
  class PtyHost {
2068
2294
  sessions = new Map;
2069
2295
  opts;
2070
2296
  scrollbackCap;
2297
+ shuttingDown = false;
2071
2298
  parkRestoreDeltas = 0;
2072
2299
  parkRestoreFallbacks = 0;
2073
2300
  childController;
@@ -2167,7 +2394,7 @@ class PtyHost {
2167
2394
  this.parkRestoreFallbacks++;
2168
2395
  }
2169
2396
  if (!sinceValid)
2170
- replay = Buffer.concat([Buffer.from(terminalModePreamble(session.ringModes.modes), "latin1"), replay]);
2397
+ replay = fullReplay(session, replay);
2171
2398
  return {
2172
2399
  replay: replay.toString("base64"),
2173
2400
  alive: session.alive,
@@ -2270,8 +2497,7 @@ class PtyHost {
2270
2497
  const peek = peekRing(session, sinceOffset);
2271
2498
  if (!preamble || !session || sinceOffset !== undefined)
2272
2499
  return peek;
2273
- const modes = Buffer.from(terminalModePreamble(session.ringModes.modes), "latin1");
2274
- return { ...peek, data: Buffer.concat([modes, Buffer.from(peek.data, "base64")]).toString("base64") };
2500
+ return { ...peek, data: fullReplay(session, Buffer.from(peek.data, "base64")).toString("base64") };
2275
2501
  }
2276
2502
  stats() {
2277
2503
  return hostStats(this.sessions.values(), this.scrollbackCap, this.parkRestoreDeltas, this.parkRestoreFallbacks);
@@ -2283,6 +2509,7 @@ class PtyHost {
2283
2509
  }
2284
2510
  async shutdown() {
2285
2511
  this.flushFrozen();
2512
+ this.shuttingDown = true;
2286
2513
  const endings = Array.from(this.sessions.values(), (session) => this.childController.endChild(session));
2287
2514
  endings.push(this.warmSpare.end());
2288
2515
  await Promise.all(endings);
@@ -2324,7 +2551,7 @@ class PtyHost {
2324
2551
  const freeze = this.opts.freeze;
2325
2552
  if (!freeze || session.key.startsWith("::"))
2326
2553
  return;
2327
- if (session.closedByRequest)
2554
+ if (session.closedByRequest || this.shuttingDown)
2328
2555
  return;
2329
2556
  const now = Date.now();
2330
2557
  if (!force && !shouldFreeze(session, now))
@@ -2343,7 +2570,7 @@ class PtyHost {
2343
2570
  }
2344
2571
 
2345
2572
  // ../rove-daemon/src/client/detached-spawn.ts
2346
- import { spawn as spawn2 } from "node:child_process";
2573
+ import { spawn as spawn3 } from "node:child_process";
2347
2574
  import { appendFileSync, closeSync, mkdirSync as mkdirSync5, openSync } from "node:fs";
2348
2575
  import { dirname as dirname7 } from "node:path";
2349
2576
 
@@ -2381,24 +2608,24 @@ function warnOnce() {
2381
2608
  } catch {}
2382
2609
  }
2383
2610
  var writeChain = Promise.resolve();
2384
- async function rotateClientLogIfNeeded(path) {
2611
+ async function rotateClientLogIfNeeded(path2) {
2385
2612
  try {
2386
- const { size } = await stat(path);
2613
+ const { size } = await stat(path2);
2387
2614
  if (!shouldRotateLog(size, DEFAULT_LOG_ROTATE_CAP_BYTES))
2388
2615
  return;
2389
- await rename2(path, `${path}.old`);
2616
+ await rename2(path2, `${path2}.old`);
2390
2617
  } catch {}
2391
2618
  }
2392
2619
  function append(line, logPath) {
2393
- const path = logPath ?? defaultClientLogPath();
2620
+ const path2 = logPath ?? defaultClientLogPath();
2394
2621
  writeChain = writeChain.then(async () => {
2395
- await rotateClientLogIfNeeded(path);
2622
+ await rotateClientLogIfNeeded(path2);
2396
2623
  try {
2397
- await appendFile(path, line);
2624
+ await appendFile(path2, line);
2398
2625
  } catch (err) {
2399
2626
  if (err?.code === "ENOENT") {
2400
- await mkdir3(dirname6(path), { recursive: true });
2401
- await appendFile(path, line);
2627
+ await mkdir3(dirname6(path2), { recursive: true });
2628
+ await appendFile(path2, line);
2402
2629
  } else {
2403
2630
  throw err;
2404
2631
  }
@@ -2574,20 +2801,20 @@ class RoveDaemonClient {
2574
2801
  } catch (err) {
2575
2802
  if (!(err instanceof Error) || !("code" in err) || !["ENOENT", "ECONNREFUSED"].includes(String(err.code)))
2576
2803
  throw err;
2577
- for (const path of preRenameRuntimePaths(this.socketPath)) {
2804
+ for (const path2 of preRenameRuntimePaths(this.socketPath)) {
2578
2805
  if (this.disposed)
2579
2806
  throw err;
2580
2807
  try {
2581
- await this.openSocket(path);
2808
+ await this.openSocket(path2);
2582
2809
  return;
2583
2810
  } catch {}
2584
2811
  }
2585
2812
  throw err;
2586
2813
  }
2587
2814
  }
2588
- openSocket(path) {
2815
+ openSocket(path2) {
2589
2816
  return new Promise((resolve2, reject) => {
2590
- const socket = connect(path);
2817
+ const socket = connect(path2);
2591
2818
  this.socket = socket;
2592
2819
  const timeoutMs = connectTimeoutMs();
2593
2820
  let timer;
@@ -2702,7 +2929,7 @@ class RoveDaemonClient {
2702
2929
  }
2703
2930
 
2704
2931
  // ../rove-daemon/src/client/win-detached-launch.ts
2705
- import { spawn } from "node:child_process";
2932
+ import { spawn as spawn2 } from "node:child_process";
2706
2933
  import { existsSync as existsSync7 } from "node:fs";
2707
2934
  import { join as join8 } from "node:path";
2708
2935
  var LAUNCH_CMD_ENV = "ROVE_LAUNCH_CMD";
@@ -2801,7 +3028,7 @@ function windowsDetachedLauncherArgs() {
2801
3028
  encodePowershellCommand(WIN_DETACHED_LAUNCHER_PS)
2802
3029
  ];
2803
3030
  }
2804
- function spawnWindowsDetached(command, args, env, logPath, spawnImpl = spawn) {
3031
+ function spawnWindowsDetached(command, args, env, logPath, spawnImpl = spawn2) {
2805
3032
  const child = spawnImpl(windowsPowershellPath(env), windowsDetachedLauncherArgs(), {
2806
3033
  windowsHide: true,
2807
3034
  stdio: "ignore",
@@ -2878,7 +3105,7 @@ function spawnDirect(command, args, env, logPath, platform) {
2878
3105
  } catch {
2879
3106
  stdio = "ignore";
2880
3107
  }
2881
- const child = spawn2(command, [...args], { ...detachOptions(platform), stdio, env });
3108
+ const child = spawn3(command, [...args], { ...detachOptions(platform), stdio, env });
2882
3109
  child.unref();
2883
3110
  if (logFd !== undefined) {
2884
3111
  try {
@@ -3081,7 +3308,7 @@ async function startPtyHostServer(options = {}) {
3081
3308
  }
3082
3309
  let owner;
3083
3310
  try {
3084
- owner = readFileSync4(pidPath, "utf8").trim();
3311
+ owner = readFileSync5(pidPath, "utf8").trim();
3085
3312
  } catch {
3086
3313
  return `pidfile ${pidPath} is gone`;
3087
3314
  }
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env bun
2
2
  // @bun
3
- import{isObject}from"./chunk-7ghwdjdc.js";import{migrateRoveClientStateLayout}from"./chunk-8t7qbr1e.js";import{updateStateFile}from"./chunk-32j6y5d1.js";import"./chunk-bejhca6z.js";import{kvStatePath}from"./chunk-z1nj22va.js";import"./chunk-br8r72bf.js";import"./chunk-zt7wfnva.js";import"./chunk-yt15y085.js";import"./chunk-eqdbfgq5.js";import"./chunk-f8gg8cqh.js";import"./chunk-nc46gddg.js";import{__require}from"./chunk-91sykzqq.js";import{readFileSync}from"fs";var RENAMED_KEY_PREFIXES=[{from:"autoEffort.",to:"autoRouting."}],NOTHING={moved:0,superseded:0};function legacyRename(key){for(let{from,to}of RENAMED_KEY_PREFIXES)if(key.startsWith(from))return`${to}${key.slice(from.length)}`;return}function isStateObject(text){try{let parsed=JSON.parse(text);return isObject(parsed)}catch{return!1}}function migrateRenamedStateKeys(){let text;try{text=readFileSync(kvStatePath(),"utf8")}catch{return NOTHING}if(!RENAMED_KEY_PREFIXES.some(({from})=>text.includes(`"${from}`)))return NOTHING;if(!isStateObject(text))return NOTHING;let moved=0,superseded=0;try{updateStateFile((state)=>{for(let[key,value]of Object.entries(state)){let renamed=legacyRename(key);if(renamed===void 0)continue;if(renamed in state)superseded+=1;else state[renamed]=value,moved+=1;delete state[key]}return moved+superseded>0})}catch{return NOTHING}return{moved,superseded}}function prepareCliStateLayout(env=process.env){let result=migrateRoveClientStateLayout(env);for(let warning of result.warnings)console.error(`[rove] state migration will retry: ${warning}. Check the source/destination permissions, then relaunch Rove.`);migrateRenamedStateKeys()}prepareCliStateLayout();await import("./index.js");
3
+ import{updateStateFile}from"./chunk-32j6y5d1.js";import{isObject}from"./chunk-7ghwdjdc.js";import{migrateRoveClientStateLayout}from"./chunk-8t7qbr1e.js";import"./chunk-bejhca6z.js";import"./chunk-br8r72bf.js";import"./chunk-yt15y085.js";import{kvStatePath}from"./chunk-z1nj22va.js";import"./chunk-zt7wfnva.js";import"./chunk-eqdbfgq5.js";import"./chunk-f8gg8cqh.js";import"./chunk-nc46gddg.js";import{__require}from"./chunk-91sykzqq.js";import{readFileSync}from"fs";var RENAMED_KEY_PREFIXES=[{from:"autoEffort.",to:"autoRouting."}],NOTHING={moved:0,superseded:0};function legacyRename(key){for(let{from,to}of RENAMED_KEY_PREFIXES)if(key.startsWith(from))return`${to}${key.slice(from.length)}`;return}function isStateObject(text){try{let parsed=JSON.parse(text);return isObject(parsed)}catch{return!1}}function migrateRenamedStateKeys(){let text;try{text=readFileSync(kvStatePath(),"utf8")}catch{return NOTHING}if(!RENAMED_KEY_PREFIXES.some(({from})=>text.includes(`"${from}`)))return NOTHING;if(!isStateObject(text))return NOTHING;let moved=0,superseded=0;try{updateStateFile((state)=>{for(let[key,value]of Object.entries(state)){let renamed=legacyRename(key);if(renamed===void 0)continue;if(renamed in state)superseded+=1;else state[renamed]=value,moved+=1;delete state[key]}return moved+superseded>0})}catch{return NOTHING}return{moved,superseded}}function prepareCliStateLayout(env=process.env){let result=migrateRoveClientStateLayout(env);for(let warning of result.warnings)console.error(`[rove] state migration will retry: ${warning}. Check the source/destination permissions, then relaunch Rove.`);migrateRenamedStateKeys()}prepareCliStateLayout();await import("./index.js");
package/dist/cli/rove.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{join as l}from"node:path";import{createInterface as a}from"node:readline/promises";import{pathToFileURL as ss}from"node:url";import{spawnSync as Q}from"node:child_process";import{constants as e,accessSync as V}from"node:fs";import{homedir as R}from"node:os";import{basename as o,delimiter as I,dirname as U,join as y}from"node:path";import{fileURLToPath as T}from"node:url";var H={$schema:"https://json.schemastore.org/package.json",name:"@sma1lboy/rove",version:"0.9.274",description:"Rove — the agent multiplexer for your terminal. Run coding agents on parallel tasks with isolated worktrees and persistent sessions.",keywords:["terminal","tui","cli","multiplexer","ai-agents","coding-agent","ai-coding-assistant","agentic-ai","parallel-agents","git-worktree","claude-code","codex","llm","developer-tools"],type:"module",packageManager:"bun@1.3.13",bin:{rove:"dist/cli/rove.js"},files:["dist/cli","dist/completions","dist/web","dist/web-ui","dist/skills","dist/*.wav","README.md","LICENSE"],publishConfig:{access:"public"},repository:{type:"git",url:"git+https://github.com/Sma1lboy/rove.git"},homepage:"https://rove.run",bugs:{url:"https://github.com/Sma1lboy/rove/issues"},engines:{bun:">=1.3.11"},scripts:{dev:"ROVE_DEV=1 bun --conditions=browser ./src/cli/rove.ts","dev:mock":"ROVE_DEV=1 bun ./src/tui-react/mock/host.tsx","dev:sandbox":"bun run scripts/dev-sandbox.ts run","dev:sandbox:reset":"bun run scripts/dev-sandbox.ts reset",build:"bun run scripts/build.ts","build:rubric":"bun run scripts/build-tier-rubric.ts",compile:"bun run scripts/compile.ts",typecheck:"tsc --noEmit","check-i18n":"bun run scripts/check-i18n.ts",test:"bun run test:fast && bun run test:socket","perf:golden":"bun scripts/perf-golden.ts","pty:soak":"bun scripts/pty-soak.ts","test:fast":"vitest run --passWithNoTests --minWorkers=1 --maxWorkers=8","test:socket":"ROVE_INCLUDE_SOCKET=1 vitest run test/daemon --pool forks --minWorkers=1 --maxWorkers=4 --passWithNoTests","test:socket:coverage":"ROVE_INCLUDE_SOCKET=1 ROVE_COVERAGE_DAEMON=1 vitest run test/daemon --coverage --pool forks --minWorkers=1 --maxWorkers=4 --passWithNoTests","test:behavior":"ROVE_INCLUDE_BEHAVIOR=1 vitest run test/behavior --pool forks --minWorkers=1 --maxWorkers=1 --retry=2 --passWithNoTests","test:render":"bun scripts/render-track.mjs",coverage:"vitest run --coverage --passWithNoTests",bench:"vitest bench --run",lint:"biome check .",knip:"knip-bun",postinstall:"bun run scripts/check-preview-deps.ts || true",prepublishOnly:"bun run typecheck && bun run build","plugin-sandbox":"bun run scripts/plugin-sandbox.ts"},"//":"biome.json + bunfig.toml live at the monorepo root since they apply repo-wide; bun.lock also lives at root (workspace-shared).",dependencies:{"@ansi-tools/parser":"^1.0.15","@opentui/core":"0.4.3","@opentui/react":"0.4.3","@xterm/addon-serialize":"^0.14.0","@xterm/addon-unicode11":"^0.9.0","@xterm/headless":"^6.0.0",react:"^19.2.8","smol-toml":"^1.7.1",ws:"^8.21.3"},optionalDependencies:{"node-pty":"^1.1.0"},devDependencies:{"@biomejs/biome":"1.9.4","@sma1lboy/rove-daemon":"0.7.23","@tsconfig/bun":"1.0.11","@types/bun":"1.3.14","@types/node":"25.6.2","@types/react":"^19.2.0","@vitest/coverage-v8":"2.1.9",knip:"^6.14.2","react-devtools-core":"^7.0.1","rove-bridge":"0.0.35","rove-weixin":"0.0.35",typescript:"5.8.2",vitest:"2.1.9"},trustedDependencies:[]};var q="rove";var k=q;var z="ROVE_BUN",_="ROVE_NO_BUN_BOOTSTRAP",F="ROVE_SKIP_BUN_CHECK",$=H.engines.bun.match(/\d+\.\d+\.\d+/)?.[0]??"0.0.0",L=(s)=>{try{return V(s,e.X_OK),!0}catch{return!1}},B=(s)=>s==="win32"?"bun.exe":"bun",f=(s)=>{let t=Q(s,["--version"],{encoding:"utf8",timeout:5000});if(t.error||t.status!==0)return null;return t.stdout?.split(`
2
+ import{join as l}from"node:path";import{createInterface as a}from"node:readline/promises";import{pathToFileURL as ss}from"node:url";import{spawnSync as Q}from"node:child_process";import{constants as e,accessSync as V}from"node:fs";import{homedir as R}from"node:os";import{basename as o,delimiter as I,dirname as U,join as y}from"node:path";import{fileURLToPath as T}from"node:url";var H={$schema:"https://json.schemastore.org/package.json",name:"@sma1lboy/rove",version:"0.9.276",description:"Rove — the agent multiplexer for your terminal. Run coding agents on parallel tasks with isolated worktrees and persistent sessions.",keywords:["terminal","tui","cli","multiplexer","ai-agents","coding-agent","ai-coding-assistant","agentic-ai","parallel-agents","git-worktree","claude-code","codex","llm","developer-tools"],type:"module",packageManager:"bun@1.3.13",bin:{rove:"dist/cli/rove.js"},files:["dist/cli","dist/completions","dist/web","dist/web-ui","dist/skills","dist/*.wav","README.md","LICENSE"],publishConfig:{access:"public"},repository:{type:"git",url:"git+https://github.com/Sma1lboy/rove.git"},homepage:"https://rove.run",bugs:{url:"https://github.com/Sma1lboy/rove/issues"},engines:{bun:">=1.3.11"},scripts:{dev:"ROVE_DEV=1 bun --conditions=browser ./src/cli/rove.ts","dev:mock":"ROVE_DEV=1 bun ./src/tui-react/mock/host.tsx","dev:sandbox":"bun run scripts/dev-sandbox.ts run","dev:sandbox:reset":"bun run scripts/dev-sandbox.ts reset",build:"bun run scripts/build.ts","build:rubric":"bun run scripts/build-tier-rubric.ts",compile:"bun run scripts/compile.ts",typecheck:"tsc --noEmit","check-i18n":"bun run scripts/check-i18n.ts",test:"bun run test:fast && bun run test:socket","perf:golden":"bun scripts/perf-golden.ts","pty:soak":"bun scripts/pty-soak.ts","test:fast":"vitest run --passWithNoTests --minWorkers=1 --maxWorkers=8","test:socket":"ROVE_INCLUDE_SOCKET=1 vitest run test/daemon --pool forks --minWorkers=1 --maxWorkers=4 --passWithNoTests","test:socket:coverage":"ROVE_INCLUDE_SOCKET=1 ROVE_COVERAGE_DAEMON=1 vitest run test/daemon --coverage --pool forks --minWorkers=1 --maxWorkers=4 --passWithNoTests","test:behavior":"ROVE_INCLUDE_BEHAVIOR=1 vitest run test/behavior --pool forks --minWorkers=1 --maxWorkers=1 --retry=2 --passWithNoTests","test:render":"bun scripts/render-track.mjs",coverage:"vitest run --coverage --passWithNoTests",bench:"vitest bench --run",lint:"biome check .",knip:"knip-bun",postinstall:"bun run scripts/check-preview-deps.ts || true",prepublishOnly:"bun run typecheck && bun run build","plugin-sandbox":"bun run scripts/plugin-sandbox.ts"},"//":"biome.json + bunfig.toml live at the monorepo root since they apply repo-wide; bun.lock also lives at root (workspace-shared).",dependencies:{"@ansi-tools/parser":"^1.0.15","@opentui/core":"0.4.3","@opentui/react":"0.4.3","@xterm/addon-serialize":"^0.14.0","@xterm/addon-unicode11":"^0.9.0","@xterm/headless":"^6.0.0",react:"^19.2.8","smol-toml":"^1.7.1",ws:"^8.21.3"},optionalDependencies:{"node-pty":"^1.1.0"},devDependencies:{"@biomejs/biome":"1.9.4","@sma1lboy/rove-daemon":"0.7.23","@tsconfig/bun":"1.0.11","@types/bun":"1.3.14","@types/node":"25.6.2","@types/react":"^19.2.0","@vitest/coverage-v8":"2.1.9",knip:"^6.14.2","react-devtools-core":"^7.0.1","rove-bridge":"0.0.37","rove-weixin":"0.0.37",typescript:"5.8.2",vitest:"2.1.9"},trustedDependencies:[]};var q="rove";var k=q;var z="ROVE_BUN",_="ROVE_NO_BUN_BOOTSTRAP",F="ROVE_SKIP_BUN_CHECK",$=H.engines.bun.match(/\d+\.\d+\.\d+/)?.[0]??"0.0.0",L=(s)=>{try{return V(s,e.X_OK),!0}catch{return!1}},B=(s)=>s==="win32"?"bun.exe":"bun",f=(s)=>{let t=Q(s,["--version"],{encoding:"utf8",timeout:5000});if(t.error||t.status!==0)return null;return t.stdout?.split(`
3
3
  `)[0]?.trim()??""};function J(s){return s.trim().match(/^v?(\d+\.\d+\.\d+)/)?.[1]??null}function X(s,t=$){let c=J(s),W=J(t);if(!c||!W)return!0;let b=c.split(".").map(Number),g=W.split(".").map(Number);for(let p=0;p<3;p++){let r=b[p]??0,i=g[p]??0;if(r!==i)return r>i}return!0}function Y(s=process.env){return s[F]==="1"}function A(s={}){let t=s.env??process.env,c=s.platform??process.platform,W=s.home??t.HOME??t.USERPROFILE??R(),b=B(c),g=[],p=t[z]?.trim();if(p)g.push(p);for(let G of(t.PATH??t.Path??"").split(I))if(G)g.push(y(G,b));let r=t.BUN_INSTALL?.trim();if(r)g.push(y(r,"bin",b));if(W)g.push(y(W,".bun","bin",b));let i=s.launcherDir;if(i)g.push(y(i,"..","..","node_modules","bun","bin",b)),g.push(y(i,"..","..","..","bun","bin",b));return g}function N(s={}){let t=s.isExecutable??L;return A(s).find((c)=>t(c))??null}function Z(s={}){let t=s.isExecutable??L,c=s.bunVersionOf??f;if(Y(s.env??process.env))return{bun:N(s),stale:null,unusable:null};let W=null,b=null;for(let g of A(s)){if(!t(g))continue;let p=c(g);if(p===null){b??=g;continue}if(X(p))return{bun:g,stale:W,unusable:b};W??={path:g,version:J(p)??p}}return{bun:null,stale:W,unusable:b}}function h(s){return U(T(s))}function C(s){return o(T(s)).replace(/\.[cm]?[jt]s$/,"")}function n(s=process.platform){return s==="win32"?["powershell","-NoProfile","-Command","irm bun.sh/install.ps1 | iex"]:["bash","-c","curl -fsSL https://bun.sh/install | bash"]}function D(s=k,t=process.platform){let c=t==="win32"?'powershell -c "irm bun.sh/install.ps1 | iex"':"curl -fsSL https://bun.sh/install | bash";return[`${s}: Rove runs on the Bun runtime, and no Bun was found on this machine.`,"","Install Bun, then run this command again:",` ${c}`," npm install -g bun # any platform, if you already have npm","","Or install Bun and Rove together in one step:"," curl -fsSL https://rove.run/install.sh | sh","",`Already have Bun somewhere unusual? Point Rove at it: ${z}=/path/to/bun`,""].join(`
4
4
  `)}function j(s,t,c=k){return[`${c}: this machine's Bun is too old for Rove — found ${t} at ${s}, need ${$} or newer.`,"","Rove's terminals are built on Bun's PTY API. An older Bun ignores it silently,","so every terminal and engine tab would open empty and stay empty.","","Upgrade Bun, then run this command again:"," bun upgrade # Bun installed itself (~/.bun)"," brew upgrade bun # Homebrew"," npm install -g bun@latest # npm-managed Bun","",`Have a newer Bun elsewhere? Point Rove at it: ${z}=/path/to/bun`,`Run on this one anyway (unsupported, terminals will be blank): ${F}=1`,""].join(`
5
5
  `)}function v(s,t=k){return[`${t}: the Bun at ${s} could not be run — \`${s} --version\` failed or never returned.`,"","Rove skipped it rather than starting through it, which would hang or fail","with a message from that binary instead of this one.","","Reinstall Bun, then run this command again:"," curl -fsSL https://bun.sh/install | bash","",`Have a working Bun elsewhere? Point Rove at it: ${z}=/path/to/bun`,""].join(`
@@ -12,12 +12,12 @@ _rove() {
12
12
  fi
13
13
  if [[ ${COMP_CWORD} -eq 2 ]]; then
14
14
  case "${prev}" in
15
- api) COMPREPLY=( $(compgen -W "schema engine-list list get-task pty-list collect context digest agent-turns inspect read-output watch ports viewers review-comments worktree-files worktree-diff worktree-diff-file repo-match repo-list publish pr-attach deliveries should-run add spawn send dispatch interrupt note note-list note-delete pane-open pane-close pane-graphics tab-close tab-new tab-split tab-revive panel-show notify prompt engine-report row-token set-active report attention-dismiss gate-raise gate-answer gate-withdraw gates feedback issue-list issue-create issue-update issue-delete routine-list routine-create routine-update routine-delete routine-run-now routine-respond routine-runs workitem-list workitem-start update land sync delete archive unarchive ensure-worktree remove-worktree worktree-usage discover-adoptable adopt github-status github-login github-logout github-sync github-apply" -- "${cur}") ) ;;
15
+ api) COMPREPLY=( $(compgen -W "schema engine-list list get-task pty-list collect context digest agent-turns inspect read-output queue-list search watch ports viewers review-comments worktree-files worktree-file worktree-diff worktree-diff-file worktree-refs repo-match repo-list publish pr-attach deliveries should-run add send dispatch interrupt queue-edit queue-cancel note note-list note-delete pane-open pane-close pane-graphics tab-close tab-new tab-split tab-revive panel-show notify prompt engine-report row-token set-active report attention-dismiss gate-raise gate-answer gate-withdraw gates feedback issue-list issue-create issue-update issue-delete routine-list routine-create routine-update routine-delete routine-run-now routine-respond routine-runs workitem-list workitem-start update todo land sync delete archive unarchive ensure-worktree remove-worktree checkpoint-list checkpoint rewind export-branch worktree-usage discover-adoptable adopt github-status github-login github-logout github-sync github-apply" -- "${cur}") ) ;;
16
16
  daemon) COMPREPLY=( $(compgen -W "status start stop restart relay" -- "${cur}") ) ;;
17
17
  machine) COMPREPLY=( $(compgen -W "add doctor remove list" -- "${cur}") ) ;;
18
18
  plugin) COMPREPLY=( $(compgen -W "install link list search outdated update enable disable unlink uninstall config-dir log action pane" -- "${cur}") ) ;;
19
19
  repo) COMPREPLY=( $(compgen -W "show set unset" -- "${cur}") ) ;;
20
- skill) COMPREPLY=( $(compgen -W "install status command print" -- "${cur}") ) ;;
20
+ skill) COMPREPLY=( $(compgen -W "install status print" -- "${cur}") ) ;;
21
21
  theme) COMPREPLY=( $(compgen -W "list add remove" -- "${cur}") ) ;;
22
22
  weixin) COMPREPLY=( $(compgen -W "login logout status allow deny send agent" -- "${cur}") ) ;;
23
23
  esac
@@ -19,11 +19,11 @@ complete -c rove -f -n __fish_use_subcommand -a skill
19
19
  complete -c rove -f -n __fish_use_subcommand -a plugin
20
20
  complete -c rove -f -n __fish_use_subcommand -a feedback
21
21
  complete -c rove -f -n __fish_use_subcommand -a update
22
- complete -c rove -f -n "__fish_seen_subcommand_from api" -a "schema engine-list list get-task pty-list collect context digest agent-turns inspect read-output watch ports viewers review-comments worktree-files worktree-diff worktree-diff-file repo-match repo-list publish pr-attach deliveries should-run add spawn send dispatch interrupt note note-list note-delete pane-open pane-close pane-graphics tab-close tab-new tab-split tab-revive panel-show notify prompt engine-report row-token set-active report attention-dismiss gate-raise gate-answer gate-withdraw gates feedback issue-list issue-create issue-update issue-delete routine-list routine-create routine-update routine-delete routine-run-now routine-respond routine-runs workitem-list workitem-start update land sync delete archive unarchive ensure-worktree remove-worktree worktree-usage discover-adoptable adopt github-status github-login github-logout github-sync github-apply"
22
+ complete -c rove -f -n "__fish_seen_subcommand_from api" -a "schema engine-list list get-task pty-list collect context digest agent-turns inspect read-output queue-list search watch ports viewers review-comments worktree-files worktree-file worktree-diff worktree-diff-file worktree-refs repo-match repo-list publish pr-attach deliveries should-run add send dispatch interrupt queue-edit queue-cancel note note-list note-delete pane-open pane-close pane-graphics tab-close tab-new tab-split tab-revive panel-show notify prompt engine-report row-token set-active report attention-dismiss gate-raise gate-answer gate-withdraw gates feedback issue-list issue-create issue-update issue-delete routine-list routine-create routine-update routine-delete routine-run-now routine-respond routine-runs workitem-list workitem-start update todo land sync delete archive unarchive ensure-worktree remove-worktree checkpoint-list checkpoint rewind export-branch worktree-usage discover-adoptable adopt github-status github-login github-logout github-sync github-apply"
23
23
  complete -c rove -f -n "__fish_seen_subcommand_from daemon" -a "status start stop restart relay"
24
24
  complete -c rove -f -n "__fish_seen_subcommand_from machine" -a "add doctor remove list"
25
25
  complete -c rove -f -n "__fish_seen_subcommand_from plugin" -a "install link list search outdated update enable disable unlink uninstall config-dir log action pane"
26
26
  complete -c rove -f -n "__fish_seen_subcommand_from repo" -a "show set unset"
27
- complete -c rove -f -n "__fish_seen_subcommand_from skill" -a "install status command print"
27
+ complete -c rove -f -n "__fish_seen_subcommand_from skill" -a "install status print"
28
28
  complete -c rove -f -n "__fish_seen_subcommand_from theme" -a "list add remove"
29
29
  complete -c rove -f -n "__fish_seen_subcommand_from weixin" -a "login logout status allow deny send agent"
@@ -13,12 +13,12 @@ _rove() {
13
13
 
14
14
  verbs=()
15
15
  case "${words[2]}" in
16
- api) verbs=("schema" "engine-list" "list" "get-task" "pty-list" "collect" "context" "digest" "agent-turns" "inspect" "read-output" "watch" "ports" "viewers" "review-comments" "worktree-files" "worktree-diff" "worktree-diff-file" "repo-match" "repo-list" "publish" "pr-attach" "deliveries" "should-run" "add" "spawn" "send" "dispatch" "interrupt" "note" "note-list" "note-delete" "pane-open" "pane-close" "pane-graphics" "tab-close" "tab-new" "tab-split" "tab-revive" "panel-show" "notify" "prompt" "engine-report" "row-token" "set-active" "report" "attention-dismiss" "gate-raise" "gate-answer" "gate-withdraw" "gates" "feedback" "issue-list" "issue-create" "issue-update" "issue-delete" "routine-list" "routine-create" "routine-update" "routine-delete" "routine-run-now" "routine-respond" "routine-runs" "workitem-list" "workitem-start" "update" "land" "sync" "delete" "archive" "unarchive" "ensure-worktree" "remove-worktree" "worktree-usage" "discover-adoptable" "adopt" "github-status" "github-login" "github-logout" "github-sync" "github-apply") ;;
16
+ api) verbs=("schema" "engine-list" "list" "get-task" "pty-list" "collect" "context" "digest" "agent-turns" "inspect" "read-output" "queue-list" "search" "watch" "ports" "viewers" "review-comments" "worktree-files" "worktree-file" "worktree-diff" "worktree-diff-file" "worktree-refs" "repo-match" "repo-list" "publish" "pr-attach" "deliveries" "should-run" "add" "send" "dispatch" "interrupt" "queue-edit" "queue-cancel" "note" "note-list" "note-delete" "pane-open" "pane-close" "pane-graphics" "tab-close" "tab-new" "tab-split" "tab-revive" "panel-show" "notify" "prompt" "engine-report" "row-token" "set-active" "report" "attention-dismiss" "gate-raise" "gate-answer" "gate-withdraw" "gates" "feedback" "issue-list" "issue-create" "issue-update" "issue-delete" "routine-list" "routine-create" "routine-update" "routine-delete" "routine-run-now" "routine-respond" "routine-runs" "workitem-list" "workitem-start" "update" "todo" "land" "sync" "delete" "archive" "unarchive" "ensure-worktree" "remove-worktree" "checkpoint-list" "checkpoint" "rewind" "export-branch" "worktree-usage" "discover-adoptable" "adopt" "github-status" "github-login" "github-logout" "github-sync" "github-apply") ;;
17
17
  daemon) verbs=("status" "start" "stop" "restart" "relay") ;;
18
18
  machine) verbs=("add" "doctor" "remove" "list") ;;
19
19
  plugin) verbs=("install" "link" "list" "search" "outdated" "update" "enable" "disable" "unlink" "uninstall" "config-dir" "log" "action" "pane") ;;
20
20
  repo) verbs=("show" "set" "unset") ;;
21
- skill) verbs=("install" "status" "command" "print") ;;
21
+ skill) verbs=("install" "status" "print") ;;
22
22
  theme) verbs=("list" "add" "remove") ;;
23
23
  weixin) verbs=("login" "logout" "status" "allow" "deny" "send" "agent") ;;
24
24
  esac