rovecode 0.3.3 → 0.4.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (495) hide show
  1. package/CHANGELOG.md +527 -0
  2. package/README.md +46 -48
  3. package/bin/rovecode.js +24 -0
  4. package/dist/cli/app-j6gn14w3.js +2 -0
  5. package/dist/cli/ask-user-cwstt8fz.js +2 -0
  6. package/dist/cli/auth-login-9bbp9915.js +2 -0
  7. package/dist/cli/auth-m8p9grty.js +2 -0
  8. package/dist/cli/bench-16zqdms5.js +9 -0
  9. package/dist/cli/catalog-1xchffa4.js +2 -0
  10. package/dist/cli/cli-1n1zb64f.js +2 -0
  11. package/dist/cli/client-2t9gjkck.js +2 -0
  12. package/dist/cli/commands-exafvm2b.js +2 -0
  13. package/dist/cli/connect-6zde0kn3.js +2 -0
  14. package/dist/cli/context-cmd-5t43wgqt.js +2 -0
  15. package/dist/cli/context-report-kt01pw8y.js +2 -0
  16. package/dist/cli/count-remote-ap7x3vh6.js +2 -0
  17. package/dist/cli/design-ne5zszyh.js +2 -0
  18. package/dist/cli/dispatch-2r5myxye.js +2 -0
  19. package/dist/cli/doctor-ws4fh4tn.js +3 -0
  20. package/dist/cli/executor-bdrjn634.js +2 -0
  21. package/dist/cli/export-1mxb9g5p.js +2 -0
  22. package/dist/cli/files-g104xghh.js +2 -0
  23. package/dist/cli/gauntlet-07xrjpj7.js +2 -0
  24. package/dist/cli/gauntlet-runner-xvy64436.js +10 -0
  25. package/dist/cli/gauntlet-wave3-jm91yt5w.js +5 -0
  26. package/dist/cli/gauntlet-wave4-r13py7p1.js +14 -0
  27. package/dist/cli/hashline-znvrat11.js +2 -0
  28. package/dist/cli/http-xafw6fsh.js +143 -0
  29. package/dist/cli/index-1sgjm25y.js +2 -0
  30. package/dist/cli/init-g2m0tn4m.js +51 -0
  31. package/dist/cli/install-avaqjjqq.js +2 -0
  32. package/dist/cli/loop-mmpfft01.js +2 -0
  33. package/dist/cli/main-0904f6ps.js +5 -0
  34. package/dist/cli/main-0ab9fc26.js +9 -0
  35. package/dist/cli/main-0jys2ccn.js +3 -0
  36. package/dist/cli/main-0mtcdbs7.js +3 -0
  37. package/dist/cli/main-0z1w2zsg.js +3 -0
  38. package/dist/cli/main-1dchs7xv.js +18 -0
  39. package/dist/cli/main-1ereejm1.js +3 -0
  40. package/dist/cli/main-1k1kw6b5.js +3 -0
  41. package/dist/cli/main-27y4sm2k.js +38 -0
  42. package/dist/cli/main-2wwjex5j.js +58 -0
  43. package/dist/cli/main-2yeveeve.js +6 -0
  44. package/dist/cli/main-2yfck9b5.js +3 -0
  45. package/dist/cli/main-2zmzgkwh.js +3 -0
  46. package/dist/cli/main-351pz3z7.js +7 -0
  47. package/dist/cli/main-3gjqfh7a.js +6 -0
  48. package/dist/cli/main-3nf3kgve.js +3 -0
  49. package/dist/cli/main-3pjrb2hd.js +3 -0
  50. package/dist/cli/main-3rxcvgna.js +19 -0
  51. package/dist/cli/main-4b3jgy66.js +19 -0
  52. package/dist/cli/main-4wndhjdc.js +7 -0
  53. package/dist/cli/main-4xcmvxnk.js +3 -0
  54. package/dist/cli/main-5tbz0wbz.js +4 -0
  55. package/dist/cli/main-5ywnwthm.js +3 -0
  56. package/dist/cli/main-6b62vkz0.js +14 -0
  57. package/dist/cli/main-6dnk69vp.js +3 -0
  58. package/dist/cli/main-6genrmhs.js +136 -0
  59. package/dist/cli/main-73g7eff4.js +15 -0
  60. package/dist/cli/main-7c5thhjd.js +5 -0
  61. package/dist/cli/main-7rn6bqje.js +3 -0
  62. package/dist/cli/main-80haw7qk.js +4 -0
  63. package/dist/cli/main-875s60s2.js +4 -0
  64. package/dist/cli/main-8kjxbpw4.js +8 -0
  65. package/dist/cli/main-90ds1z4e.js +10 -0
  66. package/dist/cli/main-9etavkew.js +3 -0
  67. package/dist/cli/main-a9njrkk1.js +3 -0
  68. package/dist/cli/main-aecrjq2d.js +12 -0
  69. package/dist/cli/main-ck9asesq.js +9 -0
  70. package/dist/cli/main-cta9racd.js +4 -0
  71. package/dist/cli/main-ddv7j2ag.js +3 -0
  72. package/dist/cli/main-dfreez27.js +10 -0
  73. package/dist/cli/main-f7rw7des.js +3 -0
  74. package/dist/cli/main-ggcn7rd7.js +5 -0
  75. package/dist/cli/main-gzkmycnv.js +3 -0
  76. package/dist/cli/main-hq51jg8v.js +18 -0
  77. package/dist/cli/main-jft389w9.js +8 -0
  78. package/dist/cli/main-k1eqkg83.js +3 -0
  79. package/dist/cli/main-k2y8a2aw.js +9 -0
  80. package/dist/cli/main-kcpbykxz.js +4 -0
  81. package/dist/cli/main-kd488vje.js +22 -0
  82. package/dist/cli/main-kh32yvgk.js +5 -0
  83. package/dist/cli/main-kqxnqjnv.js +25 -0
  84. package/dist/cli/main-kyn0xnsg.js +3 -0
  85. package/dist/cli/main-m1kk6fp5.js +21 -0
  86. package/dist/cli/main-mv40pcr2.js +4 -0
  87. package/dist/cli/main-n0t3973w.js +3 -0
  88. package/dist/cli/main-nqveez48.js +4 -0
  89. package/dist/cli/main-pknhvrmj.js +3 -0
  90. package/dist/cli/main-pn1w7a7j.js +3 -0
  91. package/dist/cli/main-prxxs70n.js +4 -0
  92. package/dist/cli/main-q3vsesf9.js +3 -0
  93. package/dist/cli/main-qsevpgsv.js +3 -0
  94. package/dist/cli/main-rdgdw24b.js +25 -0
  95. package/dist/cli/main-rfth4tbm.js +16 -0
  96. package/dist/cli/main-rg0wn0xf.js +5 -0
  97. package/dist/cli/main-sdmxhtv8.js +4 -0
  98. package/dist/cli/main-skbp13js.js +18 -0
  99. package/dist/cli/main-t4xnd213.js +7 -0
  100. package/dist/cli/main-vqak588n.js +4 -0
  101. package/dist/cli/main-w2n1303f.js +9 -0
  102. package/dist/cli/main-wbrdspr2.js +5 -0
  103. package/dist/cli/main-wsrg79c1.js +7 -0
  104. package/dist/cli/main-x4r0fne4.js +5 -0
  105. package/dist/cli/main-xea2f3tn.js +6 -0
  106. package/dist/cli/main-xg704a3c.js +3 -0
  107. package/dist/cli/main-xvnrabfp.js +16 -0
  108. package/dist/cli/main-xy53xf0r.js +4 -0
  109. package/dist/cli/main-y1fqy60y.js +3 -0
  110. package/dist/cli/main-yn8cd281.js +34 -0
  111. package/dist/cli/main-yr0ksc0h.js +4 -0
  112. package/dist/cli/main-z2ex2vyf.js +4 -0
  113. package/dist/cli/main-z3aayzvq.js +3 -0
  114. package/dist/cli/main-zaqh35jg.js +3 -0
  115. package/dist/cli/main-zc2e8e46.js +4 -0
  116. package/dist/cli/main-zzrfw6cf.js +13 -0
  117. package/dist/cli/main.js +280 -0
  118. package/dist/cli/market-cmd-e14kmx9n.js +5 -0
  119. package/dist/cli/mcp-login-wq7ktdek.js +2 -0
  120. package/dist/cli/mcp-market-cmd-9mg3jecy.js +2 -0
  121. package/dist/cli/notify-b7qc0cjb.js +2 -0
  122. package/dist/cli/oauth-z8whcgfx.js +2 -0
  123. package/dist/cli/output-b3ewj3ps.js +16 -0
  124. package/dist/cli/profiles-6mr5he5e.js +2 -0
  125. package/dist/cli/provider-config-g7j42q8x.js +2 -0
  126. package/dist/cli/provider-jr1y8vvm.js +2 -0
  127. package/dist/cli/registry-s8yk86g0.js +2 -0
  128. package/dist/cli/registry-t6p8d4mn.js +2 -0
  129. package/dist/cli/repl-bajwe1mh.js +11 -0
  130. package/dist/cli/resume-rwn9nz7y.js +2 -0
  131. package/dist/cli/run-flags-nah7ndpt.js +2 -0
  132. package/dist/cli/runtime-n7gafzhb.js +2 -0
  133. package/dist/cli/sandbox-config-emdy18x4.js +2 -0
  134. package/dist/cli/server-b0nvs2bn.js +5 -0
  135. package/dist/cli/session-arg-y75wd4kj.js +2 -0
  136. package/dist/cli/session-j62evmjq.js +2 -0
  137. package/dist/cli/sessions-cmd-tsnwz0ns.js +7 -0
  138. package/dist/cli/settings-df10wfez.js +2 -0
  139. package/dist/cli/setup-jzvv72fg.js +2 -0
  140. package/dist/cli/sextant-smoke-37m81ke6.js +5 -0
  141. package/dist/cli/skills-cmd-gjxnxnhx.js +2 -0
  142. package/dist/cli/smoke-p7748apt.js +8 -0
  143. package/dist/cli/start-chat-s4st3mm0.js +12 -0
  144. package/dist/cli/stream-gmeyewds.js +2 -0
  145. package/dist/cli/task-gh0kkp3n.js +2 -0
  146. package/dist/cli/tasks-z1kfpe8e.js +2 -0
  147. package/dist/cli/thinking-0eqkrz6t.js +2 -0
  148. package/dist/cli/todo-5brcrt9m.js +2 -0
  149. package/dist/cli/tools-7pzm0vj9.js +2 -0
  150. package/dist/cli/tools-s635p6s8.js +2 -0
  151. package/dist/cli/trust-cmd-cjav8zgm.js +2 -0
  152. package/dist/cli/update-check-pt31bm2f.js +2 -0
  153. package/dist/cli/update-cmd-tk131s9t.js +2 -0
  154. package/dist/cli/voice-56nabd8d.js +2 -0
  155. package/dist/cli/webfetch-xd8q596m.js +2 -0
  156. package/dist/cli/websearch-5hkf98k1.js +2 -0
  157. package/dist/cli/workflow-cmd-cy3cvzjp.js +4 -0
  158. package/dist/cli/workspace-q10g5z3e.js +2 -0
  159. package/dist/lib/index.js +62 -0
  160. package/dist/lib/models-index.json +1 -0
  161. package/dist/lib/plugins.js +55 -0
  162. package/dist/lib/providers.js +17 -0
  163. package/dist/lib/public-api.js +20 -0
  164. package/dist/lib/sdk.js +360 -0
  165. package/package.json +84 -72
  166. package/bin/rovecode.ts +0 -21
  167. package/src/acp/server.ts +0 -374
  168. package/src/cli/auth-login.ts +0 -122
  169. package/src/cli/connect.ts +0 -244
  170. package/src/cli/context-cmd.ts +0 -199
  171. package/src/cli/dispatch.ts +0 -82
  172. package/src/cli/doctor.ts +0 -362
  173. package/src/cli/export.ts +0 -276
  174. package/src/cli/help.ts +0 -293
  175. package/src/cli/is-tui-invocation.ts +0 -8
  176. package/src/cli/main.ts +0 -583
  177. package/src/cli/market-cmd.ts +0 -658
  178. package/src/cli/mcp-login.ts +0 -141
  179. package/src/cli/mcp-market-cmd.ts +0 -302
  180. package/src/cli/output.ts +0 -382
  181. package/src/cli/repl.ts +0 -250
  182. package/src/cli/repomap-root.ts +0 -14
  183. package/src/cli/resume.ts +0 -57
  184. package/src/cli/run-flags.ts +0 -43
  185. package/src/cli/run-limits.ts +0 -78
  186. package/src/cli/runtime.ts +0 -931
  187. package/src/cli/session-arg.ts +0 -30
  188. package/src/cli/sessions-cmd.ts +0 -145
  189. package/src/cli/setup.ts +0 -153
  190. package/src/cli/skills-cmd.ts +0 -194
  191. package/src/cli/start-chat.ts +0 -65
  192. package/src/cli/trust-cmd.ts +0 -52
  193. package/src/coding/bash.ts +0 -148
  194. package/src/coding/checkpoints.ts +0 -327
  195. package/src/coding/diff.ts +0 -138
  196. package/src/coding/files.ts +0 -341
  197. package/src/coding/hashline.ts +0 -274
  198. package/src/coding/lsp-gate.ts +0 -254
  199. package/src/coding/lsp-servers.ts +0 -147
  200. package/src/coding/lsp.ts +0 -283
  201. package/src/coding/repomap-cache.ts +0 -99
  202. package/src/coding/repomap-files.ts +0 -192
  203. package/src/coding/repomap.ts +0 -481
  204. package/src/core/agents.ts +0 -255
  205. package/src/core/compaction.ts +0 -259
  206. package/src/core/config.ts +0 -289
  207. package/src/core/context-report.ts +0 -228
  208. package/src/core/context.ts +0 -60
  209. package/src/core/count-remote.ts +0 -107
  210. package/src/core/execpolicy-rules.ts +0 -196
  211. package/src/core/execpolicy.ts +0 -385
  212. package/src/core/executor.ts +0 -454
  213. package/src/core/guardrails.ts +0 -400
  214. package/src/core/hooks.ts +0 -411
  215. package/src/core/images.ts +0 -230
  216. package/src/core/intro.ts +0 -266
  217. package/src/core/loop.ts +0 -567
  218. package/src/core/modes.ts +0 -372
  219. package/src/core/orchestrator.ts +0 -245
  220. package/src/core/proc-group.ts +0 -48
  221. package/src/core/project-trust.ts +0 -98
  222. package/src/core/reflection.ts +0 -165
  223. package/src/core/sandbox-config.ts +0 -186
  224. package/src/core/session-id.ts +0 -24
  225. package/src/core/session-images.ts +0 -73
  226. package/src/core/session-ops.ts +0 -183
  227. package/src/core/session-text.ts +0 -29
  228. package/src/core/session.ts +0 -469
  229. package/src/core/settings.ts +0 -170
  230. package/src/core/tasks.ts +0 -646
  231. package/src/core/token-scale.ts +0 -108
  232. package/src/core/tools.ts +0 -309
  233. package/src/core/trust.ts +0 -104
  234. package/src/core/types.ts +0 -330
  235. package/src/core/update-check.ts +0 -171
  236. package/src/core/usage.ts +0 -204
  237. package/src/core/validate.ts +0 -121
  238. package/src/core/verify-gate.ts +0 -159
  239. package/src/core/verify.ts +0 -236
  240. package/src/core/voice.ts +0 -158
  241. package/src/core/win-job.ts +0 -183
  242. package/src/core/workspace.ts +0 -184
  243. package/src/design/audit.ts +0 -797
  244. package/src/design/direction.ts +0 -190
  245. package/src/design/rules.ts +0 -157
  246. package/src/eval/bench.ts +0 -150
  247. package/src/eval/gauntlet-runner.ts +0 -215
  248. package/src/eval/gauntlet-support.ts +0 -84
  249. package/src/eval/gauntlet-wave3.ts +0 -269
  250. package/src/eval/gauntlet-wave4.ts +0 -217
  251. package/src/eval/gauntlet.ts +0 -253
  252. package/src/index.ts +0 -17
  253. package/src/lanes/agy.ts +0 -95
  254. package/src/lanes/approval.ts +0 -24
  255. package/src/lanes/claude.ts +0 -129
  256. package/src/lanes/codex.ts +0 -127
  257. package/src/lanes/events.ts +0 -130
  258. package/src/lanes/job.ts +0 -142
  259. package/src/lanes/opencode.ts +0 -122
  260. package/src/lanes/process.ts +0 -184
  261. package/src/lanes/progress.ts +0 -183
  262. package/src/lanes/registry.ts +0 -178
  263. package/src/lanes/runner.ts +0 -124
  264. package/src/lanes/types.ts +0 -112
  265. package/src/market/catalogs/mcp-docs.json +0 -111
  266. package/src/market/catalogs/plugins.json +0 -111
  267. package/src/market/catalogs/skills.json +0 -478
  268. package/src/market/clone.ts +0 -72
  269. package/src/market/context-cost.ts +0 -121
  270. package/src/market/digest.ts +0 -106
  271. package/src/market/index.ts +0 -22
  272. package/src/market/install.ts +0 -578
  273. package/src/market/manifest.ts +0 -187
  274. package/src/market/prereq.ts +0 -145
  275. package/src/market/registry.ts +0 -363
  276. package/src/market/resolve.ts +0 -111
  277. package/src/market/types.ts +0 -236
  278. package/src/market/validate.ts +0 -227
  279. package/src/mcp/client.ts +0 -449
  280. package/src/mcp/config.ts +0 -252
  281. package/src/mcp/local-package.ts +0 -211
  282. package/src/mcp/market-catalog.ts +0 -84
  283. package/src/mcp/market-install.ts +0 -289
  284. package/src/mcp/market.ts +0 -362
  285. package/src/mcp/oauth.ts +0 -251
  286. package/src/mcp/prompts-resources.ts +0 -249
  287. package/src/mcp/shared.ts +0 -149
  288. package/src/mcp/status.ts +0 -67
  289. package/src/mcp/tools.ts +0 -275
  290. package/src/mcp/transport.ts +0 -122
  291. package/src/mcp/trust.ts +0 -25
  292. package/src/memory/blocks.ts +0 -278
  293. package/src/memory/recall.ts +0 -355
  294. package/src/memory/scope.ts +0 -182
  295. package/src/memory/store.ts +0 -105
  296. package/src/memory/tools.ts +0 -99
  297. package/src/plugins/cli.ts +0 -119
  298. package/src/plugins/discover.ts +0 -108
  299. package/src/plugins/index.ts +0 -50
  300. package/src/plugins/install.ts +0 -184
  301. package/src/plugins/load.ts +0 -124
  302. package/src/plugins/manifest.ts +0 -92
  303. package/src/plugins/state.ts +0 -83
  304. package/src/providers/auth.ts +0 -408
  305. package/src/providers/cache.ts +0 -223
  306. package/src/providers/catalog-local.ts +0 -160
  307. package/src/providers/catalog.ts +0 -421
  308. package/src/providers/middleware-context.ts +0 -86
  309. package/src/providers/middleware.ts +0 -373
  310. package/src/providers/model-list.ts +0 -23
  311. package/src/providers/oauth/common.ts +0 -105
  312. package/src/providers/oauth/device-code.ts +0 -107
  313. package/src/providers/oauth/github-copilot.ts +0 -146
  314. package/src/providers/oauth/loopback.ts +0 -158
  315. package/src/providers/oauth/openai.ts +0 -163
  316. package/src/providers/oauth/openrouter.ts +0 -89
  317. package/src/providers/oauth/pkce.ts +0 -45
  318. package/src/providers/oauth/registry.ts +0 -39
  319. package/src/providers/oauth/seam.ts +0 -89
  320. package/src/providers/profile-glm53.ts +0 -111
  321. package/src/providers/profile-sonnet5-persona.ts +0 -65
  322. package/src/providers/profile-sonnet5-voice.ts +0 -23
  323. package/src/providers/profiles.ts +0 -156
  324. package/src/providers/provider-config.ts +0 -311
  325. package/src/providers/registry.ts +0 -333
  326. package/src/providers/responses.ts +0 -209
  327. package/src/providers/retry.ts +0 -234
  328. package/src/providers/router.ts +0 -294
  329. package/src/providers/sse.ts +0 -26
  330. package/src/providers/stream-errors.ts +0 -117
  331. package/src/providers/stream.ts +0 -566
  332. package/src/providers/thinking.ts +0 -189
  333. package/src/providers/wire-messages.ts +0 -129
  334. package/src/providers/wire-responses.ts +0 -79
  335. package/src/providers/wire-select.ts +0 -53
  336. package/src/server/http.ts +0 -291
  337. package/src/server/openapi.ts +0 -246
  338. package/src/sextant/card-hits.ts +0 -102
  339. package/src/sextant/card-keys.ts +0 -55
  340. package/src/sextant/context-source.ts +0 -157
  341. package/src/sextant/crew-cards.ts +0 -350
  342. package/src/sextant/draw-agents.ts +0 -273
  343. package/src/sextant/draw-code.ts +0 -388
  344. package/src/sextant/draw-context.ts +0 -222
  345. package/src/sextant/draw-frame.ts +0 -164
  346. package/src/sextant/draw-market.ts +0 -573
  347. package/src/sextant/draw-messages.ts +0 -386
  348. package/src/sextant/draw-pet.ts +0 -230
  349. package/src/sextant/draw-plan.ts +0 -187
  350. package/src/sextant/draw-tabs.ts +0 -85
  351. package/src/sextant/draw-util.ts +0 -65
  352. package/src/sextant/draw-wizard.ts +0 -378
  353. package/src/sextant/engine.ts +0 -230
  354. package/src/sextant/frame-hits.ts +0 -25
  355. package/src/sextant/frame.ts +0 -101
  356. package/src/sextant/git-status.ts +0 -197
  357. package/src/sextant/grid.ts +0 -59
  358. package/src/sextant/input.ts +0 -119
  359. package/src/sextant/keys.ts +0 -521
  360. package/src/sextant/layout.ts +0 -86
  361. package/src/sextant/local-commands.ts +0 -169
  362. package/src/sextant/market-source.ts +0 -287
  363. package/src/sextant/mentions.ts +0 -200
  364. package/src/sextant/message-hits.ts +0 -26
  365. package/src/sextant/model.ts +0 -387
  366. package/src/sextant/overlays.ts +0 -456
  367. package/src/sextant/panel-hits.ts +0 -38
  368. package/src/sextant/pet.ts +0 -399
  369. package/src/sextant/screen.ts +0 -324
  370. package/src/sextant/scroll-hits.ts +0 -66
  371. package/src/sextant/scrollbar.ts +0 -82
  372. package/src/sextant/sextant-bridge.ts +0 -174
  373. package/src/sextant/sextant-cards.ts +0 -142
  374. package/src/sextant/sextant-diff-base.ts +0 -63
  375. package/src/sextant/sextant-files.ts +0 -154
  376. package/src/sextant/sextant-frame-loop.ts +0 -335
  377. package/src/sextant/sextant-renderer.ts +0 -574
  378. package/src/sextant/sextant-repo.ts +0 -140
  379. package/src/sextant/theme.ts +0 -66
  380. package/src/sextant/tool-rows.ts +0 -189
  381. package/src/sextant/types.ts +0 -493
  382. package/src/skills/index.ts +0 -387
  383. package/src/skills/pack.ts +0 -220
  384. package/src/skills/spec.ts +0 -162
  385. package/src/skills/tools.ts +0 -69
  386. package/src/skills/versioned.ts +0 -227
  387. package/src/telemetry/otel-export.ts +0 -122
  388. package/src/telemetry/otel-lanes.ts +0 -89
  389. package/src/telemetry/otel-logs.ts +0 -131
  390. package/src/telemetry/otel-metrics.ts +0 -136
  391. package/src/telemetry/otel.ts +0 -397
  392. package/src/telemetry/otlp.ts +0 -76
  393. package/src/tools/ask-user.ts +0 -156
  394. package/src/tools/bash-bg.ts +0 -94
  395. package/src/tools/bash-jobs.ts +0 -237
  396. package/src/tools/design.ts +0 -151
  397. package/src/tools/evalcell.ts +0 -338
  398. package/src/tools/html-text.ts +0 -139
  399. package/src/tools/provider.ts +0 -149
  400. package/src/tools/task.ts +0 -250
  401. package/src/tools/todo.ts +0 -320
  402. package/src/tools/webfetch.ts +0 -332
  403. package/src/tools/websearch.ts +0 -359
  404. package/src/tui/agents-cmd.ts +0 -41
  405. package/src/tui/app.ts +0 -749
  406. package/src/tui/attach.ts +0 -127
  407. package/src/tui/boot-notes.ts +0 -41
  408. package/src/tui/builtin-prompts.ts +0 -59
  409. package/src/tui/checkpoints-cmd.ts +0 -70
  410. package/src/tui/clipboard-image.ts +0 -81
  411. package/src/tui/clipboard.ts +0 -78
  412. package/src/tui/commands.ts +0 -283
  413. package/src/tui/config-view.ts +0 -53
  414. package/src/tui/context-cmds.ts +0 -282
  415. package/src/tui/cost.ts +0 -108
  416. package/src/tui/crash-guard.ts +0 -173
  417. package/src/tui/focus-terminal.ts +0 -34
  418. package/src/tui/git-cmds.ts +0 -273
  419. package/src/tui/git-plain.ts +0 -58
  420. package/src/tui/info-cmd.ts +0 -150
  421. package/src/tui/input-plain.ts +0 -76
  422. package/src/tui/mcp-cmd.ts +0 -128
  423. package/src/tui/memory-note.ts +0 -77
  424. package/src/tui/modes-cmd.ts +0 -45
  425. package/src/tui/notify-seq.ts +0 -100
  426. package/src/tui/notify.ts +0 -318
  427. package/src/tui/overlays.ts +0 -97
  428. package/src/tui/pi-renderer.ts +0 -428
  429. package/src/tui/providers-cmd.ts +0 -377
  430. package/src/tui/reasoning-view.ts +0 -56
  431. package/src/tui/renderer.ts +0 -128
  432. package/src/tui/replay-marker.ts +0 -29
  433. package/src/tui/session-cmd.ts +0 -148
  434. package/src/tui/session-manage.ts +0 -95
  435. package/src/tui/sextant-attach.ts +0 -102
  436. package/src/tui/sextant-io.ts +0 -202
  437. package/src/tui/sextant-smoke.ts +0 -110
  438. package/src/tui/shell-cmd.ts +0 -158
  439. package/src/tui/smoke.ts +0 -72
  440. package/src/tui/staged-terminal.ts +0 -50
  441. package/src/tui/startup.ts +0 -12
  442. package/src/tui/theme.ts +0 -59
  443. package/src/tui/todo-label.ts +0 -7
  444. package/src/tui/trust-card.ts +0 -107
  445. package/src/tui/tui-commands.ts +0 -87
  446. package/tsconfig.json +0 -30
  447. package/vendor/pi-tui/LICENSE +0 -21
  448. package/vendor/pi-tui/PATCHES.md +0 -12
  449. package/vendor/pi-tui/PROVENANCE.md +0 -12
  450. package/vendor/pi-tui/README.upstream.md +0 -854
  451. package/vendor/pi-tui/native/win32/prebuilds/win32-arm64/win32-console-mode.node +0 -0
  452. package/vendor/pi-tui/native/win32/prebuilds/win32-x64/win32-console-mode.node +0 -0
  453. package/vendor/pi-tui/src/alt-screen-search.ts +0 -158
  454. package/vendor/pi-tui/src/autocomplete.ts +0 -827
  455. package/vendor/pi-tui/src/components/alt-screen-flash.ts +0 -52
  456. package/vendor/pi-tui/src/components/box.ts +0 -138
  457. package/vendor/pi-tui/src/components/cancellable-loader.ts +0 -41
  458. package/vendor/pi-tui/src/components/editor.ts +0 -2364
  459. package/vendor/pi-tui/src/components/h-stack.ts +0 -45
  460. package/vendor/pi-tui/src/components/image.ts +0 -128
  461. package/vendor/pi-tui/src/components/input.ts +0 -448
  462. package/vendor/pi-tui/src/components/loader.ts +0 -93
  463. package/vendor/pi-tui/src/components/markdown.ts +0 -1016
  464. package/vendor/pi-tui/src/components/scroll-view.ts +0 -217
  465. package/vendor/pi-tui/src/components/select-list.ts +0 -230
  466. package/vendor/pi-tui/src/components/settings-list.ts +0 -277
  467. package/vendor/pi-tui/src/components/spacer.ts +0 -29
  468. package/vendor/pi-tui/src/components/stack.ts +0 -155
  469. package/vendor/pi-tui/src/components/text.ts +0 -108
  470. package/vendor/pi-tui/src/components/truncated-text.ts +0 -66
  471. package/vendor/pi-tui/src/components/v-stack.ts +0 -34
  472. package/vendor/pi-tui/src/editor-component.ts +0 -75
  473. package/vendor/pi-tui/src/fuzzy.ts +0 -138
  474. package/vendor/pi-tui/src/index.ts +0 -149
  475. package/vendor/pi-tui/src/keybindings.ts +0 -321
  476. package/vendor/pi-tui/src/keys.ts +0 -1402
  477. package/vendor/pi-tui/src/kill-ring.ts +0 -47
  478. package/vendor/pi-tui/src/latex.ts +0 -1381
  479. package/vendor/pi-tui/src/layout-node.ts +0 -52
  480. package/vendor/pi-tui/src/layout.ts +0 -411
  481. package/vendor/pi-tui/src/native-modifiers.ts +0 -60
  482. package/vendor/pi-tui/src/native-module-path.ts +0 -32
  483. package/vendor/pi-tui/src/stdin-buffer.ts +0 -445
  484. package/vendor/pi-tui/src/terminal-colors.ts +0 -74
  485. package/vendor/pi-tui/src/terminal-image.ts +0 -701
  486. package/vendor/pi-tui/src/terminal.ts +0 -554
  487. package/vendor/pi-tui/src/tui-alt-screen.ts +0 -1379
  488. package/vendor/pi-tui/src/tui-main-screen.ts +0 -655
  489. package/vendor/pi-tui/src/tui.ts +0 -1264
  490. package/vendor/pi-tui/src/undo-stack.ts +0 -29
  491. package/vendor/pi-tui/src/utils.ts +0 -1327
  492. package/vendor/pi-tui/src/word-navigation.ts +0 -118
  493. package/vendor/pi-tui/test/test-themes.ts +0 -39
  494. package/vendor/pi-tui/test/virtual-terminal.ts +0 -219
  495. /package/{src/providers → dist/cli}/models-index.json +0 -0
