rovecode 0.4.0-beta.3 → 0.4.0

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 (432) hide show
  1. package/README.md +57 -72
  2. package/THIRD_PARTY_NOTICES.md +0 -44
  3. package/bin/rovecode.ts +21 -0
  4. package/package.json +16 -38
  5. package/src/account/keys.ts +97 -0
  6. package/src/account/login.ts +158 -0
  7. package/src/account/provision.ts +47 -0
  8. package/src/account/store.ts +63 -0
  9. package/src/acp/server.ts +373 -0
  10. package/src/cli/account-cmd.ts +116 -0
  11. package/src/cli/connect.ts +244 -0
  12. package/src/cli/context-cmd.ts +199 -0
  13. package/src/cli/dispatch.ts +109 -0
  14. package/src/cli/doctor.ts +324 -0
  15. package/src/cli/export.ts +278 -0
  16. package/src/cli/help.ts +240 -0
  17. package/src/cli/is-tui-invocation.ts +8 -0
  18. package/src/cli/main.ts +599 -0
  19. package/src/cli/market-cmd.ts +658 -0
  20. package/src/cli/mcp-market-cmd.ts +299 -0
  21. package/src/cli/output.ts +382 -0
  22. package/src/cli/repl.ts +172 -0
  23. package/src/cli/resume.ts +32 -0
  24. package/src/cli/run-limits.ts +78 -0
  25. package/src/cli/runtime.ts +792 -0
  26. package/src/cli/setup.ts +187 -0
  27. package/src/cli/update-cmd.ts +78 -0
  28. package/src/cli/workflow-cmd.ts +100 -0
  29. package/src/coding/checkpoints.ts +270 -0
  30. package/src/coding/diff.ts +136 -0
  31. package/src/coding/files.ts +339 -0
  32. package/src/coding/hashline.ts +319 -0
  33. package/src/coding/lsp.ts +406 -0
  34. package/src/coding/repomap-cache.ts +99 -0
  35. package/src/coding/repomap-files.ts +110 -0
  36. package/src/coding/repomap.ts +392 -0
  37. package/src/core/compaction.ts +399 -0
  38. package/src/core/config.ts +289 -0
  39. package/src/core/context-report.ts +228 -0
  40. package/src/core/context.ts +60 -0
  41. package/src/core/count-remote.ts +107 -0
  42. package/src/core/execpolicy-rules.ts +196 -0
  43. package/src/core/execpolicy.ts +385 -0
  44. package/src/core/executor.ts +397 -0
  45. package/src/core/guardrails.ts +400 -0
  46. package/src/core/hooks.ts +398 -0
  47. package/src/core/images.ts +230 -0
  48. package/src/core/intro.ts +236 -0
  49. package/src/core/loop.ts +621 -0
  50. package/src/core/modes.ts +372 -0
  51. package/src/core/orchestrator.ts +207 -0
  52. package/src/core/reflection.ts +165 -0
  53. package/src/core/sandbox-config.ts +167 -0
  54. package/src/core/session-images.ts +73 -0
  55. package/src/core/session.ts +398 -0
  56. package/src/core/settings.ts +98 -0
  57. package/src/core/stuck-detector.ts +273 -0
  58. package/src/core/tasks.ts +374 -0
  59. package/src/core/token-scale.ts +108 -0
  60. package/src/core/tool-output-budget.ts +166 -0
  61. package/src/core/tools.ts +288 -0
  62. package/src/core/types.ts +330 -0
  63. package/src/core/update-check.ts +171 -0
  64. package/src/core/update.ts +158 -0
  65. package/src/core/usage.ts +204 -0
  66. package/src/core/validate.ts +121 -0
  67. package/src/core/verify-gate.ts +159 -0
  68. package/src/core/verify.ts +237 -0
  69. package/src/core/voice.ts +158 -0
  70. package/src/core/win-job.ts +183 -0
  71. package/src/design/audit.ts +797 -0
  72. package/src/design/direction.ts +190 -0
  73. package/src/design/rules.ts +157 -0
  74. package/src/eval/bench.ts +150 -0
  75. package/src/eval/gauntlet-runner.ts +218 -0
  76. package/src/eval/gauntlet.ts +226 -0
  77. package/src/eval/grader.ts +186 -0
  78. package/src/eval/record.ts +202 -0
  79. package/src/eval/redact.ts +141 -0
  80. package/src/eval/replay.ts +147 -0
  81. package/src/eval/trajectory.ts +373 -0
  82. package/src/index.ts +17 -0
  83. package/src/market/catalogs/mcp-docs.json +111 -0
  84. package/src/market/catalogs/plugins.json +111 -0
  85. package/src/market/catalogs/skills.json +478 -0
  86. package/src/market/clone.ts +72 -0
  87. package/src/market/context-cost.ts +121 -0
  88. package/src/market/digest.ts +106 -0
  89. package/src/market/index.ts +22 -0
  90. package/src/market/install.ts +578 -0
  91. package/src/market/manifest.ts +187 -0
  92. package/src/market/prereq.ts +145 -0
  93. package/src/market/registry.ts +363 -0
  94. package/src/market/resolve.ts +111 -0
  95. package/src/market/types.ts +236 -0
  96. package/src/market/validate.ts +227 -0
  97. package/src/mcp/client.ts +431 -0
  98. package/src/mcp/config.ts +239 -0
  99. package/src/mcp/local-package.ts +211 -0
  100. package/src/mcp/market-catalog.ts +84 -0
  101. package/src/mcp/market-install.ts +289 -0
  102. package/src/mcp/market.ts +0 -0
  103. package/src/mcp/tools.ts +131 -0
  104. package/src/mcp/trust.ts +49 -0
  105. package/src/memory/blocks.ts +175 -0
  106. package/src/memory/recall.ts +355 -0
  107. package/src/memory/store.ts +105 -0
  108. package/src/memory/tools.ts +99 -0
  109. package/src/plugins/cli.ts +123 -0
  110. package/src/plugins/discover.ts +108 -0
  111. package/src/plugins/index.ts +50 -0
  112. package/src/plugins/init.ts +140 -0
  113. package/src/plugins/install.ts +184 -0
  114. package/src/plugins/load.ts +149 -0
  115. package/src/plugins/manifest.ts +106 -0
  116. package/src/plugins/state.ts +83 -0
  117. package/src/providers/auth.ts +293 -0
  118. package/src/providers/cache.ts +223 -0
  119. package/src/providers/catalog-local.ts +160 -0
  120. package/src/providers/catalog.ts +408 -0
  121. package/src/providers/middleware-context.ts +86 -0
  122. package/src/providers/middleware.ts +373 -0
  123. package/src/providers/profile-glm53.ts +111 -0
  124. package/src/providers/profile-sonnet5-persona.ts +65 -0
  125. package/src/providers/profile-sonnet5-voice.ts +23 -0
  126. package/src/providers/profiles.ts +156 -0
  127. package/src/providers/provider-config.ts +311 -0
  128. package/src/providers/registry.ts +302 -0
  129. package/src/providers/response-validation.ts +80 -0
  130. package/src/providers/retry.ts +234 -0
  131. package/src/providers/router.ts +294 -0
  132. package/src/providers/sse.ts +26 -0
  133. package/src/providers/stream-errors.ts +117 -0
  134. package/src/providers/stream.ts +569 -0
  135. package/src/providers/thinking.ts +189 -0
  136. package/src/providers/wire-messages.ts +129 -0
  137. package/src/sdk/client.ts +225 -0
  138. package/src/sdk/index.ts +3 -0
  139. package/src/server/dashboard.ts +144 -0
  140. package/src/server/http.ts +343 -0
  141. package/src/server/openapi.ts +246 -0
  142. package/src/sextant/card-hits.ts +102 -0
  143. package/src/sextant/card-keys.ts +55 -0
  144. package/src/sextant/context-source.ts +157 -0
  145. package/src/sextant/draw-agents.ts +273 -0
  146. package/src/sextant/draw-code.ts +388 -0
  147. package/src/sextant/draw-context.ts +222 -0
  148. package/src/sextant/draw-frame.ts +164 -0
  149. package/src/sextant/draw-market.ts +573 -0
  150. package/src/sextant/draw-messages.ts +386 -0
  151. package/src/sextant/draw-pet.ts +230 -0
  152. package/src/sextant/draw-plan.ts +159 -0
  153. package/src/sextant/draw-tabs.ts +85 -0
  154. package/src/sextant/draw-util.ts +65 -0
  155. package/src/sextant/engine.ts +230 -0
  156. package/src/sextant/frame-hits.ts +25 -0
  157. package/src/sextant/frame.ts +101 -0
  158. package/src/sextant/git-status.ts +197 -0
  159. package/src/sextant/grid.ts +59 -0
  160. package/src/sextant/input.ts +119 -0
  161. package/src/sextant/keys.ts +488 -0
  162. package/src/sextant/layout.ts +86 -0
  163. package/src/sextant/local-commands.ts +156 -0
  164. package/src/sextant/market-source.ts +287 -0
  165. package/src/sextant/mentions.ts +141 -0
  166. package/src/sextant/message-hits.ts +26 -0
  167. package/src/sextant/model.ts +387 -0
  168. package/src/sextant/overlays.ts +451 -0
  169. package/src/sextant/panel-hits.ts +38 -0
  170. package/src/sextant/pet.ts +399 -0
  171. package/src/sextant/screen.ts +324 -0
  172. package/src/sextant/scroll-hits.ts +66 -0
  173. package/src/sextant/scrollbar.ts +82 -0
  174. package/src/sextant/selection.ts +123 -0
  175. package/src/sextant/sextant-bridge.ts +174 -0
  176. package/src/sextant/sextant-cards.ts +142 -0
  177. package/src/sextant/sextant-diff-base.ts +63 -0
  178. package/src/sextant/sextant-files.ts +154 -0
  179. package/src/sextant/sextant-frame-loop.ts +314 -0
  180. package/src/sextant/sextant-renderer.ts +478 -0
  181. package/src/sextant/sextant-repo.ts +131 -0
  182. package/src/sextant/theme.ts +66 -0
  183. package/src/sextant/tool-rows.ts +189 -0
  184. package/src/sextant/types.ts +473 -0
  185. package/src/skills/index.ts +306 -0
  186. package/src/skills/tools.ts +69 -0
  187. package/src/skills/versioned.ts +227 -0
  188. package/src/telemetry/otel.ts +353 -0
  189. package/src/telemetry/otlp.ts +68 -0
  190. package/src/tools/ask-user.ts +156 -0
  191. package/src/tools/design.ts +151 -0
  192. package/src/tools/evalcell.ts +338 -0
  193. package/src/tools/html-text.ts +139 -0
  194. package/src/tools/provider.ts +149 -0
  195. package/src/tools/task.ts +216 -0
  196. package/src/tools/todo.ts +320 -0
  197. package/src/tools/webfetch.ts +331 -0
  198. package/src/tui/app.ts +608 -0
  199. package/src/tui/attach.ts +127 -0
  200. package/src/tui/checkpoints-cmd.ts +70 -0
  201. package/src/tui/clipboard-image.ts +81 -0
  202. package/src/tui/commands.ts +277 -0
  203. package/src/tui/cost.ts +108 -0
  204. package/src/tui/info-cmd.ts +144 -0
  205. package/src/tui/mcp-cmd.ts +128 -0
  206. package/src/tui/modes-cmd.ts +45 -0
  207. package/src/tui/overlays.ts +97 -0
  208. package/src/tui/pi-renderer.ts +424 -0
  209. package/src/tui/providers-cmd.ts +366 -0
  210. package/src/tui/renderer.ts +101 -0
  211. package/src/tui/replay-marker.ts +29 -0
  212. package/src/tui/session-cmd.ts +146 -0
  213. package/src/tui/sextant-attach.ts +68 -0
  214. package/src/tui/sextant-io.ts +184 -0
  215. package/src/tui/sextant-smoke.ts +110 -0
  216. package/src/tui/smoke.ts +72 -0
  217. package/src/tui/theme.ts +59 -0
  218. package/src/tui/todo-label.ts +7 -0
  219. package/src/workflow/engine.ts +266 -0
  220. package/tsconfig.json +30 -0
  221. package/vendor/pi-tui/LICENSE +21 -0
  222. package/vendor/pi-tui/PATCHES.md +12 -0
  223. package/vendor/pi-tui/PROVENANCE.md +12 -0
  224. package/vendor/pi-tui/README.upstream.md +854 -0
  225. package/vendor/pi-tui/native/win32/prebuilds/win32-arm64/win32-console-mode.node +0 -0
  226. package/vendor/pi-tui/native/win32/prebuilds/win32-x64/win32-console-mode.node +0 -0
  227. package/vendor/pi-tui/src/alt-screen-search.ts +158 -0
  228. package/vendor/pi-tui/src/autocomplete.ts +827 -0
  229. package/vendor/pi-tui/src/components/alt-screen-flash.ts +52 -0
  230. package/vendor/pi-tui/src/components/box.ts +138 -0
  231. package/vendor/pi-tui/src/components/cancellable-loader.ts +41 -0
  232. package/vendor/pi-tui/src/components/editor.ts +2364 -0
  233. package/vendor/pi-tui/src/components/h-stack.ts +45 -0
  234. package/vendor/pi-tui/src/components/image.ts +128 -0
  235. package/vendor/pi-tui/src/components/input.ts +448 -0
  236. package/vendor/pi-tui/src/components/loader.ts +93 -0
  237. package/vendor/pi-tui/src/components/markdown.ts +1016 -0
  238. package/vendor/pi-tui/src/components/scroll-view.ts +217 -0
  239. package/vendor/pi-tui/src/components/select-list.ts +230 -0
  240. package/vendor/pi-tui/src/components/settings-list.ts +277 -0
  241. package/vendor/pi-tui/src/components/spacer.ts +29 -0
  242. package/vendor/pi-tui/src/components/stack.ts +155 -0
  243. package/vendor/pi-tui/src/components/text.ts +108 -0
  244. package/vendor/pi-tui/src/components/truncated-text.ts +66 -0
  245. package/vendor/pi-tui/src/components/v-stack.ts +34 -0
  246. package/vendor/pi-tui/src/editor-component.ts +75 -0
  247. package/vendor/pi-tui/src/fuzzy.ts +138 -0
  248. package/vendor/pi-tui/src/index.ts +149 -0
  249. package/vendor/pi-tui/src/keybindings.ts +321 -0
  250. package/vendor/pi-tui/src/keys.ts +1402 -0
  251. package/vendor/pi-tui/src/kill-ring.ts +47 -0
  252. package/vendor/pi-tui/src/latex.ts +1381 -0
  253. package/vendor/pi-tui/src/layout-node.ts +52 -0
  254. package/vendor/pi-tui/src/layout.ts +411 -0
  255. package/vendor/pi-tui/src/native-modifiers.ts +60 -0
  256. package/vendor/pi-tui/src/native-module-path.ts +32 -0
  257. package/vendor/pi-tui/src/stdin-buffer.ts +445 -0
  258. package/vendor/pi-tui/src/terminal-colors.ts +74 -0
  259. package/vendor/pi-tui/src/terminal-image.ts +701 -0
  260. package/vendor/pi-tui/src/terminal.ts +554 -0
  261. package/vendor/pi-tui/src/tui-alt-screen.ts +1379 -0
  262. package/vendor/pi-tui/src/tui-main-screen.ts +655 -0
  263. package/vendor/pi-tui/src/tui.ts +1264 -0
  264. package/vendor/pi-tui/src/undo-stack.ts +29 -0
  265. package/vendor/pi-tui/src/utils.ts +1327 -0
  266. package/vendor/pi-tui/src/word-navigation.ts +118 -0
  267. package/vendor/pi-tui/test/test-themes.ts +39 -0
  268. package/vendor/pi-tui/test/virtual-terminal.ts +219 -0
  269. package/CHANGELOG.md +0 -527
  270. package/bin/rovecode.js +0 -24
  271. package/dist/cli/app-j6gn14w3.js +0 -2
  272. package/dist/cli/ask-user-cwstt8fz.js +0 -2
  273. package/dist/cli/auth-login-9bbp9915.js +0 -2
  274. package/dist/cli/auth-m8p9grty.js +0 -2
  275. package/dist/cli/bench-16zqdms5.js +0 -9
  276. package/dist/cli/catalog-1xchffa4.js +0 -2
  277. package/dist/cli/cli-1n1zb64f.js +0 -2
  278. package/dist/cli/client-2t9gjkck.js +0 -2
  279. package/dist/cli/commands-exafvm2b.js +0 -2
  280. package/dist/cli/connect-6zde0kn3.js +0 -2
  281. package/dist/cli/context-cmd-5t43wgqt.js +0 -2
  282. package/dist/cli/context-report-kt01pw8y.js +0 -2
  283. package/dist/cli/count-remote-ap7x3vh6.js +0 -2
  284. package/dist/cli/design-ne5zszyh.js +0 -2
  285. package/dist/cli/dispatch-2r5myxye.js +0 -2
  286. package/dist/cli/doctor-ws4fh4tn.js +0 -3
  287. package/dist/cli/executor-bdrjn634.js +0 -2
  288. package/dist/cli/export-1mxb9g5p.js +0 -2
  289. package/dist/cli/files-g104xghh.js +0 -2
  290. package/dist/cli/gauntlet-07xrjpj7.js +0 -2
  291. package/dist/cli/gauntlet-runner-xvy64436.js +0 -10
  292. package/dist/cli/gauntlet-wave3-jm91yt5w.js +0 -5
  293. package/dist/cli/gauntlet-wave4-r13py7p1.js +0 -14
  294. package/dist/cli/hashline-znvrat11.js +0 -2
  295. package/dist/cli/http-xafw6fsh.js +0 -143
  296. package/dist/cli/index-1sgjm25y.js +0 -2
  297. package/dist/cli/init-g2m0tn4m.js +0 -51
  298. package/dist/cli/install-avaqjjqq.js +0 -2
  299. package/dist/cli/loop-mmpfft01.js +0 -2
  300. package/dist/cli/main-0904f6ps.js +0 -5
  301. package/dist/cli/main-0ab9fc26.js +0 -9
  302. package/dist/cli/main-0jys2ccn.js +0 -3
  303. package/dist/cli/main-0mtcdbs7.js +0 -3
  304. package/dist/cli/main-0z1w2zsg.js +0 -3
  305. package/dist/cli/main-1dchs7xv.js +0 -18
  306. package/dist/cli/main-1ereejm1.js +0 -3
  307. package/dist/cli/main-1k1kw6b5.js +0 -3
  308. package/dist/cli/main-27y4sm2k.js +0 -38
  309. package/dist/cli/main-2wwjex5j.js +0 -58
  310. package/dist/cli/main-2yeveeve.js +0 -6
  311. package/dist/cli/main-2yfck9b5.js +0 -3
  312. package/dist/cli/main-2zmzgkwh.js +0 -3
  313. package/dist/cli/main-351pz3z7.js +0 -7
  314. package/dist/cli/main-3gjqfh7a.js +0 -6
  315. package/dist/cli/main-3nf3kgve.js +0 -3
  316. package/dist/cli/main-3pjrb2hd.js +0 -3
  317. package/dist/cli/main-3rxcvgna.js +0 -19
  318. package/dist/cli/main-4b3jgy66.js +0 -19
  319. package/dist/cli/main-4wndhjdc.js +0 -7
  320. package/dist/cli/main-4xcmvxnk.js +0 -3
  321. package/dist/cli/main-5tbz0wbz.js +0 -4
  322. package/dist/cli/main-5ywnwthm.js +0 -3
  323. package/dist/cli/main-6b62vkz0.js +0 -14
  324. package/dist/cli/main-6dnk69vp.js +0 -3
  325. package/dist/cli/main-6genrmhs.js +0 -136
  326. package/dist/cli/main-73g7eff4.js +0 -15
  327. package/dist/cli/main-7c5thhjd.js +0 -5
  328. package/dist/cli/main-7rn6bqje.js +0 -3
  329. package/dist/cli/main-80haw7qk.js +0 -4
  330. package/dist/cli/main-875s60s2.js +0 -4
  331. package/dist/cli/main-8kjxbpw4.js +0 -8
  332. package/dist/cli/main-90ds1z4e.js +0 -10
  333. package/dist/cli/main-9etavkew.js +0 -3
  334. package/dist/cli/main-a9njrkk1.js +0 -3
  335. package/dist/cli/main-aecrjq2d.js +0 -12
  336. package/dist/cli/main-ck9asesq.js +0 -9
  337. package/dist/cli/main-cta9racd.js +0 -4
  338. package/dist/cli/main-ddv7j2ag.js +0 -3
  339. package/dist/cli/main-dfreez27.js +0 -10
  340. package/dist/cli/main-f7rw7des.js +0 -3
  341. package/dist/cli/main-ggcn7rd7.js +0 -5
  342. package/dist/cli/main-gzkmycnv.js +0 -3
  343. package/dist/cli/main-hq51jg8v.js +0 -18
  344. package/dist/cli/main-jft389w9.js +0 -8
  345. package/dist/cli/main-k1eqkg83.js +0 -3
  346. package/dist/cli/main-k2y8a2aw.js +0 -9
  347. package/dist/cli/main-kcpbykxz.js +0 -4
  348. package/dist/cli/main-kd488vje.js +0 -22
  349. package/dist/cli/main-kh32yvgk.js +0 -5
  350. package/dist/cli/main-kqxnqjnv.js +0 -25
  351. package/dist/cli/main-kyn0xnsg.js +0 -3
  352. package/dist/cli/main-m1kk6fp5.js +0 -21
  353. package/dist/cli/main-mv40pcr2.js +0 -4
  354. package/dist/cli/main-n0t3973w.js +0 -3
  355. package/dist/cli/main-nqveez48.js +0 -4
  356. package/dist/cli/main-pknhvrmj.js +0 -3
  357. package/dist/cli/main-pn1w7a7j.js +0 -3
  358. package/dist/cli/main-prxxs70n.js +0 -4
  359. package/dist/cli/main-q3vsesf9.js +0 -3
  360. package/dist/cli/main-qsevpgsv.js +0 -3
  361. package/dist/cli/main-rdgdw24b.js +0 -25
  362. package/dist/cli/main-rfth4tbm.js +0 -16
  363. package/dist/cli/main-rg0wn0xf.js +0 -5
  364. package/dist/cli/main-sdmxhtv8.js +0 -4
  365. package/dist/cli/main-skbp13js.js +0 -18
  366. package/dist/cli/main-t4xnd213.js +0 -7
  367. package/dist/cli/main-vqak588n.js +0 -4
  368. package/dist/cli/main-w2n1303f.js +0 -9
  369. package/dist/cli/main-wbrdspr2.js +0 -5
  370. package/dist/cli/main-wsrg79c1.js +0 -7
  371. package/dist/cli/main-x4r0fne4.js +0 -5
  372. package/dist/cli/main-xea2f3tn.js +0 -6
  373. package/dist/cli/main-xg704a3c.js +0 -3
  374. package/dist/cli/main-xvnrabfp.js +0 -16
  375. package/dist/cli/main-xy53xf0r.js +0 -4
  376. package/dist/cli/main-y1fqy60y.js +0 -3
  377. package/dist/cli/main-yn8cd281.js +0 -34
  378. package/dist/cli/main-yr0ksc0h.js +0 -4
  379. package/dist/cli/main-z2ex2vyf.js +0 -4
  380. package/dist/cli/main-z3aayzvq.js +0 -3
  381. package/dist/cli/main-zaqh35jg.js +0 -3
  382. package/dist/cli/main-zc2e8e46.js +0 -4
  383. package/dist/cli/main-zzrfw6cf.js +0 -13
  384. package/dist/cli/main.js +0 -280
  385. package/dist/cli/market-cmd-e14kmx9n.js +0 -5
  386. package/dist/cli/mcp-login-wq7ktdek.js +0 -2
  387. package/dist/cli/mcp-market-cmd-9mg3jecy.js +0 -2
  388. package/dist/cli/notify-b7qc0cjb.js +0 -2
  389. package/dist/cli/oauth-z8whcgfx.js +0 -2
  390. package/dist/cli/output-b3ewj3ps.js +0 -16
  391. package/dist/cli/profiles-6mr5he5e.js +0 -2
  392. package/dist/cli/provider-config-g7j42q8x.js +0 -2
  393. package/dist/cli/provider-jr1y8vvm.js +0 -2
  394. package/dist/cli/registry-s8yk86g0.js +0 -2
  395. package/dist/cli/registry-t6p8d4mn.js +0 -2
  396. package/dist/cli/repl-bajwe1mh.js +0 -11
  397. package/dist/cli/resume-rwn9nz7y.js +0 -2
  398. package/dist/cli/run-flags-nah7ndpt.js +0 -2
  399. package/dist/cli/runtime-n7gafzhb.js +0 -2
  400. package/dist/cli/sandbox-config-emdy18x4.js +0 -2
  401. package/dist/cli/server-b0nvs2bn.js +0 -5
  402. package/dist/cli/session-arg-y75wd4kj.js +0 -2
  403. package/dist/cli/session-j62evmjq.js +0 -2
  404. package/dist/cli/sessions-cmd-tsnwz0ns.js +0 -7
  405. package/dist/cli/settings-df10wfez.js +0 -2
  406. package/dist/cli/setup-jzvv72fg.js +0 -2
  407. package/dist/cli/sextant-smoke-37m81ke6.js +0 -5
  408. package/dist/cli/skills-cmd-gjxnxnhx.js +0 -2
  409. package/dist/cli/smoke-p7748apt.js +0 -8
  410. package/dist/cli/start-chat-s4st3mm0.js +0 -12
  411. package/dist/cli/stream-gmeyewds.js +0 -2
  412. package/dist/cli/task-gh0kkp3n.js +0 -2
  413. package/dist/cli/tasks-z1kfpe8e.js +0 -2
  414. package/dist/cli/thinking-0eqkrz6t.js +0 -2
  415. package/dist/cli/todo-5brcrt9m.js +0 -2
  416. package/dist/cli/tools-7pzm0vj9.js +0 -2
  417. package/dist/cli/tools-s635p6s8.js +0 -2
  418. package/dist/cli/trust-cmd-cjav8zgm.js +0 -2
  419. package/dist/cli/update-check-pt31bm2f.js +0 -2
  420. package/dist/cli/update-cmd-tk131s9t.js +0 -2
  421. package/dist/cli/voice-56nabd8d.js +0 -2
  422. package/dist/cli/webfetch-xd8q596m.js +0 -2
  423. package/dist/cli/websearch-5hkf98k1.js +0 -2
  424. package/dist/cli/workflow-cmd-cy3cvzjp.js +0 -4
  425. package/dist/cli/workspace-q10g5z3e.js +0 -2
  426. package/dist/lib/index.js +0 -62
  427. package/dist/lib/models-index.json +0 -1
  428. package/dist/lib/plugins.js +0 -55
  429. package/dist/lib/providers.js +0 -17
  430. package/dist/lib/public-api.js +0 -20
  431. package/dist/lib/sdk.js +0 -360
  432. /package/{dist/cli → src/providers}/models-index.json +0 -0
