rovecode 0.3.3 → 0.4.0-beta.3

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 (495) hide show
  1. package/CHANGELOG.md +527 -0
  2. package/README.md +46 -48
  3. package/bin/rovecode.js +24 -0
  4. package/dist/cli/app-j6gn14w3.js +2 -0
  5. package/dist/cli/ask-user-cwstt8fz.js +2 -0
  6. package/dist/cli/auth-login-9bbp9915.js +2 -0
  7. package/dist/cli/auth-m8p9grty.js +2 -0
  8. package/dist/cli/bench-16zqdms5.js +9 -0
  9. package/dist/cli/catalog-1xchffa4.js +2 -0
  10. package/dist/cli/cli-1n1zb64f.js +2 -0
  11. package/dist/cli/client-2t9gjkck.js +2 -0
  12. package/dist/cli/commands-exafvm2b.js +2 -0
  13. package/dist/cli/connect-6zde0kn3.js +2 -0
  14. package/dist/cli/context-cmd-5t43wgqt.js +2 -0
  15. package/dist/cli/context-report-kt01pw8y.js +2 -0
  16. package/dist/cli/count-remote-ap7x3vh6.js +2 -0
  17. package/dist/cli/design-ne5zszyh.js +2 -0
  18. package/dist/cli/dispatch-2r5myxye.js +2 -0
  19. package/dist/cli/doctor-ws4fh4tn.js +3 -0
  20. package/dist/cli/executor-bdrjn634.js +2 -0
  21. package/dist/cli/export-1mxb9g5p.js +2 -0
  22. package/dist/cli/files-g104xghh.js +2 -0
  23. package/dist/cli/gauntlet-07xrjpj7.js +2 -0
  24. package/dist/cli/gauntlet-runner-xvy64436.js +10 -0
  25. package/dist/cli/gauntlet-wave3-jm91yt5w.js +5 -0
  26. package/dist/cli/gauntlet-wave4-r13py7p1.js +14 -0
  27. package/dist/cli/hashline-znvrat11.js +2 -0
  28. package/dist/cli/http-xafw6fsh.js +143 -0
  29. package/dist/cli/index-1sgjm25y.js +2 -0
  30. package/dist/cli/init-g2m0tn4m.js +51 -0
  31. package/dist/cli/install-avaqjjqq.js +2 -0
  32. package/dist/cli/loop-mmpfft01.js +2 -0
  33. package/dist/cli/main-0904f6ps.js +5 -0
  34. package/dist/cli/main-0ab9fc26.js +9 -0
  35. package/dist/cli/main-0jys2ccn.js +3 -0
  36. package/dist/cli/main-0mtcdbs7.js +3 -0
  37. package/dist/cli/main-0z1w2zsg.js +3 -0
  38. package/dist/cli/main-1dchs7xv.js +18 -0
  39. package/dist/cli/main-1ereejm1.js +3 -0
  40. package/dist/cli/main-1k1kw6b5.js +3 -0
  41. package/dist/cli/main-27y4sm2k.js +38 -0
  42. package/dist/cli/main-2wwjex5j.js +58 -0
  43. package/dist/cli/main-2yeveeve.js +6 -0
  44. package/dist/cli/main-2yfck9b5.js +3 -0
  45. package/dist/cli/main-2zmzgkwh.js +3 -0
  46. package/dist/cli/main-351pz3z7.js +7 -0
  47. package/dist/cli/main-3gjqfh7a.js +6 -0
  48. package/dist/cli/main-3nf3kgve.js +3 -0
  49. package/dist/cli/main-3pjrb2hd.js +3 -0
  50. package/dist/cli/main-3rxcvgna.js +19 -0
  51. package/dist/cli/main-4b3jgy66.js +19 -0
  52. package/dist/cli/main-4wndhjdc.js +7 -0
  53. package/dist/cli/main-4xcmvxnk.js +3 -0
  54. package/dist/cli/main-5tbz0wbz.js +4 -0
  55. package/dist/cli/main-5ywnwthm.js +3 -0
  56. package/dist/cli/main-6b62vkz0.js +14 -0
  57. package/dist/cli/main-6dnk69vp.js +3 -0
  58. package/dist/cli/main-6genrmhs.js +136 -0
  59. package/dist/cli/main-73g7eff4.js +15 -0
  60. package/dist/cli/main-7c5thhjd.js +5 -0
  61. package/dist/cli/main-7rn6bqje.js +3 -0
  62. package/dist/cli/main-80haw7qk.js +4 -0
  63. package/dist/cli/main-875s60s2.js +4 -0
  64. package/dist/cli/main-8kjxbpw4.js +8 -0
  65. package/dist/cli/main-90ds1z4e.js +10 -0
  66. package/dist/cli/main-9etavkew.js +3 -0
  67. package/dist/cli/main-a9njrkk1.js +3 -0
  68. package/dist/cli/main-aecrjq2d.js +12 -0
  69. package/dist/cli/main-ck9asesq.js +9 -0
  70. package/dist/cli/main-cta9racd.js +4 -0
  71. package/dist/cli/main-ddv7j2ag.js +3 -0
  72. package/dist/cli/main-dfreez27.js +10 -0
  73. package/dist/cli/main-f7rw7des.js +3 -0
  74. package/dist/cli/main-ggcn7rd7.js +5 -0
  75. package/dist/cli/main-gzkmycnv.js +3 -0
  76. package/dist/cli/main-hq51jg8v.js +18 -0
  77. package/dist/cli/main-jft389w9.js +8 -0
  78. package/dist/cli/main-k1eqkg83.js +3 -0
  79. package/dist/cli/main-k2y8a2aw.js +9 -0
  80. package/dist/cli/main-kcpbykxz.js +4 -0
  81. package/dist/cli/main-kd488vje.js +22 -0
  82. package/dist/cli/main-kh32yvgk.js +5 -0
  83. package/dist/cli/main-kqxnqjnv.js +25 -0
  84. package/dist/cli/main-kyn0xnsg.js +3 -0
  85. package/dist/cli/main-m1kk6fp5.js +21 -0
  86. package/dist/cli/main-mv40pcr2.js +4 -0
  87. package/dist/cli/main-n0t3973w.js +3 -0
  88. package/dist/cli/main-nqveez48.js +4 -0
  89. package/dist/cli/main-pknhvrmj.js +3 -0
  90. package/dist/cli/main-pn1w7a7j.js +3 -0
  91. package/dist/cli/main-prxxs70n.js +4 -0
  92. package/dist/cli/main-q3vsesf9.js +3 -0
  93. package/dist/cli/main-qsevpgsv.js +3 -0
  94. package/dist/cli/main-rdgdw24b.js +25 -0
  95. package/dist/cli/main-rfth4tbm.js +16 -0
  96. package/dist/cli/main-rg0wn0xf.js +5 -0
  97. package/dist/cli/main-sdmxhtv8.js +4 -0
  98. package/dist/cli/main-skbp13js.js +18 -0
  99. package/dist/cli/main-t4xnd213.js +7 -0
  100. package/dist/cli/main-vqak588n.js +4 -0
  101. package/dist/cli/main-w2n1303f.js +9 -0
  102. package/dist/cli/main-wbrdspr2.js +5 -0
  103. package/dist/cli/main-wsrg79c1.js +7 -0
  104. package/dist/cli/main-x4r0fne4.js +5 -0
  105. package/dist/cli/main-xea2f3tn.js +6 -0
  106. package/dist/cli/main-xg704a3c.js +3 -0
  107. package/dist/cli/main-xvnrabfp.js +16 -0
  108. package/dist/cli/main-xy53xf0r.js +4 -0
  109. package/dist/cli/main-y1fqy60y.js +3 -0
  110. package/dist/cli/main-yn8cd281.js +34 -0
  111. package/dist/cli/main-yr0ksc0h.js +4 -0
  112. package/dist/cli/main-z2ex2vyf.js +4 -0
  113. package/dist/cli/main-z3aayzvq.js +3 -0
  114. package/dist/cli/main-zaqh35jg.js +3 -0
  115. package/dist/cli/main-zc2e8e46.js +4 -0
  116. package/dist/cli/main-zzrfw6cf.js +13 -0
  117. package/dist/cli/main.js +280 -0
  118. package/dist/cli/market-cmd-e14kmx9n.js +5 -0
  119. package/dist/cli/mcp-login-wq7ktdek.js +2 -0
  120. package/dist/cli/mcp-market-cmd-9mg3jecy.js +2 -0
  121. package/dist/cli/notify-b7qc0cjb.js +2 -0
  122. package/dist/cli/oauth-z8whcgfx.js +2 -0
  123. package/dist/cli/output-b3ewj3ps.js +16 -0
  124. package/dist/cli/profiles-6mr5he5e.js +2 -0
  125. package/dist/cli/provider-config-g7j42q8x.js +2 -0
  126. package/dist/cli/provider-jr1y8vvm.js +2 -0
  127. package/dist/cli/registry-s8yk86g0.js +2 -0
  128. package/dist/cli/registry-t6p8d4mn.js +2 -0
  129. package/dist/cli/repl-bajwe1mh.js +11 -0
  130. package/dist/cli/resume-rwn9nz7y.js +2 -0
  131. package/dist/cli/run-flags-nah7ndpt.js +2 -0
  132. package/dist/cli/runtime-n7gafzhb.js +2 -0
  133. package/dist/cli/sandbox-config-emdy18x4.js +2 -0
  134. package/dist/cli/server-b0nvs2bn.js +5 -0
  135. package/dist/cli/session-arg-y75wd4kj.js +2 -0
  136. package/dist/cli/session-j62evmjq.js +2 -0
  137. package/dist/cli/sessions-cmd-tsnwz0ns.js +7 -0
  138. package/dist/cli/settings-df10wfez.js +2 -0
  139. package/dist/cli/setup-jzvv72fg.js +2 -0
  140. package/dist/cli/sextant-smoke-37m81ke6.js +5 -0
  141. package/dist/cli/skills-cmd-gjxnxnhx.js +2 -0
  142. package/dist/cli/smoke-p7748apt.js +8 -0
  143. package/dist/cli/start-chat-s4st3mm0.js +12 -0
  144. package/dist/cli/stream-gmeyewds.js +2 -0
  145. package/dist/cli/task-gh0kkp3n.js +2 -0
  146. package/dist/cli/tasks-z1kfpe8e.js +2 -0
  147. package/dist/cli/thinking-0eqkrz6t.js +2 -0
  148. package/dist/cli/todo-5brcrt9m.js +2 -0
  149. package/dist/cli/tools-7pzm0vj9.js +2 -0
  150. package/dist/cli/tools-s635p6s8.js +2 -0
  151. package/dist/cli/trust-cmd-cjav8zgm.js +2 -0
  152. package/dist/cli/update-check-pt31bm2f.js +2 -0
  153. package/dist/cli/update-cmd-tk131s9t.js +2 -0
  154. package/dist/cli/voice-56nabd8d.js +2 -0
  155. package/dist/cli/webfetch-xd8q596m.js +2 -0
  156. package/dist/cli/websearch-5hkf98k1.js +2 -0
  157. package/dist/cli/workflow-cmd-cy3cvzjp.js +4 -0
  158. package/dist/cli/workspace-q10g5z3e.js +2 -0
  159. package/dist/lib/index.js +62 -0
  160. package/dist/lib/models-index.json +1 -0
  161. package/dist/lib/plugins.js +55 -0
  162. package/dist/lib/providers.js +17 -0
  163. package/dist/lib/public-api.js +20 -0
  164. package/dist/lib/sdk.js +360 -0
  165. package/package.json +84 -72
  166. package/bin/rovecode.ts +0 -21
  167. package/src/acp/server.ts +0 -374
  168. package/src/cli/auth-login.ts +0 -122
  169. package/src/cli/connect.ts +0 -244
  170. package/src/cli/context-cmd.ts +0 -199
  171. package/src/cli/dispatch.ts +0 -82
  172. package/src/cli/doctor.ts +0 -362
  173. package/src/cli/export.ts +0 -276
  174. package/src/cli/help.ts +0 -293
  175. package/src/cli/is-tui-invocation.ts +0 -8
  176. package/src/cli/main.ts +0 -583
  177. package/src/cli/market-cmd.ts +0 -658
  178. package/src/cli/mcp-login.ts +0 -141
  179. package/src/cli/mcp-market-cmd.ts +0 -302
  180. package/src/cli/output.ts +0 -382
  181. package/src/cli/repl.ts +0 -250
  182. package/src/cli/repomap-root.ts +0 -14
  183. package/src/cli/resume.ts +0 -57
  184. package/src/cli/run-flags.ts +0 -43
  185. package/src/cli/run-limits.ts +0 -78
  186. package/src/cli/runtime.ts +0 -931
  187. package/src/cli/session-arg.ts +0 -30
  188. package/src/cli/sessions-cmd.ts +0 -145
  189. package/src/cli/setup.ts +0 -153
  190. package/src/cli/skills-cmd.ts +0 -194
  191. package/src/cli/start-chat.ts +0 -65
  192. package/src/cli/trust-cmd.ts +0 -52
  193. package/src/coding/bash.ts +0 -148
  194. package/src/coding/checkpoints.ts +0 -327
  195. package/src/coding/diff.ts +0 -138
  196. package/src/coding/files.ts +0 -341
  197. package/src/coding/hashline.ts +0 -274
  198. package/src/coding/lsp-gate.ts +0 -254
  199. package/src/coding/lsp-servers.ts +0 -147
  200. package/src/coding/lsp.ts +0 -283
  201. package/src/coding/repomap-cache.ts +0 -99
  202. package/src/coding/repomap-files.ts +0 -192
  203. package/src/coding/repomap.ts +0 -481
  204. package/src/core/agents.ts +0 -255
  205. package/src/core/compaction.ts +0 -259
  206. package/src/core/config.ts +0 -289
  207. package/src/core/context-report.ts +0 -228
  208. package/src/core/context.ts +0 -60
  209. package/src/core/count-remote.ts +0 -107
  210. package/src/core/execpolicy-rules.ts +0 -196
  211. package/src/core/execpolicy.ts +0 -385
  212. package/src/core/executor.ts +0 -454
  213. package/src/core/guardrails.ts +0 -400
  214. package/src/core/hooks.ts +0 -411
  215. package/src/core/images.ts +0 -230
  216. package/src/core/intro.ts +0 -266
  217. package/src/core/loop.ts +0 -567
  218. package/src/core/modes.ts +0 -372
  219. package/src/core/orchestrator.ts +0 -245
  220. package/src/core/proc-group.ts +0 -48
  221. package/src/core/project-trust.ts +0 -98
  222. package/src/core/reflection.ts +0 -165
  223. package/src/core/sandbox-config.ts +0 -186
  224. package/src/core/session-id.ts +0 -24
  225. package/src/core/session-images.ts +0 -73
  226. package/src/core/session-ops.ts +0 -183
  227. package/src/core/session-text.ts +0 -29
  228. package/src/core/session.ts +0 -469
  229. package/src/core/settings.ts +0 -170
  230. package/src/core/tasks.ts +0 -646
  231. package/src/core/token-scale.ts +0 -108
  232. package/src/core/tools.ts +0 -309
  233. package/src/core/trust.ts +0 -104
  234. package/src/core/types.ts +0 -330
  235. package/src/core/update-check.ts +0 -171
  236. package/src/core/usage.ts +0 -204
  237. package/src/core/validate.ts +0 -121
  238. package/src/core/verify-gate.ts +0 -159
  239. package/src/core/verify.ts +0 -236
  240. package/src/core/voice.ts +0 -158
  241. package/src/core/win-job.ts +0 -183
  242. package/src/core/workspace.ts +0 -184
  243. package/src/design/audit.ts +0 -797
  244. package/src/design/direction.ts +0 -190
  245. package/src/design/rules.ts +0 -157
  246. package/src/eval/bench.ts +0 -150
  247. package/src/eval/gauntlet-runner.ts +0 -215
  248. package/src/eval/gauntlet-support.ts +0 -84
  249. package/src/eval/gauntlet-wave3.ts +0 -269
  250. package/src/eval/gauntlet-wave4.ts +0 -217
  251. package/src/eval/gauntlet.ts +0 -253
  252. package/src/index.ts +0 -17
  253. package/src/lanes/agy.ts +0 -95
  254. package/src/lanes/approval.ts +0 -24
  255. package/src/lanes/claude.ts +0 -129
  256. package/src/lanes/codex.ts +0 -127
  257. package/src/lanes/events.ts +0 -130
  258. package/src/lanes/job.ts +0 -142
  259. package/src/lanes/opencode.ts +0 -122
  260. package/src/lanes/process.ts +0 -184
  261. package/src/lanes/progress.ts +0 -183
  262. package/src/lanes/registry.ts +0 -178
  263. package/src/lanes/runner.ts +0 -124
  264. package/src/lanes/types.ts +0 -112
  265. package/src/market/catalogs/mcp-docs.json +0 -111
  266. package/src/market/catalogs/plugins.json +0 -111
  267. package/src/market/catalogs/skills.json +0 -478
  268. package/src/market/clone.ts +0 -72
  269. package/src/market/context-cost.ts +0 -121
  270. package/src/market/digest.ts +0 -106
  271. package/src/market/index.ts +0 -22
  272. package/src/market/install.ts +0 -578
  273. package/src/market/manifest.ts +0 -187
  274. package/src/market/prereq.ts +0 -145
  275. package/src/market/registry.ts +0 -363
  276. package/src/market/resolve.ts +0 -111
  277. package/src/market/types.ts +0 -236
  278. package/src/market/validate.ts +0 -227
  279. package/src/mcp/client.ts +0 -449
  280. package/src/mcp/config.ts +0 -252
  281. package/src/mcp/local-package.ts +0 -211
  282. package/src/mcp/market-catalog.ts +0 -84
  283. package/src/mcp/market-install.ts +0 -289
  284. package/src/mcp/market.ts +0 -362
  285. package/src/mcp/oauth.ts +0 -251
  286. package/src/mcp/prompts-resources.ts +0 -249
  287. package/src/mcp/shared.ts +0 -149
  288. package/src/mcp/status.ts +0 -67
  289. package/src/mcp/tools.ts +0 -275
  290. package/src/mcp/transport.ts +0 -122
  291. package/src/mcp/trust.ts +0 -25
  292. package/src/memory/blocks.ts +0 -278
  293. package/src/memory/recall.ts +0 -355
  294. package/src/memory/scope.ts +0 -182
  295. package/src/memory/store.ts +0 -105
  296. package/src/memory/tools.ts +0 -99
  297. package/src/plugins/cli.ts +0 -119
  298. package/src/plugins/discover.ts +0 -108
  299. package/src/plugins/index.ts +0 -50
  300. package/src/plugins/install.ts +0 -184
  301. package/src/plugins/load.ts +0 -124
  302. package/src/plugins/manifest.ts +0 -92
  303. package/src/plugins/state.ts +0 -83
  304. package/src/providers/auth.ts +0 -408
  305. package/src/providers/cache.ts +0 -223
  306. package/src/providers/catalog-local.ts +0 -160
  307. package/src/providers/catalog.ts +0 -421
  308. package/src/providers/middleware-context.ts +0 -86
  309. package/src/providers/middleware.ts +0 -373
  310. package/src/providers/model-list.ts +0 -23
  311. package/src/providers/oauth/common.ts +0 -105
  312. package/src/providers/oauth/device-code.ts +0 -107
  313. package/src/providers/oauth/github-copilot.ts +0 -146
  314. package/src/providers/oauth/loopback.ts +0 -158
  315. package/src/providers/oauth/openai.ts +0 -163
  316. package/src/providers/oauth/openrouter.ts +0 -89
  317. package/src/providers/oauth/pkce.ts +0 -45
  318. package/src/providers/oauth/registry.ts +0 -39
  319. package/src/providers/oauth/seam.ts +0 -89
  320. package/src/providers/profile-glm53.ts +0 -111
  321. package/src/providers/profile-sonnet5-persona.ts +0 -65
  322. package/src/providers/profile-sonnet5-voice.ts +0 -23
  323. package/src/providers/profiles.ts +0 -156
  324. package/src/providers/provider-config.ts +0 -311
  325. package/src/providers/registry.ts +0 -333
  326. package/src/providers/responses.ts +0 -209
  327. package/src/providers/retry.ts +0 -234
  328. package/src/providers/router.ts +0 -294
  329. package/src/providers/sse.ts +0 -26
  330. package/src/providers/stream-errors.ts +0 -117
  331. package/src/providers/stream.ts +0 -566
  332. package/src/providers/thinking.ts +0 -189
  333. package/src/providers/wire-messages.ts +0 -129
  334. package/src/providers/wire-responses.ts +0 -79
  335. package/src/providers/wire-select.ts +0 -53
  336. package/src/server/http.ts +0 -291
  337. package/src/server/openapi.ts +0 -246
  338. package/src/sextant/card-hits.ts +0 -102
  339. package/src/sextant/card-keys.ts +0 -55
  340. package/src/sextant/context-source.ts +0 -157
  341. package/src/sextant/crew-cards.ts +0 -350
  342. package/src/sextant/draw-agents.ts +0 -273
  343. package/src/sextant/draw-code.ts +0 -388
  344. package/src/sextant/draw-context.ts +0 -222
  345. package/src/sextant/draw-frame.ts +0 -164
  346. package/src/sextant/draw-market.ts +0 -573
  347. package/src/sextant/draw-messages.ts +0 -386
  348. package/src/sextant/draw-pet.ts +0 -230
  349. package/src/sextant/draw-plan.ts +0 -187
  350. package/src/sextant/draw-tabs.ts +0 -85
  351. package/src/sextant/draw-util.ts +0 -65
  352. package/src/sextant/draw-wizard.ts +0 -378
  353. package/src/sextant/engine.ts +0 -230
  354. package/src/sextant/frame-hits.ts +0 -25
  355. package/src/sextant/frame.ts +0 -101
  356. package/src/sextant/git-status.ts +0 -197
  357. package/src/sextant/grid.ts +0 -59
  358. package/src/sextant/input.ts +0 -119
  359. package/src/sextant/keys.ts +0 -521
  360. package/src/sextant/layout.ts +0 -86
  361. package/src/sextant/local-commands.ts +0 -169
  362. package/src/sextant/market-source.ts +0 -287
  363. package/src/sextant/mentions.ts +0 -200
  364. package/src/sextant/message-hits.ts +0 -26
  365. package/src/sextant/model.ts +0 -387
  366. package/src/sextant/overlays.ts +0 -456
  367. package/src/sextant/panel-hits.ts +0 -38
  368. package/src/sextant/pet.ts +0 -399
  369. package/src/sextant/screen.ts +0 -324
  370. package/src/sextant/scroll-hits.ts +0 -66
  371. package/src/sextant/scrollbar.ts +0 -82
  372. package/src/sextant/sextant-bridge.ts +0 -174
  373. package/src/sextant/sextant-cards.ts +0 -142
  374. package/src/sextant/sextant-diff-base.ts +0 -63
  375. package/src/sextant/sextant-files.ts +0 -154
  376. package/src/sextant/sextant-frame-loop.ts +0 -335
  377. package/src/sextant/sextant-renderer.ts +0 -574
  378. package/src/sextant/sextant-repo.ts +0 -140
  379. package/src/sextant/theme.ts +0 -66
  380. package/src/sextant/tool-rows.ts +0 -189
  381. package/src/sextant/types.ts +0 -493
  382. package/src/skills/index.ts +0 -387
  383. package/src/skills/pack.ts +0 -220
  384. package/src/skills/spec.ts +0 -162
  385. package/src/skills/tools.ts +0 -69
  386. package/src/skills/versioned.ts +0 -227
  387. package/src/telemetry/otel-export.ts +0 -122
  388. package/src/telemetry/otel-lanes.ts +0 -89
  389. package/src/telemetry/otel-logs.ts +0 -131
  390. package/src/telemetry/otel-metrics.ts +0 -136
  391. package/src/telemetry/otel.ts +0 -397
  392. package/src/telemetry/otlp.ts +0 -76
  393. package/src/tools/ask-user.ts +0 -156
  394. package/src/tools/bash-bg.ts +0 -94
  395. package/src/tools/bash-jobs.ts +0 -237
  396. package/src/tools/design.ts +0 -151
  397. package/src/tools/evalcell.ts +0 -338
  398. package/src/tools/html-text.ts +0 -139
  399. package/src/tools/provider.ts +0 -149
  400. package/src/tools/task.ts +0 -250
  401. package/src/tools/todo.ts +0 -320
  402. package/src/tools/webfetch.ts +0 -332
  403. package/src/tools/websearch.ts +0 -359
  404. package/src/tui/agents-cmd.ts +0 -41
  405. package/src/tui/app.ts +0 -749
  406. package/src/tui/attach.ts +0 -127
  407. package/src/tui/boot-notes.ts +0 -41
  408. package/src/tui/builtin-prompts.ts +0 -59
  409. package/src/tui/checkpoints-cmd.ts +0 -70
  410. package/src/tui/clipboard-image.ts +0 -81
  411. package/src/tui/clipboard.ts +0 -78
  412. package/src/tui/commands.ts +0 -283
  413. package/src/tui/config-view.ts +0 -53
  414. package/src/tui/context-cmds.ts +0 -282
  415. package/src/tui/cost.ts +0 -108
  416. package/src/tui/crash-guard.ts +0 -173
  417. package/src/tui/focus-terminal.ts +0 -34
  418. package/src/tui/git-cmds.ts +0 -273
  419. package/src/tui/git-plain.ts +0 -58
  420. package/src/tui/info-cmd.ts +0 -150
  421. package/src/tui/input-plain.ts +0 -76
  422. package/src/tui/mcp-cmd.ts +0 -128
  423. package/src/tui/memory-note.ts +0 -77
  424. package/src/tui/modes-cmd.ts +0 -45
  425. package/src/tui/notify-seq.ts +0 -100
  426. package/src/tui/notify.ts +0 -318
  427. package/src/tui/overlays.ts +0 -97
  428. package/src/tui/pi-renderer.ts +0 -428
  429. package/src/tui/providers-cmd.ts +0 -377
  430. package/src/tui/reasoning-view.ts +0 -56
  431. package/src/tui/renderer.ts +0 -128
  432. package/src/tui/replay-marker.ts +0 -29
  433. package/src/tui/session-cmd.ts +0 -148
  434. package/src/tui/session-manage.ts +0 -95
  435. package/src/tui/sextant-attach.ts +0 -102
  436. package/src/tui/sextant-io.ts +0 -202
  437. package/src/tui/sextant-smoke.ts +0 -110
  438. package/src/tui/shell-cmd.ts +0 -158
  439. package/src/tui/smoke.ts +0 -72
  440. package/src/tui/staged-terminal.ts +0 -50
  441. package/src/tui/startup.ts +0 -12
  442. package/src/tui/theme.ts +0 -59
  443. package/src/tui/todo-label.ts +0 -7
  444. package/src/tui/trust-card.ts +0 -107
  445. package/src/tui/tui-commands.ts +0 -87
  446. package/tsconfig.json +0 -30
  447. package/vendor/pi-tui/LICENSE +0 -21
  448. package/vendor/pi-tui/PATCHES.md +0 -12
  449. package/vendor/pi-tui/PROVENANCE.md +0 -12
  450. package/vendor/pi-tui/README.upstream.md +0 -854
  451. package/vendor/pi-tui/native/win32/prebuilds/win32-arm64/win32-console-mode.node +0 -0
  452. package/vendor/pi-tui/native/win32/prebuilds/win32-x64/win32-console-mode.node +0 -0
  453. package/vendor/pi-tui/src/alt-screen-search.ts +0 -158
  454. package/vendor/pi-tui/src/autocomplete.ts +0 -827
  455. package/vendor/pi-tui/src/components/alt-screen-flash.ts +0 -52
  456. package/vendor/pi-tui/src/components/box.ts +0 -138
  457. package/vendor/pi-tui/src/components/cancellable-loader.ts +0 -41
  458. package/vendor/pi-tui/src/components/editor.ts +0 -2364
  459. package/vendor/pi-tui/src/components/h-stack.ts +0 -45
  460. package/vendor/pi-tui/src/components/image.ts +0 -128
  461. package/vendor/pi-tui/src/components/input.ts +0 -448
  462. package/vendor/pi-tui/src/components/loader.ts +0 -93
  463. package/vendor/pi-tui/src/components/markdown.ts +0 -1016
  464. package/vendor/pi-tui/src/components/scroll-view.ts +0 -217
  465. package/vendor/pi-tui/src/components/select-list.ts +0 -230
  466. package/vendor/pi-tui/src/components/settings-list.ts +0 -277
  467. package/vendor/pi-tui/src/components/spacer.ts +0 -29
  468. package/vendor/pi-tui/src/components/stack.ts +0 -155
  469. package/vendor/pi-tui/src/components/text.ts +0 -108
  470. package/vendor/pi-tui/src/components/truncated-text.ts +0 -66
  471. package/vendor/pi-tui/src/components/v-stack.ts +0 -34
  472. package/vendor/pi-tui/src/editor-component.ts +0 -75
  473. package/vendor/pi-tui/src/fuzzy.ts +0 -138
  474. package/vendor/pi-tui/src/index.ts +0 -149
  475. package/vendor/pi-tui/src/keybindings.ts +0 -321
  476. package/vendor/pi-tui/src/keys.ts +0 -1402
  477. package/vendor/pi-tui/src/kill-ring.ts +0 -47
  478. package/vendor/pi-tui/src/latex.ts +0 -1381
  479. package/vendor/pi-tui/src/layout-node.ts +0 -52
  480. package/vendor/pi-tui/src/layout.ts +0 -411
  481. package/vendor/pi-tui/src/native-modifiers.ts +0 -60
  482. package/vendor/pi-tui/src/native-module-path.ts +0 -32
  483. package/vendor/pi-tui/src/stdin-buffer.ts +0 -445
  484. package/vendor/pi-tui/src/terminal-colors.ts +0 -74
  485. package/vendor/pi-tui/src/terminal-image.ts +0 -701
  486. package/vendor/pi-tui/src/terminal.ts +0 -554
  487. package/vendor/pi-tui/src/tui-alt-screen.ts +0 -1379
  488. package/vendor/pi-tui/src/tui-main-screen.ts +0 -655
  489. package/vendor/pi-tui/src/tui.ts +0 -1264
  490. package/vendor/pi-tui/src/undo-stack.ts +0 -29
  491. package/vendor/pi-tui/src/utils.ts +0 -1327
  492. package/vendor/pi-tui/src/word-navigation.ts +0 -118
  493. package/vendor/pi-tui/test/test-themes.ts +0 -39
  494. package/vendor/pi-tui/test/virtual-terminal.ts +0 -219
  495. /package/{src/providers → dist/cli}/models-index.json +0 -0
