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
package/src/mcp/config.ts DELETED
@@ -1,252 +0,0 @@
1
- /** MCP server configuration loading (port #3).
2
- * Merges `.rovecode/mcp.json` (ours) with `.mcp.json` (harvested, claude-code
3
- * format `{ mcpServers: { name: {command,args,env,url,type} } }`); ours wins
4
- * on a name clash. With a `home`, the USER file `<home>/mcp.json` is the lowest
5
- * layer under both (that is where `rovecode mcp add` writes by default).
6
- * `${NAME}` in args, env, headers or url is filled from the environment — so a
7
- * project file can name a secret without holding it; an unset name skips the
8
- * entry with a warning rather than launching a server with an empty key.
9
- * Malformed files/entries are skipped with a warning — this loader never throws. */
10
-
11
- import { existsSync, readFileSync } from "node:fs";
12
- import { join } from "node:path";
13
- import { fileDigest } from "../core/trust.ts";
14
-
15
- /** sha256 (hex) of a file's bytes — the trust key for a project file; since 2026-09-07 core/trust.ts's memoised one */
16
- export { fileDigest };
17
-
18
- /** the one line an untrusted project file gets — names the file, the count, the review and the approval command */
19
- export function untrustedNote(file: string, count: number): string {
20
- return `${file}: not trusted on this machine — its ${count} MCP server${count === 1 ? "" : "s"} stay off (they would run commands from this repo). Review: rovecode mcp show · approve: rovecode mcp trust (or rovecode trust for every gated file)`;
21
- }
22
-
23
- /** the PROJECT file — what the status hint and `mcp login` name (mcpConfigFiles(cwd).project) */
24
- export function mcpConfigPath(cwd: string): string {
25
- return mcpConfigFiles(cwd).project;
26
- }
27
-
28
- /** where each scope's file lives; the market's `add`/`remove` write exactly these */
29
- export function mcpConfigFiles(cwd: string, home?: string): { user?: string; harvest: string; project: string } {
30
- return { ...(home !== undefined ? { user: join(home, "mcp.json") } : {}), harvest: join(cwd, ".mcp.json"), project: join(cwd, ".rovecode", "mcp.json") };
31
- }
32
-
33
- const VAR_REF = /\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g;
34
- /** an unfilled market placeholder: `<directory the server may touch>`. Angle brackets around prose, which
35
- * is not something a real argument, URL or header value looks like. */
36
- const PLACEHOLDER_REF = /<[^<>]*[a-z][^<>]*>/g;
37
- /** `${NAME}` → env value; every missing name lands in `missing` (the caller decides that it is fatal) */
38
- export function expandVars(text: string, env: Record<string, string | undefined>, missing: string[]): string {
39
- return text.replace(VAR_REF, (_m, name: string) => { const v = env[name]; if (v === undefined) { missing.push(name); return ""; } return v; });
40
- }
41
-
42
- export interface McpServerConfig {
43
- name: string;
44
- /** `sse` is the legacy HTTP+SSE wire (port #57): a first-class url transport, and the wire an `http`
45
- * entry falls back to ONCE when its initialize POST answers 404/405 (client.ts) */
46
- transport: "stdio" | "http" | "sse";
47
- command?: string;
48
- args?: string[];
49
- env?: Record<string, string>;
50
- url?: string;
51
- /** extra HTTP headers (auth tokens etc.) for http transports */
52
- headers?: Record<string, string>;
53
- /** port #76 (mcp/oauth.ts): a configured client id beats dynamic registration; scope rides the authorize request */
54
- oauth?: { clientId?: string; scope?: string };
55
- enabled?: boolean;
56
- }
57
-
58
- /** Shared narrow helper (also used by the manager in client.ts). */
59
- export function isRecord(v: unknown): v is Record<string, unknown> {
60
- return typeof v === "object" && v !== null && !Array.isArray(v);
61
- }
62
-
63
- /** Shared error-to-string helper (also used by the manager in client.ts). */
64
- export function message(err: unknown): string {
65
- return err instanceof Error ? err.message : String(err);
66
- }
67
-
68
- /** Normalize one server entry (claude-code `.mcp.json` style or ours). Returns
69
- * undefined (and records a warning) when the entry cannot produce a usable config. */
70
- export function normalizeEntry(name: string, raw: unknown, file: string, warnings: string[], envSource: Record<string, string | undefined> = process.env, opts: { allowPlaceholders?: boolean } = {}): McpServerConfig | undefined {
71
- if (!isRecord(raw)) {
72
- warnings.push(`${file}: server "${name}" is not an object; skipped`);
73
- return undefined;
74
- }
75
- const missing: string[] = [];
76
- const fill = (s: string): string => expandVars(s, envSource, missing);
77
- const command = typeof raw.command === "string" && raw.command.length > 0 ? raw.command : undefined;
78
- const url = typeof raw.url === "string" && raw.url.length > 0 ? fill(raw.url) : undefined;
79
- const declared = typeof raw.transport === "string" ? raw.transport : typeof raw.type === "string" ? raw.type : undefined;
80
-
81
- let transport: McpServerConfig["transport"] | undefined;
82
- if (declared === "stdio") transport = "stdio";
83
- else if (declared === "http" || declared === "streamable-http" || declared === "streamable_http") transport = "http";
84
- else if (declared === "sse") transport = "sse"; // port #57: legacy HTTP+SSE, spoken by client.ts
85
- else if (declared !== undefined) {
86
- warnings.push(`${file}: server "${name}" has unknown transport "${declared}"; skipped`);
87
- return undefined;
88
- } else transport = url !== undefined ? "http" : command !== undefined ? "stdio" : undefined;
89
-
90
- if (transport === undefined) {
91
- warnings.push(`${file}: server "${name}" has neither command nor url; skipped`);
92
- return undefined;
93
- }
94
- if (transport === "stdio" && command === undefined) {
95
- warnings.push(`${file}: stdio server "${name}" is missing command; skipped`);
96
- return undefined;
97
- }
98
- if (transport === "http" || transport === "sse") {
99
- if (url === undefined) {
100
- warnings.push(`${file}: ${transport} server "${name}" is missing url; skipped`);
101
- return undefined;
102
- }
103
- try {
104
- new URL(url);
105
- } catch {
106
- warnings.push(`${file}: ${transport} server "${name}" has invalid url "${url}"; skipped`);
107
- return undefined;
108
- }
109
- }
110
-
111
- let args: string[] | undefined;
112
- if (raw.args !== undefined) {
113
- if (Array.isArray(raw.args) && raw.args.every((x): x is string => typeof x === "string")) {
114
- args = raw.args.map(fill);
115
- } else {
116
- warnings.push(`${file}: server "${name}" has non-string args; skipped`);
117
- return undefined;
118
- }
119
- }
120
- let env: Record<string, string> | undefined;
121
- if (isRecord(raw.env)) {
122
- env = {};
123
- for (const [k, v] of Object.entries(raw.env)) if (typeof v === "string") env[k] = fill(v);
124
- }
125
- let headers: Record<string, string> | undefined;
126
- if (isRecord(raw.headers)) {
127
- headers = {};
128
- for (const [k, v] of Object.entries(raw.headers)) if (typeof v === "string") headers[k] = fill(v);
129
- }
130
- let oauth: McpServerConfig["oauth"];
131
- if (isRecord(raw.oauth)) {
132
- oauth = {};
133
- if (typeof raw.oauth.clientId === "string" && raw.oauth.clientId.length > 0) oauth.clientId = raw.oauth.clientId;
134
- if (typeof raw.oauth.scope === "string" && raw.oauth.scope.length > 0) oauth.scope = raw.oauth.scope;
135
- if (Object.keys(oauth).length === 0) oauth = undefined;
136
- }
137
- if (missing.length > 0) {
138
- // an empty key would launch a server that fails on its first call; naming the variable is the fix
139
- warnings.push(`${file}: server "${name}" needs ${[...new Set(missing)].map((m) => `\${${m}}`).join(", ")} set in the environment; skipped`);
140
- return undefined;
141
- }
142
- // The other half of the same rule, for the values a market install could not fill: a required argument
143
- // that only the human knows (which directory the filesystem server may touch) is written into the file
144
- // as `<directory the server may touch>`, and a server still carrying one is not launched. Launching it
145
- // means npx starts, the server rejects its own arguments, and the failure surfaces as a connect error
146
- // several layers from the thing that is actually wrong — an editable line in a file rovecode named.
147
- const holes = placeholderHoles({ args, env, headers, url });
148
- if (holes.length > 0 && opts.allowPlaceholders !== true) {
149
- warnings.push(`${file}: server "${name}" still has ${holes.join(", ")} to fill in; skipped (edit that line and it will connect)`);
150
- return undefined;
151
- }
152
-
153
- const out: McpServerConfig = { name, transport };
154
- if (command !== undefined) out.command = command;
155
- if (args !== undefined) out.args = args;
156
- if (env !== undefined) out.env = env;
157
- if (url !== undefined) out.url = url;
158
- if (headers !== undefined) out.headers = headers;
159
- if (oauth !== undefined) out.oauth = oauth;
160
- if (typeof raw.enabled === "boolean") out.enabled = raw.enabled;
161
- return out;
162
- }
163
-
164
- /** Parse one config file. Accepts the claude-code map form
165
- * `{ mcpServers: { name: {...} } }` and, additionally (ours), a
166
- * `{ servers: McpServerConfig[] }` array form. */
167
- /** The `<…>` placeholders an entry still carries, in file order, each once. Empty = launchable as far as
168
- * arguments go. Shared by the loader (which refuses to launch while any remain) and the listing surfaces
169
- * (which must SHOW such an entry, marked, rather than pretend it was never written). */
170
- export function placeholderHoles(s: { args?: string[]; env?: Record<string, string>; headers?: Record<string, string>; url?: string }): string[] {
171
- return [...new Set([...(s.args ?? []), ...Object.values(s.env ?? {}), ...Object.values(s.headers ?? {}), ...(s.url !== undefined ? [s.url] : [])]
172
- .flatMap((v) => [...v.matchAll(PLACEHOLDER_REF)].map((m) => m[0])))];
173
- }
174
-
175
- /** `opts.allowPlaceholders`: keep entries that still carry a `<…>` hole (a LISTING wants to show them, marked);
176
- * the loader leaves it off and such an entry is skipped with a warning naming the hole. */
177
- export function parseConfigFile(path: string, warnings: string[], envSource: Record<string, string | undefined> = process.env, opts: { allowPlaceholders?: boolean } = {}): McpServerConfig[] {
178
- if (!existsSync(path)) return [];
179
- let text: string;
180
- try {
181
- text = readFileSync(path, "utf8");
182
- } catch (err) {
183
- warnings.push(`${path}: unreadable (${message(err)}); file skipped`);
184
- return [];
185
- }
186
- let json: unknown;
187
- try {
188
- json = JSON.parse(text);
189
- } catch (err) {
190
- warnings.push(`${path}: invalid JSON (${message(err)}); file skipped`);
191
- return [];
192
- }
193
- if (!isRecord(json)) {
194
- warnings.push(`${path}: root is not an object; file skipped`);
195
- return [];
196
- }
197
- const out: McpServerConfig[] = [];
198
- if (json.mcpServers !== undefined) {
199
- if (isRecord(json.mcpServers)) {
200
- for (const [name, raw] of Object.entries(json.mcpServers)) {
201
- const cfg = normalizeEntry(name, raw, path, warnings, envSource, opts);
202
- if (cfg) out.push(cfg);
203
- }
204
- } else warnings.push(`${path}: "mcpServers" is not an object; ignored`);
205
- }
206
- if (json.servers !== undefined) {
207
- if (Array.isArray(json.servers)) {
208
- for (const raw of json.servers) {
209
- const name = isRecord(raw) && typeof raw.name === "string" && raw.name.length > 0 ? raw.name : undefined;
210
- if (name === undefined) {
211
- warnings.push(`${path}: servers[] entry without a name; skipped`);
212
- continue;
213
- }
214
- const cfg = normalizeEntry(name, raw, path, warnings, envSource, opts);
215
- if (cfg) out.push(cfg);
216
- }
217
- } else warnings.push(`${path}: "servers" is not an array; ignored`);
218
- }
219
- return out;
220
- }
221
-
222
- export interface LoadMcpOptions {
223
- /** the user home; without it the user file is not read (existing callers and tests) */
224
- home?: string;
225
- /** what `${NAME}` is filled from (default process.env) */
226
- env?: Record<string, string | undefined>;
227
- /** the trust gate for PROJECT files (mcp/trust.ts trustedPredicate). Without it project files load as
228
- * they always did; with it an unapproved file contributes nothing and leaves one warning. The user
229
- * file is never gated — it is yours. */
230
- trusted?: (file: string, digest: string) => boolean;
231
- }
232
-
233
- /** Merge the user file (`<home>/mcp.json`, only when a home is given) under `.mcp.json` (harvest)
234
- * under `.rovecode/mcp.json` (ours). The most local wins on a name clash. Pass a `warnings` array
235
- * to collect human-readable skip reasons. */
236
- export function loadMcpConfig(cwd: string, warnings: string[] = [], opts: LoadMcpOptions = {}): McpServerConfig[] {
237
- const files = mcpConfigFiles(cwd, opts.home);
238
- const byName = new Map<string, McpServerConfig>();
239
- const anySet = new Proxy({}, { get: () => "set" }) as Record<string, string>; // counting entries, not launching them
240
- for (const [scope, path] of [["user", files.user], ["harvest", files.harvest], ["project", files.project]] as const) {
241
- if (path === undefined) continue;
242
- if (scope !== "user" && opts.trusted !== undefined) {
243
- const digest = fileDigest(path);
244
- if (digest !== undefined && !opts.trusted(path, digest)) {
245
- warnings.push(untrustedNote(path, parseConfigFile(path, [], anySet).length));
246
- continue; // absence, not "loaded but marked"
247
- }
248
- }
249
- for (const c of parseConfigFile(path, warnings, opts.env)) byName.set(c.name, c); // later layers win
250
- }
251
- return [...byName.values()];
252
- }
@@ -1,211 +0,0 @@
1
- /** Install-once for MCP servers the market would otherwise launch with `npx -y <package>`.
2
- *
3
- * Why this exists, in numbers (Windows 11, node 24, npm 11, the memory and filesystem servers, medians of
4
- * 3–5 runs through McpManager, measured 2026-09-06): a warm `npx -y` takes 1.8–2.1 s from spawn to the
5
- * initialize handshake; the same package installed once and launched with `node <its bin>` takes
6
- * 0.35–0.47 s. The difference is npx itself — `npx --version` alone is 0.6 s, and every warm launch still
7
- * asks registry.npmjs.org to revalidate the package (0.3–1.3 s, and no network means a timeout path). A
8
- * cold cache is 7 s and a 47 MB download, repeated whenever upstream publishes, because `-y <package>`
9
- * means "latest". The one-time install is ~6 s and ~30 MB for two servers sharing one SDK copy.
10
- *
11
- * What it is NOT: silent, or the only path. The human is asked, in the plan they approve, and "no" leaves
12
- * the npx line exactly as it is today. Installing code is a bigger act than writing a config line, and
13
- * the plan says so in those words. The record in installed.json carries the package name, the version
14
- * that landed and npm's integrity hash from the lockfile — an install that is recorded is auditable; an
15
- * `npx -y` that runs whatever "latest" is at every start is not.
16
- *
17
- * Where: one shared prefix, `~/.rovecode/mcp/`, with its own package.json so npm never mistakes a parent
18
- * folder for the project. N servers share one node_modules and one SDK copy. The launch line is `node`
19
- * plus the ABSOLUTE path of the package's bin — never the .cmd shim (it means cmd.exe and its quoting),
20
- * and the path survives a space because it is one argv entry, not a shell string. */
21
-
22
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
23
- import { join, resolve } from "node:path";
24
- import type { McpServerConfig } from "./config.ts";
25
- import type { MarketInstall } from "./market.ts";
26
-
27
- export type Spawn = (cmd: string[], cwd: string) => Promise<{ code: number; stderr: string }>;
28
-
29
- /** the package an `npx …` launch line runs, taken apart */
30
- export interface NpxPackage {
31
- /** the package name, `@scope/name` or `name` */
32
- name: string;
33
- /** what npx was given: name, or `name@version` when the catalog pinned one */
34
- spec: string;
35
- /** the pinned version, when the spec carried one */
36
- version?: string;
37
- /** the arguments the SERVER receives — everything after the package spec */
38
- rest: string[];
39
- }
40
-
41
- const NPX_FLAGS_NO_VALUE = new Set(["-y", "--yes", "-q", "--quiet", "--no-install", "--prefer-offline", "--prefer-online"]);
42
- /** `@scope/name`, `name`, optionally `@version` — a registry package and nothing else (no git URL, no tarball, no path) */
43
- const PACKAGE_SPEC = /^(@[a-z0-9][a-z0-9._-]*\/[a-z0-9][a-z0-9._-]*|[a-z0-9][a-z0-9._-]*)(?:@([^@\s/]+))?$/;
44
-
45
- /** The package a stdio `npx` launch runs, or undefined when the line is not a plain `npx [flags] <package>
46
- * [args]` — an `npx -p x cmd`, a git URL or a tarball is left to npx, since we cannot say what we would be
47
- * installing. Undefined means "no offer", never an error: the npx line still works. */
48
- export function npxPackage(install: MarketInstall): NpxPackage | undefined {
49
- if (install.kind !== "stdio" || install.runtime !== "npx" || install.command !== "npx") return undefined;
50
- let i = 0;
51
- while (i < install.args.length && install.args[i]!.startsWith("-")) {
52
- if (!NPX_FLAGS_NO_VALUE.has(install.args[i]!)) return undefined; // a flag with a value (-p, --package, -c): not our shape
53
- i += 1;
54
- }
55
- const spec = install.args[i];
56
- if (spec === undefined) return undefined;
57
- const m = PACKAGE_SPEC.exec(spec);
58
- if (!m) return undefined;
59
- const out: NpxPackage = { name: m[1]!, spec, rest: install.args.slice(i + 1) };
60
- if (m[2] !== undefined) out.version = m[2];
61
- return out;
62
- }
63
-
64
- /** the shared prefix every install-once server lives in */
65
- export function localPrefix(home: string): string { return join(home, "mcp"); }
66
-
67
- /** what landed on disk, read back after npm finished — the record's source of truth */
68
- export interface LocalPackage {
69
- name: string;
70
- version: string;
71
- /** ABSOLUTE path of the package's bin script — what `node` runs */
72
- bin: string;
73
- /** npm's integrity hash for the tarball, from package-lock.json */
74
- integrity?: string;
75
- /** the tarball URL npm resolved, from package-lock.json */
76
- resolved?: string;
77
- /** what could not be recorded and why — an empty list is the normal case. Written into installed.json
78
- * as it is, so a record with a hole says where the hole is instead of leaving a field silently absent. */
79
- missing: string[];
80
- }
81
-
82
- export interface InstallLocalDeps {
83
- /** how `npm install` runs — tests inject one that writes a fake node_modules and never touches the network */
84
- spawn?: Spawn;
85
- }
86
-
87
- const defaultSpawn: Spawn = async (cmd, cwd) => {
88
- const p = Bun.spawn(cmd, { cwd, stdout: "ignore", stderr: "pipe", stdin: "ignore" });
89
- return { code: await p.exited, stderr: await new Response(p.stderr).text() };
90
- };
91
-
92
- /** the exact argv `installLocalPackage` runs — exported so the plan can show it verbatim */
93
- export function npmInstallArgv(pkg: NpxPackage, prefix: string): string[] {
94
- return ["npm", "install", "--prefix", prefix, "--save", "--no-fund", "--no-audit", "--loglevel=error", pkg.spec];
95
- }
96
-
97
- /** Run `npm install` for one package into the shared prefix, then read back what landed. Never throws for
98
- * an npm failure — the caller shows the error and nothing has been written to mcp.json yet. */
99
- export async function installLocalPackage(pkg: NpxPackage, prefix: string, deps: InstallLocalDeps = {}): Promise<{ ok: true; pkg: LocalPackage } | { ok: false; error: string }> {
100
- const spawn = deps.spawn ?? defaultSpawn;
101
- try {
102
- mkdirSync(prefix, { recursive: true });
103
- // a package.json of its own, so npm treats the prefix as the project: without one it can walk up and
104
- // install into whatever package.json it finds above ~/.rovecode
105
- const manifest = join(prefix, "package.json");
106
- if (!existsSync(manifest)) {
107
- writeFileSync(manifest, JSON.stringify({ name: "rovecode-mcp-servers", private: true, description: "MCP servers installed once by rovecode's market — launched with node, not npx (docs/mcp-market.md)" }, null, 2) + "\n");
108
- }
109
- const r = await spawn(npmInstallArgv(pkg, prefix), prefix);
110
- if (r.code !== 0) return { ok: false, error: `npm install ${pkg.spec} failed (exit ${r.code})${r.stderr.trim() ? `: ${r.stderr.trim().split("\n").slice(-3).join(" · ")}` : ""}` };
111
- } catch (e) {
112
- return { ok: false, error: `npm install ${pkg.spec} could not run: ${e instanceof Error ? e.message : String(e)}` };
113
- }
114
- return readLocalPackage(pkg.name, prefix);
115
- }
116
-
117
- /** What is on disk for one package under the prefix: version and bin from its package.json, integrity from
118
- * the lockfile. `ok: false` when the package or its bin is not there — then there is nothing to launch. */
119
- export function readLocalPackage(name: string, prefix: string): { ok: true; pkg: LocalPackage } | { ok: false; error: string } {
120
- const dir = join(prefix, "node_modules", ...name.split("/"));
121
- const manifestPath = join(dir, "package.json");
122
- if (!existsSync(manifestPath)) return { ok: false, error: `npm reported success but ${manifestPath} is not there` };
123
- let manifest: Record<string, unknown>;
124
- try { manifest = JSON.parse(readFileSync(manifestPath, "utf8")) as Record<string, unknown>; }
125
- catch (e) { return { ok: false, error: `${manifestPath}: ${e instanceof Error ? e.message : String(e)}` }; }
126
- const version = typeof manifest.version === "string" ? manifest.version : undefined;
127
- if (version === undefined) return { ok: false, error: `${manifestPath} states no version` };
128
- const binRel = binOf(name, manifest.bin);
129
- if (binRel === undefined) return { ok: false, error: `${name} declares no bin — there is nothing for node to run; npx would have failed the same way` };
130
- const bin = resolve(dir, binRel);
131
- if (!existsSync(bin)) return { ok: false, error: `${name}'s bin ${bin} is not on disk` };
132
- const missing: string[] = [];
133
- const lock = lockEntry(prefix, name, missing);
134
- const pkg: LocalPackage = { name, version, bin, missing };
135
- if (lock?.integrity !== undefined) pkg.integrity = lock.integrity;
136
- if (lock?.resolved !== undefined) pkg.resolved = lock.resolved;
137
- return { ok: true, pkg };
138
- }
139
-
140
- /** the bin a package declares: a string, or a map — the entry named like the package, else the only one */
141
- function binOf(name: string, bin: unknown): string | undefined {
142
- if (typeof bin === "string") return bin;
143
- if (typeof bin !== "object" || bin === null) return undefined;
144
- const entries = Object.entries(bin as Record<string, unknown>).filter((e): e is [string, string] => typeof e[1] === "string");
145
- if (entries.length === 0) return undefined;
146
- const short = name.split("/").pop()!;
147
- return (entries.find(([k]) => k === short) ?? entries[0]!)[1];
148
- }
149
-
150
- /** package-lock.json (lockfileVersion 2/3) → the entry for `node_modules/<name>`. Every way it can fall
151
- * short is written into `missing` in words, because a silent undefined here becomes a record that looks
152
- * complete and is not. */
153
- function lockEntry(prefix: string, name: string, missing: string[]): { integrity?: string; resolved?: string } | undefined {
154
- const lockPath = join(prefix, "package-lock.json");
155
- if (!existsSync(lockPath)) { missing.push(`integrity: ${lockPath} was not written by npm`); return undefined; }
156
- let lock: unknown;
157
- try { lock = JSON.parse(readFileSync(lockPath, "utf8")); }
158
- catch { missing.push(`integrity: ${lockPath} is not valid JSON`); return undefined; }
159
- const packages = typeof lock === "object" && lock !== null ? (lock as { packages?: unknown }).packages : undefined;
160
- if (typeof packages !== "object" || packages === null) { missing.push(`integrity: ${lockPath} has no "packages" map (lockfileVersion 1?)`); return undefined; }
161
- const entry = (packages as Record<string, unknown>)[`node_modules/${name}`];
162
- if (typeof entry !== "object" || entry === null) { missing.push(`integrity: ${lockPath} has no entry for node_modules/${name}`); return undefined; }
163
- const e = entry as { integrity?: unknown; resolved?: unknown };
164
- const out: { integrity?: string; resolved?: string } = {};
165
- if (typeof e.integrity === "string") out.integrity = e.integrity; else missing.push(`integrity: the lockfile entry for ${name} carries no integrity field`);
166
- if (typeof e.resolved === "string") out.resolved = e.resolved;
167
- return out;
168
- }
169
-
170
- /** the mcp.json launch line for an installed package: `node` + the bin's absolute path + the server's own
171
- * arguments. One argv entry per item — a path with a space in it is still one argument, because nothing
172
- * here goes through a shell (mcp/client.ts spawns with shell: false). */
173
- export function localLaunch(pkg: LocalPackage, rest: string[]): { command: "node"; args: string[] } {
174
- return { command: "node", args: [pkg.bin, ...rest] };
175
- }
176
-
177
- /** the launch line as the plan can show it BEFORE the install: the bin's exact filename is read from the
178
- * package after npm has put it there, so the preview names the folder and marks the file as pending */
179
- export function plannedLaunchLabel(pkg: NpxPackage, prefix: string): string {
180
- return ["node", `${join(prefix, "node_modules", ...pkg.name.split("/"))}${process.platform === "win32" ? "\\" : "/"}<its bin, read after the install>`, ...pkg.rest].join(" ");
181
- }
182
-
183
- /** the plan rows that say what installing once means — every word the human should read before the yes */
184
- export function localPlanLines(pkg: NpxPackage, prefix: string): string[] {
185
- return [
186
- ` installs ${npmInstallArgv(pkg, prefix).join(" ")}`,
187
- ` rovecode runs a package manager for you here. npm downloads ${pkg.spec} and everything it depends`,
188
- ` on and puts their CODE on this machine, under ${prefix} — typically 20–30 MB and a few seconds, once.`,
189
- ` In return the server starts in ~0.4 s instead of ~2 s and needs no network to start.`,
190
- ` Requires npm (it comes with Node.js, as npx does).`,
191
- ` records package name, version and npm's integrity hash in installed.json — what ran is on record`,
192
- ` (an npx line runs whatever "latest" is at every start, and records nothing)`,
193
- ];
194
- }
195
-
196
- /** a configured server that still launches through npx — the rows `mcp list` may offer the install-once line for */
197
- export function launchesViaNpx(server: McpServerConfig): boolean {
198
- return server.transport === "stdio" && server.command === "npx" && server.enabled !== false;
199
- }
200
-
201
- /** the one-line offer `mcp list` prints under the rows when some of them start through npx. Says what
202
- * changes, what it costs and that nothing happens until the human runs the command — no config is
203
- * rewritten by a listing. */
204
- export function npxOfferLine(names: string[]): string | undefined {
205
- if (names.length === 0) return undefined;
206
- const n = names.length;
207
- // `<catalog name>`, not the server name the row shows: `mcp add` takes the name you installed it by (a
208
- // registry server is `io.github.acme/widgets`, its row is `widgets`), and a renamed one needs its `--as` back
209
- return `${n} server${n === 1 ? "" : "s"} start${n === 1 ? "s" : ""} through npx, which re-resolves the package at every start (~2 s each): ${names.join(", ")}. `
210
- + `To start in ~0.4 s, reinstall with \`rovecode mcp add <catalog name> --local --force\` (the name you installed it by; add \`--as <server name>\` if you renamed it; installs the package once, ~25 MB). Nothing changes until you do.`;
211
- }
@@ -1,84 +0,0 @@
1
- /** The curated half of the MCP market: servers we have looked at, from publishers we can name, with
2
- * the exact launch line spelled out. Offline by design — `rovecode mcp search` answers from this list
3
- * before it asks the registry, and /mcp with an empty query shows only this list. Rules for an entry:
4
- * the publisher is the org that owns the package or the host; secrets travel by environment variable
5
- * (or a header for a remote), never as an argument; anything OAuth-only is left out because our http
6
- * transport carries a header, not a browser flow. Keep it short — this is a shelf, not a mirror. */
7
-
8
- import type { MarketEntry } from "./market.ts";
9
-
10
- const npx = (pkg: string, ...rest: string[]): string[] => ["-y", pkg, ...rest];
11
-
12
- export const CURATED: readonly MarketEntry[] = [
13
- { key: "filesystem", title: "Filesystem", source: "curated", publisher: "modelcontextprotocol (Anthropic)",
14
- description: "Read, write, search and move files under the directories you name.",
15
- repository: "https://github.com/modelcontextprotocol/servers",
16
- installs: [{ kind: "stdio", runtime: "npx", command: "npx", args: npx("@modelcontextprotocol/server-filesystem"), env: [], pending: ["<directory the server may touch>"] }] },
17
- { key: "memory", title: "Memory", source: "curated", publisher: "modelcontextprotocol (Anthropic)",
18
- description: "A knowledge graph the model can remember across sessions with (entities, relations, observations).",
19
- repository: "https://github.com/modelcontextprotocol/servers",
20
- installs: [{ kind: "stdio", runtime: "npx", command: "npx", args: npx("@modelcontextprotocol/server-memory"), env: [], pending: [] }] },
21
- { key: "sequential-thinking", title: "Sequential Thinking", source: "curated", publisher: "modelcontextprotocol (Anthropic)",
22
- description: "A scratchpad tool for step-by-step reasoning with revisions and branches.",
23
- repository: "https://github.com/modelcontextprotocol/servers",
24
- installs: [{ kind: "stdio", runtime: "npx", command: "npx", args: npx("@modelcontextprotocol/server-sequential-thinking"), env: [], pending: [] }] },
25
- { key: "everything", title: "Everything (test server)", source: "curated", publisher: "modelcontextprotocol (Anthropic)",
26
- description: "Exercises every MCP feature — prompts, resources, sampling, progress. For testing a client, not for work.",
27
- repository: "https://github.com/modelcontextprotocol/servers",
28
- installs: [{ kind: "stdio", runtime: "npx", command: "npx", args: npx("@modelcontextprotocol/server-everything"), env: [], pending: [] }] },
29
- { key: "fetch", title: "Fetch", source: "curated", publisher: "modelcontextprotocol (Anthropic)",
30
- description: "Fetch a URL and hand the page back as markdown (Python; needs uv).",
31
- repository: "https://github.com/modelcontextprotocol/servers",
32
- installs: [{ kind: "stdio", runtime: "uvx", command: "uvx", args: ["mcp-server-fetch"], env: [], pending: [] }] },
33
- { key: "git", title: "Git", source: "curated", publisher: "modelcontextprotocol (Anthropic)",
34
- description: "Read and search git repositories: log, diff, show, status (Python; needs uv).",
35
- repository: "https://github.com/modelcontextprotocol/servers",
36
- installs: [{ kind: "stdio", runtime: "uvx", command: "uvx", args: ["mcp-server-git"], env: [], pending: [] }] },
37
- { key: "time", title: "Time", source: "curated", publisher: "modelcontextprotocol (Anthropic)",
38
- description: "Current time and timezone conversion (Python; needs uv).",
39
- repository: "https://github.com/modelcontextprotocol/servers",
40
- installs: [{ kind: "stdio", runtime: "uvx", command: "uvx", args: ["mcp-server-time"], env: [], pending: [] }] },
41
- { key: "github", title: "GitHub", source: "curated", publisher: "GitHub",
42
- description: "Issues, pull requests, code search and Actions on GitHub — remote with a personal access token, or the official image via docker.",
43
- repository: "https://github.com/github/github-mcp-server",
44
- installs: [
45
- { kind: "http", url: "https://api.githubcopilot.com/mcp/", headers: [{ name: "Authorization", template: "Bearer {GITHUB_PAT}", required: true, secret: true, description: "a GitHub personal access token" }] },
46
- { kind: "stdio", runtime: "docker", command: "docker", args: ["run", "-i", "--rm", "-e", "GITHUB_PERSONAL_ACCESS_TOKEN", "ghcr.io/github/github-mcp-server"],
47
- env: [{ name: "GITHUB_PERSONAL_ACCESS_TOKEN", required: true, secret: true, description: "a GitHub personal access token" }], pending: [] },
48
- ] },
49
- { key: "playwright", title: "Playwright", source: "curated", publisher: "Microsoft",
50
- description: "Drive a real browser through accessibility snapshots: navigate, click, type, screenshot.",
51
- repository: "https://github.com/microsoft/playwright-mcp",
52
- installs: [{ kind: "stdio", runtime: "npx", command: "npx", args: npx("@playwright/mcp@latest"), env: [], pending: [] }] },
53
- { key: "context7", title: "Context7", source: "curated", publisher: "Upstash",
54
- description: "Up-to-date library documentation and code examples for the versions you actually use.",
55
- repository: "https://github.com/upstash/context7",
56
- installs: [
57
- { kind: "http", url: "https://mcp.context7.com/mcp", headers: [{ name: "CONTEXT7_API_KEY", required: false, secret: true, description: "optional API key for higher limits" }] },
58
- { kind: "stdio", runtime: "npx", command: "npx", args: npx("@upstash/context7-mcp"), env: [{ name: "CONTEXT7_API_KEY", required: false, secret: true, description: "optional API key for higher limits" }], pending: [] },
59
- ] },
60
- { key: "brave-search", title: "Brave Search", source: "curated", publisher: "Brave",
61
- description: "Web, news, image and local search through the Brave Search API.",
62
- repository: "https://github.com/brave/brave-search-mcp-server",
63
- installs: [{ kind: "stdio", runtime: "npx", command: "npx", args: npx("@brave/brave-search-mcp-server"), env: [{ name: "BRAVE_API_KEY", required: true, secret: true, description: "Brave Search API key" }], pending: [] }] },
64
- { key: "firecrawl", title: "Firecrawl", source: "curated", publisher: "Firecrawl (Mendable)",
65
- description: "Scrape, crawl and extract structured data from websites.",
66
- repository: "https://github.com/mendableai/firecrawl-mcp-server",
67
- installs: [{ kind: "stdio", runtime: "npx", command: "npx", args: npx("firecrawl-mcp"), env: [{ name: "FIRECRAWL_API_KEY", required: true, secret: true, description: "Firecrawl API key" }], pending: [] }] },
68
- { key: "tavily", title: "Tavily", source: "curated", publisher: "Tavily",
69
- description: "Search and extract built for agents: web search, page extraction, site crawl.",
70
- repository: "https://github.com/tavily-ai/tavily-mcp",
71
- installs: [{ kind: "stdio", runtime: "npx", command: "npx", args: npx("tavily-mcp"), env: [{ name: "TAVILY_API_KEY", required: true, secret: true, description: "Tavily API key" }], pending: [] }] },
72
- { key: "exa", title: "Exa", source: "curated", publisher: "Exa",
73
- description: "Neural web search and page contents for AI; the remote works without a key at a low rate.",
74
- repository: "https://github.com/exa-labs/exa-mcp-server",
75
- installs: [{ kind: "http", url: "https://mcp.exa.ai/mcp", headers: [] }] },
76
- { key: "deepwiki", title: "DeepWiki", source: "curated", publisher: "Cognition (Devin)",
77
- description: "Ask questions about any public GitHub repository, answered from its generated wiki. No key.",
78
- homepage: "https://docs.devin.ai/work-with-devin/deepwiki-mcp",
79
- installs: [{ kind: "http", url: "https://mcp.deepwiki.com/mcp", headers: [] }] },
80
- { key: "cloudflare-docs", title: "Cloudflare Docs", source: "curated", publisher: "Cloudflare",
81
- description: "Search Cloudflare's developer documentation. No key.",
82
- repository: "https://github.com/cloudflare/mcp-server-cloudflare",
83
- installs: [{ kind: "http", url: "https://docs.mcp.cloudflare.com/mcp", headers: [] }] },
84
- ];