@@ -0,0 +1,278 @@
1
+ /** Port #38: session export — markdown transcript or raw JSONL copy, LOCAL only.
2
+ * Pattern: opencode cli/cmd/export.ts @ ebece6e (MIT) — session resolution → serialize;
3
+ * their export emits the raw session data verbatim to stdout, which maps to --json here
4
+ * (verbatim byte copy of entries.jsonl, the whole tree incl. abandoned branches). The
5
+ * cloud-share half of opencode's feature (share/session.ts) is explicitly deferred
6
+ * (PORTS.md wave-3 ledger: "export stays local"), and the markdown layout is rovecode-native:
7
+ * the snapshot has no session→markdown renderer at ebece6e.
8
+ *
9
+ * Markdown walks the ACTIVE path only (store.path()), mirroring TUI replayHistory:
10
+ * user/assistant text, tool cards (args one-liner, bounded output, ok/ERROR badge),
11
+ * mode switches as "mode → plan" lines (wave-2 replay convention, never raw
12
+ * <mode_notice> XML), compaction markers, and a costs section over per-origin usage
13
+ * totals + buildCostNote. Output is deterministic: every timestamp comes from the
14
+ * entries themselves (ISO UTC), there is no "generated at" wall-clock line, and the
15
+ * catalog is the offline snapshot (lookup() never fetches). */
16
+
17
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
18
+ import { join, isAbsolute } from "node:path";
19
+ import { SessionStore, listSessions, type Entry } from "../core/session.ts";
20
+ import { modeSwitchOf } from "../core/modes.ts";
21
+ import { ModelCatalog } from "../providers/catalog.ts";
22
+ import { buildCostNote } from "../tui/cost.ts";
23
+ import { describeImage } from "../core/images.ts";
24
+ import type { ImagePart, Message, ToolCallPart, ToolResultPart } from "../core/types.ts";
25
+
26
+ /** Tool output cap (chars) per card. Clipped output gets an explicit marker line. */
27
+ export const TOOL_OUTPUT_CAP = 2000;
28
+ /** One-line args summary cap — same 120-char clip the TUI uses for tool cards. */
29
+ const ARGS_CAP = 120;
30
+ /** CLI usage line — thrown on a missing id or a dangling --out; cmdExport turns it into exit 2, the
31
+ * usage/startup class README documents, while a real export failure stays exit 1. */
32
+ const USAGE = "usage: rovecode export <session-id|prefix> [--json] [--out <path>] [--force]";
33
+
34
+ export interface ExportOptions {
35
+ /** raw JSONL copy (verbatim bytes) instead of markdown */
36
+ json?: boolean;
37
+ /** target path; default ./<sessionId-short>.(md|jsonl) under cwd */
38
+ out?: string;
39
+ /** overwrite an existing target file */
40
+ force?: boolean;
41
+ /** base dir for relative/default output paths; default process.cwd() */
42
+ cwd?: string;
43
+ }
44
+
45
+ export interface ExportResult { path: string; format: "markdown" | "jsonl" }
46
+
47
+ // ---------- session-prefix resolution (mirrors TUI /resume: app.ts cmdSessions) ----------
48
+
49
+ /** Exact id wins outright; a prefix must match exactly ONE session; an ambiguous
50
+ * prefix lists candidates instead of silently picking one (same rule as /resume). */
51
+ export function resolveSessionId(sessionsRoot: string, idOrPrefix: string): string {
52
+ const all = listSessions(sessionsRoot);
53
+ const exact = all.find((s) => s.id === idOrPrefix);
54
+ const matches = exact ? [exact] : all.filter((s) => s.id.startsWith(idOrPrefix));
55
+ if (matches.length === 1) return matches[0]!.id;
56
+ if (matches.length > 1) {
57
+ throw new Error(
58
+ `"${idOrPrefix}" matches ${matches.length} sessions: ` +
59
+ `${matches.slice(0, 4).map((s) => s.id.slice(0, 8)).join(", ")}${matches.length > 4 ? ", …" : ""} — be more specific`,
60
+ );
61
+ }
62
+ throw new Error(`no session matching "${idOrPrefix}"`);
63
+ }
64
+
65
+ // ---------- markdown rendering ----------
66
+
67
+ function isMessage(e: Entry): e is Message { return "role" in e; }
68
+
69
+ /** Longest backtick run in s (0 when none) — a CommonMark span/fence must be longer. */
70
+ function tickRun(s: string): number {
71
+ let run = 0;
72
+ for (const m of s.matchAll(/`+/g)) run = Math.max(run, m[0].length);
73
+ return run;
74
+ }
75
+
76
+ /** Inline-code span that survives backticks in the content (args may contain them):
77
+ * delimiter = longest run + 1 (a fixed `` closes at the first inner double tick),
78
+ * space-padded so a leading/trailing tick stays inside the span. */
79
+ function inlineCode(s: string): string {
80
+ const run = tickRun(s);
81
+ if (run === 0) return `\`${s}\``;
82
+ const tick = "`".repeat(run + 1);
83
+ return `${tick} ${s} ${tick}`;
84
+ }
85
+
86
+ /** Fenced block whose fence is longer than any backtick run in the content. */
87
+ function fenced(content: string): string {
88
+ const fence = "`".repeat(Math.max(3, tickRun(content) + 1));
89
+ return `${fence}\n${content}\n${fence}`;
90
+ }
91
+
92
+ /** One tool card: name + badge header, one-line args, bounded output block. */
93
+ function toolCard(tool: string, args: unknown, res: ToolResultPart | undefined): string {
94
+ const badge = res === undefined ? "no result recorded" : res.ok ? "ok" : "ERROR";
95
+ const argsLine = JSON.stringify(args) ?? "undefined";
96
+ const argsShown = argsLine.length > ARGS_CAP ? argsLine.slice(0, ARGS_CAP) + "…" : argsLine;
97
+ const parts = [`### tool: ${tool} — ${badge}`, `args: ${inlineCode(argsShown)}`];
98
+ if (res !== undefined) {
99
+ if (res.output.length === 0) parts.push("*(no output)*");
100
+ else {
101
+ const clipped = res.output.length > TOOL_OUTPUT_CAP;
102
+ parts.push(fenced(clipped ? res.output.slice(0, TOOL_OUTPUT_CAP) : res.output));
103
+ if (clipped) parts.push(`*+${res.output.length - TOOL_OUTPUT_CAP} chars clipped (cap ${TOOL_OUTPUT_CAP})*`);
104
+ }
105
+ }
106
+ return parts.join("\n\n");
107
+ }
108
+
109
+ function textOf(m: Message): string {
110
+ return m.parts.filter((p) => p.kind === "text").map((p) => (p as { text: string }).text).join("");
111
+ }
112
+
113
+ /** Render the active path as markdown. Exported for tests; pure over the entries. */
114
+ export function renderSessionMarkdown(entries: readonly Entry[], sessionId: string, catalog: ModelCatalog): string {
115
+ const messages = entries.filter(isMessage);
116
+ // pair tool_call parts with their results up front so a card renders where the
117
+ // assistant issued the call; results without a visible call render as orphan cards
118
+ const results = new Map<string, ToolResultPart>();
119
+ for (const m of messages) {
120
+ if (m.role !== "tool") continue;
121
+ for (const p of m.parts) if (p.kind === "tool_result" && !results.has(p.callId)) results.set(p.callId, p);
122
+ }
123
+ const consumed = new Set<string>();
124
+
125
+ // title block: id, date range, model origins (first-appearance order)
126
+ const stamps = entries.map((e) => e.createdAt).filter((t) => typeof t === "number");
127
+ const range = stamps.length > 0
128
+ ? `${new Date(Math.min(...stamps)).toISOString()} → ${new Date(Math.max(...stamps)).toISOString()}`
129
+ : "(empty)";
130
+ const origins: string[] = [];
131
+ for (const m of messages) {
132
+ if (!m.origin) continue;
133
+ const key = `${m.origin.provider}/${m.origin.model}`;
134
+ if (!origins.includes(key)) origins.push(key);
135
+ }
136
+ const blocks: string[] = [
137
+ `# rovecode session ${sessionId.slice(0, 8)}`,
138
+ [`- id: ${inlineCode(sessionId)}`, `- range: ${range}`, `- models: ${origins.length > 0 ? origins.join(", ") : "(none)"}`].join("\n"),
139
+ ];
140
+
141
+ for (const e of entries) {
142
+ if (!isMessage(e)) {
143
+ // event entries: compaction becomes a marker (TUI wording, app.ts); others skipped
144
+ if (e.event.type === "compaction") {
145
+ blocks.push(`> compacted (${e.event.strategy}): ${e.event.tokensBefore} → ${e.event.tokensAfter} tokens`);
146
+ }
147
+ continue;
148
+ }
149
+ const sw = modeSwitchOf(e);
150
+ if (sw) { blocks.push(`> mode → ${sw.to}`); continue; } // replay convention, never the raw XML
151
+ const text = textOf(e);
152
+ if (e.role === "user") {
153
+ // port #34: image parts render as one chip line each under the text (name, WxH, size), the
154
+ // same describeImage text the TUI notes use; the bytes stay in the session's attachments
155
+ // dir (header) so no image link that would dangle next to the export is emitted
156
+ const chips = e.parts.filter((p): p is ImagePart => p.kind === "image").map((p) => `[image: ${describeImage(p)}]`);
157
+ if (text || chips.length > 0) blocks.push("## User", ...(text ? [text] : []), ...chips);
158
+ } else if (e.role === "assistant") {
159
+ blocks.push("## Assistant");
160
+ if (text) blocks.push(text);
161
+ for (const p of e.parts) {
162
+ if (p.kind !== "tool_call") continue;
163
+ const call = p as ToolCallPart;
164
+ blocks.push(toolCard(call.tool, call.args, results.get(call.id)));
165
+ consumed.add(call.id);
166
+ }
167
+ } else if (e.role === "tool") {
168
+ for (const p of e.parts) {
169
+ if (p.kind === "tool_result" && !consumed.has(p.callId)) {
170
+ blocks.push(toolCard("(unknown)", undefined, p));
171
+ consumed.add(p.callId);
172
+ }
173
+ }
174
+ } else if (text) {
175
+ // plain system note (e.g. a compaction summary message)
176
+ blocks.push(text.split("\n").map((l) => `> ${l}`).join("\n"));
177
+ }
178
+ }
179
+ if (messages.length === 0) blocks.push("*(no entries)*");
180
+
181
+ // costs: per-origin usage totals, then the /cost note (existing helpers, deterministic
182
+ // against the offline catalog; "current" = the last message origin on the path)
183
+ const byOrigin = new Map<string, { input: number; output: number; cacheRead: number; cacheWrite: number; msgs: number }>();
184
+ for (const m of messages) {
185
+ if (!m.usage) continue;
186
+ const key = m.origin ? `${m.origin.provider}/${m.origin.model}` : "(no origin)";
187
+ const row = byOrigin.get(key) ?? { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, msgs: 0 };
188
+ row.input += m.usage.input; row.output += m.usage.output;
189
+ row.cacheRead += m.usage.cacheRead ?? 0; row.cacheWrite += m.usage.cacheWrite ?? 0;
190
+ row.msgs += 1;
191
+ byOrigin.set(key, row);
192
+ }
193
+ blocks.push("## Costs");
194
+ if (byOrigin.size > 0) {
195
+ blocks.push([
196
+ "| model | input | output | cache read | cache write | messages |",
197
+ "| --- | ---: | ---: | ---: | ---: | ---: |",
198
+ ...[...byOrigin.entries()].map(([k, r]) => `| ${k} | ${r.input} | ${r.output} | ${r.cacheRead} | ${r.cacheWrite} | ${r.msgs} |`),
199
+ ].join("\n"));
200
+ }
201
+ const current = [...messages].reverse().find((m) => m.origin)?.origin ?? { provider: "unknown", model: "unknown" };
202
+ blocks.push(buildCostNote(messages, catalog, current).split("\n").map((l) => `- ${l}`).join("\n"));
203
+
204
+ return blocks.join("\n\n") + "\n";
205
+ }
206
+
207
+ // ---------- export entrypoint ----------
208
+
209
+ function targetPath(out: string | undefined, id: string, format: "markdown" | "jsonl", cwd: string): string {
210
+ const fallback = `${id.slice(0, 8)}.${format === "jsonl" ? "jsonl" : "md"}`;
211
+ const p = out ?? fallback;
212
+ return isAbsolute(p) ? p : join(cwd, p);
213
+ }
214
+
215
+ /** Export a session (full id or unique prefix) to markdown or a raw JSONL copy.
216
+ * --json copies entries.jsonl BYTE-VERBATIM (whole tree, every branch); markdown
217
+ * renders the active path only. Never overwrites an existing file without force. */
218
+ export function exportSession(sessionsRoot: string, idOrPrefix: string, opts: ExportOptions = {}): ExportResult {
219
+ if (!idOrPrefix) throw new Error(USAGE);
220
+ const id = resolveSessionId(sessionsRoot, idOrPrefix);
221
+ const format: ExportResult["format"] = opts.json ? "jsonl" : "markdown";
222
+ const target = targetPath(opts.out, id, format, opts.cwd ?? process.cwd());
223
+ if (existsSync(target) && !opts.force) throw new Error(`refusing to overwrite ${target} — pass --force`);
224
+ if (opts.json) {
225
+ const src = join(sessionsRoot, id, "entries.jsonl");
226
+ if (!existsSync(src)) throw new Error(`session ${id.slice(0, 8)} has no entries.jsonl to copy`);
227
+ writeFileSync(target, readFileSync(src)); // Buffer in → Buffer out: verbatim bytes
228
+ } else {
229
+ const store = new SessionStore(sessionsRoot, id);
230
+ writeFileSync(target, renderSessionMarkdown(store.path(), id, new ModelCatalog()));
231
+ }
232
+ return { path: target, format };
233
+ }
234
+
235
+ // ---------- CLI glue (rovecode export …) ----------
236
+
237
+ export interface ExportCliArgs { idOrPrefix?: string; json: boolean; out?: string; force: boolean }
238
+
239
+ /** Parse `rovecode export` argv. Flags may sit anywhere — parseCli accepts `rovecode --json
240
+ * export <id>` for every subcommand — so the whole argv after the script path is
241
+ * scanned and the single `export` command token skipped. parseCli strips flags but
242
+ * leaves flag VALUES in rest, so --out is consumed here (same reason main.ts hand-
243
+ * parses --resume: dispatch flags are boolean-only); a missing or flag-shaped --out
244
+ * value is a usage error, never a silent default. First remaining non-flag = the id. */
245
+ export function parseExportArgs(argv: readonly string[]): ExportCliArgs {
246
+ const args = argv.slice(2);
247
+ const parsed: ExportCliArgs = { json: false, force: false };
248
+ let cmdSeen = false;
249
+ for (let i = 0; i < args.length; i++) {
250
+ const a = args[i]!;
251
+ if (a === "--json") parsed.json = true;
252
+ else if (a === "--force") parsed.force = true;
253
+ else if (a === "--out") {
254
+ const v = args[++i];
255
+ if (v === undefined || v.startsWith("-")) throw new Error(`--out needs a path — ${USAGE}`);
256
+ parsed.out = v;
257
+ } else if (!a.startsWith("-")) { // other flags (--yolo, --plain, …) belong to dispatch
258
+ if (!cmdSeen && a === "export") cmdSeen = true; // the command token itself
259
+ else if (parsed.idOrPrefix === undefined) parsed.idOrPrefix = a;
260
+ }
261
+ }
262
+ return parsed;
263
+ }
264
+
265
+ /** `rovecode export <session> [--json] [--out <path>] [--force]` — errors exit 1. */
266
+ export function cmdExport(argv: readonly string[]): void {
267
+ try {
268
+ const a = parseExportArgs(argv); // inside: a dangling --out is a usage error too
269
+ const res = exportSession(join(process.cwd(), ".rovecode", "sessions"), a.idOrPrefix ?? "", a);
270
+ console.log(`exported ${res.format} → ${res.path}`);
271
+ } catch (e) {
272
+ const msg = e instanceof Error ? e.message : String(e);
273
+ console.error(`error: ${msg}`);
274
+ // "you typed it wrong" and "it did not work" are different answers to a script: 2 is the usage class
275
+ // (README: 0 done · 1 error/budget · 2 usage/startup), and every other command already answers that way
276
+ process.exit(msg.startsWith("usage:") ? 2 : 1);
277
+ }
278
+ }
@@ -0,0 +1,240 @@
1
+ /** `rovecode help [topic]` — short and grouped by default; `env`, `advanced` and `all` hold the full
2
+ * reference. Pure text so it is unit-testable (main.ts dispatches on import). Wording follows
3
+ * core/voice.ts: plain sentences, the two permission modes by their screen names. */
4
+
5
+ import { MODE_ASK, MODE_AUTO } from "../core/voice.ts";
6
+
7
+ export const HELP_TOPICS = ["", "env", "advanced", "all"] as const;
8
+ export type HelpTopic = (typeof HELP_TOPICS)[number];
9
+
10
+ const SHORT = `rovecode — your coding agent
11
+
12
+ start here
13
+ 1 rovecode connect connect a model (about a minute)
14
+ 2 rovecode open the cockpit and describe what you need
15
+ 3 rovecode "fix the failing test" run one task, then exit
16
+
17
+ tip Start with a sentence. Rovecode reads first and asks before changing anything.
18
+
19
+ everyday
20
+ rovecode model choose a model
21
+ rovecode doctor diagnose setup problems
22
+ rovecode --resume <id> continue a session
23
+ rovecode run "<prompt>" --yolo run without approval prompts (${MODE_AUTO})
24
+ rovecode market search <q> find skills, plugins and MCP servers
25
+
26
+ safety
27
+ ${MODE_ASK} (default) read freely; ask before writes, shell commands and subagents
28
+ accept edits (--accept-edits) write in this folder; still ask for shell, network and outside writes
29
+ auto (--yolo, ROVECODE_YOLO=1) never ask; deny rules still apply
30
+ plan mode (/plan in the TUI) inspect and plan without changing files
31
+
32
+ more
33
+ rovecode help advanced every command and option
34
+ rovecode help env every ROVECODE_* setting
35
+ rovecode help all both reference pages`;
36
+
37
+ const ADVANCED = `advanced — the full command reference
38
+ rovecode interactive TUI chat — the sextant surface (files · code · messages · plan · usage · pet)
39
+ on a colour TTY of at least 100x30 (truecolor, or 256 colours through the
40
+ quantizer), else the classic pi-tui chat;
41
+ --classic forces the classic chat · --pet <name> names the pet · --plain = readline REPL
42
+ --no-intro (or ROVECODE_INTRO=0) skips the ~0.9s opening animation
43
+ rovecode chat · rovecode repl the same as bare rovecode (repl still needs --plain for the readline REPL)
44
+ rovecode --help | -h this help (only with no command in front of it) · rovecode --version prints the
45
+ version to stdout and the update check’s answer to stderr
46
+ rovecode --resume <id> open the TUI resuming a session (full id or unique prefix)
47
+ rovecode --continue reopen the newest session that holds something (also: --resume with no id);
48
+ nothing to continue from → a fresh session
49
+ rovecode "prompt" one-shot task (same as run; a lone path-shaped word — ./x, x.ts, an existing
50
+ name — is confirmed on a TTY and refused with exit 2 off one: use "rovecode run" to send it)
51
+ rovecode setup connect a model step by step (TTY only; piped stdin prints the recipe and exits 2)
52
+ rovecode connect the same wizard when given no arguments
53
+ rovecode connect <id> [<baseUrl>] [--model <id>] [--key | --key-stdin | --key-env NAME | --no-key]
54
+ [--protocol openai|anthropic] [--project] [--no-test]
55
+ one line: register the endpoint, store the key, pick the model, one tiny real
56
+ call, persist the default. A key is never a flag value (shell history, ps):
57
+ --key prompts hidden, --key-stdin reads one piped line (CI), --key-env names
58
+ an env var, --no-key marks a local server.
59
+ exit 0 connected · 1 the test call failed (config still written) · 2 usage
60
+ rovecode smoke-tui render check: full pipeline into an 80x24 terminal emulator (dev-only)
61
+ rovecode smoke-tui --sextant render check: the sextant surface at 160x44 through the full pipeline (no emulator needed)
62
+ rovecode run "<prompt>" run an agent task (--yolo = ${MODE_AUTO}; with no provider configured this is a
63
+ startup error, exit 2 — ROVECODE_MOCK=1 asks for the scripted mock on purpose)
64
+ "/name args" expands a custom command (.rovecode/commands/<name>.md, else ~/.rovecode/commands)
65
+ the way the TUI does; an unknown /name is sent verbatim; model:/mode: frontmatter is
66
+ TUI-only and not applied headlessly
67
+ piped stdin is appended to the prompt as a fenced block — git diff | rovecode run "review this"
68
+ (never read from a terminal; --no-stdin ignores it; an open pipe that sends nothing
69
+ for 3 s is skipped with a note; capped at 1 MB)
70
+ --max-turns N · --max-seconds S|off ceilings on one run; a hit ends it cleanly with status
71
+ "budget" (exit 1) and the work so far, instead of an external kill. Headless runs
72
+ default to a 20-minute wall clock; --max-seconds off removes it
73
+ --max-cost D|off a spend ceiling in dollars for one run, priced from each turn's usage as it lands
74
+ (the catalog's rates for the model that served it); the same clean "budget" end.
75
+ A turn the catalog cannot price adds nothing and is counted in the summary
76
+ --output <text|json|ndjson> text (default): progress + the final answer on stdout
77
+ json: exactly ONE result object on stdout {status, summary, sessionId,
78
+ model:{provider,model}, origin (served model|null), usage:{input,output,cacheRead,
79
+ cacheWrite}, costUsd (null when unpriced), toolCalls:[{tool,ok,ms?}], durationMs, exitCode}
80
+ ndjson: one JSON line per RunEvent, then a final {type:"result"} line
81
+ json/ndjson: stdout carries only JSON, progress goes to stderr
82
+ exit codes: 0 done · 1 error/budget · 2 usage/startup error · 130 aborted (Ctrl-C)
83
+ exit 2 = usage/startup error (bad --output value, sandbox misconfig or unavailable rung):
84
+ one stderr line, nothing on stdout; --output=<mode> is accepted as well
85
+ rovecode bench run cross-harness micro-benchmarks (edits, sessions)
86
+ rovecode gauntlet run the adversarial evaluation suite (offline, scripted model)
87
+ rovecode gauntlet --live the gauntlet's tasks minus loop-guard (9) against the configured REAL model through
88
+ the real prompt — --model <provider/model> and --effort pick; compare pass/calls/tokens
89
+ rovecode tools list registered tools
90
+ rovecode plugin list plugins in ~/.rovecode/plugins and .rovecode/plugins with status (active · disabled · untrusted · broken)
91
+ rovecode plugin add <folder|git-url> [--project] [--force] install a plugin folder (tools, hooks, commands, skills, MCP in one manifest)
92
+ rovecode plugin trust <name> approve a PROJECT plugin's current files on this machine (show <name> lists them first)
93
+ rovecode plugin remove|enable|disable|untrust|show <name> (docs/plugins.md; restart to load — read once per process, like hooks)
94
+ rovecode mcp search [query] MCP servers to install: the curated shelf, then the official registry (cached a day)
95
+ rovecode mcp info <name> publisher, version, the exact command or URL, the keys it asks for
96
+ rovecode mcp add <name> [--project] [--pick N] [--as <name>] [--yes] [--force] show the plan, ask for keys
97
+ masked, write ~/.rovecode/mcp.json (or .rovecode/mcp.json); --as renames it, --force replaces an entry
98
+ rovecode mcp remove <name> [--project] · rovecode mcp list (docs/mcp-market.md; /mcp does the same inside the TUI)
99
+ rovecode mcp show this repo's .rovecode/mcp.json + .mcp.json: exact commands/URLs, env names, trusted or not
100
+ rovecode mcp trust [--yes] · rovecode mcp untrust approve those files as they are now, or withdraw that
101
+ approval — until trusted nothing in them loads; your own add --project is trusted as you approve it
102
+ rovecode market search [query] [--kind mcp|skill|plugin] one shelf over MCP servers, skills and plugins
103
+ rovecode market info <id> publisher, licence, version, exactly what an install would write
104
+ rovecode market docs <id> the item's own documentation, as the catalog carries it — no network
105
+ rovecode market install <id|kind:id|git-url|npm-pkg> [--project] [--ref <branch|tag|commit>] [--yes]
106
+ plan first, write only after you agree
107
+ rovecode market list|remove|update|sources what is installed, what is behind, where each shelf came from
108
+ rovecode market verify [id] re-hash what is installed and say what has changed since
109
+ rovecode market validate <path|url> [--kind skill|plugin] check a catalog before anyone trusts it
110
+ (docs/market.md; /market does the same inside the TUI; every subcommand takes --json)
111
+ rovecode doctor [--json] [--no-connect] one pass over the setup: home (and a legacy ~/.cumulus), the default
112
+ provider and where its key comes from (names, never values), the permission level and
113
+ which rung set it, git/node/npm/npx/uvx on PATH with what each absence costs HERE,
114
+ every configured MCP server (loads? skipped for a placeholder or an unset variable?
115
+ untrusted file? connects?), the shadow checkpoints' size — and a list of what it did
116
+ NOT check. exit 0 nothing broken · 1 something to fix · a missing provider is a note
117
+ rovecode context [session] [--json] what fills the window, item by item, and how far our estimate is from
118
+ the provider's own count of the same prompt (cache reads included — they are the prompt too)
119
+ (--exact asks Anthropic to count it for real; --no-runtime skips the system prompt and tool schemas)
120
+ rovecode auth set <provider> [--key <name>] store an API key (prompts on stdin; ~/.rovecode/credentials.json)
121
+ rovecode auth list stored providers + key names (values redacted)
122
+ rovecode auth remove <provider> delete a stored credential
123
+ rovecode login [--api <url>] link this machine to a rovecode account: prints a code to approve at
124
+ <url>/cli-auth, then stores the issued token in ~/.rovecode/account.json
125
+ (--token rc_live_… links a hand-pasted key instead; --json for scripts)
126
+ rovecode account [--json] the linked account, its API base and when it was linked
127
+ rovecode logout unlink: remove ~/.rovecode/account.json
128
+ rovecode provider list [--all] providers with a key + every providers.json entry, and the default provider/model
129
+ rovecode provider add <id> <baseUrl> [--protocol openai|anthropic] [--key-env NAME] [--model <id>] [--no-key]
130
+ [--project | --user | --scope user|project] [--key]
131
+ register any OpenAI-compatible or Anthropic endpoint in ~/.rovecode/providers.json
132
+ (--project: ./.rovecode/providers.json); --key prompts for the secret (never echoed);
133
+ running TUIs/servers pick the change up live — no restart
134
+ rovecode provider remove <id> delete a providers.json entry (built-ins: rovecode auth remove <id> drops the key)
135
+ rovecode provider test <id> [model] one tiny real call — proves url + key + model together
136
+ rovecode model list [provider] model ids (providers.json "models" or the endpoint's /models); * = current default
137
+ rovecode models [provider] alias for model list
138
+ rovecode model no arguments on a terminal: every configured provider's models in one
139
+ numbered menu, the current one first; a pipe gets the usage line instead
140
+ rovecode model use <provider/model> [--project] persist the default (in the TUI: /model <provider/model> --save)
141
+ rovecode model show [provider/model] the model, its protocol, and the exact thinking field each /effort
142
+ level puts on the wire (docs/thinking.md)
143
+ rovecode trace <session-id> the session's messages, one line each (role · first 120 chars · tool-call count)
144
+ rovecode export <session> write a session as markdown (--json: raw JSONL copy; --out <path>; --force)
145
+ rovecode eval alias for gauntlet
146
+ rovecode acp Agent Client Protocol v1 endpoint over stdio (Zed/JetBrains)
147
+ rovecode serve headless HTTP server (ROVECODE_PORT, default 4100; loopback-only)`;
148
+
149
+ const ENV = `env — every ROVECODE_* setting
150
+ ROVECODE_BASE_URL any OpenAI-compatible or Anthropic endpoint
151
+ ROVECODE_API_KEY API key (falls back to OPENAI_API_KEY)
152
+ ROVECODE_MODEL model id (e.g. zai-org/glm-5.3)
153
+ ROVECODE_MODEL_<ROLE> role fallback chain, comma-separated provider/model list; on 429/5xx
154
+ the next candidate serves. Roles: DEFAULT SMOL PLAN COMMIT TASK
155
+ (e.g. ROVECODE_MODEL_DEFAULT=kaesra/zai-org/glm-5.3-flash,openai/gpt-4o-mini)
156
+ ROVECODE_STREAM streaming is on by default (both protocols); off|json|0|false|none use the one-shot JSON
157
+ adapters; sse forces the raw SSE adapter, without the tool-call middleware, for one-shot runs
158
+ ROVECODE_EFFORT auto|off|low|medium|high thinking before the answer (default auto: the provider's
159
+ own default stands). Anthropic gets output_config.effort or a thinking budget,
160
+ whichever the model takes (learned from its own 400, then remembered); OpenAI gets
161
+ reasoning_effort. Thinking is billed as output and delays the first word.
162
+ ROVECODE_PROFILE model profile: off, or an id (glm-5.3 | glm-5.3-plain) whose PROMPT section is forced onto
163
+ every model (request fields always follow the model id). Unset = by model id: GLM-5.3 / -Flash
164
+ get the Claude Sonnet 5 persona + the working agreement appended to the system prompt
165
+ (glm-5.3-plain = agreement only) plus, on OpenAI-compatible providers, Z.ai's
166
+ request fields (thinking always on, reasoning_effort low|high|max — off leaves the endpoint's
167
+ max, medium rounds up to high, high means max — and tool_stream when streaming). The text
168
+ comes from .rovecode/profiles/<id>.md (project) or ~/.rovecode/profiles/<id>.md when present.
169
+ ROVECODE_DESIGN off drops the interface-design section from the system prompt (for runs with no UI in
170
+ them). Otherwise every run carries it: propose three distinct directions before the first
171
+ UI in a project, let the human choose, record it with design_direction, then build to it.
172
+ The section prescribes NO palette, typeface or layout -- there is no default look, on
173
+ purpose -- and names the patterns to climb out of (amber accents, the reflex full-viewport
174
+ hero, Inter/Roboto/Poppins, hairlines round everything, all-square corners, everything
175
+ centred, violet gradients). The choice lives in .rovecode/design.json; design_audit counts
176
+ those patterns in the files you touched and checks them against it.
177
+ ROVECODE_PERMISSION ask|accept-edits|auto — the level this run starts at. Ladder, widest first:
178
+ a CLI flag, then this, then <cwd>/.rovecode/settings.json, then ~/.rovecode/settings.json,
179
+ then "ask". Write the files with /yolo --save or /accept-edits --save [--project].
180
+ ROVECODE_ACCEPT_EDITS=1 start in accept-edits (writes inside the workspace do not ask)
181
+ ROVECODE_YOLO=1 ${MODE_AUTO}: allow all tool actions
182
+ ROVECODE_TUI sextant | classic — force the TUI surface (sextant still needs a TTY; --classic wins)
183
+ ROVECODE_THEME sextant palette: night (default) | ember | contrast (/theme switches it live)
184
+ ROVECODE_PET=0 hide the sextant pet panel (rovecode); --pet <name> renames it
185
+ ROVECODE_SANDBOX executor rung for bash: direct (default) | wsl | docker; beats .rovecode/sandbox.json {"rung","dockerImage"}
186
+ ROVECODE_SANDBOX_IMAGE image for the docker rung (default debian:stable-slim; must contain bash)
187
+ ROVECODE_RETRY_MAX same-model retries after a 429/5xx/transport failure (default 3 = 4 attempts; 0 = off)
188
+ The wait is announced live, while it is happening, not in a summary after the run
189
+ ROVECODE_RETRY_BASE_MS cap of the FIRST backoff, ms (default 1000; full jitter; a Retry-After hint is a floor)
190
+ It doubles per attempt up to 20 s, and a server hint can raise the wait, never shorten it
191
+ ROVECODE_FIRST_BYTE_TIMEOUT_MS how long a provider may go without ANY response before the request
192
+ counts as failed and is retried (default 60000). Only the FIRST byte is on this clock:
193
+ once the model is talking, the body may take as long as it takes
194
+ ROVECODE_WEBFETCH_TIMEOUT_MS web_fetch request timeout in ms (default 30000)
195
+ ROVECODE_WEBFETCH_ALLOW_PRIVATE=1 let web_fetch reach loopback/private hosts (SSRF guard escape for local dev)
196
+ ROVECODE_COMPACTION history compaction strategy: head-summarize (default) | keep-window | provider-native
197
+ ROVECODE_TASKS_MAX concurrent background tasks (default 3; further task starts queue FIFO)
198
+ ROVECODE_OTEL_ENDPOINT OTLP/HTTP collector, e.g. http://host:4318 — one trace per run (run ⊃ turn ⊃ tool); unset = off
199
+ ROVECODE_OTEL_HEADERS extra OTLP headers as k=v,k2=v2 (e.g. authorization=Bearer …)
200
+ ROVECODE_REFLECTION=0 disable reflection nudges after failed edits; ROVECODE_REFLECTION_MAX caps them per run (default 2)
201
+ ROVECODE_PORT port for rovecode serve (default 4100; loopback-only)
202
+ ROVECODE_IMAGE_MAX_BYTES per-image cap in bytes for pasted and attached images (default 5 MB;
203
+ at most 8 images per message). Over it, the image is refused by name, not silently dropped.
204
+ ROVECODE_REPOMAP_TOKENS repo-map budget in tokens (default 1024); ROVECODE_NO_REPOMAP=1 drops the map entirely
205
+ ROVECODE_HOOK_TIMEOUT_MS per-hook-call budget in ms (default 5000); ROVECODE_NO_HOOKS=1 skips hook files
206
+ ROVECODE_PLUGIN_TIMEOUT_MS per-plugin import + tools() budget in ms (default 5000);
207
+ ROVECODE_NO_PLUGINS=1 skips plugin discovery
208
+ ROVECODE_NO_CHECKPOINTS=1 turn off the shadow-git checkpoints taken after mutating tools
209
+ ROVECODE_TOOL_MIDDLEWARE=1 force the text tool-call protocol (a prompt block + a parser) even for a model
210
+ the catalog says has native tool calling; ROVECODE_NO_TOOL_MIDDLEWARE=1 forces native only
211
+ ROVECODE_EVAL_CELL=1 register the persistent eval cell tool (a REPL that keeps state between calls)
212
+ ROVECODE_MAX_TURNS turn ceiling for one run, every surface (TUI included); a hit ends it with status
213
+ "budget" and exit 1
214
+ ROVECODE_MAX_SECONDS the same as a wall clock, or "off". Every surface honours it, but only
215
+ one-shot runs have a DEFAULT (1200 s) — the TUI has no clock unless this sets one
216
+ ROVECODE_MAX_COST the same in dollars for one run (--max-cost on a one-shot run), or "off"; no default
217
+ ROVECODE_FINISH_CHECK=0 turn off the once-per-run finish check: when the model stops right after a failed tool
218
+ call or an unanswered question, it is asked ONCE to finish or say what is left; the next
219
+ reply ends the run either way. "done · …" on run_end still names what was left
220
+ ROVECODE_VERIFY=1 turn ON the verify gate (off by default): a run that wrote files runs the project's configured
221
+ check before "done"; a failure goes back to the model once, then "done · check failed (…)" says
222
+ so. No check configured → nothing runs, run_end says "not verified". ROVECODE_VERIFY_TIMEOUT=<s> (120)
223
+ ROVECODE_HOME credentials + user-scope providers/commands dir (default ~/.rovecode)
224
+ providers: built in — kaesra openai anthropic deepseek groq openrouter ollama lmstudio
225
+ together mistral cerebras fireworks perplexity xai moondream vllm
226
+ plus anything in ~/.rovecode/providers.json or ./.rovecode/providers.json (rovecode provider add)
227
+ key: rovecode auth set <id>, or set <ID>_API_KEY — stored creds beat env;
228
+ default: providers.json "default" ("provider/model"), ROVECODE_MODEL overrides the model,
229
+ ROVECODE_BASE_URL/ROVECODE_API_KEY always wins`;
230
+
231
+ /** the text for a topic; an unknown topic gets the short page plus a one-line note */
232
+ export function helpText(topic = ""): string {
233
+ switch (topic) {
234
+ case "": return SHORT;
235
+ case "env": return ENV;
236
+ case "advanced": return ADVANCED;
237
+ case "all": return `${SHORT}\n\n${ADVANCED}\n\n${ENV}`;
238
+ default: return `${SHORT}\n\nno help topic "${topic}" — topics: env · advanced · all`;
239
+ }
240
+ }
@@ -0,0 +1,8 @@
1
+ /** Returns true when argv will start the interactive TUI (as opposed to a lightweight subcommand).
2
+ * Used by bin/rovecode.ts to decide whether to route through the pre-bundled dist/cli/main.js. */
3
+ import { parseCli } from "./dispatch.ts";
4
+
5
+ export function isTuiInvocation(argv: string[]): boolean {
6
+ const { cmd, plain } = parseCli(argv);
7
+ return (cmd === "" || cmd === "chat" || cmd === "repl") && !plain;
8
+ }