@@ -1,236 +0,0 @@
1
- /** What check this project runs before the agent's work counts as done — decided without ever guessing.
2
- *
3
- * Berkay (2026-09-06): the CLI should govern its own work and catch its own mistakes before saying done. The
4
- * loop's gate (core/verify-gate.ts, nimbus-99) runs a command after the last edit; THIS module decides which one,
5
- * and it is the half that can do damage: a gate that runs the wrong command once — `npm test` that deploys,
6
- * wipes a database, or takes twenty minutes — is turned off forever. Two measurements shaped it (nimbus-6f, same
7
- * night): in Berkay's real projects (plain HTML/CSS/JS, no package.json) there is nothing to run at all, so
8
- * "none" is the MAIN path and its text is what a person reads; and in a TypeScript project a type-check caught
9
- * the same three constructed mistakes as the full suite in a tenth of the time (10 s against 170 s here). So:
10
- *
11
- * 1. Configuration first. `verify` in .rovecode/settings.json (project) or ~/.rovecode/settings.json (user),
12
- * a command string or a list, project winning like every other key. This is the one source that needs
13
- * no inference, and the ONLY way a test suite becomes the gate. `false` turns the gate off on purpose and
14
- * stops the inference below as well.
15
- * 2. Inference second, aimed at the FAST check, and only where both the name and the shape are recognised:
16
- * - package.json `typecheck` whose body is tsc; `lint` whose body is eslint, biome or oxlint. Name alone is
17
- * not enough (a `lint` script may do anything); the body has to be a runner known to run unattended and end.
18
- * - package.json `check`, only when neither of those was taken, and only when its body compiles or lints
19
- * without running tests: a `check` that runs the suite is the thorough gate, and the thorough gate is
20
- * configured, never inferred — the refusal names it and how to opt in.
21
- * - Cargo.toml → `cargo check`; go.mod → `go vet ./...`; a ruff-configured Python project → `ruff check .`.
22
- * - A `test` script, `cargo test`, `pytest`, Makefile targets: never inferred, always listed with the reason.
23
- * 3. Everything seen and NOT inferred goes into `refused`, in words specific enough that a person reads the
24
- * line and either agrees or sets the key. "Nothing" is a good answer; "could not infer" is not.
25
- *
26
- * The seam for the runner is `commands: string[]` it does not interpret, so per-file targeting ("tsc --noEmit"
27
- * plus the tests that import the changed files) can be added here later without touching anything downstream.
28
- * Pure apart from reading the files named above; never throws; never runs anything. */
29
-
30
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
31
- import { join } from "node:path";
32
- import { loadSettingsScoped, settingsPath } from "./settings.ts";
33
-
34
- export interface VerifyPlan {
35
- /** where the commands came from; "none" = the gate has nothing to run */
36
- source: "settings" | "inferred" | "none";
37
- /** the shell commands the gate runs, in order, uninterpreted; empty when source is "none" */
38
- commands: string[];
39
- /** one sentence: the file and key or script the answer came from, or why there is none */
40
- reason: string;
41
- /** what was seen and deliberately not inferred, each with its reason — the argument for trusting the gate */
42
- refused: string[];
43
- }
44
-
45
- export interface VerifyDeps {
46
- exists?: (p: string) => boolean;
47
- read?: (p: string) => string;
48
- }
49
-
50
- /** words in a `check` script's body that mean it is not a check */
51
- const DANGEROUS = /\b(deploy|publish|release|push|migrate|drop|rm\s+-rf|docker|kubectl|terraform|curl|wget|ssh|scp|rsync)\b/i;
52
- /** a body that keeps running until killed — never a gate */
53
- const WATCH = /(^|\s)(--watch(=\S*)?|-w|--watchAll)(\s|$)|\bnodemon\b|\bvitest\s*$/;
54
- /** a body that runs a test suite — the thorough gate, configured only */
55
- const RUNS_TESTS = /\b(bun test|vitest|jest|mocha|node --test|playwright test|cypress run|ava|tap|uvu)\b/;
56
- /** runners whose bare invocation runs once, unattended, and exits */
57
- const TYPECHECK_RUNNER = /^(bunx |npx |pnpm exec |yarn )?(tsc|vue-tsc|svelte-check)(\s|$)/;
58
- const LINT_RUNNER = /^(bunx |npx |pnpm exec |yarn )?(eslint|biome (check|lint)|oxlint)(\s|$)/;
59
-
60
- /** the package manager the lockfile says this project uses; npm when none says */
61
- function packageRunner(cwd: string, exists: (p: string) => boolean): { run: string; from: string } {
62
- if (exists(join(cwd, "bun.lock")) || exists(join(cwd, "bun.lockb"))) return { run: "bun run", from: "bun.lock" };
63
- if (exists(join(cwd, "pnpm-lock.yaml"))) return { run: "pnpm run", from: "pnpm-lock.yaml" };
64
- if (exists(join(cwd, "yarn.lock"))) return { run: "yarn", from: "yarn.lock" };
65
- if (exists(join(cwd, "package-lock.json"))) return { run: "npm run", from: "package-lock.json" };
66
- return { run: "npm run", from: "no lockfile (npm assumed)" };
67
- }
68
-
69
- export const NONE_REASON = "nothing configured and nothing fast and safe to infer — set verify in .rovecode/settings.json (a command, or a list) to turn the gate on";
70
- export const NOTHING_HERE = "no package.json, Cargo.toml, go.mod or pyproject.toml here, so there is no compiler, linter or test runner to run; for a plain HTML/CSS/JS site that is the normal answer, and the gate stays off";
71
-
72
- /** Resolve this project's verify command(s). */
73
- export function resolveVerify(cwd: string, deps: VerifyDeps = {}): VerifyPlan {
74
- const exists = deps.exists ?? existsSync;
75
- const read = deps.read ?? ((p: string) => readFileSync(p, "utf8"));
76
-
77
- // 1. configuration
78
- // loadSettingsScoped already applied the trust gate: an UNTRUSTED project file's `verify` is not here (core/settings.ts
79
- // COMMAND_KEYS) — a cloned repo does not choose the command this gate runs. `verify: false` is honoured from any file.
80
- const scoped = loadSettingsScoped(cwd);
81
- const settings = { ...scoped.user, ...scoped.project };
82
- if (settings.verify === false) {
83
- return { source: "none", commands: [], reason: "settings.json verify: false — the gate is off by choice, nothing is inferred", refused: [] };
84
- }
85
- if (settings.verify !== undefined) {
86
- const commands = Array.isArray(settings.verify) ? settings.verify : [settings.verify];
87
- const where = scoped.project.verify !== undefined ? scoped.projectPath : settingsPath("user", cwd);
88
- return { source: "settings", commands, reason: `${where} verify`, refused: [] };
89
- }
90
-
91
- // 2. inference
92
- const commands: string[] = [];
93
- const from: string[] = [];
94
- const refused: string[] = [];
95
-
96
- const pkgPath = join(cwd, "package.json");
97
- if (exists(pkgPath)) {
98
- let scripts: Record<string, string> = {};
99
- let ok = true;
100
- try {
101
- const raw = JSON.parse(read(pkgPath)) as { scripts?: unknown };
102
- const s = raw.scripts;
103
- if (s !== undefined && (typeof s !== "object" || s === null || Array.isArray(s))) { refused.push('package.json: "scripts" is not an object — nothing inferred from it'); ok = false; }
104
- else if (s) for (const [k, v] of Object.entries(s as Record<string, unknown>)) if (typeof v === "string") scripts[k] = v;
105
- } catch { refused.push("package.json is not valid JSON — nothing inferred from it"); ok = false; scripts = {}; }
106
- if (ok) {
107
- const pm = packageRunner(cwd, exists);
108
- const body = (name: string): string => scripts[name]!.trim();
109
- const optIn = (name: string) => `set \`"verify": "${pm.run} ${name}"\` in .rovecode/settings.json`;
110
-
111
- // the fast checks: a recognised runner, or a refusal that quotes the body
112
- const take = (name: string, runner: RegExp, what: string, known: string): void => {
113
- if (scripts[name] === undefined) return;
114
- const b = body(name);
115
- if (WATCH.test(b)) { refused.push(`package.json script "${name}" runs \`${b}\`: a watch mode never exits, so it cannot gate a run`); return; }
116
- if (!runner.test(b)) { refused.push(`package.json script "${name}" runs \`${b}\`: not a ${what} this gate knows runs unattended and ends (${known}) — ${optIn(name)} to run it anyway`); return; }
117
- commands.push(`${pm.run} ${name}`); from.push(`package.json script "${name}" (${pm.from})`);
118
- };
119
- take("typecheck", TYPECHECK_RUNNER, "type-checker", "tsc, vue-tsc, svelte-check");
120
- take("lint", LINT_RUNNER, "linter", "eslint, biome check, oxlint");
121
-
122
- // `check`: the convention means "verify, change nothing" — taken as the fallback fast check when it only
123
- // compiles or lints; refused, with the cost named, when it runs the suite or does anything a check must not
124
- if (scripts.check !== undefined) {
125
- const b = body("check");
126
- const bad = DANGEROUS.exec(b);
127
- const tests = RUNS_TESTS.exec(b);
128
- if (bad) refused.push(`package.json script "check" runs \`${b}\`: it names \`${bad[1]}\`, which a check must not do — ${optIn("check")} if that is really what you want the gate to run`);
129
- else if (WATCH.test(b)) refused.push(`package.json script "check" runs \`${b}\`: a watch mode never exits, so it cannot gate a run`);
130
- else if (tests) refused.push(`package.json script "check" runs \`${b}\`: it runs the test suite (\`${tests[1]}\`), which is minutes here rather than seconds; the thorough gate is configured, never inferred — ${optIn("check")} if that cost is right for this project`);
131
- else if (commands.length > 0) refused.push(`package.json script "check" runs \`${b}\`: a faster script already covers it (${from.map((f) => f.split(" (")[0]).join(", ")}) — ${optIn("check")} to run it instead`);
132
- else { commands.push(`${pm.run} check`); from.push(`package.json script "check" (${pm.from})`); }
133
- }
134
-
135
- // `test`: never inferred — the name promises nothing about the body, and a suite is the slow gate
136
- if (scripts.test !== undefined) {
137
- const b = body("test");
138
- refused.push(`package.json script "test" runs \`${b}\`: a test suite is never inferred, only configured (the fast gate is a type-check; a suite can take minutes and may need services) — ${optIn("test")} if it is quick enough here`);
139
- }
140
- if (commands.length === 0 && refused.length === 0) refused.push('package.json has no "typecheck", "lint", "check" or "test" script — name one, or set verify in .rovecode/settings.json');
141
- }
142
- }
143
-
144
- if (exists(join(cwd, "Cargo.toml"))) {
145
- commands.push("cargo check"); from.push("Cargo.toml");
146
- refused.push("`cargo test` is not inferred: it runs the crate's tests, which may be slow or need services — set verify to run it");
147
- }
148
- if (exists(join(cwd, "go.mod"))) {
149
- commands.push("go vet ./..."); from.push("go.mod");
150
- refused.push("`go test ./...` is not inferred: it runs the module's tests — set verify to run it");
151
- }
152
- const pyproject = join(cwd, "pyproject.toml");
153
- if (exists(pyproject) || exists(join(cwd, "ruff.toml"))) {
154
- const ruffToml = exists(join(cwd, "ruff.toml"));
155
- let ruff = ruffToml;
156
- if (!ruff && exists(pyproject)) { try { ruff = /^\[tool\.ruff(\.|\])/m.test(read(pyproject)); } catch { /* unreadable: no ruff */ } }
157
- if (ruff) { commands.push("ruff check ."); from.push(ruffToml ? "ruff.toml" : "pyproject.toml [tool.ruff]"); }
158
- else refused.push("pyproject.toml without a [tool.ruff] section: no linter is configured that this gate knows — set verify (for example `ruff check .` or `pytest -q`) to run one");
159
- refused.push("`pytest` is not inferred: it runs the project's tests — set verify to run it");
160
- }
161
- if (exists(join(cwd, "Makefile")) || exists(join(cwd, "makefile"))) {
162
- refused.push("a Makefile is here, but make targets are never inferred (a target can do anything) — set verify to `make check` or the target you mean");
163
- }
164
-
165
- if (commands.length > 0) {
166
- return { source: "inferred", commands, reason: `inferred from ${from.join(", ")}`, refused };
167
- }
168
- if (refused.length === 0) return { source: "none", commands: [], reason: NOTHING_HERE, refused: [] };
169
- return { source: "none", commands: [], reason: NONE_REASON, refused };
170
- }
171
-
172
-
173
- /** the commands as one label — the SAME words in the doctor row and in the loop's `verify` RunEvent ("running
174
- * bun run check && bun test"), so a person sees one name for one thing */
175
- export function verifyLabel(plan: VerifyPlan): string {
176
- return plan.commands.join(" && ");
177
- }
178
-
179
- /** one line for `rovecode doctor` and the settings docs */
180
- export function describeVerify(plan: VerifyPlan): string {
181
- if (plan.source === "none") return `none — ${plan.reason}`;
182
- return `${verifyLabel(plan)} — ${plan.reason}`;
183
- }
184
-
185
- /** what the gate does NOT see, said wherever the gate is described (doctor, README): the loop counts edits made
186
- * through `edit` and `write`; a run that changed files only through `bash` has no counted write, so it is not
187
- * verified. Owned here so the doctor row and the docs cannot drift apart. */
188
- export const VERIFY_BLIND_SPOT = "runs after edits made with `edit` or `write`; a run that changed files only through `bash` is not counted, so it is not verified";
189
-
190
- // ---- cost: a check's duration is the fact that makes the doctor row honest ("bun run check, 170 s last time").
191
- // The resolver never runs anything, so it cannot measure; the gate can, and records here after each run. Project-local
192
- // because the same command costs different amounts in different repos; one small file, one entry per command.
193
-
194
- export const VERIFY_TIMING_FILE = join(".rovecode", "verify-timing.json");
195
- type Timings = Record<string, { ms: number; at: string }>;
196
-
197
- function readTimings(cwd: string): Timings {
198
- try {
199
- const raw = JSON.parse(readFileSync(join(cwd, VERIFY_TIMING_FILE), "utf8")) as unknown;
200
- if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return {};
201
- const out: Timings = {};
202
- for (const [k, v] of Object.entries(raw as Record<string, unknown>)) {
203
- if (v && typeof v === "object" && typeof (v as { ms?: unknown }).ms === "number" && typeof (v as { at?: unknown }).at === "string") out[k] = v as { ms: number; at: string };
204
- }
205
- return out;
206
- } catch { return {}; }
207
- }
208
-
209
- /** for the gate: remember how long `command` took in this project. Never throws (a timing is not worth a crash). */
210
- export function recordVerifyTiming(cwd: string, command: string, ms: number, now: Date = new Date()): void {
211
- try {
212
- const t = readTimings(cwd);
213
- t[command] = { ms: Math.max(0, Math.round(ms)), at: now.toISOString() };
214
- mkdirSync(join(cwd, ".rovecode"), { recursive: true });
215
- writeFileSync(join(cwd, VERIFY_TIMING_FILE), JSON.stringify(t, null, 2) + "\n");
216
- } catch { /* a timing is not worth a crash */ }
217
- }
218
-
219
- /** the last measured duration of `command` here, or undefined when it has not run yet */
220
- export function lastVerifyTiming(cwd: string, command: string): number | undefined {
221
- return readTimings(cwd)[command]?.ms;
222
- }
223
-
224
- /** "3 s" / "170 s" / "2 min 50 s" — the cost as a person says it */
225
- export function formatDuration(ms: number): string {
226
- const s = Math.round(ms / 1000);
227
- if (s < 1) return "under a second";
228
- if (s < 120) return `${s} s`;
229
- const m = Math.floor(s / 60), r = s % 60;
230
- return r === 0 ? `${m} min` : `${m} min ${r} s`;
231
- }
232
-
233
- /** the label with each command's last cost when known: "bun run typecheck (9 s) && bun test (not run yet)" */
234
- export function verifyLabelWithCost(cwd: string, plan: VerifyPlan): string {
235
- return plan.commands.map((c) => { const ms = lastVerifyTiming(cwd, c); return ms === undefined ? `${c} (not run here yet)` : `${c} (${formatDuration(ms)} last time)`; }).join(" && ");
236
- }
package/src/core/voice.ts DELETED
@@ -1,158 +0,0 @@
1
- /** rovecode's voice — the one place user-facing wording lives: mode labels, the no-model recipe, the
2
- * welcome card, the panels' empty-state hints. First person, short plain sentences, one idea per
3
- * line, no emoji; the ◆ glyph marks rovecode's own lines; a problem always ends with the next step.
4
- * Pure strings and string builders: every surface (CLI, REPL, TUI, server, ACP) reads from here so a
5
- * wording change lands everywhere at once. */
6
-
7
- /** the permission modes as the screen names them; the flags/commands keep their names (--yolo, /yolo, ROVECODE_YOLO) */
8
- export const MODE_ASK = "ask first";
9
- export const MODE_AUTO = "auto (never asks)";
10
- export const MODE_ACCEPT = "accept edits";
11
-
12
- /** "ask first" | "auto (never asks)" — the status/notes label for the yolo flag */
13
- export function modeLabel(yolo: boolean): string { return yolo ? MODE_AUTO : MODE_ASK; }
14
- /** compact form for footers and status bars: "ask first" | "auto" */
15
- export function modeLabelShort(yolo: boolean): string { return yolo ? "auto" : MODE_ASK; }
16
- /** what each mode means, in one sentence */
17
- export function modeMeaning(yolo: boolean): string {
18
- return yolo ? "I won't stop to ask before writes or shell commands" : "I ask before I write or run anything";
19
- }
20
-
21
- /** the marker every problem message ends with */
22
- export const NEXT = "→ next:";
23
- export const next = (text: string): string => `${NEXT} ${text}`;
24
-
25
- /** The no-model recipe — three lines, `rovecode setup` first. `where` picks the commands that exist
26
- * on that surface; the first line is stable ("no provider configured") for callers that match it. */
27
- export function noModelHint(where: "cli" | "tui" = "cli"): string {
28
- const setup = where === "tui" ? "/setup" : "rovecode setup";
29
- const alt = where === "tui"
30
- ? "/provider add <id> <baseUrl> · /provider key <id> <secret>"
31
- : "rovecode provider add <id> <baseUrl>, then rovecode auth set <id>";
32
- return [
33
- "no provider configured — no model to think with yet.",
34
- ` ${next(setup)} (pick a provider, paste the key hidden, one test call)`,
35
- ` or: ${alt} · or set ROVECODE_BASE_URL + ROVECODE_API_KEY`,
36
- ].join("\n");
37
- }
38
-
39
- /** `rovecode run` with nothing configured answers from a scripted mock; this is what it says. */
40
- export const MOCK_PROVIDER_TEXT =
41
- `Rovecode mock provider: no model is connected, so this is a canned reply. ${next("rovecode setup")} (or rovecode provider add <id> <baseUrl> + rovecode auth set <id>, or set ROVECODE_BASE_URL and ROVECODE_API_KEY)`;
42
-
43
- export interface WelcomeOpts {
44
- /** the session's provider/model when one is connected; null = nothing configured */
45
- connected: { provider: string; model: string } | null;
46
- cwd: string;
47
- yolo: boolean;
48
- /** plan/act; act is the default and is not mentioned */
49
- mode?: "plan" | "act";
50
- /** the running version, so "which rovecode is this" never needs a second command */
51
- version?: string;
52
- /** what this session actually loaded. Zeroes are omitted rather than printed: a line reading
53
- * "0 skills · 0 plugins · 0 MCP servers" is three facts nobody asked for, while "19 skills · 2 MCP
54
- * servers" is the answer to "did my install take". */
55
- loaded?: { skills?: number; plugins?: number; mcp?: number };
56
- /** the one-line update notice, when there is one; see core/update-check.ts */
57
- update?: string | null;
58
- /** columns available; under BANNER_COLS the wordmark is dropped rather than wrapped (default 80) */
59
- width?: number;
60
- }
61
-
62
- /** ROVECODE in half-block letters, two rows. Berkay picked this over a boxed header and a plain block
63
- * (2026-09-06). It is 31 columns wide, so it fits a narrow split, and it only appears when the card
64
- * knows the version — a banner with nothing to say under it is decoration. */
65
- const WORDMARK = ["█▀█ █▀█ █ █ █▀▀ █▀▀ █▀█ █▀▄ █▀▀", "█▀▄ █▄█ ▀▄▀ █▄▄ █▄▄ █▄█ █▄▀ █▄▄"] as const;
66
- const BANNER_COLS = 46;
67
-
68
- /** "19 skills · 3 plugins · 2 MCP servers", counting only what is there. Null when nothing loaded,
69
- * because the absence of the line says that better than the line saying zero three times. */
70
- export function loadedLine(loaded: WelcomeOpts["loaded"]): string | null {
71
- if (!loaded) return null;
72
- const plural = (n: number, one: string) => `${n} ${one}${n === 1 ? "" : "s"}`;
73
- const bits: string[] = [];
74
- if (loaded.skills) bits.push(plural(loaded.skills, "skill"));
75
- if (loaded.plugins) bits.push(plural(loaded.plugins, "plugin"));
76
- if (loaded.mcp) bits.push(plural(loaded.mcp, "MCP server"));
77
- return bits.length > 0 ? bits.join(" · ") : null;
78
- }
79
-
80
- /** The card a fresh session opens with (the messages panel's first note). */
81
- export function welcomeCard(o: WelcomeOpts): string {
82
- const where = `${o.cwd} · ${modeLabelShort(o.yolo)}${o.mode === "plan" ? " · plan mode (read-only)" : ""}`;
83
- const version = o.version ? ` ${o.version}` : "";
84
- // the two optional footers, in the order a reader wants them: what this session has, then what it
85
- // could have. Both drop out entirely when there is nothing to say — see loadedLine and updateLine.
86
- const tail = [loadedLine(o.loaded), where, o.update ?? null].filter((l): l is string => l !== null);
87
- // The banner form: the wordmark, then one line per fact. It needs a version (there is nothing to put
88
- // beside the mark otherwise) and room (under BANNER_COLS the mark would wrap into noise), and it falls
89
- // back to exactly the prose card below — which is what a resumed or narrow session still sees.
90
- if (o.version !== undefined && (o.width ?? 80) >= BANNER_COLS) {
91
- const model = o.connected === null ? null
92
- : o.connected.model.length > 0 ? `${o.connected.provider}/${o.connected.model}` : o.connected.provider;
93
- const loaded = loadedLine(o.loaded);
94
- return [
95
- ` ${WORDMARK[0]}`,
96
- ` ${WORDMARK[1]} ${o.version}`,
97
- "",
98
- model === null ? " no model connected yet — /setup fixes that in about a minute"
99
- : ` ${[model, loaded].filter((s) => s !== null).join(" · ")}`,
100
- ` ${where}`,
101
- ...(model === null ? [] : [` I read first, then ${o.yolo ? "work without asking" : "ask before I write or run anything"}. /help lists commands by topic.`]),
102
- ...(o.update ? [` ${o.update}`] : []),
103
- ].join("\n");
104
- }
105
- if (o.connected === null) {
106
- return [
107
- `◆ rovecode${version} here. No model connected yet, so I can't think.`,
108
- "/setup fixes that in about a minute.",
109
- ...tail,
110
- ].join("\n");
111
- }
112
- const model = o.connected.model.length > 0 ? `${o.connected.provider}/${o.connected.model}` : o.connected.provider;
113
- return [
114
- `◆ rovecode${version} here. Connected to ${model}.`,
115
- `Tell me what you want done; I read first, then ${o.yolo ? "work without asking" : "ask before I write or run anything"}.`,
116
- "/help lists commands by topic.",
117
- ...tail,
118
- ].join("\n");
119
- }
120
-
121
- /** one-liner for a resumed session (its transcript is the card) */
122
- export function resumedLine(id: string, cwd: string, yolo: boolean): string {
123
- return `◆ back in session ${id.slice(0, 8)} · ${cwd} · ${modeLabelShort(yolo)}`;
124
- }
125
-
126
- /** the /effort note. Says what the level costs, because that is the part that surprises people:
127
- * thinking tokens are billed as output and they arrive before any answer does. */
128
- export function effortNote(level: string, receives?: string): string {
129
- const head = level === "off" ? "thinking: off — I answer straight away."
130
- : level === "auto" ? "thinking: auto — the model decides how much to reason; I send no dial."
131
- : `thinking: ${level} — I reason before answering. It costs output tokens and delays the first word.`;
132
- // the second line is the truth on the wire (providers/thinking.ts thinkingLine): the level is one word,
133
- // what this model's endpoint actually receives for it is another, and a model without a reasoning mode
134
- // receives nothing at all — the person should not have to guess which
135
- return receives ? `${head}\n ${receives}` : head;
136
- }
137
-
138
- /** the /yolo toggle's note */
139
- export function modeSwitchNote(yolo: boolean): string {
140
- return `mode: ${modeLabel(yolo)} — ${modeMeaning(yolo)}`;
141
- }
142
-
143
- /** the /accept-edits toggle's note. Says the boundary out loud: this is not auto mode, and the two
144
- * things it does NOT cover are the two that can leave the repository. */
145
- export function acceptEditsNote(on: boolean): string {
146
- return on
147
- ? `mode: ${MODE_ACCEPT} — I write inside this folder without asking. Shell commands, subagents, network and any write outside it still ask, and deny rules still hold.`
148
- : `mode: ${MODE_ASK} — I ask before every write again.`;
149
- }
150
-
151
- // ---------- panel empty states (one dim line each; a second line only when the panel has room) ----------
152
-
153
- export const EMPTY = {
154
- code: "nothing open — when I read a file it shows here",
155
- files: ["no files yet", "they appear as I read them"] as const,
156
- plan: ["no plan yet", "my steps show up here"] as const,
157
- usage: "0 so far",
158
- } as const;
@@ -1,183 +0,0 @@
1
- /** Windows process-TREE kill via a kernel Job Object (port #21 HIGH-1).
2
- *
3
- * `taskkill /T` walks LIVE parent links. msys2 (Git bash) implements a
4
- * Cygwin→Cygwin exec by handing the pid to the new image and exiting the
5
- * forked stub, so the external command actually running inside a compound
6
- * (`a; sleep N; b`), nested (`bash -c '…'`) or backgrounded (`x & y & wait`)
7
- * shape has a DEAD Win32 parent and the walk never reaches it. Measured
8
- * through bunRunner on the reference box with an msys `sleep` child: 3/3
9
- * leaks + 3/3 runner hangs per shape (the orphan kept stdout open); only a
10
- * bare `sleep N`, exec'd without a fork, died. A native child (bun.exe) stays
11
- * reachable, which is why the shipped test passed. A Job Object records
12
- * membership at CreateProcess time and inherits it down the tree, so
13
- * TerminateJobObject kills every descendant regardless of parent links.
14
- *
15
- * Per-spawn lifecycle (executor.ts bunRunner):
16
- * createWinJob() → assign(launcherPid) right after Bun.spawn
17
- * abort → terminate() TerminateJobObject, then close
18
- * settle → release() a run that completed on its own:
19
- * drop the close-kill limit, then close — a child the command
20
- * deliberately left behind (`server > log 2>&1 &`) survives, as
21
- * it does on POSIX and did before this port. While the command is
22
- * in flight the limit stays armed, so an rovecode crash takes the
23
- * tree with it (the OS closes the handle).
24
- * assign() also sweeps the launcher's already-visible descendants by a
25
- * Toolhelp32 parent-chain walk: a child forked in the spawn→assign window is
26
- * not a member by inheritance (under load that window can span a scheduler
27
- * quantum). Residual: a Cygwin stub that already exec'd AND exited inside
28
- * that window leaves its child unreachable by any parent walk. The sweep
29
- * costs one process snapshot (~15ms with ~300 processes on the loaded
30
- * reference box).
31
- * Fail-safe: non-win32, no bun:ffi, or any kernel32 call failing → null; the
32
- * caller keeps `taskkill /T /F` alone and reports treeKill "taskkill-only".
33
- * Nested jobs (Windows 8+) let this work when rovecode itself already runs
34
- * inside a job (terminals and IDEs do that): the launcher is then in both. */
35
-
36
- import { dlopen, FFIType, ptr } from "bun:ffi";
37
-
38
- const JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE = 0x2000;
39
- const JobObjectExtendedLimitInformation = 9;
40
- /** sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION) on x64; LimitFlags sits at
41
- * BasicLimitInformation offset 16 (after two LARGE_INTEGERs). */
42
- const EXTENDED_LIMIT_SIZE = 144;
43
- const LIMIT_FLAGS_OFFSET = 16;
44
- const PROCESS_SET_QUOTA_AND_TERMINATE = 0x0101;
45
- const TH32CS_SNAPPROCESS = 0x2;
46
- /** sizeof(PROCESSENTRY32W) on x64; th32ProcessID at 8, th32ParentProcessID at 32. */
47
- const PE32_SIZE = 568;
48
- const PE32_PID = 8;
49
- const PE32_PPID = 32;
50
-
51
- type Handle = number;
52
-
53
- interface Kernel32 {
54
- CreateJobObjectW(attrs: null, name: null): Handle | null;
55
- SetInformationJobObject(job: Handle, cls: number, info: number, len: number): number;
56
- AssignProcessToJobObject(job: Handle, proc: Handle): number;
57
- TerminateJobObject(job: Handle, exitCode: number): number;
58
- OpenProcess(access: number, inherit: number, pid: number): Handle | null;
59
- CloseHandle(h: Handle): number;
60
- CreateToolhelp32Snapshot(flags: number, pid: number): Handle | null;
61
- Process32FirstW(snap: Handle, entry: number): number;
62
- Process32NextW(snap: Handle, entry: number): number;
63
- }
64
-
65
- let library: { symbols: unknown } | null | undefined; // undefined = not tried yet
66
- let override: boolean | null = null;
67
-
68
- function kernel32(): Kernel32 | null {
69
- if (library === undefined) {
70
- library = null;
71
- if (process.platform === "win32") {
72
- try {
73
- library = dlopen("kernel32.dll", {
74
- CreateJobObjectW: { args: [FFIType.ptr, FFIType.ptr], returns: FFIType.ptr },
75
- SetInformationJobObject: { args: [FFIType.ptr, FFIType.i32, FFIType.ptr, FFIType.u32], returns: FFIType.i32 },
76
- AssignProcessToJobObject: { args: [FFIType.ptr, FFIType.ptr], returns: FFIType.i32 },
77
- TerminateJobObject: { args: [FFIType.ptr, FFIType.u32], returns: FFIType.i32 },
78
- OpenProcess: { args: [FFIType.u32, FFIType.i32, FFIType.u32], returns: FFIType.ptr },
79
- CloseHandle: { args: [FFIType.ptr], returns: FFIType.i32 },
80
- CreateToolhelp32Snapshot: { args: [FFIType.u32, FFIType.u32], returns: FFIType.ptr },
81
- Process32FirstW: { args: [FFIType.ptr, FFIType.ptr], returns: FFIType.i32 },
82
- Process32NextW: { args: [FFIType.ptr, FFIType.ptr], returns: FFIType.i32 },
83
- });
84
- } catch { library = null; }
85
- }
86
- }
87
- return library ? (library.symbols as Kernel32) : null;
88
- }
89
-
90
- /** A kernel HANDLE is a small positive value: NULL arrives as null and
91
- * INVALID_HANDLE_VALUE (-1) fits this range in no representation. */
92
- const isHandle = (h: unknown): h is Handle => typeof h === "number" && h > 0 && h <= 0xffff_ffff;
93
-
94
- /** Whether the real Job Object path is usable here (status surfaces, tests). */
95
- export function winJobsAvailable(): boolean { return override ?? kernel32() !== null; }
96
-
97
- /** Test seam: `false` forces the fail-safe path (the box-without-kernel32
98
- * shape — callers fall back to taskkill-only); `null` restores detection. */
99
- export function overrideWinJobs(available: boolean | null): void { override = available; }
100
-
101
- export interface WinJob {
102
- /** Put `pid` and its currently visible descendants in the job. false →
103
- * nothing is a member (caller must fall back); the job is closed. */
104
- assign(pid: number): boolean;
105
- /** Abort: kill every member now, then close. Idempotent. */
106
- terminate(): void;
107
- /** Normal settle: clear the close-kill limit, then close — members that
108
- * outlived the command keep running. No-op after terminate(). */
109
- release(): void;
110
- }
111
-
112
- /** One job per spawn, armed with KILL_ON_JOB_CLOSE. null = unavailable. */
113
- export function createWinJob(): WinJob | null {
114
- if (override === false) return null;
115
- const k = kernel32();
116
- if (!k) return null;
117
- const job = k.CreateJobObjectW(null, null);
118
- if (!isHandle(job)) return null;
119
- const limits = new Uint8Array(EXTENDED_LIMIT_SIZE);
120
- new DataView(limits.buffer).setUint32(LIMIT_FLAGS_OFFSET, JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE, true);
121
- if (!k.SetInformationJobObject(job, JobObjectExtendedLimitInformation, ptr(limits), EXTENDED_LIMIT_SIZE)) {
122
- k.CloseHandle(job);
123
- return null;
124
- }
125
- let handle: Handle | null = job;
126
- const close = (): void => { if (handle !== null) { k.CloseHandle(handle); handle = null; } };
127
- const assignOne = (pid: number): boolean => {
128
- if (handle === null) return false;
129
- const p = k.OpenProcess(PROCESS_SET_QUOTA_AND_TERMINATE, 0, pid);
130
- if (!isHandle(p)) return false;
131
- try { return k.AssignProcessToJobObject(handle, p) !== 0; } finally { k.CloseHandle(p); }
132
- };
133
- return {
134
- assign(pid) {
135
- if (!assignOne(pid)) { close(); return false; }
136
- // belt-and-braces for the spawn→assign window; already-member or
137
- // already-exited descendants simply fail to assign, which is fine
138
- for (const d of descendants(k, pid)) assignOne(d);
139
- return true;
140
- },
141
- terminate() {
142
- if (handle === null) return;
143
- k.TerminateJobObject(handle, 1);
144
- close();
145
- },
146
- release() {
147
- if (handle === null) return;
148
- k.SetInformationJobObject(handle, JobObjectExtendedLimitInformation, ptr(new Uint8Array(EXTENDED_LIMIT_SIZE)), EXTENDED_LIMIT_SIZE);
149
- close();
150
- },
151
- };
152
- }
153
-
154
- /** Live descendants of `root` by parent-pid chain (one Toolhelp32 snapshot).
155
- * pids recycle, so a stale parent link could form a cycle: visited-set walk. */
156
- function descendants(k: Kernel32, root: number): number[] {
157
- const snap = k.CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
158
- if (!isHandle(snap)) return [];
159
- const children = new Map<number, number[]>();
160
- try {
161
- const entry = new Uint8Array(PE32_SIZE);
162
- const view = new DataView(entry.buffer);
163
- view.setUint32(0, PE32_SIZE, true); // dwSize must be set before Process32FirstW
164
- if (!k.Process32FirstW(snap, ptr(entry))) return [];
165
- do {
166
- const pid = view.getUint32(PE32_PID, true);
167
- const ppid = view.getUint32(PE32_PPID, true);
168
- const list = children.get(ppid);
169
- if (list) list.push(pid); else children.set(ppid, [pid]);
170
- } while (k.Process32NextW(snap, ptr(entry)));
171
- } finally {
172
- k.CloseHandle(snap);
173
- }
174
- const seen = new Set<number>([root]);
175
- const out: number[] = [];
176
- const stack = [root];
177
- while (stack.length > 0) {
178
- for (const c of children.get(stack.pop()!) ?? []) {
179
- if (!seen.has(c)) { seen.add(c); out.push(c); stack.push(c); }
180
- }
181
- }
182
- return out;
183
- }