rovecode 0.4.0-beta.2 → 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 (428) hide show
  1. package/README.md +67 -69
  2. package/THIRD_PARTY_NOTICES.md +0 -44
  3. package/bin/rovecode.ts +21 -0
  4. package/package.json +16 -37
  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 -512
  270. package/bin/rovecode.js +0 -24
  271. package/dist/cli/app-dybnr56b.js +0 -2
  272. package/dist/cli/ask-user-p8hq4xgj.js +0 -2
  273. package/dist/cli/auth-login-ewpgw5sm.js +0 -2
  274. package/dist/cli/auth-m8p9grty.js +0 -2
  275. package/dist/cli/bench-xv3ypwev.js +0 -9
  276. package/dist/cli/catalog-737wb2s0.js +0 -2
  277. package/dist/cli/cli-arhg40m0.js +0 -2
  278. package/dist/cli/client-cf2pxx8q.js +0 -2
  279. package/dist/cli/commands-3p7e4xxs.js +0 -2
  280. package/dist/cli/connect-3q93d7cb.js +0 -2
  281. package/dist/cli/context-cmd-eqxmxhzq.js +0 -2
  282. package/dist/cli/context-report-hbw9zfes.js +0 -2
  283. package/dist/cli/count-remote-mby98cd0.js +0 -2
  284. package/dist/cli/design-122y0axd.js +0 -2
  285. package/dist/cli/dispatch-b4egzvvh.js +0 -2
  286. package/dist/cli/doctor-x4jkv72e.js +0 -3
  287. package/dist/cli/executor-ftvg6tsy.js +0 -2
  288. package/dist/cli/export-pdgdhkch.js +0 -2
  289. package/dist/cli/files-cez9a96p.js +0 -2
  290. package/dist/cli/gauntlet-r3xxaszc.js +0 -2
  291. package/dist/cli/gauntlet-runner-r515m7kk.js +0 -10
  292. package/dist/cli/gauntlet-wave3-bnkjk2v2.js +0 -5
  293. package/dist/cli/gauntlet-wave4-acs9s60q.js +0 -14
  294. package/dist/cli/hashline-ewg5hbe3.js +0 -2
  295. package/dist/cli/http-n0kehsk8.js +0 -5
  296. package/dist/cli/index-z5qt1s76.js +0 -2
  297. package/dist/cli/install-80mp63kx.js +0 -2
  298. package/dist/cli/loop-12twjcat.js +0 -2
  299. package/dist/cli/main-01pv9206.js +0 -4
  300. package/dist/cli/main-0jys2ccn.js +0 -3
  301. package/dist/cli/main-1ztz6fkj.js +0 -10
  302. package/dist/cli/main-23q7cmww.js +0 -9
  303. package/dist/cli/main-2rzbexn2.js +0 -3
  304. package/dist/cli/main-2wyax8k9.js +0 -9
  305. package/dist/cli/main-2yeveeve.js +0 -6
  306. package/dist/cli/main-2z3dek0b.js +0 -3
  307. package/dist/cli/main-2zgsknth.js +0 -3
  308. package/dist/cli/main-45ejth3a.js +0 -4
  309. package/dist/cli/main-45rn3trk.js +0 -22
  310. package/dist/cli/main-4p4e2w7x.js +0 -4
  311. package/dist/cli/main-4y0tnfpa.js +0 -16
  312. package/dist/cli/main-5py0rkmc.js +0 -4
  313. package/dist/cli/main-6dtqmbt6.js +0 -7
  314. package/dist/cli/main-6h9x282m.js +0 -4
  315. package/dist/cli/main-6vjeds42.js +0 -3
  316. package/dist/cli/main-78gq4bt9.js +0 -6
  317. package/dist/cli/main-7jd5vh3x.js +0 -4
  318. package/dist/cli/main-7kt6r53y.js +0 -4
  319. package/dist/cli/main-8c1tbazx.js +0 -58
  320. package/dist/cli/main-9a9rnh47.js +0 -19
  321. package/dist/cli/main-9ht36z12.js +0 -3
  322. package/dist/cli/main-a2yfvcy9.js +0 -7
  323. package/dist/cli/main-a3f51n0x.js +0 -5
  324. package/dist/cli/main-b8zq261k.js +0 -3
  325. package/dist/cli/main-bxtvnf6d.js +0 -13
  326. package/dist/cli/main-edxc3yzt.js +0 -4
  327. package/dist/cli/main-evgz4mp5.js +0 -21
  328. package/dist/cli/main-f33fc5je.js +0 -9
  329. package/dist/cli/main-fvnpq46y.js +0 -12
  330. package/dist/cli/main-gbbty4d4.js +0 -3
  331. package/dist/cli/main-gth53dnt.js +0 -25
  332. package/dist/cli/main-hqbz10aw.js +0 -9
  333. package/dist/cli/main-hrrvcfan.js +0 -38
  334. package/dist/cli/main-hzwtsb2m.js +0 -5
  335. package/dist/cli/main-j7ttv0sd.js +0 -34
  336. package/dist/cli/main-jak598k9.js +0 -5
  337. package/dist/cli/main-kba6zeyd.js +0 -6
  338. package/dist/cli/main-kwwsz6rq.js +0 -3
  339. package/dist/cli/main-m8vm17zq.js +0 -3
  340. package/dist/cli/main-mg4f96e1.js +0 -3
  341. package/dist/cli/main-mg9b20ac.js +0 -18
  342. package/dist/cli/main-mgb9ccnx.js +0 -3
  343. package/dist/cli/main-mjt2p7aj.js +0 -3
  344. package/dist/cli/main-n6qrdbmy.js +0 -3
  345. package/dist/cli/main-na7wse0x.js +0 -5
  346. package/dist/cli/main-nqveez48.js +0 -4
  347. package/dist/cli/main-ntqef02r.js +0 -10
  348. package/dist/cli/main-nvc3yjay.js +0 -136
  349. package/dist/cli/main-p0cfn6nr.js +0 -16
  350. package/dist/cli/main-qj2djy17.js +0 -19
  351. package/dist/cli/main-qsevpgsv.js +0 -3
  352. package/dist/cli/main-qvarybsp.js +0 -3
  353. package/dist/cli/main-rebtt91r.js +0 -5
  354. package/dist/cli/main-rpg7h8mb.js +0 -3
  355. package/dist/cli/main-rsy72qmw.js +0 -15
  356. package/dist/cli/main-rvetps99.js +0 -18
  357. package/dist/cli/main-s4bb0jav.js +0 -3
  358. package/dist/cli/main-s9v8k74e.js +0 -3
  359. package/dist/cli/main-tjvwmscs.js +0 -3
  360. package/dist/cli/main-tkgarpjj.js +0 -4
  361. package/dist/cli/main-v8y60bb2.js +0 -3
  362. package/dist/cli/main-vhrrq337.js +0 -3
  363. package/dist/cli/main-vp2dfb7s.js +0 -4
  364. package/dist/cli/main-vqbr22sz.js +0 -8
  365. package/dist/cli/main-vxnwe5xx.js +0 -18
  366. package/dist/cli/main-wgph00xf.js +0 -5
  367. package/dist/cli/main-wk2csfnj.js +0 -5
  368. package/dist/cli/main-wm997zjx.js +0 -3
  369. package/dist/cli/main-wpkyraxh.js +0 -3
  370. package/dist/cli/main-wqt32p5x.js +0 -4
  371. package/dist/cli/main-x9ct6y1a.js +0 -3
  372. package/dist/cli/main-xfekqh9m.js +0 -7
  373. package/dist/cli/main-xt9zc3n6.js +0 -7
  374. package/dist/cli/main-xx2z3zh5.js +0 -4
  375. package/dist/cli/main-y5c82rxr.js +0 -3
  376. package/dist/cli/main-yrjt2sqt.js +0 -14
  377. package/dist/cli/main-ys6zj3yr.js +0 -3
  378. package/dist/cli/main-ywbxshqc.js +0 -8
  379. package/dist/cli/main-z13755t8.js +0 -25
  380. package/dist/cli/main-zc7pyrbj.js +0 -4
  381. package/dist/cli/main.js +0 -279
  382. package/dist/cli/market-cmd-bm5xvn9f.js +0 -5
  383. package/dist/cli/mcp-login-bthtfpt7.js +0 -2
  384. package/dist/cli/mcp-market-cmd-mbeshfyd.js +0 -2
  385. package/dist/cli/notify-54v5z9dz.js +0 -2
  386. package/dist/cli/oauth-g5gme95c.js +0 -2
  387. package/dist/cli/output-satndjap.js +0 -16
  388. package/dist/cli/profiles-sfhpbq3m.js +0 -2
  389. package/dist/cli/provider-config-hv3xtdt4.js +0 -2
  390. package/dist/cli/provider-kwzq6g84.js +0 -2
  391. package/dist/cli/registry-fh0hdnyn.js +0 -2
  392. package/dist/cli/registry-y1y8e94r.js +0 -2
  393. package/dist/cli/repl-t4z03mqq.js +0 -11
  394. package/dist/cli/resume-fqt4chg8.js +0 -2
  395. package/dist/cli/run-flags-rysbag9t.js +0 -2
  396. package/dist/cli/runtime-j19fjbsa.js +0 -2
  397. package/dist/cli/sandbox-config-g4qxd7y5.js +0 -2
  398. package/dist/cli/server-r0b6bksk.js +0 -5
  399. package/dist/cli/session-arg-txmn5g4x.js +0 -2
  400. package/dist/cli/session-ed250d9j.js +0 -2
  401. package/dist/cli/sessions-cmd-adw7svfn.js +0 -7
  402. package/dist/cli/settings-y9rzcqx8.js +0 -2
  403. package/dist/cli/setup-jmbr11j0.js +0 -2
  404. package/dist/cli/sextant-smoke-tcth0vea.js +0 -5
  405. package/dist/cli/skills-cmd-zbdy99v6.js +0 -2
  406. package/dist/cli/smoke-1bg937kx.js +0 -8
  407. package/dist/cli/start-chat-p01cdks3.js +0 -12
  408. package/dist/cli/stream-4wmyaypz.js +0 -2
  409. package/dist/cli/task-eg4s093s.js +0 -2
  410. package/dist/cli/tasks-12v9rr9k.js +0 -2
  411. package/dist/cli/thinking-a5ngvqyh.js +0 -2
  412. package/dist/cli/todo-1wxpcecx.js +0 -2
  413. package/dist/cli/tools-2ftsya7w.js +0 -2
  414. package/dist/cli/tools-x1tj4fxm.js +0 -2
  415. package/dist/cli/trust-cmd-hccxehzb.js +0 -2
  416. package/dist/cli/update-check-ygt3vd7m.js +0 -2
  417. package/dist/cli/update-cmd-v23qhr8c.js +0 -2
  418. package/dist/cli/voice-g1gtck92.js +0 -2
  419. package/dist/cli/webfetch-0nnrjgb5.js +0 -2
  420. package/dist/cli/websearch-f0vr2p7d.js +0 -2
  421. package/dist/cli/workspace-9rq1w4ta.js +0 -2
  422. package/dist/lib/index.js +0 -62
  423. package/dist/lib/models-index.json +0 -1
  424. package/dist/lib/plugins.js +0 -6
  425. package/dist/lib/providers.js +0 -17
  426. package/dist/lib/public-api.js +0 -20
  427. package/dist/rovecode.exe +0 -4
  428. /package/{dist/cli → src/providers}/models-index.json +0 -0
