rovecode 0.3.2 → 0.4.0-beta.2

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 (491) hide show
  1. package/CHANGELOG.md +512 -0
  2. package/README.md +33 -45
  3. package/bin/rovecode.js +24 -0
  4. package/dist/cli/app-dybnr56b.js +2 -0
  5. package/dist/cli/ask-user-p8hq4xgj.js +2 -0
  6. package/dist/cli/auth-login-ewpgw5sm.js +2 -0
  7. package/dist/cli/auth-m8p9grty.js +2 -0
  8. package/dist/cli/bench-xv3ypwev.js +9 -0
  9. package/dist/cli/catalog-737wb2s0.js +2 -0
  10. package/dist/cli/cli-arhg40m0.js +2 -0
  11. package/dist/cli/client-cf2pxx8q.js +2 -0
  12. package/dist/cli/commands-3p7e4xxs.js +2 -0
  13. package/dist/cli/connect-3q93d7cb.js +2 -0
  14. package/dist/cli/context-cmd-eqxmxhzq.js +2 -0
  15. package/dist/cli/context-report-hbw9zfes.js +2 -0
  16. package/dist/cli/count-remote-mby98cd0.js +2 -0
  17. package/dist/cli/design-122y0axd.js +2 -0
  18. package/dist/cli/dispatch-b4egzvvh.js +2 -0
  19. package/dist/cli/doctor-x4jkv72e.js +3 -0
  20. package/dist/cli/executor-ftvg6tsy.js +2 -0
  21. package/dist/cli/export-pdgdhkch.js +2 -0
  22. package/dist/cli/files-cez9a96p.js +2 -0
  23. package/dist/cli/gauntlet-r3xxaszc.js +2 -0
  24. package/dist/cli/gauntlet-runner-r515m7kk.js +10 -0
  25. package/dist/cli/gauntlet-wave3-bnkjk2v2.js +5 -0
  26. package/dist/cli/gauntlet-wave4-acs9s60q.js +14 -0
  27. package/dist/cli/hashline-ewg5hbe3.js +2 -0
  28. package/dist/cli/http-n0kehsk8.js +5 -0
  29. package/dist/cli/index-z5qt1s76.js +2 -0
  30. package/dist/cli/install-80mp63kx.js +2 -0
  31. package/dist/cli/loop-12twjcat.js +2 -0
  32. package/dist/cli/main-01pv9206.js +4 -0
  33. package/dist/cli/main-0jys2ccn.js +3 -0
  34. package/dist/cli/main-1ztz6fkj.js +10 -0
  35. package/dist/cli/main-23q7cmww.js +9 -0
  36. package/dist/cli/main-2rzbexn2.js +3 -0
  37. package/dist/cli/main-2wyax8k9.js +9 -0
  38. package/dist/cli/main-2yeveeve.js +6 -0
  39. package/dist/cli/main-2z3dek0b.js +3 -0
  40. package/dist/cli/main-2zgsknth.js +3 -0
  41. package/dist/cli/main-45ejth3a.js +4 -0
  42. package/dist/cli/main-45rn3trk.js +22 -0
  43. package/dist/cli/main-4p4e2w7x.js +4 -0
  44. package/dist/cli/main-4y0tnfpa.js +16 -0
  45. package/dist/cli/main-5py0rkmc.js +4 -0
  46. package/dist/cli/main-6dtqmbt6.js +7 -0
  47. package/dist/cli/main-6h9x282m.js +4 -0
  48. package/dist/cli/main-6vjeds42.js +3 -0
  49. package/dist/cli/main-78gq4bt9.js +6 -0
  50. package/dist/cli/main-7jd5vh3x.js +4 -0
  51. package/dist/cli/main-7kt6r53y.js +4 -0
  52. package/dist/cli/main-8c1tbazx.js +58 -0
  53. package/dist/cli/main-9a9rnh47.js +19 -0
  54. package/dist/cli/main-9ht36z12.js +3 -0
  55. package/dist/cli/main-a2yfvcy9.js +7 -0
  56. package/dist/cli/main-a3f51n0x.js +5 -0
  57. package/dist/cli/main-b8zq261k.js +3 -0
  58. package/dist/cli/main-bxtvnf6d.js +13 -0
  59. package/dist/cli/main-edxc3yzt.js +4 -0
  60. package/dist/cli/main-evgz4mp5.js +21 -0
  61. package/dist/cli/main-f33fc5je.js +9 -0
  62. package/dist/cli/main-fvnpq46y.js +12 -0
  63. package/dist/cli/main-gbbty4d4.js +3 -0
  64. package/dist/cli/main-gth53dnt.js +25 -0
  65. package/dist/cli/main-hqbz10aw.js +9 -0
  66. package/dist/cli/main-hrrvcfan.js +38 -0
  67. package/dist/cli/main-hzwtsb2m.js +5 -0
  68. package/dist/cli/main-j7ttv0sd.js +34 -0
  69. package/dist/cli/main-jak598k9.js +5 -0
  70. package/dist/cli/main-kba6zeyd.js +6 -0
  71. package/dist/cli/main-kwwsz6rq.js +3 -0
  72. package/dist/cli/main-m8vm17zq.js +3 -0
  73. package/dist/cli/main-mg4f96e1.js +3 -0
  74. package/dist/cli/main-mg9b20ac.js +18 -0
  75. package/dist/cli/main-mgb9ccnx.js +3 -0
  76. package/dist/cli/main-mjt2p7aj.js +3 -0
  77. package/dist/cli/main-n6qrdbmy.js +3 -0
  78. package/dist/cli/main-na7wse0x.js +5 -0
  79. package/dist/cli/main-nqveez48.js +4 -0
  80. package/dist/cli/main-ntqef02r.js +10 -0
  81. package/dist/cli/main-nvc3yjay.js +136 -0
  82. package/dist/cli/main-p0cfn6nr.js +16 -0
  83. package/dist/cli/main-qj2djy17.js +19 -0
  84. package/dist/cli/main-qsevpgsv.js +3 -0
  85. package/dist/cli/main-qvarybsp.js +3 -0
  86. package/dist/cli/main-rebtt91r.js +5 -0
  87. package/dist/cli/main-rpg7h8mb.js +3 -0
  88. package/dist/cli/main-rsy72qmw.js +15 -0
  89. package/dist/cli/main-rvetps99.js +18 -0
  90. package/dist/cli/main-s4bb0jav.js +3 -0
  91. package/dist/cli/main-s9v8k74e.js +3 -0
  92. package/dist/cli/main-tjvwmscs.js +3 -0
  93. package/dist/cli/main-tkgarpjj.js +4 -0
  94. package/dist/cli/main-v8y60bb2.js +3 -0
  95. package/dist/cli/main-vhrrq337.js +3 -0
  96. package/dist/cli/main-vp2dfb7s.js +4 -0
  97. package/dist/cli/main-vqbr22sz.js +8 -0
  98. package/dist/cli/main-vxnwe5xx.js +18 -0
  99. package/dist/cli/main-wgph00xf.js +5 -0
  100. package/dist/cli/main-wk2csfnj.js +5 -0
  101. package/dist/cli/main-wm997zjx.js +3 -0
  102. package/dist/cli/main-wpkyraxh.js +3 -0
  103. package/dist/cli/main-wqt32p5x.js +4 -0
  104. package/dist/cli/main-x9ct6y1a.js +3 -0
  105. package/dist/cli/main-xfekqh9m.js +7 -0
  106. package/dist/cli/main-xt9zc3n6.js +7 -0
  107. package/dist/cli/main-xx2z3zh5.js +4 -0
  108. package/dist/cli/main-y5c82rxr.js +3 -0
  109. package/dist/cli/main-yrjt2sqt.js +14 -0
  110. package/dist/cli/main-ys6zj3yr.js +3 -0
  111. package/dist/cli/main-ywbxshqc.js +8 -0
  112. package/dist/cli/main-z13755t8.js +25 -0
  113. package/dist/cli/main-zc7pyrbj.js +4 -0
  114. package/dist/cli/main.js +279 -0
  115. package/dist/cli/market-cmd-bm5xvn9f.js +5 -0
  116. package/dist/cli/mcp-login-bthtfpt7.js +2 -0
  117. package/dist/cli/mcp-market-cmd-mbeshfyd.js +2 -0
  118. package/dist/cli/notify-54v5z9dz.js +2 -0
  119. package/dist/cli/oauth-g5gme95c.js +2 -0
  120. package/dist/cli/output-satndjap.js +16 -0
  121. package/dist/cli/profiles-sfhpbq3m.js +2 -0
  122. package/dist/cli/provider-config-hv3xtdt4.js +2 -0
  123. package/dist/cli/provider-kwzq6g84.js +2 -0
  124. package/dist/cli/registry-fh0hdnyn.js +2 -0
  125. package/dist/cli/registry-y1y8e94r.js +2 -0
  126. package/dist/cli/repl-t4z03mqq.js +11 -0
  127. package/dist/cli/resume-fqt4chg8.js +2 -0
  128. package/dist/cli/run-flags-rysbag9t.js +2 -0
  129. package/dist/cli/runtime-j19fjbsa.js +2 -0
  130. package/dist/cli/sandbox-config-g4qxd7y5.js +2 -0
  131. package/dist/cli/server-r0b6bksk.js +5 -0
  132. package/dist/cli/session-arg-txmn5g4x.js +2 -0
  133. package/dist/cli/session-ed250d9j.js +2 -0
  134. package/dist/cli/sessions-cmd-adw7svfn.js +7 -0
  135. package/dist/cli/settings-y9rzcqx8.js +2 -0
  136. package/dist/cli/setup-jmbr11j0.js +2 -0
  137. package/dist/cli/sextant-smoke-tcth0vea.js +5 -0
  138. package/dist/cli/skills-cmd-zbdy99v6.js +2 -0
  139. package/dist/cli/smoke-1bg937kx.js +8 -0
  140. package/dist/cli/start-chat-p01cdks3.js +12 -0
  141. package/dist/cli/stream-4wmyaypz.js +2 -0
  142. package/dist/cli/task-eg4s093s.js +2 -0
  143. package/dist/cli/tasks-12v9rr9k.js +2 -0
  144. package/dist/cli/thinking-a5ngvqyh.js +2 -0
  145. package/dist/cli/todo-1wxpcecx.js +2 -0
  146. package/dist/cli/tools-2ftsya7w.js +2 -0
  147. package/dist/cli/tools-x1tj4fxm.js +2 -0
  148. package/dist/cli/trust-cmd-hccxehzb.js +2 -0
  149. package/dist/cli/update-check-ygt3vd7m.js +2 -0
  150. package/dist/cli/update-cmd-v23qhr8c.js +2 -0
  151. package/dist/cli/voice-g1gtck92.js +2 -0
  152. package/dist/cli/webfetch-0nnrjgb5.js +2 -0
  153. package/dist/cli/websearch-f0vr2p7d.js +2 -0
  154. package/dist/cli/workspace-9rq1w4ta.js +2 -0
  155. package/dist/lib/index.js +62 -0
  156. package/dist/lib/models-index.json +1 -0
  157. package/dist/lib/plugins.js +6 -0
  158. package/dist/lib/providers.js +17 -0
  159. package/dist/lib/public-api.js +20 -0
  160. package/dist/rovecode.exe +4 -0
  161. package/package.json +38 -11
  162. package/bin/rovecode.ts +0 -21
  163. package/src/acp/server.ts +0 -374
  164. package/src/cli/auth-login.ts +0 -122
  165. package/src/cli/connect.ts +0 -244
  166. package/src/cli/context-cmd.ts +0 -199
  167. package/src/cli/dispatch.ts +0 -82
  168. package/src/cli/doctor.ts +0 -362
  169. package/src/cli/export.ts +0 -276
  170. package/src/cli/help.ts +0 -293
  171. package/src/cli/is-tui-invocation.ts +0 -8
  172. package/src/cli/main.ts +0 -583
  173. package/src/cli/market-cmd.ts +0 -658
  174. package/src/cli/mcp-login.ts +0 -141
  175. package/src/cli/mcp-market-cmd.ts +0 -302
  176. package/src/cli/output.ts +0 -382
  177. package/src/cli/repl.ts +0 -250
  178. package/src/cli/repomap-root.ts +0 -14
  179. package/src/cli/resume.ts +0 -57
  180. package/src/cli/run-flags.ts +0 -43
  181. package/src/cli/run-limits.ts +0 -78
  182. package/src/cli/runtime.ts +0 -931
  183. package/src/cli/session-arg.ts +0 -30
  184. package/src/cli/sessions-cmd.ts +0 -145
  185. package/src/cli/setup.ts +0 -153
  186. package/src/cli/skills-cmd.ts +0 -194
  187. package/src/cli/start-chat.ts +0 -65
  188. package/src/cli/trust-cmd.ts +0 -52
  189. package/src/coding/bash.ts +0 -148
  190. package/src/coding/checkpoints.ts +0 -327
  191. package/src/coding/diff.ts +0 -138
  192. package/src/coding/files.ts +0 -341
  193. package/src/coding/hashline.ts +0 -274
  194. package/src/coding/lsp-gate.ts +0 -254
  195. package/src/coding/lsp-servers.ts +0 -147
  196. package/src/coding/lsp.ts +0 -283
  197. package/src/coding/repomap-cache.ts +0 -99
  198. package/src/coding/repomap-files.ts +0 -192
  199. package/src/coding/repomap.ts +0 -481
  200. package/src/core/agents.ts +0 -255
  201. package/src/core/compaction.ts +0 -259
  202. package/src/core/config.ts +0 -289
  203. package/src/core/context-report.ts +0 -228
  204. package/src/core/context.ts +0 -60
  205. package/src/core/count-remote.ts +0 -107
  206. package/src/core/execpolicy-rules.ts +0 -196
  207. package/src/core/execpolicy.ts +0 -385
  208. package/src/core/executor.ts +0 -454
  209. package/src/core/guardrails.ts +0 -400
  210. package/src/core/hooks.ts +0 -411
  211. package/src/core/images.ts +0 -230
  212. package/src/core/intro.ts +0 -266
  213. package/src/core/loop.ts +0 -567
  214. package/src/core/modes.ts +0 -372
  215. package/src/core/orchestrator.ts +0 -245
  216. package/src/core/proc-group.ts +0 -48
  217. package/src/core/project-trust.ts +0 -98
  218. package/src/core/reflection.ts +0 -165
  219. package/src/core/sandbox-config.ts +0 -186
  220. package/src/core/session-id.ts +0 -24
  221. package/src/core/session-images.ts +0 -73
  222. package/src/core/session-ops.ts +0 -183
  223. package/src/core/session-text.ts +0 -29
  224. package/src/core/session.ts +0 -469
  225. package/src/core/settings.ts +0 -170
  226. package/src/core/tasks.ts +0 -646
  227. package/src/core/token-scale.ts +0 -108
  228. package/src/core/tools.ts +0 -309
  229. package/src/core/trust.ts +0 -104
  230. package/src/core/types.ts +0 -330
  231. package/src/core/update-check.ts +0 -171
  232. package/src/core/usage.ts +0 -204
  233. package/src/core/validate.ts +0 -121
  234. package/src/core/verify-gate.ts +0 -159
  235. package/src/core/verify.ts +0 -236
  236. package/src/core/voice.ts +0 -158
  237. package/src/core/win-job.ts +0 -183
  238. package/src/core/workspace.ts +0 -184
  239. package/src/design/audit.ts +0 -797
  240. package/src/design/direction.ts +0 -190
  241. package/src/design/rules.ts +0 -157
  242. package/src/eval/bench.ts +0 -150
  243. package/src/eval/gauntlet-runner.ts +0 -215
  244. package/src/eval/gauntlet-support.ts +0 -84
  245. package/src/eval/gauntlet-wave3.ts +0 -269
  246. package/src/eval/gauntlet-wave4.ts +0 -217
  247. package/src/eval/gauntlet.ts +0 -253
  248. package/src/index.ts +0 -17
  249. package/src/lanes/agy.ts +0 -95
  250. package/src/lanes/approval.ts +0 -24
  251. package/src/lanes/claude.ts +0 -129
  252. package/src/lanes/codex.ts +0 -127
  253. package/src/lanes/events.ts +0 -130
  254. package/src/lanes/job.ts +0 -142
  255. package/src/lanes/opencode.ts +0 -122
  256. package/src/lanes/process.ts +0 -184
  257. package/src/lanes/progress.ts +0 -183
  258. package/src/lanes/registry.ts +0 -178
  259. package/src/lanes/runner.ts +0 -124
  260. package/src/lanes/types.ts +0 -112
  261. package/src/market/catalogs/mcp-docs.json +0 -111
  262. package/src/market/catalogs/plugins.json +0 -111
  263. package/src/market/catalogs/skills.json +0 -478
  264. package/src/market/clone.ts +0 -72
  265. package/src/market/context-cost.ts +0 -121
  266. package/src/market/digest.ts +0 -106
  267. package/src/market/index.ts +0 -22
  268. package/src/market/install.ts +0 -578
  269. package/src/market/manifest.ts +0 -187
  270. package/src/market/prereq.ts +0 -145
  271. package/src/market/registry.ts +0 -363
  272. package/src/market/resolve.ts +0 -111
  273. package/src/market/types.ts +0 -236
  274. package/src/market/validate.ts +0 -227
  275. package/src/mcp/client.ts +0 -449
  276. package/src/mcp/config.ts +0 -252
  277. package/src/mcp/local-package.ts +0 -211
  278. package/src/mcp/market-catalog.ts +0 -84
  279. package/src/mcp/market-install.ts +0 -289
  280. package/src/mcp/market.ts +0 -362
  281. package/src/mcp/oauth.ts +0 -251
  282. package/src/mcp/prompts-resources.ts +0 -249
  283. package/src/mcp/shared.ts +0 -149
  284. package/src/mcp/status.ts +0 -67
  285. package/src/mcp/tools.ts +0 -275
  286. package/src/mcp/transport.ts +0 -122
  287. package/src/mcp/trust.ts +0 -25
  288. package/src/memory/blocks.ts +0 -278
  289. package/src/memory/recall.ts +0 -355
  290. package/src/memory/scope.ts +0 -182
  291. package/src/memory/store.ts +0 -105
  292. package/src/memory/tools.ts +0 -99
  293. package/src/plugins/cli.ts +0 -119
  294. package/src/plugins/discover.ts +0 -108
  295. package/src/plugins/index.ts +0 -50
  296. package/src/plugins/install.ts +0 -184
  297. package/src/plugins/load.ts +0 -124
  298. package/src/plugins/manifest.ts +0 -92
  299. package/src/plugins/state.ts +0 -83
  300. package/src/providers/auth.ts +0 -408
  301. package/src/providers/cache.ts +0 -223
  302. package/src/providers/catalog-local.ts +0 -160
  303. package/src/providers/catalog.ts +0 -421
  304. package/src/providers/middleware-context.ts +0 -86
  305. package/src/providers/middleware.ts +0 -373
  306. package/src/providers/model-list.ts +0 -23
  307. package/src/providers/oauth/common.ts +0 -105
  308. package/src/providers/oauth/device-code.ts +0 -107
  309. package/src/providers/oauth/github-copilot.ts +0 -146
  310. package/src/providers/oauth/loopback.ts +0 -158
  311. package/src/providers/oauth/openai.ts +0 -163
  312. package/src/providers/oauth/openrouter.ts +0 -89
  313. package/src/providers/oauth/pkce.ts +0 -45
  314. package/src/providers/oauth/registry.ts +0 -39
  315. package/src/providers/oauth/seam.ts +0 -89
  316. package/src/providers/profile-glm53.ts +0 -111
  317. package/src/providers/profile-sonnet5-persona.ts +0 -65
  318. package/src/providers/profile-sonnet5-voice.ts +0 -23
  319. package/src/providers/profiles.ts +0 -156
  320. package/src/providers/provider-config.ts +0 -311
  321. package/src/providers/registry.ts +0 -333
  322. package/src/providers/responses.ts +0 -209
  323. package/src/providers/retry.ts +0 -234
  324. package/src/providers/router.ts +0 -294
  325. package/src/providers/sse.ts +0 -26
  326. package/src/providers/stream-errors.ts +0 -117
  327. package/src/providers/stream.ts +0 -566
  328. package/src/providers/thinking.ts +0 -189
  329. package/src/providers/wire-messages.ts +0 -129
  330. package/src/providers/wire-responses.ts +0 -79
  331. package/src/providers/wire-select.ts +0 -53
  332. package/src/server/http.ts +0 -291
  333. package/src/server/openapi.ts +0 -246
  334. package/src/sextant/card-hits.ts +0 -102
  335. package/src/sextant/card-keys.ts +0 -55
  336. package/src/sextant/context-source.ts +0 -157
  337. package/src/sextant/crew-cards.ts +0 -350
  338. package/src/sextant/draw-agents.ts +0 -273
  339. package/src/sextant/draw-code.ts +0 -388
  340. package/src/sextant/draw-context.ts +0 -222
  341. package/src/sextant/draw-frame.ts +0 -164
  342. package/src/sextant/draw-market.ts +0 -573
  343. package/src/sextant/draw-messages.ts +0 -386
  344. package/src/sextant/draw-pet.ts +0 -230
  345. package/src/sextant/draw-plan.ts +0 -187
  346. package/src/sextant/draw-tabs.ts +0 -85
  347. package/src/sextant/draw-util.ts +0 -65
  348. package/src/sextant/draw-wizard.ts +0 -378
  349. package/src/sextant/engine.ts +0 -230
  350. package/src/sextant/frame-hits.ts +0 -25
  351. package/src/sextant/frame.ts +0 -101
  352. package/src/sextant/git-status.ts +0 -197
  353. package/src/sextant/grid.ts +0 -59
  354. package/src/sextant/input.ts +0 -119
  355. package/src/sextant/keys.ts +0 -521
  356. package/src/sextant/layout.ts +0 -86
  357. package/src/sextant/local-commands.ts +0 -169
  358. package/src/sextant/market-source.ts +0 -287
  359. package/src/sextant/mentions.ts +0 -200
  360. package/src/sextant/message-hits.ts +0 -26
  361. package/src/sextant/model.ts +0 -387
  362. package/src/sextant/overlays.ts +0 -456
  363. package/src/sextant/panel-hits.ts +0 -38
  364. package/src/sextant/pet.ts +0 -399
  365. package/src/sextant/screen.ts +0 -324
  366. package/src/sextant/scroll-hits.ts +0 -66
  367. package/src/sextant/scrollbar.ts +0 -82
  368. package/src/sextant/sextant-bridge.ts +0 -174
  369. package/src/sextant/sextant-cards.ts +0 -142
  370. package/src/sextant/sextant-diff-base.ts +0 -63
  371. package/src/sextant/sextant-files.ts +0 -154
  372. package/src/sextant/sextant-frame-loop.ts +0 -335
  373. package/src/sextant/sextant-renderer.ts +0 -574
  374. package/src/sextant/sextant-repo.ts +0 -140
  375. package/src/sextant/theme.ts +0 -66
  376. package/src/sextant/tool-rows.ts +0 -189
  377. package/src/sextant/types.ts +0 -493
  378. package/src/skills/index.ts +0 -387
  379. package/src/skills/pack.ts +0 -220
  380. package/src/skills/spec.ts +0 -162
  381. package/src/skills/tools.ts +0 -69
  382. package/src/skills/versioned.ts +0 -227
  383. package/src/telemetry/otel-export.ts +0 -122
  384. package/src/telemetry/otel-lanes.ts +0 -89
  385. package/src/telemetry/otel-logs.ts +0 -131
  386. package/src/telemetry/otel-metrics.ts +0 -136
  387. package/src/telemetry/otel.ts +0 -397
  388. package/src/telemetry/otlp.ts +0 -76
  389. package/src/tools/ask-user.ts +0 -156
  390. package/src/tools/bash-bg.ts +0 -94
  391. package/src/tools/bash-jobs.ts +0 -237
  392. package/src/tools/design.ts +0 -151
  393. package/src/tools/evalcell.ts +0 -338
  394. package/src/tools/html-text.ts +0 -139
  395. package/src/tools/provider.ts +0 -149
  396. package/src/tools/task.ts +0 -250
  397. package/src/tools/todo.ts +0 -320
  398. package/src/tools/webfetch.ts +0 -332
  399. package/src/tools/websearch.ts +0 -359
  400. package/src/tui/agents-cmd.ts +0 -41
  401. package/src/tui/app.ts +0 -749
  402. package/src/tui/attach.ts +0 -127
  403. package/src/tui/boot-notes.ts +0 -41
  404. package/src/tui/builtin-prompts.ts +0 -59
  405. package/src/tui/checkpoints-cmd.ts +0 -70
  406. package/src/tui/clipboard-image.ts +0 -81
  407. package/src/tui/clipboard.ts +0 -78
  408. package/src/tui/commands.ts +0 -283
  409. package/src/tui/config-view.ts +0 -53
  410. package/src/tui/context-cmds.ts +0 -282
  411. package/src/tui/cost.ts +0 -108
  412. package/src/tui/crash-guard.ts +0 -173
  413. package/src/tui/focus-terminal.ts +0 -34
  414. package/src/tui/git-cmds.ts +0 -273
  415. package/src/tui/git-plain.ts +0 -58
  416. package/src/tui/info-cmd.ts +0 -150
  417. package/src/tui/input-plain.ts +0 -76
  418. package/src/tui/mcp-cmd.ts +0 -128
  419. package/src/tui/memory-note.ts +0 -77
  420. package/src/tui/modes-cmd.ts +0 -45
  421. package/src/tui/notify-seq.ts +0 -100
  422. package/src/tui/notify.ts +0 -318
  423. package/src/tui/overlays.ts +0 -97
  424. package/src/tui/pi-renderer.ts +0 -428
  425. package/src/tui/providers-cmd.ts +0 -377
  426. package/src/tui/reasoning-view.ts +0 -56
  427. package/src/tui/renderer.ts +0 -128
  428. package/src/tui/replay-marker.ts +0 -29
  429. package/src/tui/session-cmd.ts +0 -148
  430. package/src/tui/session-manage.ts +0 -95
  431. package/src/tui/sextant-attach.ts +0 -102
  432. package/src/tui/sextant-io.ts +0 -202
  433. package/src/tui/sextant-smoke.ts +0 -110
  434. package/src/tui/shell-cmd.ts +0 -158
  435. package/src/tui/smoke.ts +0 -72
  436. package/src/tui/staged-terminal.ts +0 -50
  437. package/src/tui/startup.ts +0 -12
  438. package/src/tui/theme.ts +0 -59
  439. package/src/tui/todo-label.ts +0 -7
  440. package/src/tui/trust-card.ts +0 -107
  441. package/src/tui/tui-commands.ts +0 -87
  442. package/tsconfig.json +0 -30
  443. package/vendor/pi-tui/LICENSE +0 -21
  444. package/vendor/pi-tui/PATCHES.md +0 -12
  445. package/vendor/pi-tui/PROVENANCE.md +0 -12
  446. package/vendor/pi-tui/README.upstream.md +0 -854
  447. package/vendor/pi-tui/native/win32/prebuilds/win32-arm64/win32-console-mode.node +0 -0
  448. package/vendor/pi-tui/native/win32/prebuilds/win32-x64/win32-console-mode.node +0 -0
  449. package/vendor/pi-tui/src/alt-screen-search.ts +0 -158
  450. package/vendor/pi-tui/src/autocomplete.ts +0 -827
  451. package/vendor/pi-tui/src/components/alt-screen-flash.ts +0 -52
  452. package/vendor/pi-tui/src/components/box.ts +0 -138
  453. package/vendor/pi-tui/src/components/cancellable-loader.ts +0 -41
  454. package/vendor/pi-tui/src/components/editor.ts +0 -2364
  455. package/vendor/pi-tui/src/components/h-stack.ts +0 -45
  456. package/vendor/pi-tui/src/components/image.ts +0 -128
  457. package/vendor/pi-tui/src/components/input.ts +0 -448
  458. package/vendor/pi-tui/src/components/loader.ts +0 -93
  459. package/vendor/pi-tui/src/components/markdown.ts +0 -1016
  460. package/vendor/pi-tui/src/components/scroll-view.ts +0 -217
  461. package/vendor/pi-tui/src/components/select-list.ts +0 -230
  462. package/vendor/pi-tui/src/components/settings-list.ts +0 -277
  463. package/vendor/pi-tui/src/components/spacer.ts +0 -29
  464. package/vendor/pi-tui/src/components/stack.ts +0 -155
  465. package/vendor/pi-tui/src/components/text.ts +0 -108
  466. package/vendor/pi-tui/src/components/truncated-text.ts +0 -66
  467. package/vendor/pi-tui/src/components/v-stack.ts +0 -34
  468. package/vendor/pi-tui/src/editor-component.ts +0 -75
  469. package/vendor/pi-tui/src/fuzzy.ts +0 -138
  470. package/vendor/pi-tui/src/index.ts +0 -149
  471. package/vendor/pi-tui/src/keybindings.ts +0 -321
  472. package/vendor/pi-tui/src/keys.ts +0 -1402
  473. package/vendor/pi-tui/src/kill-ring.ts +0 -47
  474. package/vendor/pi-tui/src/latex.ts +0 -1381
  475. package/vendor/pi-tui/src/layout-node.ts +0 -52
  476. package/vendor/pi-tui/src/layout.ts +0 -411
  477. package/vendor/pi-tui/src/native-modifiers.ts +0 -60
  478. package/vendor/pi-tui/src/native-module-path.ts +0 -32
  479. package/vendor/pi-tui/src/stdin-buffer.ts +0 -445
  480. package/vendor/pi-tui/src/terminal-colors.ts +0 -74
  481. package/vendor/pi-tui/src/terminal-image.ts +0 -701
  482. package/vendor/pi-tui/src/terminal.ts +0 -554
  483. package/vendor/pi-tui/src/tui-alt-screen.ts +0 -1379
  484. package/vendor/pi-tui/src/tui-main-screen.ts +0 -655
  485. package/vendor/pi-tui/src/tui.ts +0 -1264
  486. package/vendor/pi-tui/src/undo-stack.ts +0 -29
  487. package/vendor/pi-tui/src/utils.ts +0 -1327
  488. package/vendor/pi-tui/src/word-navigation.ts +0 -118
  489. package/vendor/pi-tui/test/test-themes.ts +0 -39
  490. package/vendor/pi-tui/test/virtual-terminal.ts +0 -219
  491. /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
- }