@@ -1,324 +0,0 @@
1
- /** ported from the user's sextant v0.4.0 prototype, src/term.js (Screen, sgr) — cell buffer + diff flush + SGR */
2
- /* Pure over an injected Sink: no process access, no clock. The renderer (#44) owns stdout, resize
3
- events and the frame interval; this module only turns a cell buffer into the minimal byte stream
4
- that repaints what changed. Additions over the prototype: truecolor → xterm-256 quantization,
5
- East-Asian width measurement (a width-2 glyph occupies two cells; a later write over either half
6
- breaks the glyph into spaces so borders stay put), zero-width code points (combining marks, VS16,
7
- ZWJ and the glyph it joins) ride on the cell before them so the terminal cursor never ends left of
8
- the buffer, frame glyphs measure 1 cell even under ambiguousAsWide, and control characters never
9
- reach a cell (toText()/flush cannot leak stray escape bytes). */
10
-
11
- import { eastAsianWidth } from "get-east-asian-width";
12
- import { hex } from "./theme.ts";
13
- import { ATTR, type ScreenLike, type Seg, type Style } from "./types.ts";
14
-
15
- export const ESC = "\x1b";
16
- export const CSI = ESC + "[";
17
- /** the prototype's floor (Screen.resize); layout() clamps to the same numbers */
18
- export const MIN_COLS = 40;
19
- export const MIN_ROWS = 12;
20
-
21
- export interface Sink { write(s: string): void }
22
- export interface Cursor { x: number; y: number }
23
- export interface ScreenOptions {
24
- /** emit 38;2/48;2 truecolor SGR (default true); false quantizes to the xterm 256 cube (38;5/48;5) */
25
- truecolor?: boolean;
26
- /** count East-Asian-ambiguous text (◆, ¡ …) as 2 cells; default false. Frame glyphs (box drawing,
27
- * block elements, …) stay 1 cell either way — the option measures content, never the frame */
28
- ambiguousAsWide?: boolean;
29
- }
30
- /** one buffer cell for tests/panels: width 2 = a wide glyph, 0 = the continuation half of one;
31
- * ch holds the glyph plus any zero-width code points that joined it (e + U+0301, ZWJ sequences) */
32
- export interface Cell { ch: string; fg: number; bg: number; a: number; width: number }
33
-
34
- /* ------------------------------------------------------------ width */
35
-
36
- /** zero-width code points join the glyph before them: combining marks (Mn/Me), format characters
37
- * (Cf — ZWSP/ZWNJ/ZWJ U+200B–D, BOM, tags…) and variation selectors U+FE00–0F. Nothing below
38
- * U+0300 qualifies (U+00AD soft hyphen stays 1 as in wcwidth), which keeps Latin text off the regex. */
39
- const ZERO_WIDTH_RE = /^[\p{Mn}\p{Me}\p{Cf}\u200B-\u200D\uFE00-\uFE0F]$/u;
40
- const isZeroWidth = (cp: number): boolean => cp >= 0x300 && ZERO_WIDTH_RE.test(String.fromCodePoint(cp));
41
- /** Box Drawing + Block Elements (U+2500–259F) and the ellipsis: a frame is 1 cell whatever ambiguousAsWide says */
42
- const isFrameGlyph = (cp: number): boolean => (cp >= 0x2500 && cp < 0x25a0) || cp === 0x2026;
43
- const ZWJ = 0x200d;
44
- const CONTROL_RE = /[\x00-\x1f\x7f-\x9f]/g;
45
-
46
- /** display width of one code point: 0 (joins the previous glyph), else 1 or 2 via get-east-asian-width;
47
- * no wide/ambiguous code point exists below U+1100/U+00A1 */
48
- export function charWidth(cp: number, ambiguousAsWide = false): 0 | 1 | 2 {
49
- if (cp < 0x80) return 1;
50
- if (isZeroWidth(cp)) return 0;
51
- if (ambiguousAsWide ? isFrameGlyph(cp) : cp < 0x1100) return 1;
52
- return eastAsianWidth(cp, { ambiguousAsWide });
53
- }
54
-
55
- /** a string as cells, [text, width] per glyph: zero-width code points — and the code point a ZWJ
56
- * joins — ride on the glyph before them; a leading one has nothing to join and is dropped */
57
- export function* glyphs(s: string, ambiguousAsWide = false): Generator<[string, 1 | 2], void> {
58
- let cur = "", cw: 1 | 2 = 1, join = false;
59
- for (const c of s) {
60
- const cp = c.codePointAt(0)!;
61
- const w = charWidth(cp, ambiguousAsWide);
62
- if (cur && (w === 0 || (join && cp >= 0x80))) { cur += c; join = cp === ZWJ; continue; }
63
- if (w === 0) continue;
64
- if (cur) yield [cur, cw];
65
- cur = c; cw = w; join = false;
66
- }
67
- if (cur) yield [cur, cw];
68
- }
69
-
70
- /** display width of a string in cells (control characters count as the space they become) */
71
- export function strWidth(s: string, ambiguousAsWide = false): number {
72
- let w = 0;
73
- for (const [, cw] of glyphs(s, ambiguousAsWide)) w += cw;
74
- return w;
75
- }
76
-
77
- /* ------------------------------------------------------------ colors */
78
-
79
- const CUBE = [0, 95, 135, 175, 215, 255] as const;
80
- /** xterm's default 16 ANSI colors — so color256() covers every index; sgr() never emits 0-15 */
81
- const ANSI16 = [0x000000, 0x800000, 0x008000, 0x808000, 0x000080, 0x800080, 0x008080, 0xc0c0c0, 0x808080, 0xff0000, 0x00ff00, 0xffff00, 0x0000ff, 0xff00ff, 0x00ffff, 0xffffff];
82
- /** nearest cube level for one channel (the 0/95/135/175/215/255 ramp) */
83
- const cubeLevel = (v: number): number => (v < 48 ? 0 : v < 115 ? 1 : Math.min(5, Math.floor((v - 35) / 40)));
84
- function dist2(a: number, b: number): number {
85
- const dr = ((a >> 16) & 255) - ((b >> 16) & 255), dg = ((a >> 8) & 255) - ((b >> 8) & 255), db = (a & 255) - (b & 255);
86
- return dr * dr + dg * dg + db * db;
87
- }
88
-
89
- /** packed rgb of an xterm-256 palette index */
90
- export function color256(i: number): number {
91
- if (i < 16) return ANSI16[i] ?? 0;
92
- if (i < 232) { const k = i - 16; return (CUBE[Math.floor(k / 36)]! << 16) | (CUBE[Math.floor(k / 6) % 6]! << 8) | CUBE[k % 6]!; }
93
- const g = 8 + 10 * Math.min(23, i - 232);
94
- return (g << 16) | (g << 8) | g;
95
- }
96
-
97
- /** nearest xterm-256 index (16..255) for a packed rgb: the 6×6×6 cube or the 24-step gray ramp, whichever is closer */
98
- export function quantize256(c: number): number {
99
- const r = (c >> 16) & 255, g = (c >> 8) & 255, b = c & 255;
100
- const cube = 16 + 36 * cubeLevel(r) + 6 * cubeLevel(g) + cubeLevel(b);
101
- const gray = 232 + Math.max(0, Math.min(23, Math.round(((r + g + b) / 3 - 8) / 10)));
102
- return dist2(c, color256(gray)) < dist2(c, color256(cube)) ? gray : cube;
103
- }
104
-
105
- /** SGR for a cell style: reset + attribute bits + fg/bg (truecolor 38;2 or quantized 38;5); -1 = default color */
106
- export function sgr(fg: number, bg: number, a: number, truecolor = true): string {
107
- let s = CSI + "0";
108
- if (a & ATTR.BOLD) s += ";1";
109
- if (a & ATTR.DIM) s += ";2";
110
- if (a & ATTR.ITALIC) s += ";3";
111
- if (a & ATTR.UNDERLINE) s += ";4";
112
- if (a & ATTR.INVERSE) s += ";7";
113
- if (a & ATTR.STRIKE) s += ";9";
114
- if (fg >= 0) s += truecolor ? `;38;2;${(fg >> 16) & 255};${(fg >> 8) & 255};${fg & 255}` : `;38;5;${quantize256(fg)}`;
115
- if (bg >= 0) s += truecolor ? `;48;2;${(bg >> 16) & 255};${(bg >> 8) & 255};${bg & 255}` : `;48;5;${quantize256(bg)}`;
116
- return s + "m";
117
- }
118
-
119
- /* ------------------------------------------------------------ screen */
120
-
121
- interface Prev { ch: (string | null)[]; fg: Int32Array; bg: Int32Array; at: Uint8Array }
122
-
123
- export class Screen implements ScreenLike {
124
- w = 0;
125
- h = 0;
126
- private ch: string[] = [];
127
- /** cell widths: 1, 2 (wide glyph) or 0 (continuation half of the wide glyph to its left) */
128
- private wd = new Uint8Array(0);
129
- private fg = new Int32Array(0);
130
- private bg = new Int32Array(0);
131
- private at = new Uint8Array(0);
132
- private prev: Prev | null = null;
133
- private readonly truecolor: boolean;
134
- private readonly ambiguousAsWide: boolean;
135
-
136
- constructor(private readonly sink: Sink, cols: number, rows: number, opts: ScreenOptions = {}) {
137
- this.truecolor = opts.truecolor ?? true;
138
- this.ambiguousAsWide = opts.ambiguousAsWide ?? false;
139
- this.resize(cols, rows);
140
- }
141
-
142
- /** (re)allocate the buffer at ≥ 40×12; the next flush repaints everything */
143
- resize(cols: number, rows: number): void {
144
- this.w = Math.max(MIN_COLS, Number.isFinite(cols) ? Math.floor(cols) : 0);
145
- this.h = Math.max(MIN_ROWS, Number.isFinite(rows) ? Math.floor(rows) : 0);
146
- const n = this.w * this.h;
147
- this.ch = new Array<string>(n).fill(" ");
148
- this.wd = new Uint8Array(n).fill(1);
149
- this.fg = new Int32Array(n).fill(-1);
150
- this.bg = new Int32Array(n).fill(-1);
151
- this.at = new Uint8Array(n);
152
- this.prev = null;
153
- }
154
-
155
- /** start a frame: every cell becomes a plain space over the given background */
156
- begin(bg?: number): void {
157
- this.ch.fill(" "); this.wd.fill(1); this.fg.fill(-1); this.bg.fill(bg == null ? -1 : bg); this.at.fill(0);
158
- }
159
-
160
- cellAt(x: number, y: number): Cell | null {
161
- if (x < 0 || y < 0 || x >= this.w || y >= this.h) return null;
162
- const i = y * this.w + x;
163
- return { ch: this.ch[i]!, fg: this.fg[i]!, bg: this.bg[i]!, a: this.at[i]!, width: this.wd[i]! };
164
- }
165
-
166
- /** a write over either half of a wide glyph turns its other half into a space */
167
- private breakWide(i: number): void {
168
- const w = this.wd[i];
169
- if (w === 0 && i > 0) { this.ch[i - 1] = " "; this.wd[i - 1] = 1; }
170
- else if (w === 2 && i + 1 < this.wd.length) { this.ch[i + 1] = " "; this.wd[i + 1] = 1; }
171
- }
172
-
173
- private set(i: number, c: string, w: 1 | 2, fg: number, bg: number, a: number): void {
174
- this.breakWide(i);
175
- if (w === 2) this.breakWide(i + 1);
176
- this.ch[i] = c; this.wd[i] = w; this.fg[i] = fg; if (bg >= 0) this.bg[i] = bg; this.at[i] = a;
177
- if (w === 2) { this.ch[i + 1] = ""; this.wd[i + 1] = 0; this.fg[i + 1] = fg; if (bg >= 0) this.bg[i + 1] = bg; this.at[i + 1] = a; }
178
- }
179
-
180
- /** the longest prefix of s that fits in w cells */
181
- private head(s: string, w: number): string {
182
- let out = "", used = 0;
183
- for (const [g, cw] of glyphs(s, this.ambiguousAsWide)) {
184
- if (used + cw > w) break;
185
- out += g; used += cw;
186
- }
187
- return out;
188
- }
189
-
190
- /** write a string; returns the x after the last cell written. bg < 0 keeps the cell's background. */
191
- put(x: number, y: number, str: string, st?: Style, maxW = Infinity): number {
192
- if (y < 0 || y >= this.h || !str) return x;
193
- const fg = st ? st.fg : -1, bg = st ? st.bg : -1, a = st ? st.a : 0;
194
- let cx = x;
195
- const end = Math.min(this.w, x + maxW);
196
- for (const [g, cw] of glyphs(str.replace(CONTROL_RE, " "), this.ambiguousAsWide)) {
197
- if (cx >= end) break;
198
- if (cw === 2 && cx + 2 > end) break; // a wide glyph that does not fit is dropped, never half-drawn
199
- if (cx >= 0) this.set(y * this.w + cx, g, cw, fg, bg, a);
200
- cx += cw;
201
- }
202
- return cx;
203
- }
204
-
205
- /** write segments clipped to maxW; returns the x after the last cell */
206
- text(x: number, y: number, segs: readonly Seg[], maxW = Infinity): number {
207
- let cx = x;
208
- const end = x + maxW;
209
- for (const [s, st] of segs) {
210
- if (cx >= end) break;
211
- cx = this.put(cx, y, s, st, end - cx);
212
- }
213
- return cx;
214
- }
215
-
216
- /** clipped text with a trailing ellipsis when it does not fit (measured in cells) */
217
- clip(x: number, y: number, str: string, st: Style | undefined, maxW: number): number {
218
- if (maxW <= 0) return x;
219
- if (strWidth(str, this.ambiguousAsWide) > maxW) str = maxW > 1 ? this.head(str, maxW - 1) + "…" : this.head(str, maxW);
220
- return this.put(x, y, str, st, maxW);
221
- }
222
-
223
- fill(x: number, y: number, w: number, h: number, ch: string, st?: Style): void {
224
- const fg = st ? st.fg : -1, bg = st ? st.bg : -1, a = st ? st.a : 0;
225
- let cp = ch.replace(CONTROL_RE, " ").codePointAt(0) ?? 0x20;
226
- if (isZeroWidth(cp)) cp = 0x20; // a lone zero-width glyph has nothing to join (and a 0-cell step would never advance)
227
- const g = String.fromCodePoint(cp), cw = charWidth(cp, this.ambiguousAsWide) || 1;
228
- for (let yy = y; yy < y + h; yy++) {
229
- if (yy < 0 || yy >= this.h) continue;
230
- for (let xx = x; xx < x + w; xx += cw) {
231
- if (xx < 0 || xx + cw > this.w || xx + cw > x + w) continue;
232
- this.set(yy * this.w + xx, g, cw, fg, bg, a);
233
- }
234
- }
235
- }
236
-
237
- /** recolor a rectangle's background only */
238
- tint(x: number, y: number, w: number, h: number, bg: number): void {
239
- for (let yy = y; yy < y + h; yy++) {
240
- if (yy < 0 || yy >= this.h) continue;
241
- for (let xx = x; xx < x + w; xx++) {
242
- if (xx < 0 || xx >= this.w) continue;
243
- this.bg[yy * this.w + xx] = bg;
244
- }
245
- }
246
- }
247
-
248
- hline(x: number, y: number, w: number, st?: Style, ch = "─"): void { for (let i = 0; i < w; i++) this.put(x + i, y, ch, st); }
249
- vline(x: number, y: number, h: number, st?: Style, ch = "│"): void { for (let i = 0; i < h; i++) this.put(x, y + i, ch, st); }
250
-
251
- /** rounded box; bgFill paints the interior first when given */
252
- box(x: number, y: number, w: number, h: number, st?: Style, bgFill?: number): void {
253
- if (bgFill != null) this.fill(x, y, w, h, " ", { fg: -1, bg: bgFill, a: 0 });
254
- this.put(x, y, "╭", st); this.put(x + w - 1, y, "╮", st);
255
- this.put(x, y + h - 1, "╰", st); this.put(x + w - 1, y + h - 1, "╯", st);
256
- this.hline(x + 1, y, w - 2, st); this.hline(x + 1, y + h - 1, w - 2, st);
257
- this.vline(x, y + 1, h - 2, st); this.vline(x + w - 1, y + 1, h - 2, st);
258
- }
259
-
260
- /** emit the difference to the previous flush: full paint (ESC[2J) on the first frame or after
261
- * resize, otherwise only changed cells — a cursor move only where the run is discontiguous, an
262
- * SGR only when the style changes, and never the bottom-right cell (terminals may scroll on it). */
263
- flush(cursor?: Cursor | null): void {
264
- const n = this.w * this.h;
265
- let full = false;
266
- if (!this.prev || this.prev.ch.length !== n) {
267
- this.prev = { ch: new Array<string | null>(n).fill(null), fg: new Int32Array(n).fill(-2), bg: new Int32Array(n).fill(-2), at: new Uint8Array(n).fill(255) };
268
- full = true;
269
- }
270
- const p = this.prev;
271
- let out = full ? CSI + "2J" : "";
272
- let cfg: number | null = null, cbg: number | null = null, cat: number | null = null, lx = -1, ly = -1;
273
- const last = n - 1;
274
- for (let y = 0; y < this.h; y++) {
275
- for (let x = 0; x < this.w; x++) {
276
- const i = y * this.w + x;
277
- const wd = this.wd[i]!;
278
- if (wd === 0) continue; // continuation half: painted together with its glyph
279
- if (i + wd - 1 >= last) continue; // scroll guard: the last cell (or a glyph spilling into it) is never written
280
- if (!full && this.ch[i] === p.ch[i] && this.fg[i] === p.fg[i] && this.bg[i] === p.bg[i] && this.at[i] === p.at[i]) continue;
281
- if (!(ly === y && lx === x)) out += CSI + (y + 1) + ";" + (x + 1) + "H";
282
- const fg = this.fg[i]!, bg = this.bg[i]!, at = this.at[i]!;
283
- if (fg !== cfg || bg !== cbg || at !== cat) { out += sgr(fg, bg, at, this.truecolor); cfg = fg; cbg = bg; cat = at; }
284
- out += this.ch[i]!;
285
- lx = x + wd; ly = y;
286
- p.ch[i] = this.ch[i]!; p.fg[i] = fg; p.bg[i] = bg; p.at[i] = at;
287
- if (wd === 2) { p.ch[i + 1] = ""; p.fg[i + 1] = fg; p.bg[i + 1] = bg; p.at[i + 1] = at; }
288
- }
289
- }
290
- out += cursor ? CSI + (cursor.y + 1) + ";" + (cursor.x + 1) + "H" + CSI + "?25h" : CSI + "?25l";
291
- this.sink.write(out);
292
- }
293
-
294
- /** plain-text dump: one line per row, trailing whitespace removed, no escape bytes ever */
295
- toText(): string {
296
- const lines: string[] = [];
297
- for (let y = 0; y < this.h; y++) lines.push(this.ch.slice(y * this.w, (y + 1) * this.w).join("").replace(/\s+$/, ""));
298
- return lines.join("\n");
299
- }
300
-
301
- /** html dump with colors (debug/screenshots) */
302
- toHTML(font = "Cascadia Mono"): string {
303
- let html = "";
304
- for (let y = 0; y < this.h; y++) {
305
- let row = "", run = "";
306
- let cur: Style | null = null;
307
- const flushRun = (): void => {
308
- if (!run || !cur) return;
309
- const s = cur;
310
- row += `<span style="color:${s.fg >= 0 ? hex(s.fg) : "inherit"};background:${s.bg >= 0 ? hex(s.bg) : "transparent"};${s.a & ATTR.BOLD ? "font-weight:600;" : ""}${s.a & ATTR.ITALIC ? "font-style:italic;" : ""}${s.a & ATTR.STRIKE ? "text-decoration:line-through;" : ""}">${run.replace(/&/g, "&amp;").replace(/</g, "&lt;")}</span>`;
311
- run = "";
312
- };
313
- for (let x = 0; x < this.w; x++) {
314
- const i = y * this.w + x;
315
- const s: Style = { fg: this.fg[i]!, bg: this.bg[i]!, a: this.at[i]! };
316
- if (!cur || cur.fg !== s.fg || cur.bg !== s.bg || cur.a !== s.a) { flushRun(); cur = s; }
317
- run += this.ch[i]!;
318
- }
319
- flushRun();
320
- html += row + "\n";
321
- }
322
- return `<!doctype html><meta charset="utf-8"><body style="margin:0;background:#000"><pre style="margin:0;font:14px/1.25 '${font}',Consolas,monospace;display:inline-block">${html}</pre></body>`;
323
- }
324
- }
@@ -1,66 +0,0 @@
1
- /** Scrollbar thumbs as grab zones (types.ts HitZone.onDrag). Each painter draws its bar from a
2
- * handful of numbers — track x/y/h, content rows, viewport rows, offset (draw-messages.ts:338,
3
- * draw-frame.ts:111, draw-code.ts:385). The same numbers rebuilt here give the thumb's rect; a drag
4
- * slides the thumb by `dy` rows from where it was painted and maps that back onto an offset, so the
5
- * thumb stays under the finger wherever it was grabbed. */
6
- import { codeScrollTop, RAIL_W, rowCount } from "./draw-code.ts";
7
- import { areas, messagesScroll } from "./draw-messages.ts";
8
- import { inner } from "./draw-util.ts";
9
- import { scrollbarGeom, thumbRect, type ScrollbarGeom } from "./scrollbar.ts";
10
- import type { HitZone, Layout, Page, SextantState, Theme, TreeRow } from "./types.ts";
11
-
12
- /** the content offset after sliding the thumb `dy` rows from where it was painted (clamped) */
13
- export function slideOffset(g: ScrollbarGeom, dy: number, total: number, viewport: number): number {
14
- const range = Math.max(0, total - viewport), track = g.trackH - g.thumbH;
15
- if (track <= 0 || range === 0) return 0;
16
- const top = Math.max(g.trackY, Math.min(g.trackY + track, g.thumbY + dy));
17
- return Math.round((top - g.trackY) / track * range);
18
- }
19
-
20
- function thumbZone(g: ScrollbarGeom, total: number, viewport: number, set: (offset: number) => void): HitZone | null {
21
- if (!g.visible) return null;
22
- return { rect: thumbRect(g), onClick: () => {}, onDrag: (_y, dy) => set(slideOffset(g, dy, total, viewport)) };
23
- }
24
-
25
- /** Wheeling the messages up unsticks the view from the tail; once the person scrolls back down to the end
26
- * (wheel, drag, keys) the view follows the tail again — otherwise a conversation that has been scrolled
27
- * once never follows new text until pgdn/end. Called by the frame loop after the paint. */
28
- export function followTailIfAtEnd(L: Layout, s: SextantState, theme: Theme, now: number): void {
29
- if (s.stick) return;
30
- const { max } = messagesScroll(L.messages, s, theme, now);
31
- if (s.msgScroll >= max) { s.stick = true; s.msgScroll = max; }
32
- }
33
-
34
- /** one zone per visible scrollbar thumb: messages, the files tree (in its panel or paged into the
35
- * main slot), and the code panel in a scrolling mode (file / diff / search; run and agents tail) */
36
- export function scrollThumbHits(L: Layout, main: Page, s: SextantState, theme: Theme, now: number, rows: TreeRow[]): HitZone[] {
37
- const out: HitZone[] = [];
38
- {
39
- const B = inner(L.messages);
40
- const { msgH } = areas(B, s);
41
- const { offset, max } = messagesScroll(L.messages, s, theme, now);
42
- const total = max + msgH;
43
- const z = thumbZone(scrollbarGeom(B.x + B.w - 1, B.y, msgH, total, msgH, offset), total, msgH,
44
- (o) => { s.msgScroll = o; s.stick = o >= max; }); // dragged to the bottom = follow the tail again
45
- if (z) out.push(z);
46
- }
47
- // the files painter re-clamps scroll around the cursor, so the cursor is pulled into the new window
48
- const filesRect = L.files ?? (main === "files" ? L.code : null);
49
- if (filesRect) {
50
- const B = inner(filesRect);
51
- const z = thumbZone(scrollbarGeom(B.x + B.w - 1, B.y, B.h, rows.length, B.h, s.files.scroll), rows.length, B.h,
52
- (o) => { s.files.scroll = o; s.files.cursor = Math.max(o, Math.min(s.files.cursor, o + B.h - 1)); });
53
- if (z) out.push(z);
54
- }
55
- const c = s.code;
56
- if (main === "code" && (c.mode === "code" || c.mode === "diff" || c.mode === "search")) {
57
- const B = inner(L.code);
58
- if (B.w >= RAIL_W + 2) {
59
- const total = rowCount(s, B.w - RAIL_W - 2), top = codeScrollTop(L.code, s);
60
- const z = thumbZone(scrollbarGeom(B.x + B.w - RAIL_W - 1, B.y, B.h, total, B.h, top), total, B.h,
61
- (o) => { c.scroll = o; });
62
- if (z) out.push(z);
63
- }
64
- }
65
- return out;
66
- }
@@ -1,82 +0,0 @@
1
- /** Sextant surface — shared one-column scrollbar painter.
2
- * Pure: no I/O, no timers, no state mutation. All geometry is exported so a
3
- * caller can hang a mouse hit-zone on the thumb rectangle. */
4
-
5
- import type { Rect, ScreenLike, Theme } from "./types.ts";
6
- import { st } from "./theme.ts";
7
-
8
- /** Geometry for a vertical scrollbar track.
9
- * When `visible` is false, no other fields are meaningful. */
10
- export interface ScrollbarGeom {
11
- /** column the bar occupies */
12
- x: number;
13
- /** first row of the track */
14
- trackY: number;
15
- /** number of rows in the track */
16
- trackH: number;
17
- /** first row of the thumb (absolute) */
18
- thumbY: number;
19
- /** number of rows the thumb spans (≥ 1 when visible) */
20
- thumbH: number;
21
- visible: boolean;
22
- }
23
-
24
- /** Compute scrollbar geometry without drawing.
25
- * @param x - column for the bar
26
- * @param trackY - first row of the track
27
- * @param trackH - track height (rows)
28
- * @param total - total content rows
29
- * @param viewport - visible rows (same unit as total)
30
- * @param offset - first visible row (0-based)
31
- */
32
- export function scrollbarGeom(
33
- x: number,
34
- trackY: number,
35
- trackH: number,
36
- total: number,
37
- viewport: number,
38
- offset: number,
39
- ): ScrollbarGeom {
40
- const visible = total > viewport && trackH >= 2;
41
- if (!visible) return { x, trackY, trackH, thumbY: trackY, thumbH: 0, visible: false };
42
- const thumbH = Math.max(1, Math.round(trackH * viewport / total));
43
- const scrollRange = Math.max(1, total - viewport);
44
- const trackRange = Math.max(0, trackH - thumbH);
45
- const rawThumbY = trackY + Math.round(trackRange * Math.max(0, offset) / scrollRange);
46
- const thumbY = Math.min(rawThumbY, trackY + trackH - thumbH);
47
- return { x, trackY, trackH, thumbY, thumbH, visible: true };
48
- }
49
-
50
- /** Paint the scrollbar described by `geom`.
51
- * Track: thin `│` in theme.rule; thumb: `▌` in theme.dim. */
52
- export function drawScrollbar(scr: ScreenLike, geom: ScrollbarGeom, theme: Theme): void {
53
- if (!geom.visible) return;
54
- const trackSt = st(theme.rule);
55
- const thumbSt = st(theme.dim);
56
- for (let i = 0; i < geom.trackH; i++) {
57
- const y = geom.trackY + i;
58
- const inThumb = y >= geom.thumbY && y < geom.thumbY + geom.thumbH;
59
- scr.put(geom.x, y, inThumb ? "▌" : "│", inThumb ? thumbSt : trackSt);
60
- }
61
- }
62
-
63
- /** Convenience: compute + draw in one call; returns the geometry (for hit-zone export). */
64
- export function scrollbar(
65
- scr: ScreenLike,
66
- theme: Theme,
67
- x: number,
68
- trackY: number,
69
- trackH: number,
70
- total: number,
71
- viewport: number,
72
- offset: number,
73
- ): ScrollbarGeom {
74
- const geom = scrollbarGeom(x, trackY, trackH, total, viewport, offset);
75
- drawScrollbar(scr, geom, theme);
76
- return geom;
77
- }
78
-
79
- /** A Rect covering the thumb — useful for registering a mouse hit-zone. */
80
- export function thumbRect(geom: ScrollbarGeom): Rect {
81
- return { x: geom.x, y: geom.thumbY, w: 1, h: geom.thumbH };
82
- }
@@ -1,174 +0,0 @@
1
- /** Sextant bridge (port #44): pure helpers between rovecode's app/Renderer seam and the surface state —
2
- * a user line → row (image chips split off), a replayed tool card → row, how many duplicate app
3
- * notes a RunEvent triggers (the #41 reducer already produced the row), and the RunEvent / TaskInfo
4
- * → rovecode forwarding table (#45's report: start/read/edit/write/remove/run/glob/plan/spawn/
5
- * permission/fetch/crew/tinker on starts — every tool says its specific thing, a risky command gets
6
- * the risk line — + observe over written content and edit newLines; grep's count, tool_fail/pass/fail + a fail-line
7
- * reaction on tool ends; denied on a permission refusal; done/stopped/error at run_end; laneDone /
8
- * laneFail from the task manager). Pure: `now` is a parameter, no I/O, no timers. */
9
-
10
- import type { RunEvent } from "../core/types.ts";
11
- import type { TaskInfo } from "../core/tasks.ts";
12
- import type { Pet, PetEventData } from "./pet.ts";
13
- import { baseName, describeCall, relPath } from "./tool-rows.ts";
14
- import { splitAttached } from "./mentions.ts";
15
- import type { MessageRow, ToolRow } from "./types.ts";
16
-
17
- type UserRow = Extract<MessageRow, { kind: "user" }>;
18
- const CHIP_RE = /\[image: ([^\]]*)\]/g;
19
- const TEST_CMD = /\b(tests?|vitest|jest|pytest|mocha|spec)\b/i;
20
- /** commands worth a second look before they run: recursive deletes, force pushes, history rewrites,
21
- * world-writable modes, piping the network into a shell, dropping tables */
22
- const RISKY_CMD = /\brm\s+(-[a-z]*r[a-z]*f|-[a-z]*f[a-z]*r)\b|--force\b|\bpush\s+-f\b|\breset\s+--hard\b|\bchmod\s+777\b|\bcurl\b[^|]*\|\s*(ba|z)?sh\b|\bdrop\s+(table|database)\b/i;
23
- const RUN_TOOLS = new Set(["bash", "shell", "run"]);
24
- const REMOVE_TOOLS = new Set(["remove", "rm", "delete", "unlink"]);
25
-
26
- const rec = (v: unknown): Record<string, unknown> => (v && typeof v === "object" && !Array.isArray(v) ? (v as Record<string, unknown>) : {});
27
- const str = (v: unknown): string => (typeof v === "string" ? v : "");
28
- const oneLine = (s: string, max = 40): string => s.replace(/\s+/g, " ").trim().slice(0, max);
29
-
30
- /** tui/attach.ts userTurnLine: the text, then ONE line of `[image: name]` chips (or chips alone) */
31
- export function userRow(line: string, now: number): UserRow {
32
- const lines = line.split("\n");
33
- const last = lines[lines.length - 1] ?? "";
34
- const chips = [...last.matchAll(CHIP_RE)].map((m) => m[1]!);
35
- const chipLine = chips.length > 0 && last.replace(CHIP_RE, "").trim() === "";
36
- // `@file` read blocks (mentions.ts) stay out of the panel: the typed text and one chip per file
37
- const { text, files } = splitAttached((chipLine ? lines.slice(0, -1) : lines).join("\n"));
38
- const row: UserRow = { kind: "user", text, at: now };
39
- if (chipLine) row.images = chips;
40
- if (files.length > 0) row.files = files;
41
- return row;
42
- }
43
-
44
- /** args for a replayed tool card: session-cmd replayTranscript hands the renderer a ≤120-char JSON
45
- * slice — the whole object when it still parses, else the path/command/pattern/url/question/label
46
- * fields recovered from the intact prefix (a truncated escape yields nothing for that key) */
47
- export function argsFromPreview(preview: string): Record<string, unknown> {
48
- try {
49
- const v: unknown = JSON.parse(preview);
50
- if (v && typeof v === "object" && !Array.isArray(v)) return v as Record<string, unknown>;
51
- } catch { /* truncated — fall through */ }
52
- const out: Record<string, unknown> = {};
53
- for (const k of ["path", "command", "pattern", "url", "question", "label"]) {
54
- const m = new RegExp(`"${k}":"((?:[^"\\\\]|\\\\.)*)"`).exec(preview);
55
- if (!m) continue;
56
- try { out[k] = JSON.parse(`"${m[1]}"`); } catch { /* unterminated escape */ }
57
- }
58
- return out;
59
- }
60
-
61
- /** a replayed tool card (the renderer is NOT busy: session history) → a settled row; toolEnd fills ok/detail */
62
- export function replayToolRow(callId: string, tool: string, argsPreview: string, cwd: string): ToolRow {
63
- const d = describeCall(tool, argsFromPreview(argsPreview), cwd);
64
- const row: ToolRow = { kind: "tool", callId, tool, verb: d.verb, label: d.label, running: false };
65
- if (d.path) row.path = d.path;
66
- if (d.verb === "edit" || d.verb === "write") { row.add = d.add; row.del = d.del; }
67
- return row;
68
- }
69
-
70
- /** how many addSystemNote calls app.ts makes for this event that duplicate a reducer row: the
71
- * compaction note, "↪ steering applied", and the run_end error/warn line (none for `done`) — the
72
- * renderer drops exactly that many, and only those */
73
- export function duplicateNotes(ev: RunEvent): number {
74
- if (ev.type === "compaction" || ev.type === "steer") return 1;
75
- if (ev.type === "run_end") return ev.status === "done" ? 0 : 1;
76
- return 0;
77
- }
78
-
79
- /** what the renderer remembers per live call so the end event can find its tool/command */
80
- export interface LiveCall { tool: string; cmd: string }
81
-
82
- /** RunEvent → rovecode (see the header table) */
83
- export function petOnEvent(pet: Pet, ev: RunEvent, calls: Map<string, LiveCall>, cwd: string, now: number): void {
84
- switch (ev.type) {
85
- case "run_start": pet.event("start", undefined, now); break;
86
- case "tool_execution_start": {
87
- const a = rec(ev.args), f = baseName(relPath(cwd, str(a.path))) || "file";
88
- calls.set(ev.callId, { tool: ev.tool, cmd: str(a.command) || str(a.cmd) });
89
- petOnStart(pet, ev.tool, a, f, now);
90
- break;
91
- }
92
- case "tool_execution_end": {
93
- const c = calls.get(ev.callId);
94
- calls.delete(ev.callId);
95
- petOnEnd(pet, c, ev.ok, ev.output, now);
96
- break;
97
- }
98
- case "tool_call_failed":
99
- calls.delete(ev.callId);
100
- pet.event(ev.reason === "permission_denied" ? "denied" : "tool_fail", undefined, now);
101
- break;
102
- case "run_end":
103
- calls.clear();
104
- pet.event(ev.status === "done" ? "done" : ev.status === "error" ? "error" : "stopped", undefined, now);
105
- break;
106
- default: break;
107
- }
108
- }
109
-
110
- /** the host of a URL for the fetch quip; a bare or broken URL keeps its first 30 chars */
111
- const hostOf = (u: string): string => { try { return new URL(u).host || oneLine(u, 30); } catch { return oneLine(u, 30) || "the web"; } };
112
-
113
- /** Every tool the agent has says something SPECIFIC — the file, the pattern, the host, the child,
114
- * the thing being tinkered with — because a bubble that only says "working" is worse than silence.
115
- * Kinds are the existing ones where they fit (a directory listing is a read, an ask is a permission,
116
- * a search start is glob's line with the pattern); fetch / crew / tinker are the three acts that
117
- * had none. Unknown tools (an MCP server's own, a future one) fall to tinker with their name. */
118
- function petOnStart(pet: Pet, tool: string, a: Record<string, unknown>, f: string, now: number): void {
119
- const data: PetEventData = { f };
120
- if (tool === "read") pet.event("read", data, now);
121
- else if (tool === "edit") {
122
- pet.event("edit", data, now);
123
- const lines = (Array.isArray(a.edits) ? a.edits : []).flatMap((e) => { const nl = rec(e).newLines; return Array.isArray(nl) ? nl.map(String) : []; });
124
- if (lines.length) pet.observe(lines.join("\n"), "ins", now);
125
- } else if (tool === "write") { pet.event("write", data, now); if (str(a.content)) pet.observe(str(a.content), "ins", now); }
126
- else if (REMOVE_TOOLS.has(tool)) pet.event("remove", data, now);
127
- else if (RUN_TOOLS.has(tool)) {
128
- // a destructive-looking command gets the risk line instead of "thunder time" — keyed off the
129
- // command text the agent asked for, never off an error message (the validator owns those)
130
- const cmd = str(a.command) || str(a.cmd);
131
- if (RISKY_CMD.test(cmd)) pet.react("risk", now); else pet.event("run", undefined, now);
132
- }
133
- else if (tool === "glob" || tool === "grep") pet.event("glob", { q: oneLine(str(a.pattern), 24) || "it" }, now);
134
- else if (tool === "ls") pet.event("read", { f: (baseName(str(a.path)) || ".") + "/" }, now);
135
- else if (tool === "web_fetch") pet.event("fetch", { f: hostOf(str(a.url)) }, now);
136
- else if (tool === "todo_write") { const n = Array.isArray(a.todos) ? a.todos.length : 0; if (n) pet.event("plan", { n }, now); }
137
- else if (tool === "todo_read") pet.event("read", { f: "the plan" }, now);
138
- else if (tool === "ask_user") pet.event("permission", undefined, now);
139
- else if (tool === "task") pet.event("spawn", { a: oneLine(str(a.label) || str(a.agent) || "a worker", 20) }, now);
140
- else if (tool === "task_status") pet.event("crew", { a: str(a.action) === "list" ? "the crew" : oneLine(str(a.id), 20) || "the crew" }, now);
141
- else pet.event("tinker", { f: tinkerTarget(tool, a) }, now);
142
- }
143
-
144
- /** what the housekeeping tools are about, by name: `providers`, `skills`, `memory`, `notes`, `search/issues` */
145
- function tinkerTarget(tool: string, a: Record<string, unknown>): string {
146
- if (tool.startsWith("provider_")) return str(a.action) === "use" && str(a.selector) ? oneLine(str(a.selector), 24) : "providers";
147
- if (tool === "skill_view") return oneLine(str(a.name) || str(a.skill), 24) || "a skill";
148
- if (tool === "skills_list") return "the skills";
149
- if (tool === "memory_edit") return "memory";
150
- if (tool === "recall") return oneLine(str(a.query), 24) ? `notes on ${oneLine(str(a.query), 24)}` : "the notes";
151
- if (tool === "eval_cell") return "a scratch cell";
152
- if (tool === "mcp_call" || tool === "mcp_list") return [str(a.server), str(a.tool)].filter(Boolean).map((s) => oneLine(s, 16)).join(" ") || "mcp";
153
- return oneLine(tool, 24);
154
- }
155
-
156
- function petOnEnd(pet: Pet, c: LiveCall | undefined, ok: boolean, output: string, now: number): void {
157
- if (c && RUN_TOOLS.has(c.tool)) {
158
- const lines = output.replace(/^exit=-?\d+\r?\n?/, "").split(/\r?\n/).filter((l) => l.trim());
159
- const r = oneLine(lines[lines.length - 1] ?? "");
160
- if (TEST_CMD.test(c.cmd)) pet.event(ok ? "pass" : "fail", { r }, now);
161
- else if (!ok) pet.event("tool_fail", undefined, now);
162
- if (lines.some((l) => /^\s*FAIL\b/.test(l))) pet.react("fail-line", now);
163
- else if (ok && lines.some((l) => /^\s*PASS\b/.test(l))) pet.react("pass-line", now);
164
- return;
165
- }
166
- if (!ok) { pet.event("tool_fail", undefined, now); return; }
167
- if (c?.tool === "grep") pet.event("grep", { n: output.split(/\r?\n/).filter((l) => l.trim() && !l.startsWith("(")).length }, now);
168
- }
169
-
170
- /** TaskManager status transitions → laneDone / laneFail quips (queued/running/cancelled say nothing) */
171
- export function petOnTask(pet: Pet, t: TaskInfo, now: number): void {
172
- if (t.status === "done") pet.event("laneDone", { a: oneLine(t.label, 20), r: oneLine(t.summary ?? "done") }, now);
173
- else if (t.status === "failed") pet.event("laneFail", { a: oneLine(t.label, 20), r: oneLine(t.error ?? "failed") }, now);
174
- }