@@ -0,0 +1,319 @@
1
+ /** Hashline-anchored edits (ADR-006): read emits path#TAG + N#hash|content;
2
+ * edit requires LINE#HASH anchors to match, applies in reverse order,
3
+ * failures return nearest-match diagnostics (aider did-you-mean).
4
+ * Port #28: a rejected edit/write is an ACTIONABLE message (describeEditFailure) — expected vs
5
+ * what the file holds NOW (the anchor line's current text + hash, the lines whose hash IS the
6
+ * anchor), the line count for out-of-range, the missing directory for write — plus the remedy,
7
+ * bounded to MAX_EDIT_MESSAGE_CHARS with the remedy always surviving the clip. Pattern: aider
8
+ * @ 5dc9490 aider/coders/editblock_coder.py:84-124 (failed-block report → "Did you mean to match
9
+ * some of these actual lines", "The SEARCH section must exactly match…"); no code copied. */
10
+
11
+ import { createHash } from "node:crypto";
12
+ import { readFileSync, writeFileSync, existsSync } from "node:fs";
13
+ import { dirname, isAbsolute, join } from "node:path";
14
+ import type { Tool, ToolContext, ToolOutput } from "../core/types.ts";
15
+ import { getExecutor } from "../core/executor.ts";
16
+
17
+ /** FNV-1a over whitespace-stripped line → 3 base36 chars (phi hash.go). */
18
+ export function lineHash(line: string): string {
19
+ const stripped = line.replace(/\s/g, "");
20
+ let h = 0x811c9dc5;
21
+ for (let i = 0; i < stripped.length; i++) {
22
+ h ^= stripped.charCodeAt(i);
23
+ h = Math.imul(h, 0x01000193) >>> 0;
24
+ }
25
+ return h.toString(36).padStart(3, "0").slice(-3);
26
+ }
27
+
28
+ /** 4-hex file TAG from content (phi hash.go). */
29
+ export function fileTag(content: string): string {
30
+ return createHash("sha1").update(content).digest("hex").slice(0, 4);
31
+ }
32
+
33
+ export interface AnchoredFile { path: string; tag: string; lines: { n: number; hash: string; text: string }[] }
34
+
35
+ export function readAnchored(absPath: string): AnchoredFile {
36
+ const content = readFileSync(absPath, "utf8");
37
+ const lines = content.split("\n").map((text, i) => ({ n: i + 1, hash: lineHash(text), text }));
38
+ return { path: absPath, tag: fileTag(content), lines };
39
+ }
40
+
41
+ export function renderAnchored(f: AnchoredFile): string {
42
+ const header = `${f.path}#${f.tag}`;
43
+ const body = f.lines.map((l) => `${l.n}#${l.hash}|${l.text}`).join("\n");
44
+ return `${header}\n${body}`;
45
+ }
46
+
47
+ export interface EditOp {
48
+ path: string;
49
+ tag: string; // must match current fileTag, else stale-read rejection
50
+ anchorLine: number; // 1-based line the edit replaces
51
+ anchorHash: string; // must match lineHash at anchorLine
52
+ newLines: string[]; // replacement content (empty = delete line)
53
+ }
54
+
55
+ /** lines listed as "carry your anchor's hash" in a hash-mismatch failure */
56
+ const MAX_ANCHOR_MATCHES = 3;
57
+
58
+ export type EditFailure =
59
+ | { kind: "tag-mismatch"; path: string; expected: string; actual: string }
60
+ /** text = the anchor line's CURRENT content (clipped); matches = line numbers whose hash is the anchor (≤ MAX_ANCHOR_MATCHES) */
61
+ | { kind: "hash-mismatch"; path: string; line: number; expected: string; actual: string; nearest: string; text: string; matches: number[] }
62
+ | { kind: "out-of-range"; path: string; line: number; lineCount: number };
63
+
64
+ export type EditResult = { ok: true; newTag: string } | { ok: false; failure: EditFailure };
65
+ export type ApplyResult = { ok: true; content: string; newTag: string } | { ok: false; failure: EditFailure };
66
+
67
+ /** Pure core of applyEdits over in-memory content: tag check, reverse-order anchored splices
68
+ * (later lines first so earlier anchors stay valid — phi hashline.go), nearest-match
69
+ * diagnostics. Port #24 previews the exact post-edit content through this without writing. */
70
+ export function applyEditsToContent(content: string, edits: EditOp[], path: string): ApplyResult {
71
+ const tag = fileTag(content);
72
+ const stale = edits.find((e) => e.tag !== tag);
73
+ if (stale) return { ok: false, failure: { kind: "tag-mismatch", path, expected: stale.tag, actual: tag } };
74
+
75
+ const lines = content.split("\n");
76
+ const sorted = [...edits].sort((a, b) => b.anchorLine - a.anchorLine);
77
+ for (const e of sorted) {
78
+ if (e.anchorLine < 1 || e.anchorLine > lines.length) {
79
+ return { ok: false, failure: { kind: "out-of-range", path, line: e.anchorLine, lineCount: lines.length } };
80
+ }
81
+ const text = lines[e.anchorLine - 1]!;
82
+ const actual = lineHash(text);
83
+ if (actual !== e.anchorHash) {
84
+ // nearest-match diagnostic (aider find_similar_lines): the lines that DO carry the anchor's hash
85
+ const matches: number[] = [];
86
+ for (let i = 0; i < lines.length && matches.length < MAX_ANCHOR_MATCHES; i++) if (lineHash(lines[i]!) === e.anchorHash) matches.push(i + 1);
87
+ const nearest = matches.length > 0
88
+ ? `line ${matches[0]} currently holds that hash: ${lines[matches[0]! - 1]!.slice(0, 80)}`
89
+ : `no line matches; line ${e.anchorLine} is now: ${text.slice(0, 80)}`;
90
+ return { ok: false, failure: { kind: "hash-mismatch", path, line: e.anchorLine, expected: e.anchorHash, actual, nearest, text: text.slice(0, 80), matches } };
91
+ }
92
+ lines.splice(e.anchorLine - 1, 1, ...e.newLines);
93
+ }
94
+ const next = lines.join("\n");
95
+ return { ok: true, content: next, newTag: fileTag(next) };
96
+ }
97
+
98
+ /** Applies edits to the file on disk (applyEditsToContent + write); a missing file is out-of-range. */
99
+ export function applyEdits(absPath: string, edits: EditOp[]): EditResult {
100
+ if (!existsSync(absPath)) return { ok: false, failure: { kind: "out-of-range", path: absPath, line: 0, lineCount: 0 } };
101
+ const r = applyEditsToContent(readFileSync(absPath, "utf8"), edits, absPath);
102
+ if (!r.ok) return r;
103
+ writeFileSync(absPath, r.content);
104
+ return { ok: true, newTag: r.newTag };
105
+ }
106
+
107
+ // ---------- port #28: actionable failure text ----------
108
+
109
+ /** hard bound on every rejection message the model sees (the remedy is never the part clipped) */
110
+ export const MAX_EDIT_MESSAGE_CHARS = 600;
111
+ const EDIT_REMEDY = "Remedy: re-read the file with `read` to get fresh line hashes, then retry the edit.";
112
+ /** lint errors listed in a lint-gate rejection before "… and N more" */
113
+ const MAX_LINT_LINES = 8;
114
+
115
+ /** What went wrong, what the file holds NOW, and what to do — aider's failed-block report shape
116
+ * (editblock_coder.py:84-124: the failing block, "Did you mean to match some of these actual
117
+ * lines", the exact-match rule) for hashline anchors. Detail is clipped first; the remedy survives. */
118
+ export function describeEditFailure(f: EditFailure): string {
119
+ const head = "Edit rejected: ";
120
+ const room = MAX_EDIT_MESSAGE_CHARS - head.length - EDIT_REMEDY.length - 1;
121
+ return `${head}${clip(editFailureDetail(f), room)} ${EDIT_REMEDY}`;
122
+ }
123
+
124
+ function editFailureDetail(f: EditFailure): string {
125
+ switch (f.kind) {
126
+ case "tag-mismatch":
127
+ return `stale read — ${f.path} changed since you read it (file TAG is now ${f.actual}, your edit carries ${f.expected}).`;
128
+ case "hash-mismatch": {
129
+ const where = f.matches.length > 0
130
+ ? `Lines whose hash matches your anchor: ${f.matches.join(", ")} — did you mean one of those?`
131
+ : "No line in the file has that hash now — the content changed since your read.";
132
+ return `anchor mismatch at ${f.path}:${f.line} — line ${f.line} now reads ${JSON.stringify(f.text)} (hash ${f.actual}), your anchor expected hash ${f.expected}. ${where}`;
133
+ }
134
+ case "out-of-range":
135
+ return `line ${f.line} is out of range — ${f.path} has ${f.lineCount} lines (valid anchors: 1-${f.lineCount}).`;
136
+ }
137
+ }
138
+
139
+ function clip(s: string, max: number): string { return s.length <= max ? s : s.slice(0, Math.max(0, max - 1)) + "…"; }
140
+
141
+ // ---------- Tools ----------
142
+
143
+ function resolvePath(cwd: string, p: string): string { return isAbsolute(p) ? p : join(cwd, p); }
144
+
145
+ /** Windowed anchored read: keep absolute line numbers, note the slice bounds. */
146
+ function renderWindow(f: AnchoredFile, offset: number, limit: number): string {
147
+ const total = f.lines.length;
148
+ const start = Math.max(1, Math.floor(offset));
149
+ if (start > total) return `${f.path}#${f.tag}\n(showing lines 0-0 of ${total}; offset ${start} is past EOF)`;
150
+ const end = Math.min(total, start + Math.floor(limit) - 1);
151
+ const slice = f.lines.slice(start - 1, end);
152
+ return renderAnchored({ ...f, lines: slice }).replace(/\n$/, "") + `\n(showing lines ${start}-${end} of ${total})`;
153
+ }
154
+
155
+
156
+
157
+ export const readTool: Tool = {
158
+ schema: {
159
+ name: "read",
160
+ description: "Read a file window. Output is `path#TAG` header plus `N#hash|content` lines; use hashes for edit anchors. Defaults: offset 1, limit 2000 lines. Footer notes `showing lines X-Y of Z`; if Y < Z pass a larger offset to see more.",
161
+ args: {
162
+ type: "object",
163
+ properties: {
164
+ path: { type: "string" },
165
+ offset: { type: "integer", description: "first line to show (1-based, default 1)" },
166
+ limit: { type: "integer", description: "max lines to show (default 2000)" },
167
+ },
168
+ required: ["path"],
169
+ },
170
+ },
171
+ kind: "read",
172
+ sequential: false,
173
+ execute(args, ctx): Promise<ToolOutput> {
174
+ const a = args as { path: string; offset?: number; limit?: number };
175
+ const p = resolvePath(ctx.cwd, a.path);
176
+ if (!existsSync(p)) return Promise.resolve({ ok: false, output: `file not found: ${p}` });
177
+ const offset = Number.isFinite(a.offset) && a.offset! > 0 ? Math.floor(a.offset!) : 1;
178
+ const limit = Number.isFinite(a.limit) && a.limit! > 0 ? Math.floor(a.limit!) : 2000;
179
+ return Promise.resolve({ ok: true, output: renderWindow(readAnchored(p), offset, limit) });
180
+ },
181
+ };
182
+
183
+ // ---------- Edit lint-gate ----------
184
+
185
+ export type EditLinter = (content: string, path: string) => string[];
186
+
187
+ let editLinter: EditLinter | undefined;
188
+
189
+ /** Install a linter (e.g. `tsc --noEmit` or biome) consulted after every applied edit.
190
+ * When set, an edit that introduces NEW lint errors is reverted and reported. */
191
+ export function setEditLinter(fn: EditLinter | undefined): void { editLinter = fn; }
192
+
193
+ export const editTool: Tool = {
194
+ schema: {
195
+ name: "edit",
196
+ description: "Anchored edit. Each op replaces the line at anchorLine (whose hash must equal anchorHash) with newLines. tag must match the TAG from your last read.",
197
+ args: {
198
+ type: "object",
199
+ properties: {
200
+ path: { type: "string" },
201
+ edits: {
202
+ type: "array",
203
+ items: {
204
+ type: "object",
205
+ properties: {
206
+ tag: { type: "string" }, anchorLine: { type: "integer" },
207
+ anchorHash: { type: "string" }, newLines: { type: "array", items: { type: "string" } },
208
+ },
209
+ required: ["tag", "anchorLine", "anchorHash", "newLines"],
210
+ },
211
+ },
212
+ },
213
+ required: ["path", "edits"],
214
+ },
215
+ },
216
+ kind: "write",
217
+ sequential: true,
218
+ execute(args, ctx): Promise<ToolOutput> {
219
+ const a = args as { path: string; edits: EditOp[] };
220
+ const p = resolvePath(ctx.cwd, a.path);
221
+ if (!existsSync(p)) {
222
+ // port #28: a missing file used to surface as "line 0 out of range (file has 0 lines)"
223
+ return Promise.resolve({ ok: false, output: clip(`Edit rejected: file not found: ${p} — check the path (relative paths resolve against ${ctx.cwd}) or create the file with \`write\`.`, MAX_EDIT_MESSAGE_CHARS) });
224
+ }
225
+ const before = readFileSync(p, "utf8");
226
+ const r = applyEdits(p, a.edits.map((e) => ({ ...e, path: p })));
227
+ if (!r.ok) return Promise.resolve({ ok: false, output: describeEditFailure(r.failure) });
228
+ // Lint-gate (SWE-agent revert+requery): if the edit introduced NEW lint errors,
229
+ // revert to the pre-edit content and report them so the agent retries.
230
+ if (editLinter) {
231
+ const errorsBefore = editLinter(before, p);
232
+ const errorsAfter = editLinter(readFileSync(p, "utf8"), p);
233
+ const before2 = new Set(errorsBefore);
234
+ const newErrors = errorsAfter.filter((e) => !before2.has(e));
235
+ if (newErrors.length > 0) {
236
+ writeFileSync(p, before);
237
+ const shown = newErrors.slice(0, MAX_LINT_LINES).join("\n") + (newErrors.length > MAX_LINT_LINES ? `\n… and ${newErrors.length - MAX_LINT_LINES} more` : "");
238
+ return Promise.resolve({
239
+ ok: false,
240
+ output: `Edit applied but lint failed — file reverted to original. New lint errors:\n${shown}\nFix these and retry the edit.`,
241
+ });
242
+ }
243
+ }
244
+ return Promise.resolve({ ok: true, output: `applied ${a.edits.length} edit(s); new TAG ${r.newTag}` });
245
+ },
246
+ };
247
+
248
+ export const writeTool: Tool = {
249
+ schema: {
250
+ name: "write",
251
+ description: "Create or overwrite a file with content.",
252
+ args: { type: "object", properties: { path: { type: "string" }, content: { type: "string" } }, required: ["path", "content"] },
253
+ },
254
+ kind: "write",
255
+ sequential: true,
256
+ execute(args, ctx): Promise<ToolOutput> {
257
+ const a = args as { path: string; content: string };
258
+ const p = resolvePath(ctx.cwd, a.path);
259
+ const dir = dirname(p);
260
+ if (!existsSync(dir)) {
261
+ // port #28: say WHY instead of leaking the raw ENOENT — the fix is a mkdir, not a different path
262
+ return Promise.resolve({ ok: false, output: clip(`Write rejected: directory ${dir} does not exist — create it first (bash: mkdir -p ${JSON.stringify(dir)}) or write into an existing directory.`, MAX_EDIT_MESSAGE_CHARS) });
263
+ }
264
+ writeFileSync(p, a.content);
265
+ return Promise.resolve({ ok: true, output: `wrote ${p} (${a.content.length} bytes, TAG ${fileTag(a.content)})` });
266
+ },
267
+ };
268
+
269
+ export const bashTool: Tool = {
270
+ schema: {
271
+ name: "bash",
272
+ description: "Run a shell command in the workspace (cwd locked to the session cwd). One automatic retry on non-zero exit. Destructive system commands are refused by a best-effort blocklist — this is NOT a sandbox. Output truncated to 10k chars.",
273
+ args: { type: "object", properties: { command: { type: "string" } }, required: ["command"] },
274
+ },
275
+ kind: "execute",
276
+ sequential: true,
277
+ async execute(args, ctx): Promise<ToolOutput> {
278
+ const cmd = String((args as { command: string }).command);
279
+ const denied = deniedCommand(cmd);
280
+ if (denied) return { ok: false, output: denied };
281
+ // port #10: shell execution goes through the Executor seam (direct/wsl/docker
282
+ // rungs, probed not assumed). Direct rung is byte-compatible with the old
283
+ // inline runOnce; a missing bash now returns exit=-1 instead of throwing.
284
+ let r = await getExecutor().run(cmd, ctx.cwd, ctx.signal);
285
+ // single self-contained retry — but NEVER after an abort (port #21): the kill
286
+ // makes the exit non-zero, and a blind retry would respawn the cancelled
287
+ // command as a detached subprocess that outlives the run
288
+ if (r.code !== 0 && !ctx.signal.aborted) r = await getExecutor().run(cmd, ctx.cwd, ctx.signal);
289
+ return { ok: r.code === 0, output: `exit=${r.code}\n${r.text}` };
290
+ },
291
+ };
292
+
293
+ // ---------- Bash safety (best-effort blocklist, NOT a sandbox) ----------
294
+
295
+ /** Footgun guard on the raw command string. A determined agent bypasses it;
296
+ * real isolation belongs at the process/OS layer. */
297
+ const denyPatterns: RegExp[] = [
298
+ /rm\s+(-[a-z]*\s+)*\/(\s|$)/, // rm -rf /
299
+ /rm\s+(-[a-z]*\s+)*\/\*/, // rm -rf /*
300
+ /rm\s+(-[a-z]*\s+)*(--no-preserve-root\s+)?\*(\s|$)/, // rm -rf *
301
+ /:\(\)\s*\{/, // fork bomb body :(){ ...
302
+ /\bmkfs(\.\w+)?\b/,
303
+ /\b(shutdown|reboot|poweroff|halt)\b/,
304
+ /(^|[;&|\s])(sudo\s+)?format\s+(\/|[c-z]:)/i, // windows format
305
+ /(^|[;&|\s])(sudo\s+)?del\s+\/[fqs]/i, // windows del /f
306
+ /(^|[;&|\s])(sudo\s+)?rd\s+\/[sq]/i,
307
+ /(^|[;&|\s])(sudo\s+)?remove-item\s+-(rec|r|f|force)/i,
308
+ /\bdd\s+[^|]*of=\/dev\/(sd|nvme|hd|disk)/, // raw disk overwrite
309
+ />\s*\/dev\/(sd|nvme|hd|disk)/,
310
+ /\bsudo\b.*\b(rm|mkfs|dd|shutdown|reboot|halt|format)\b/, // sudo + destructive core
311
+ ];
312
+
313
+ function deniedCommand(cmd: string): string | null {
314
+ const hit = denyPatterns.find((re) => re.test(cmd));
315
+ return hit
316
+ ? `command refused by safety blocklist (matched ${hit.source}): this tool is not a sandbox; rephrase without destructive system commands`
317
+ : null;
318
+ }
319
+