openhorse 0.1.5

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 (587) hide show
  1. package/README.md +460 -0
  2. package/bin/openhorse +56 -0
  3. package/dist/agents/coder.d.ts +12 -0
  4. package/dist/agents/coder.d.ts.map +1 -0
  5. package/dist/agents/coder.js +48 -0
  6. package/dist/agents/coder.js.map +1 -0
  7. package/dist/agents/leader.d.ts +12 -0
  8. package/dist/agents/leader.d.ts.map +1 -0
  9. package/dist/agents/leader.js +49 -0
  10. package/dist/agents/leader.js.map +1 -0
  11. package/dist/agents/router.d.ts +59 -0
  12. package/dist/agents/router.d.ts.map +1 -0
  13. package/dist/agents/router.js +193 -0
  14. package/dist/agents/router.js.map +1 -0
  15. package/dist/cli-ink.d.ts +7 -0
  16. package/dist/cli-ink.d.ts.map +1 -0
  17. package/dist/cli-ink.js +135 -0
  18. package/dist/cli-ink.js.map +1 -0
  19. package/dist/cli.d.ts +7 -0
  20. package/dist/cli.d.ts.map +1 -0
  21. package/dist/cli.js +638 -0
  22. package/dist/cli.js.map +1 -0
  23. package/dist/commands/index.d.ts +12 -0
  24. package/dist/commands/index.d.ts.map +1 -0
  25. package/dist/commands/index.js +1095 -0
  26. package/dist/commands/index.js.map +1 -0
  27. package/dist/commands/parser.d.ts +26 -0
  28. package/dist/commands/parser.d.ts.map +1 -0
  29. package/dist/commands/parser.js +61 -0
  30. package/dist/commands/parser.js.map +1 -0
  31. package/dist/commands/types.d.ts +61 -0
  32. package/dist/commands/types.d.ts.map +1 -0
  33. package/dist/commands/types.js +32 -0
  34. package/dist/commands/types.js.map +1 -0
  35. package/dist/core/agent.d.ts +66 -0
  36. package/dist/core/agent.d.ts.map +1 -0
  37. package/dist/core/agent.js +55 -0
  38. package/dist/core/agent.js.map +1 -0
  39. package/dist/core/brain.d.ts +41 -0
  40. package/dist/core/brain.d.ts.map +1 -0
  41. package/dist/core/brain.js +92 -0
  42. package/dist/core/brain.js.map +1 -0
  43. package/dist/core/cost-tracker.d.ts +107 -0
  44. package/dist/core/cost-tracker.d.ts.map +1 -0
  45. package/dist/core/cost-tracker.js +199 -0
  46. package/dist/core/cost-tracker.js.map +1 -0
  47. package/dist/core/strategy-tracker.d.ts +61 -0
  48. package/dist/core/strategy-tracker.d.ts.map +1 -0
  49. package/dist/core/strategy-tracker.js +124 -0
  50. package/dist/core/strategy-tracker.js.map +1 -0
  51. package/dist/framework/index.d.ts +20 -0
  52. package/dist/framework/index.d.ts.map +1 -0
  53. package/dist/framework/index.js +29 -0
  54. package/dist/framework/index.js.map +1 -0
  55. package/dist/framework/prompt.d.ts +40 -0
  56. package/dist/framework/prompt.d.ts.map +1 -0
  57. package/dist/framework/prompt.js +112 -0
  58. package/dist/framework/prompt.js.map +1 -0
  59. package/dist/framework/query.d.ts +86 -0
  60. package/dist/framework/query.d.ts.map +1 -0
  61. package/dist/framework/query.js +177 -0
  62. package/dist/framework/query.js.map +1 -0
  63. package/dist/framework/store.d.ts +64 -0
  64. package/dist/framework/store.d.ts.map +1 -0
  65. package/dist/framework/store.js +78 -0
  66. package/dist/framework/store.js.map +1 -0
  67. package/dist/framework/tool-state.d.ts +22 -0
  68. package/dist/framework/tool-state.d.ts.map +1 -0
  69. package/dist/framework/tool-state.js +40 -0
  70. package/dist/framework/tool-state.js.map +1 -0
  71. package/dist/framework/tool.d.ts +88 -0
  72. package/dist/framework/tool.d.ts.map +1 -0
  73. package/dist/framework/tool.js +60 -0
  74. package/dist/framework/tool.js.map +1 -0
  75. package/dist/harness/harness.d.ts +96 -0
  76. package/dist/harness/harness.d.ts.map +1 -0
  77. package/dist/harness/harness.js +224 -0
  78. package/dist/harness/harness.js.map +1 -0
  79. package/dist/harness/safety.d.ts +89 -0
  80. package/dist/harness/safety.d.ts.map +1 -0
  81. package/dist/harness/safety.js +178 -0
  82. package/dist/harness/safety.js.map +1 -0
  83. package/dist/index.d.ts +30 -0
  84. package/dist/index.d.ts.map +1 -0
  85. package/dist/index.js +57 -0
  86. package/dist/index.js.map +1 -0
  87. package/dist/init.d.ts +178 -0
  88. package/dist/init.d.ts.map +1 -0
  89. package/dist/init.js +473 -0
  90. package/dist/init.js.map +1 -0
  91. package/dist/ink/bidi.d.ts +16 -0
  92. package/dist/ink/bidi.d.ts.map +1 -0
  93. package/dist/ink/bidi.js +124 -0
  94. package/dist/ink/bidi.js.map +1 -0
  95. package/dist/ink/clearTerminal.d.ts +14 -0
  96. package/dist/ink/clearTerminal.d.ts.map +1 -0
  97. package/dist/ink/clearTerminal.js +63 -0
  98. package/dist/ink/clearTerminal.js.map +1 -0
  99. package/dist/ink/colorize.d.ts +17 -0
  100. package/dist/ink/colorize.d.ts.map +1 -0
  101. package/dist/ink/colorize.js +208 -0
  102. package/dist/ink/colorize.js.map +1 -0
  103. package/dist/ink/components/App.d.ts +73 -0
  104. package/dist/ink/components/App.d.ts.map +1 -0
  105. package/dist/ink/components/App.js +646 -0
  106. package/dist/ink/components/App.js.map +1 -0
  107. package/dist/ink/components/AppContext.d.ts +12 -0
  108. package/dist/ink/components/AppContext.d.ts.map +1 -0
  109. package/dist/ink/components/AppContext.js +14 -0
  110. package/dist/ink/components/AppContext.js.map +1 -0
  111. package/dist/ink/components/Box.d.ts +44 -0
  112. package/dist/ink/components/Box.d.ts.map +1 -0
  113. package/dist/ink/components/Box.js +191 -0
  114. package/dist/ink/components/Box.js.map +1 -0
  115. package/dist/ink/components/ClockContext.d.ts +9 -0
  116. package/dist/ink/components/ClockContext.d.ts.map +1 -0
  117. package/dist/ink/components/ClockContext.js +146 -0
  118. package/dist/ink/components/ClockContext.js.map +1 -0
  119. package/dist/ink/components/CursorDeclarationContext.d.ts +23 -0
  120. package/dist/ink/components/CursorDeclarationContext.d.ts.map +1 -0
  121. package/dist/ink/components/CursorDeclarationContext.js +6 -0
  122. package/dist/ink/components/CursorDeclarationContext.js.map +1 -0
  123. package/dist/ink/components/ErrorOverview.d.ts +6 -0
  124. package/dist/ink/components/ErrorOverview.d.ts.map +1 -0
  125. package/dist/ink/components/ErrorOverview.js +27 -0
  126. package/dist/ink/components/ErrorOverview.js.map +1 -0
  127. package/dist/ink/components/Newline.d.ts +13 -0
  128. package/dist/ink/components/Newline.d.ts.map +1 -0
  129. package/dist/ink/components/Newline.js +36 -0
  130. package/dist/ink/components/Newline.js.map +1 -0
  131. package/dist/ink/components/NoSelect.d.ts +20 -0
  132. package/dist/ink/components/NoSelect.d.ts.map +1 -0
  133. package/dist/ink/components/NoSelect.js +63 -0
  134. package/dist/ink/components/NoSelect.js.map +1 -0
  135. package/dist/ink/components/RawAnsi.d.ts +17 -0
  136. package/dist/ink/components/RawAnsi.d.ts.map +1 -0
  137. package/dist/ink/components/RawAnsi.js +52 -0
  138. package/dist/ink/components/RawAnsi.js.map +1 -0
  139. package/dist/ink/components/Spacer.d.ts +6 -0
  140. package/dist/ink/components/Spacer.d.ts.map +1 -0
  141. package/dist/ink/components/Spacer.js +26 -0
  142. package/dist/ink/components/Spacer.js.map +1 -0
  143. package/dist/ink/components/StdinContext.d.ts +28 -0
  144. package/dist/ink/components/StdinContext.d.ts.map +1 -0
  145. package/dist/ink/components/StdinContext.js +19 -0
  146. package/dist/ink/components/StdinContext.js.map +1 -0
  147. package/dist/ink/components/TerminalFocusContext.d.ts +10 -0
  148. package/dist/ink/components/TerminalFocusContext.d.ts.map +1 -0
  149. package/dist/ink/components/TerminalFocusContext.js +81 -0
  150. package/dist/ink/components/TerminalFocusContext.js.map +1 -0
  151. package/dist/ink/components/TerminalSizeContext.d.ts +6 -0
  152. package/dist/ink/components/TerminalSizeContext.d.ts.map +1 -0
  153. package/dist/ink/components/TerminalSizeContext.js +6 -0
  154. package/dist/ink/components/TerminalSizeContext.js.map +1 -0
  155. package/dist/ink/components/Text.d.ts +56 -0
  156. package/dist/ink/components/Text.d.ts.map +1 -0
  157. package/dist/ink/components/Text.js +201 -0
  158. package/dist/ink/components/Text.js.map +1 -0
  159. package/dist/ink/constants.d.ts +2 -0
  160. package/dist/ink/constants.d.ts.map +1 -0
  161. package/dist/ink/constants.js +6 -0
  162. package/dist/ink/constants.js.map +1 -0
  163. package/dist/ink/devtools.d.ts +3 -0
  164. package/dist/ink/devtools.d.ts.map +1 -0
  165. package/dist/ink/devtools.js +5 -0
  166. package/dist/ink/devtools.js.map +1 -0
  167. package/dist/ink/dom.d.ts +77 -0
  168. package/dist/ink/dom.d.ts.map +1 -0
  169. package/dist/ink/dom.js +322 -0
  170. package/dist/ink/dom.js.map +1 -0
  171. package/dist/ink/events/click-event.d.ts +32 -0
  172. package/dist/ink/events/click-event.d.ts.map +1 -0
  173. package/dist/ink/events/click-event.js +30 -0
  174. package/dist/ink/events/click-event.js.map +1 -0
  175. package/dist/ink/events/dispatcher.d.ts +41 -0
  176. package/dist/ink/events/dispatcher.d.ts.map +1 -0
  177. package/dist/ink/events/dispatcher.js +181 -0
  178. package/dist/ink/events/dispatcher.js.map +1 -0
  179. package/dist/ink/events/emitter.d.ts +6 -0
  180. package/dist/ink/events/emitter.d.ts.map +1 -0
  181. package/dist/ink/events/emitter.js +36 -0
  182. package/dist/ink/events/emitter.js.map +1 -0
  183. package/dist/ink/events/event-handlers.d.ts +47 -0
  184. package/dist/ink/events/event-handlers.d.ts.map +1 -0
  185. package/dist/ink/events/event-handlers.js +34 -0
  186. package/dist/ink/events/event-handlers.js.map +1 -0
  187. package/dist/ink/events/event.d.ts +6 -0
  188. package/dist/ink/events/event.d.ts.map +1 -0
  189. package/dist/ink/events/event.js +16 -0
  190. package/dist/ink/events/event.js.map +1 -0
  191. package/dist/ink/events/focus-event.d.ts +14 -0
  192. package/dist/ink/events/focus-event.d.ts.map +1 -0
  193. package/dist/ink/events/focus-event.js +20 -0
  194. package/dist/ink/events/focus-event.js.map +1 -0
  195. package/dist/ink/events/input-event.d.ts +31 -0
  196. package/dist/ink/events/input-event.d.ts.map +1 -0
  197. package/dist/ink/events/input-event.js +163 -0
  198. package/dist/ink/events/input-event.js.map +1 -0
  199. package/dist/ink/events/keyboard-event.d.ts +20 -0
  200. package/dist/ink/events/keyboard-event.d.ts.map +1 -0
  201. package/dist/ink/events/keyboard-event.js +44 -0
  202. package/dist/ink/events/keyboard-event.js.map +1 -0
  203. package/dist/ink/events/terminal-event.d.ts +55 -0
  204. package/dist/ink/events/terminal-event.d.ts.map +1 -0
  205. package/dist/ink/events/terminal-event.js +79 -0
  206. package/dist/ink/events/terminal-event.js.map +1 -0
  207. package/dist/ink/events/terminal-focus-event.d.ts +14 -0
  208. package/dist/ink/events/terminal-focus-event.d.ts.map +1 -0
  209. package/dist/ink/events/terminal-focus-event.js +19 -0
  210. package/dist/ink/events/terminal-focus-event.js.map +1 -0
  211. package/dist/ink/focus.d.ts +44 -0
  212. package/dist/ink/focus.d.ts.map +1 -0
  213. package/dist/ink/focus.js +164 -0
  214. package/dist/ink/focus.js.map +1 -0
  215. package/dist/ink/frame.d.ts +95 -0
  216. package/dist/ink/frame.d.ts.map +1 -0
  217. package/dist/ink/frame.js +35 -0
  218. package/dist/ink/frame.js.map +1 -0
  219. package/dist/ink/get-max-width.d.ts +18 -0
  220. package/dist/ink/get-max-width.d.ts.map +1 -0
  221. package/dist/ink/get-max-width.js +26 -0
  222. package/dist/ink/get-max-width.js.map +1 -0
  223. package/dist/ink/hit-test.d.ts +34 -0
  224. package/dist/ink/hit-test.d.ts.map +1 -0
  225. package/dist/ink/hit-test.js +119 -0
  226. package/dist/ink/hit-test.js.map +1 -0
  227. package/dist/ink/hooks/use-animation-frame.d.ts +27 -0
  228. package/dist/ink/hooks/use-animation-frame.d.ts.map +1 -0
  229. package/dist/ink/hooks/use-animation-frame.js +52 -0
  230. package/dist/ink/hooks/use-animation-frame.js.map +1 -0
  231. package/dist/ink/hooks/use-app.d.ts +6 -0
  232. package/dist/ink/hooks/use-app.d.ts.map +1 -0
  233. package/dist/ink/hooks/use-app.js +13 -0
  234. package/dist/ink/hooks/use-app.js.map +1 -0
  235. package/dist/ink/hooks/use-declared-cursor.d.ts +27 -0
  236. package/dist/ink/hooks/use-declared-cursor.d.ts.map +1 -0
  237. package/dist/ink/hooks/use-declared-cursor.js +67 -0
  238. package/dist/ink/hooks/use-declared-cursor.js.map +1 -0
  239. package/dist/ink/hooks/use-input.d.ts +38 -0
  240. package/dist/ink/hooks/use-input.d.ts.map +1 -0
  241. package/dist/ink/hooks/use-input.js +86 -0
  242. package/dist/ink/hooks/use-input.js.map +1 -0
  243. package/dist/ink/hooks/use-interval.d.ts +19 -0
  244. package/dist/ink/hooks/use-interval.d.ts.map +1 -0
  245. package/dist/ink/hooks/use-interval.js +59 -0
  246. package/dist/ink/hooks/use-interval.js.map +1 -0
  247. package/dist/ink/hooks/use-search-highlight.d.ts +31 -0
  248. package/dist/ink/hooks/use-search-highlight.d.ts.map +1 -0
  249. package/dist/ink/hooks/use-search-highlight.js +39 -0
  250. package/dist/ink/hooks/use-search-highlight.js.map +1 -0
  251. package/dist/ink/hooks/use-selection.d.ts +40 -0
  252. package/dist/ink/hooks/use-selection.d.ts.map +1 -0
  253. package/dist/ink/hooks/use-selection.js +68 -0
  254. package/dist/ink/hooks/use-selection.js.map +1 -0
  255. package/dist/ink/hooks/use-stdin.d.ts +6 -0
  256. package/dist/ink/hooks/use-stdin.d.ts.map +1 -0
  257. package/dist/ink/hooks/use-stdin.js +13 -0
  258. package/dist/ink/hooks/use-stdin.js.map +1 -0
  259. package/dist/ink/hooks/use-tab-status.d.ts +14 -0
  260. package/dist/ink/hooks/use-tab-status.d.ts.map +1 -0
  261. package/dist/ink/hooks/use-tab-status.js +61 -0
  262. package/dist/ink/hooks/use-tab-status.js.map +1 -0
  263. package/dist/ink/hooks/use-terminal-focus.d.ts +11 -0
  264. package/dist/ink/hooks/use-terminal-focus.d.ts.map +1 -0
  265. package/dist/ink/hooks/use-terminal-focus.js +22 -0
  266. package/dist/ink/hooks/use-terminal-focus.js.map +1 -0
  267. package/dist/ink/hooks/use-terminal-title.d.ts +13 -0
  268. package/dist/ink/hooks/use-terminal-title.d.ts.map +1 -0
  269. package/dist/ink/hooks/use-terminal-title.js +36 -0
  270. package/dist/ink/hooks/use-terminal-title.js.map +1 -0
  271. package/dist/ink/hooks/use-terminal-viewport.d.ts +30 -0
  272. package/dist/ink/hooks/use-terminal-viewport.d.ts.map +1 -0
  273. package/dist/ink/hooks/use-terminal-viewport.js +81 -0
  274. package/dist/ink/hooks/use-terminal-viewport.js.map +1 -0
  275. package/dist/ink/index.d.ts +54 -0
  276. package/dist/ink/index.d.ts.map +1 -0
  277. package/dist/ink/index.js +111 -0
  278. package/dist/ink/index.js.map +1 -0
  279. package/dist/ink/ink.d.ts +371 -0
  280. package/dist/ink/ink.d.ts.map +1 -0
  281. package/dist/ink/ink.js +1686 -0
  282. package/dist/ink/ink.js.map +1 -0
  283. package/dist/ink/instances.d.ts +4 -0
  284. package/dist/ink/instances.d.ts.map +1 -0
  285. package/dist/ink/instances.js +10 -0
  286. package/dist/ink/instances.js.map +1 -0
  287. package/dist/ink/line-width-cache.d.ts +2 -0
  288. package/dist/ink/line-width-cache.d.ts.map +1 -0
  289. package/dist/ink/line-width-cache.js +23 -0
  290. package/dist/ink/line-width-cache.js.map +1 -0
  291. package/dist/ink/log-update.d.ts +18 -0
  292. package/dist/ink/log-update.d.ts.map +1 -0
  293. package/dist/ink/log-update.js +637 -0
  294. package/dist/ink/log-update.js.map +1 -0
  295. package/dist/ink/measure-element.d.ts +17 -0
  296. package/dist/ink/measure-element.d.ts.map +1 -0
  297. package/dist/ink/measure-element.js +11 -0
  298. package/dist/ink/measure-element.js.map +1 -0
  299. package/dist/ink/measure-text.d.ts +7 -0
  300. package/dist/ink/measure-text.d.ts.map +1 -0
  301. package/dist/ink/measure-text.js +38 -0
  302. package/dist/ink/measure-text.js.map +1 -0
  303. package/dist/ink/node-cache.d.ts +21 -0
  304. package/dist/ink/node-cache.d.ts.map +1 -0
  305. package/dist/ink/node-cache.js +36 -0
  306. package/dist/ink/node-cache.js.map +1 -0
  307. package/dist/ink/optimizer.d.ts +16 -0
  308. package/dist/ink/optimizer.d.ts.map +1 -0
  309. package/dist/ink/optimizer.js +85 -0
  310. package/dist/ink/optimizer.js.map +1 -0
  311. package/dist/ink/output.d.ts +120 -0
  312. package/dist/ink/output.d.ts.map +1 -0
  313. package/dist/ink/output.js +559 -0
  314. package/dist/ink/output.js.map +1 -0
  315. package/dist/ink/parse-keypress.d.ts +112 -0
  316. package/dist/ink/parse-keypress.d.ts.map +1 -0
  317. package/dist/ink/parse-keypress.js +719 -0
  318. package/dist/ink/parse-keypress.js.map +1 -0
  319. package/dist/ink/parse-keypress.test.d.ts +2 -0
  320. package/dist/ink/parse-keypress.test.d.ts.map +1 -0
  321. package/dist/ink/parse-keypress.test.js +37 -0
  322. package/dist/ink/parse-keypress.test.js.map +1 -0
  323. package/dist/ink/reconciler.d.ts +12 -0
  324. package/dist/ink/reconciler.d.ts.map +1 -0
  325. package/dist/ink/reconciler.js +456 -0
  326. package/dist/ink/reconciler.js.map +1 -0
  327. package/dist/ink/render-border.d.ts +25 -0
  328. package/dist/ink/render-border.d.ts.map +1 -0
  329. package/dist/ink/render-border.js +141 -0
  330. package/dist/ink/render-border.js.map +1 -0
  331. package/dist/ink/render-node-to-output.d.ts +46 -0
  332. package/dist/ink/render-node-to-output.d.ts.map +1 -0
  333. package/dist/ink/render-node-to-output.js +1257 -0
  334. package/dist/ink/render-node-to-output.js.map +1 -0
  335. package/dist/ink/render-to-screen.d.ts +47 -0
  336. package/dist/ink/render-to-screen.d.ts.map +1 -0
  337. package/dist/ink/render-to-screen.js +213 -0
  338. package/dist/ink/render-to-screen.js.map +1 -0
  339. package/dist/ink/renderer.d.ts +15 -0
  340. package/dist/ink/renderer.d.ts.map +1 -0
  341. package/dist/ink/renderer.js +169 -0
  342. package/dist/ink/renderer.js.map +1 -0
  343. package/dist/ink/root.d.ts +75 -0
  344. package/dist/ink/root.d.ts.map +1 -0
  345. package/dist/ink/root.js +89 -0
  346. package/dist/ink/root.js.map +1 -0
  347. package/dist/ink/screen.d.ts +270 -0
  348. package/dist/ink/screen.d.ts.map +1 -0
  349. package/dist/ink/screen.js +1194 -0
  350. package/dist/ink/screen.js.map +1 -0
  351. package/dist/ink/searchHighlight.d.ts +21 -0
  352. package/dist/ink/searchHighlight.d.ts.map +1 -0
  353. package/dist/ink/searchHighlight.js +82 -0
  354. package/dist/ink/searchHighlight.js.map +1 -0
  355. package/dist/ink/selection.d.ts +230 -0
  356. package/dist/ink/selection.d.ts.map +1 -0
  357. package/dist/ink/selection.js +814 -0
  358. package/dist/ink/selection.js.map +1 -0
  359. package/dist/ink/squash-text-nodes.d.ts +23 -0
  360. package/dist/ink/squash-text-nodes.d.ts.map +1 -0
  361. package/dist/ink/squash-text-nodes.js +60 -0
  362. package/dist/ink/squash-text-nodes.js.map +1 -0
  363. package/dist/ink/stringWidth.d.ts +2 -0
  364. package/dist/ink/stringWidth.d.ts.map +1 -0
  365. package/dist/ink/stringWidth.js +207 -0
  366. package/dist/ink/stringWidth.js.map +1 -0
  367. package/dist/ink/styles.d.ts +307 -0
  368. package/dist/ink/styles.d.ts.map +1 -0
  369. package/dist/ink/styles.js +302 -0
  370. package/dist/ink/styles.js.map +1 -0
  371. package/dist/ink/supports-hyperlinks.d.ts +14 -0
  372. package/dist/ink/supports-hyperlinks.d.ts.map +1 -0
  373. package/dist/ink/supports-hyperlinks.js +48 -0
  374. package/dist/ink/supports-hyperlinks.js.map +1 -0
  375. package/dist/ink/tabstops.d.ts +2 -0
  376. package/dist/ink/tabstops.d.ts.map +1 -0
  377. package/dist/ink/tabstops.js +43 -0
  378. package/dist/ink/tabstops.js.map +1 -0
  379. package/dist/ink/terminal-focus-state.d.ts +7 -0
  380. package/dist/ink/terminal-focus-state.d.ts.map +1 -0
  381. package/dist/ink/terminal-focus-state.js +43 -0
  382. package/dist/ink/terminal-focus-state.js.map +1 -0
  383. package/dist/ink/terminal-querier.d.ts +130 -0
  384. package/dist/ink/terminal-querier.d.ts.map +1 -0
  385. package/dist/ink/terminal-querier.js +184 -0
  386. package/dist/ink/terminal-querier.js.map +1 -0
  387. package/dist/ink/terminal.d.ts +56 -0
  388. package/dist/ink/terminal.d.ts.map +1 -0
  389. package/dist/ink/terminal.js +249 -0
  390. package/dist/ink/terminal.js.map +1 -0
  391. package/dist/ink/termio/csi.d.ts +166 -0
  392. package/dist/ink/termio/csi.d.ts.map +1 -0
  393. package/dist/ink/termio/csi.js +285 -0
  394. package/dist/ink/termio/csi.js.map +1 -0
  395. package/dist/ink/termio/dec.d.ts +38 -0
  396. package/dist/ink/termio/dec.d.ts.map +1 -0
  397. package/dist/ink/termio/dec.js +59 -0
  398. package/dist/ink/termio/dec.js.map +1 -0
  399. package/dist/ink/termio.d.ts +25 -0
  400. package/dist/ink/termio.d.ts.map +1 -0
  401. package/dist/ink/termio.js +32 -0
  402. package/dist/ink/termio.js.map +1 -0
  403. package/dist/ink/useTerminalNotification.d.ts +27 -0
  404. package/dist/ink/useTerminalNotification.d.ts.map +1 -0
  405. package/dist/ink/useTerminalNotification.js +62 -0
  406. package/dist/ink/useTerminalNotification.js.map +1 -0
  407. package/dist/ink/warn.d.ts +2 -0
  408. package/dist/ink/warn.d.ts.map +1 -0
  409. package/dist/ink/warn.js +14 -0
  410. package/dist/ink/warn.js.map +1 -0
  411. package/dist/ink/widest-line.d.ts +2 -0
  412. package/dist/ink/widest-line.d.ts.map +1 -0
  413. package/dist/ink/widest-line.js +18 -0
  414. package/dist/ink/widest-line.js.map +1 -0
  415. package/dist/ink/wrap-text.d.ts +3 -0
  416. package/dist/ink/wrap-text.d.ts.map +1 -0
  417. package/dist/ink/wrap-text.js +61 -0
  418. package/dist/ink/wrap-text.js.map +1 -0
  419. package/dist/ink/wrapAnsi.d.ts +8 -0
  420. package/dist/ink/wrapAnsi.d.ts.map +1 -0
  421. package/dist/ink/wrapAnsi.js +13 -0
  422. package/dist/ink/wrapAnsi.js.map +1 -0
  423. package/dist/memory/embeddings.d.ts +33 -0
  424. package/dist/memory/embeddings.d.ts.map +1 -0
  425. package/dist/memory/embeddings.js +123 -0
  426. package/dist/memory/embeddings.js.map +1 -0
  427. package/dist/memory/index.d.ts +14 -0
  428. package/dist/memory/index.d.ts.map +1 -0
  429. package/dist/memory/index.js +31 -0
  430. package/dist/memory/index.js.map +1 -0
  431. package/dist/memory/prompts.d.ts +12 -0
  432. package/dist/memory/prompts.d.ts.map +1 -0
  433. package/dist/memory/prompts.js +117 -0
  434. package/dist/memory/prompts.js.map +1 -0
  435. package/dist/memory/semantic-search.d.ts +45 -0
  436. package/dist/memory/semantic-search.d.ts.map +1 -0
  437. package/dist/memory/semantic-search.js +112 -0
  438. package/dist/memory/semantic-search.js.map +1 -0
  439. package/dist/memory/storage.d.ts +79 -0
  440. package/dist/memory/storage.d.ts.map +1 -0
  441. package/dist/memory/storage.js +285 -0
  442. package/dist/memory/storage.js.map +1 -0
  443. package/dist/memory/store.d.ts +103 -0
  444. package/dist/memory/store.d.ts.map +1 -0
  445. package/dist/memory/store.js +226 -0
  446. package/dist/memory/store.js.map +1 -0
  447. package/dist/memory/types.d.ts +40 -0
  448. package/dist/memory/types.d.ts.map +1 -0
  449. package/dist/memory/types.js +71 -0
  450. package/dist/memory/types.js.map +1 -0
  451. package/dist/memory/validation.d.ts +28 -0
  452. package/dist/memory/validation.d.ts.map +1 -0
  453. package/dist/memory/validation.js +147 -0
  454. package/dist/memory/validation.js.map +1 -0
  455. package/dist/memory/vector-store.d.ts +49 -0
  456. package/dist/memory/vector-store.d.ts.map +1 -0
  457. package/dist/memory/vector-store.js +259 -0
  458. package/dist/memory/vector-store.js.map +1 -0
  459. package/dist/screens/REPL.d.ts +21 -0
  460. package/dist/screens/REPL.d.ts.map +1 -0
  461. package/dist/screens/REPL.js +139 -0
  462. package/dist/screens/REPL.js.map +1 -0
  463. package/dist/services/agent-runner.d.ts +68 -0
  464. package/dist/services/agent-runner.d.ts.map +1 -0
  465. package/dist/services/agent-runner.js +186 -0
  466. package/dist/services/agent-runner.js.map +1 -0
  467. package/dist/services/atomic-write.d.ts +12 -0
  468. package/dist/services/atomic-write.d.ts.map +1 -0
  469. package/dist/services/atomic-write.js +27 -0
  470. package/dist/services/atomic-write.js.map +1 -0
  471. package/dist/services/config-dir.d.ts +55 -0
  472. package/dist/services/config-dir.d.ts.map +1 -0
  473. package/dist/services/config-dir.js +136 -0
  474. package/dist/services/config-dir.js.map +1 -0
  475. package/dist/services/config.d.ts +54 -0
  476. package/dist/services/config.d.ts.map +1 -0
  477. package/dist/services/config.js +98 -0
  478. package/dist/services/config.js.map +1 -0
  479. package/dist/services/file-glob.d.ts +26 -0
  480. package/dist/services/file-glob.d.ts.map +1 -0
  481. package/dist/services/file-glob.js +134 -0
  482. package/dist/services/file-glob.js.map +1 -0
  483. package/dist/services/global-config.d.ts +109 -0
  484. package/dist/services/global-config.d.ts.map +1 -0
  485. package/dist/services/global-config.js +211 -0
  486. package/dist/services/global-config.js.map +1 -0
  487. package/dist/services/llm.d.ts +139 -0
  488. package/dist/services/llm.d.ts.map +1 -0
  489. package/dist/services/llm.js +376 -0
  490. package/dist/services/llm.js.map +1 -0
  491. package/dist/services/memory.d.ts +39 -0
  492. package/dist/services/memory.d.ts.map +1 -0
  493. package/dist/services/memory.js +88 -0
  494. package/dist/services/memory.js.map +1 -0
  495. package/dist/services/session-storage.d.ts +136 -0
  496. package/dist/services/session-storage.d.ts.map +1 -0
  497. package/dist/services/session-storage.js +304 -0
  498. package/dist/services/session-storage.js.map +1 -0
  499. package/dist/services/task-manager.d.ts +154 -0
  500. package/dist/services/task-manager.d.ts.map +1 -0
  501. package/dist/services/task-manager.js +288 -0
  502. package/dist/services/task-manager.js.map +1 -0
  503. package/dist/services/yaml-config.d.ts +57 -0
  504. package/dist/services/yaml-config.d.ts.map +1 -0
  505. package/dist/services/yaml-config.js +176 -0
  506. package/dist/services/yaml-config.js.map +1 -0
  507. package/dist/skills/discovery.d.ts +22 -0
  508. package/dist/skills/discovery.d.ts.map +1 -0
  509. package/dist/skills/discovery.js +75 -0
  510. package/dist/skills/discovery.js.map +1 -0
  511. package/dist/skills/index.d.ts +10 -0
  512. package/dist/skills/index.d.ts.map +1 -0
  513. package/dist/skills/index.js +26 -0
  514. package/dist/skills/index.js.map +1 -0
  515. package/dist/skills/loader.d.ts +48 -0
  516. package/dist/skills/loader.d.ts.map +1 -0
  517. package/dist/skills/loader.js +231 -0
  518. package/dist/skills/loader.js.map +1 -0
  519. package/dist/skills/registry.d.ts +37 -0
  520. package/dist/skills/registry.d.ts.map +1 -0
  521. package/dist/skills/registry.js +134 -0
  522. package/dist/skills/registry.js.map +1 -0
  523. package/dist/skills/types.d.ts +89 -0
  524. package/dist/skills/types.d.ts.map +1 -0
  525. package/dist/skills/types.js +24 -0
  526. package/dist/skills/types.js.map +1 -0
  527. package/dist/tools/bash_security.d.ts +64 -0
  528. package/dist/tools/bash_security.d.ts.map +1 -0
  529. package/dist/tools/bash_security.js +291 -0
  530. package/dist/tools/bash_security.js.map +1 -0
  531. package/dist/tools/index.d.ts +23 -0
  532. package/dist/tools/index.d.ts.map +1 -0
  533. package/dist/tools/index.js +965 -0
  534. package/dist/tools/index.js.map +1 -0
  535. package/dist/tools/mcp.d.ts +72 -0
  536. package/dist/tools/mcp.d.ts.map +1 -0
  537. package/dist/tools/mcp.js +422 -0
  538. package/dist/tools/mcp.js.map +1 -0
  539. package/dist/tools/plan.d.ts +18 -0
  540. package/dist/tools/plan.d.ts.map +1 -0
  541. package/dist/tools/plan.js +75 -0
  542. package/dist/tools/plan.js.map +1 -0
  543. package/dist/tools/todo.d.ts +18 -0
  544. package/dist/tools/todo.d.ts.map +1 -0
  545. package/dist/tools/todo.js +153 -0
  546. package/dist/tools/todo.js.map +1 -0
  547. package/dist/tools/web.d.ts +13 -0
  548. package/dist/tools/web.d.ts.map +1 -0
  549. package/dist/tools/web.js +377 -0
  550. package/dist/tools/web.js.map +1 -0
  551. package/dist/ui/box.d.ts +56 -0
  552. package/dist/ui/box.d.ts.map +1 -0
  553. package/dist/ui/box.js +241 -0
  554. package/dist/ui/box.js.map +1 -0
  555. package/dist/ui/command-panel.d.ts +55 -0
  556. package/dist/ui/command-panel.d.ts.map +1 -0
  557. package/dist/ui/command-panel.js +212 -0
  558. package/dist/ui/command-panel.js.map +1 -0
  559. package/dist/ui/file-completion.d.ts +62 -0
  560. package/dist/ui/file-completion.d.ts.map +1 -0
  561. package/dist/ui/file-completion.js +209 -0
  562. package/dist/ui/file-completion.js.map +1 -0
  563. package/dist/ui/markdown.d.ts +12 -0
  564. package/dist/ui/markdown.d.ts.map +1 -0
  565. package/dist/ui/markdown.js +215 -0
  566. package/dist/ui/markdown.js.map +1 -0
  567. package/dist/ui/multiline-input.d.ts +47 -0
  568. package/dist/ui/multiline-input.d.ts.map +1 -0
  569. package/dist/ui/multiline-input.js +94 -0
  570. package/dist/ui/multiline-input.js.map +1 -0
  571. package/dist/ui/status-bar.d.ts +33 -0
  572. package/dist/ui/status-bar.d.ts.map +1 -0
  573. package/dist/ui/status-bar.js +96 -0
  574. package/dist/ui/status-bar.js.map +1 -0
  575. package/dist/ui/stream-markdown.d.ts +35 -0
  576. package/dist/ui/stream-markdown.d.ts.map +1 -0
  577. package/dist/ui/stream-markdown.js +138 -0
  578. package/dist/ui/stream-markdown.js.map +1 -0
  579. package/dist/ui/suggestions.d.ts +35 -0
  580. package/dist/ui/suggestions.d.ts.map +1 -0
  581. package/dist/ui/suggestions.js +118 -0
  582. package/dist/ui/suggestions.js.map +1 -0
  583. package/dist/ui/tool-preview.d.ts +34 -0
  584. package/dist/ui/tool-preview.d.ts.map +1 -0
  585. package/dist/ui/tool-preview.js +128 -0
  586. package/dist/ui/tool-preview.js.map +1 -0
  587. package/package.json +93 -0
@@ -0,0 +1,814 @@
1
+ "use strict";
2
+ /**
3
+ * Text selection state for fullscreen mode.
4
+ *
5
+ * Tracks a linear selection in screen-buffer coordinates (0-indexed col/row).
6
+ * Selection is line-based: cells from (startCol, startRow) through
7
+ * (endCol, endRow) inclusive, wrapping across line boundaries. This matches
8
+ * terminal-native selection behavior (not rectangular/block).
9
+ *
10
+ * The selection is stored as ANCHOR (where the drag started) + FOCUS (where
11
+ * the cursor is now). The rendered highlight normalizes to start ≤ end.
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.createSelectionState = createSelectionState;
15
+ exports.startSelection = startSelection;
16
+ exports.updateSelection = updateSelection;
17
+ exports.finishSelection = finishSelection;
18
+ exports.clearSelection = clearSelection;
19
+ exports.selectWordAt = selectWordAt;
20
+ exports.findPlainTextUrlAt = findPlainTextUrlAt;
21
+ exports.selectLineAt = selectLineAt;
22
+ exports.extendSelection = extendSelection;
23
+ exports.moveFocus = moveFocus;
24
+ exports.shiftSelection = shiftSelection;
25
+ exports.shiftAnchor = shiftAnchor;
26
+ exports.shiftSelectionForFollow = shiftSelectionForFollow;
27
+ exports.hasSelection = hasSelection;
28
+ exports.selectionBounds = selectionBounds;
29
+ exports.isCellSelected = isCellSelected;
30
+ exports.getSelectedText = getSelectedText;
31
+ exports.captureScrolledRows = captureScrolledRows;
32
+ exports.applySelectionOverlay = applySelectionOverlay;
33
+ const geometry_js_1 = require("./layout/geometry.js");
34
+ const screen_js_1 = require("./screen.js");
35
+ function createSelectionState() {
36
+ return {
37
+ anchor: null,
38
+ focus: null,
39
+ isDragging: false,
40
+ anchorSpan: null,
41
+ scrolledOffAbove: [],
42
+ scrolledOffBelow: [],
43
+ scrolledOffAboveSW: [],
44
+ scrolledOffBelowSW: [],
45
+ lastPressHadAlt: false,
46
+ };
47
+ }
48
+ function startSelection(s, col, row) {
49
+ s.anchor = { col, row };
50
+ // Focus is not set until the first drag motion. A click-release with no
51
+ // drag leaves focus null → hasSelection/selectionBounds return false/null
52
+ // via the `!s.focus` check, so a bare click never highlights a cell.
53
+ s.focus = null;
54
+ s.isDragging = true;
55
+ s.anchorSpan = null;
56
+ s.scrolledOffAbove = [];
57
+ s.scrolledOffBelow = [];
58
+ s.scrolledOffAboveSW = [];
59
+ s.scrolledOffBelowSW = [];
60
+ s.virtualAnchorRow = undefined;
61
+ s.virtualFocusRow = undefined;
62
+ s.lastPressHadAlt = false;
63
+ }
64
+ function updateSelection(s, col, row) {
65
+ if (!s.isDragging)
66
+ return;
67
+ // First motion at the same cell as anchor is a no-op. Terminals in mode
68
+ // 1002 can fire a drag event at the anchor cell (sub-pixel tremor, or a
69
+ // motion-release pair). Setting focus here would turn a bare click into
70
+ // a 1-cell selection and clobber the clipboard via useCopyOnSelect. Once
71
+ // focus is set (real drag), we track normally including back to anchor.
72
+ if (!s.focus && s.anchor && s.anchor.col === col && s.anchor.row === row)
73
+ return;
74
+ s.focus = { col, row };
75
+ }
76
+ function finishSelection(s) {
77
+ s.isDragging = false;
78
+ // Keep anchor/focus so highlight stays visible and text can be copied.
79
+ // Clear via clearSelection() on Esc or after copy.
80
+ }
81
+ function clearSelection(s) {
82
+ s.anchor = null;
83
+ s.focus = null;
84
+ s.isDragging = false;
85
+ s.anchorSpan = null;
86
+ s.scrolledOffAbove = [];
87
+ s.scrolledOffBelow = [];
88
+ s.scrolledOffAboveSW = [];
89
+ s.scrolledOffBelowSW = [];
90
+ s.virtualAnchorRow = undefined;
91
+ s.virtualFocusRow = undefined;
92
+ s.lastPressHadAlt = false;
93
+ }
94
+ // Unicode-aware word character matcher: letters (any script), digits,
95
+ // and the punctuation set iTerm2 treats as word-part by default.
96
+ // Matching iTerm2's default means double-clicking a path like
97
+ // `/usr/bin/bash` or `~/.claude/config.json` selects the whole thing,
98
+ // which is the muscle memory most macOS terminal users have.
99
+ // iTerm2 default "characters considered part of a word": /-+\~_.
100
+ const WORD_CHAR = /[\p{L}\p{N}_/.\-+~\\]/u;
101
+ /**
102
+ * Character class for double-click word-expansion. Cells with the same
103
+ * class as the clicked cell are included in the selection; a class change
104
+ * is a boundary. Matches typical terminal-emulator behavior (iTerm2 etc.):
105
+ * double-click on `foo` selects `foo`, on `->` selects `->`, on spaces
106
+ * selects the whitespace run.
107
+ */
108
+ function charClass(c) {
109
+ if (c === ' ' || c === '')
110
+ return 0;
111
+ if (WORD_CHAR.test(c))
112
+ return 1;
113
+ return 2;
114
+ }
115
+ /**
116
+ * Find the bounds of the same-class character run at (col, row). Returns
117
+ * null if the click is out of bounds or lands on a noSelect cell. Used by
118
+ * selectWordAt (initial double-click) and extendWordSelection (drag).
119
+ */
120
+ function wordBoundsAt(screen, col, row) {
121
+ if (row < 0 || row >= screen.height)
122
+ return null;
123
+ const width = screen.width;
124
+ const noSelect = screen.noSelect;
125
+ const rowOff = row * width;
126
+ // If the click landed on the spacer tail of a wide char, step back to
127
+ // the head so the class check sees the actual grapheme.
128
+ let c = col;
129
+ if (c > 0) {
130
+ const cell = (0, screen_js_1.cellAt)(screen, c, row);
131
+ if (cell && cell.width === 2 /* CellWidth.SpacerTail */)
132
+ c -= 1;
133
+ }
134
+ if (c < 0 || c >= width || noSelect[rowOff + c] === 1)
135
+ return null;
136
+ const startCell = (0, screen_js_1.cellAt)(screen, c, row);
137
+ if (!startCell)
138
+ return null;
139
+ const cls = charClass(startCell.char);
140
+ // Expand left: include cells of the same class, stop at noSelect or
141
+ // class change. SpacerTail cells are stepped over (the wide-char head
142
+ // at the preceding column determines the class).
143
+ let lo = c;
144
+ while (lo > 0) {
145
+ const prev = lo - 1;
146
+ if (noSelect[rowOff + prev] === 1)
147
+ break;
148
+ const pc = (0, screen_js_1.cellAt)(screen, prev, row);
149
+ if (!pc)
150
+ break;
151
+ if (pc.width === 2 /* CellWidth.SpacerTail */) {
152
+ // Step over the spacer to the wide-char head
153
+ if (prev === 0 || noSelect[rowOff + prev - 1] === 1)
154
+ break;
155
+ const head = (0, screen_js_1.cellAt)(screen, prev - 1, row);
156
+ if (!head || charClass(head.char) !== cls)
157
+ break;
158
+ lo = prev - 1;
159
+ continue;
160
+ }
161
+ if (charClass(pc.char) !== cls)
162
+ break;
163
+ lo = prev;
164
+ }
165
+ // Expand right: same logic, skipping spacer tails.
166
+ let hi = c;
167
+ while (hi < width - 1) {
168
+ const next = hi + 1;
169
+ if (noSelect[rowOff + next] === 1)
170
+ break;
171
+ const nc = (0, screen_js_1.cellAt)(screen, next, row);
172
+ if (!nc)
173
+ break;
174
+ if (nc.width === 2 /* CellWidth.SpacerTail */) {
175
+ // Include the spacer tail in the selection range (it belongs to
176
+ // the wide char at hi) and continue past it.
177
+ hi = next;
178
+ continue;
179
+ }
180
+ if (charClass(nc.char) !== cls)
181
+ break;
182
+ hi = next;
183
+ }
184
+ return { lo, hi };
185
+ }
186
+ /** -1 if a < b, 1 if a > b, 0 if equal (reading order: row then col). */
187
+ function comparePoints(a, b) {
188
+ if (a.row !== b.row)
189
+ return a.row < b.row ? -1 : 1;
190
+ if (a.col !== b.col)
191
+ return a.col < b.col ? -1 : 1;
192
+ return 0;
193
+ }
194
+ /**
195
+ * Select the word at (col, row) by scanning the screen buffer for the
196
+ * bounds of the same-class character run. Mutates the selection in place.
197
+ * No-op if the click is out of bounds or lands on a noSelect cell.
198
+ * Sets isDragging=true and anchorSpan so a subsequent drag extends the
199
+ * selection word-by-word (native macOS behavior).
200
+ */
201
+ function selectWordAt(s, screen, col, row) {
202
+ const b = wordBoundsAt(screen, col, row);
203
+ if (!b)
204
+ return;
205
+ const lo = { col: b.lo, row };
206
+ const hi = { col: b.hi, row };
207
+ s.anchor = lo;
208
+ s.focus = hi;
209
+ s.isDragging = true;
210
+ s.anchorSpan = { lo, hi, kind: 'word' };
211
+ }
212
+ // Printable ASCII minus terminal URL delimiters. Restricting to single-
213
+ // codeunit ASCII keeps cell-count === string-index, so the column-span
214
+ // check below is exact (no wide-char/grapheme drift).
215
+ const URL_BOUNDARY = new Set([...'<>"\'` ']);
216
+ function isUrlChar(c) {
217
+ if (c.length !== 1)
218
+ return false;
219
+ const code = c.charCodeAt(0);
220
+ return code >= 0x21 && code <= 0x7e && !URL_BOUNDARY.has(c);
221
+ }
222
+ /**
223
+ * Scan the screen buffer for a plain-text URL at (col, row). Mirrors the
224
+ * terminal's native Cmd+Click URL detection, which fullscreen mode's mouse
225
+ * tracking intercepts. Called from getHyperlinkAt as a fallback when the
226
+ * cell has no OSC 8 hyperlink.
227
+ */
228
+ function findPlainTextUrlAt(screen, col, row) {
229
+ if (row < 0 || row >= screen.height)
230
+ return undefined;
231
+ const width = screen.width;
232
+ const noSelect = screen.noSelect;
233
+ const rowOff = row * width;
234
+ let c = col;
235
+ if (c > 0) {
236
+ const cell = (0, screen_js_1.cellAt)(screen, c, row);
237
+ if (cell && cell.width === 2 /* CellWidth.SpacerTail */)
238
+ c -= 1;
239
+ }
240
+ if (c < 0 || c >= width || noSelect[rowOff + c] === 1)
241
+ return undefined;
242
+ const startCell = (0, screen_js_1.cellAt)(screen, c, row);
243
+ if (!startCell || !isUrlChar(startCell.char))
244
+ return undefined;
245
+ // Expand left/right to the bounds of the URL-char run. URLs are ASCII
246
+ // (CellWidth.Narrow, 1 codeunit), so hitting a non-ASCII/wide/spacer
247
+ // cell is a boundary — no need to step over spacers like wordBoundsAt.
248
+ let lo = c;
249
+ while (lo > 0) {
250
+ const prev = lo - 1;
251
+ if (noSelect[rowOff + prev] === 1)
252
+ break;
253
+ const pc = (0, screen_js_1.cellAt)(screen, prev, row);
254
+ if (!pc || pc.width !== 0 /* CellWidth.Narrow */ || !isUrlChar(pc.char))
255
+ break;
256
+ lo = prev;
257
+ }
258
+ let hi = c;
259
+ while (hi < width - 1) {
260
+ const next = hi + 1;
261
+ if (noSelect[rowOff + next] === 1)
262
+ break;
263
+ const nc = (0, screen_js_1.cellAt)(screen, next, row);
264
+ if (!nc || nc.width !== 0 /* CellWidth.Narrow */ || !isUrlChar(nc.char))
265
+ break;
266
+ hi = next;
267
+ }
268
+ let token = '';
269
+ for (let i = lo; i <= hi; i++)
270
+ token += (0, screen_js_1.cellAt)(screen, i, row).char;
271
+ // 1 cell = 1 char across [lo, hi] (ASCII-only run), so string index =
272
+ // column offset. Find the last scheme anchor at or before the click —
273
+ // a run like `https://a.com,https://b.com` has two, and clicking the
274
+ // second should return the second URL, not the greedy match of both.
275
+ const clickIdx = c - lo;
276
+ const schemeRe = /(?:https?|file):\/\//g;
277
+ let urlStart = -1;
278
+ let urlEnd = token.length;
279
+ for (let m; (m = schemeRe.exec(token));) {
280
+ if (m.index > clickIdx) {
281
+ urlEnd = m.index;
282
+ break;
283
+ }
284
+ urlStart = m.index;
285
+ }
286
+ if (urlStart < 0)
287
+ return undefined;
288
+ let url = token.slice(urlStart, urlEnd);
289
+ // Strip trailing sentence punctuation. For closers () ] }, only strip
290
+ // if unbalanced — `/wiki/Foo_(bar)` keeps `)`, `/arr[0]` keeps `]`.
291
+ const OPENER = { ')': '(', ']': '[', '}': '{' };
292
+ while (url.length > 0) {
293
+ const last = url.at(-1);
294
+ if ('.,;:!?'.includes(last)) {
295
+ url = url.slice(0, -1);
296
+ continue;
297
+ }
298
+ const opener = OPENER[last];
299
+ if (!opener)
300
+ break;
301
+ let opens = 0;
302
+ let closes = 0;
303
+ for (let i = 0; i < url.length; i++) {
304
+ const ch = url.charAt(i);
305
+ if (ch === opener)
306
+ opens++;
307
+ else if (ch === last)
308
+ closes++;
309
+ }
310
+ if (closes > opens)
311
+ url = url.slice(0, -1);
312
+ else
313
+ break;
314
+ }
315
+ // urlStart already guarantees click >= URL start; check right edge.
316
+ if (clickIdx >= urlStart + url.length)
317
+ return undefined;
318
+ return url;
319
+ }
320
+ /**
321
+ * Select the entire row. Sets isDragging=true and anchorSpan so a
322
+ * subsequent drag extends the selection line-by-line. The anchor/focus
323
+ * span from col 0 to width-1; getSelectedText handles noSelect skipping
324
+ * and trailing-whitespace trimming so the copied text is just the visible
325
+ * line content.
326
+ */
327
+ function selectLineAt(s, screen, row) {
328
+ if (row < 0 || row >= screen.height)
329
+ return;
330
+ const lo = { col: 0, row };
331
+ const hi = { col: screen.width - 1, row };
332
+ s.anchor = lo;
333
+ s.focus = hi;
334
+ s.isDragging = true;
335
+ s.anchorSpan = { lo, hi, kind: 'line' };
336
+ }
337
+ /**
338
+ * Extend a word/line-mode selection to the word/line at (col, row). The
339
+ * anchor span (the original multi-clicked word/line) stays selected; the
340
+ * selection grows from that span to the word/line at the current mouse
341
+ * position. Word mode falls back to the raw cell when the mouse is over a
342
+ * noSelect cell or out of bounds, so dragging into gutters still extends.
343
+ */
344
+ function extendSelection(s, screen, col, row) {
345
+ if (!s.isDragging || !s.anchorSpan)
346
+ return;
347
+ const span = s.anchorSpan;
348
+ let mLo;
349
+ let mHi;
350
+ if (span.kind === 'word') {
351
+ const b = wordBoundsAt(screen, col, row);
352
+ mLo = { col: b ? b.lo : col, row };
353
+ mHi = { col: b ? b.hi : col, row };
354
+ }
355
+ else {
356
+ const r = (0, geometry_js_1.clamp)(row, 0, screen.height - 1);
357
+ mLo = { col: 0, row: r };
358
+ mHi = { col: screen.width - 1, row: r };
359
+ }
360
+ if (comparePoints(mHi, span.lo) < 0) {
361
+ // Mouse target ends before anchor span: extend backward.
362
+ s.anchor = span.hi;
363
+ s.focus = mLo;
364
+ }
365
+ else if (comparePoints(mLo, span.hi) > 0) {
366
+ // Mouse target starts after anchor span: extend forward.
367
+ s.anchor = span.lo;
368
+ s.focus = mHi;
369
+ }
370
+ else {
371
+ // Mouse overlaps the anchor span: just select the anchor span.
372
+ s.anchor = span.lo;
373
+ s.focus = span.hi;
374
+ }
375
+ }
376
+ /**
377
+ * Set focus to (col, row) for keyboard selection extension (shift+arrow).
378
+ * Anchor stays fixed; selection grows or shrinks depending on where focus
379
+ * moves relative to anchor. Drops to char mode (clears anchorSpan) —
380
+ * native macOS does this too: shift+arrow after a double-click word-select
381
+ * extends char-by-char from the word edge, not word-by-word. Scrolled-off
382
+ * accumulators are preserved: keyboard-extending a drag-scrolled selection
383
+ * keeps the off-screen rows. Caller supplies coords already clamped/wrapped.
384
+ */
385
+ function moveFocus(s, col, row) {
386
+ if (!s.focus)
387
+ return;
388
+ s.anchorSpan = null;
389
+ s.focus = { col, row };
390
+ // Explicit user repositioning — any stale virtual focus (from a prior
391
+ // shiftSelection clamp) no longer reflects intent. Anchor stays put so
392
+ // virtualAnchorRow is still valid for its own round-trip.
393
+ s.virtualFocusRow = undefined;
394
+ }
395
+ /**
396
+ * Shift anchor AND focus by dRow, clamped to [minRow, maxRow]. Used for
397
+ * keyboard scroll (PgUp/PgDn/ctrl+u/d/b/f): the whole selection must track
398
+ * the content, unlike drag-to-scroll where focus stays at the mouse. Any
399
+ * point that hits a clamp bound gets its col reset to the full-width edge —
400
+ * its original content scrolled off-screen and was captured by
401
+ * captureScrolledRows, so the col constraint was already consumed. Keeping
402
+ * it would truncate the NEW content now at that screen row. Clamp col is 0
403
+ * for dRow<0 (scrolling down, top leaves, 'above' semantics) or width-1 for
404
+ * dRow>0 (scrolling up, bottom leaves, 'below' semantics).
405
+ *
406
+ * If both ends overshoot the SAME viewport edge (select text → Home/End/g/G
407
+ * jumps far enough that both are out of view), clear — otherwise both clamp
408
+ * to the same corner cell and a ghost 1-cell highlight lingers, and
409
+ * getSelectedText returns one unrelated char from that corner. Symmetric
410
+ * with shiftSelectionForFollow's top-edge check, but bidirectional: keyboard
411
+ * scroll can jump either way.
412
+ */
413
+ function shiftSelection(s, dRow, minRow, maxRow, width) {
414
+ if (!s.anchor || !s.focus)
415
+ return;
416
+ // Virtual rows track pre-clamp positions so reverse scrolls restore
417
+ // correctly. Without this, clamp(5→0) + shift(+10) = 10, not the true 5,
418
+ // and scrolledOffAbove stays stale (highlight ≠ copy).
419
+ const vAnchor = (s.virtualAnchorRow ?? s.anchor.row) + dRow;
420
+ const vFocus = (s.virtualFocusRow ?? s.focus.row) + dRow;
421
+ if ((vAnchor < minRow && vFocus < minRow) ||
422
+ (vAnchor > maxRow && vFocus > maxRow)) {
423
+ clearSelection(s);
424
+ return;
425
+ }
426
+ // Debt = how far the nearer endpoint overshoots each edge. When debt
427
+ // shrinks (reverse scroll), those rows are back on-screen — pop from
428
+ // the accumulator so getSelectedText doesn't double-count them.
429
+ const oldMin = Math.min(s.virtualAnchorRow ?? s.anchor.row, s.virtualFocusRow ?? s.focus.row);
430
+ const oldMax = Math.max(s.virtualAnchorRow ?? s.anchor.row, s.virtualFocusRow ?? s.focus.row);
431
+ const oldAboveDebt = Math.max(0, minRow - oldMin);
432
+ const oldBelowDebt = Math.max(0, oldMax - maxRow);
433
+ const newAboveDebt = Math.max(0, minRow - Math.min(vAnchor, vFocus));
434
+ const newBelowDebt = Math.max(0, Math.max(vAnchor, vFocus) - maxRow);
435
+ if (newAboveDebt < oldAboveDebt) {
436
+ // scrolledOffAbove pushes newest at the end (closest to on-screen).
437
+ const drop = oldAboveDebt - newAboveDebt;
438
+ s.scrolledOffAbove.length -= drop;
439
+ s.scrolledOffAboveSW.length = s.scrolledOffAbove.length;
440
+ }
441
+ if (newBelowDebt < oldBelowDebt) {
442
+ // scrolledOffBelow unshifts newest at the front (closest to on-screen).
443
+ const drop = oldBelowDebt - newBelowDebt;
444
+ s.scrolledOffBelow.splice(0, drop);
445
+ s.scrolledOffBelowSW.splice(0, drop);
446
+ }
447
+ // Invariant: accumulator length ≤ debt. If the accumulator exceeds debt,
448
+ // the excess is stale — e.g., moveFocus cleared virtualFocusRow without
449
+ // trimming the accumulator, orphaning entries the pop above can never
450
+ // reach because oldDebt was ALREADY 0. Truncate to debt (keeping the
451
+ // newest = closest-to-on-screen entries). Check newDebt (not oldDebt):
452
+ // captureScrolledRows runs BEFORE this shift in the real flow (ink.tsx),
453
+ // so at entry the accumulator is populated but oldDebt is still 0 —
454
+ // that's the normal establish-debt path, not stale.
455
+ if (s.scrolledOffAbove.length > newAboveDebt) {
456
+ // Above pushes newest at END → keep END.
457
+ s.scrolledOffAbove =
458
+ newAboveDebt > 0 ? s.scrolledOffAbove.slice(-newAboveDebt) : [];
459
+ s.scrolledOffAboveSW =
460
+ newAboveDebt > 0 ? s.scrolledOffAboveSW.slice(-newAboveDebt) : [];
461
+ }
462
+ if (s.scrolledOffBelow.length > newBelowDebt) {
463
+ // Below unshifts newest at FRONT → keep FRONT.
464
+ s.scrolledOffBelow = s.scrolledOffBelow.slice(0, newBelowDebt);
465
+ s.scrolledOffBelowSW = s.scrolledOffBelowSW.slice(0, newBelowDebt);
466
+ }
467
+ // Clamp col depends on which EDGE (not dRow direction): virtual tracking
468
+ // means a top-clamped point can stay top-clamped during a dRow>0 reverse
469
+ // shift — dRow-based clampCol would give it the bottom col.
470
+ const shift = (p, vRow) => {
471
+ if (vRow < minRow)
472
+ return { col: 0, row: minRow };
473
+ if (vRow > maxRow)
474
+ return { col: width - 1, row: maxRow };
475
+ return { col: p.col, row: vRow };
476
+ };
477
+ s.anchor = shift(s.anchor, vAnchor);
478
+ s.focus = shift(s.focus, vFocus);
479
+ s.virtualAnchorRow =
480
+ vAnchor < minRow || vAnchor > maxRow ? vAnchor : undefined;
481
+ s.virtualFocusRow = vFocus < minRow || vFocus > maxRow ? vFocus : undefined;
482
+ // anchorSpan not virtual-tracked: it's for word/line extend-on-drag,
483
+ // irrelevant to the keyboard-scroll round-trip case.
484
+ if (s.anchorSpan) {
485
+ const sp = (p) => {
486
+ const r = p.row + dRow;
487
+ if (r < minRow)
488
+ return { col: 0, row: minRow };
489
+ if (r > maxRow)
490
+ return { col: width - 1, row: maxRow };
491
+ return { col: p.col, row: r };
492
+ };
493
+ s.anchorSpan = {
494
+ lo: sp(s.anchorSpan.lo),
495
+ hi: sp(s.anchorSpan.hi),
496
+ kind: s.anchorSpan.kind,
497
+ };
498
+ }
499
+ }
500
+ /**
501
+ * Shift the anchor row by dRow, clamped to [minRow, maxRow]. Used during
502
+ * drag-to-scroll: when the ScrollBox scrolls by N rows, the content that
503
+ * was under the anchor is now at a different viewport row, so the anchor
504
+ * must follow it. Focus is left unchanged (it stays at the mouse position).
505
+ */
506
+ function shiftAnchor(s, dRow, minRow, maxRow) {
507
+ if (!s.anchor)
508
+ return;
509
+ // Same virtual-row tracking as shiftSelection/shiftSelectionForFollow: the
510
+ // drag→follow transition hands off to shiftSelectionForFollow, which reads
511
+ // (virtualAnchorRow ?? anchor.row). Without this, drag-phase clamping
512
+ // leaves virtual undefined → follow initializes from the already-clamped
513
+ // row, under-counting total drift → shiftSelection's invariant-restore
514
+ // prematurely clears valid drag-phase accumulator entries.
515
+ const raw = (s.virtualAnchorRow ?? s.anchor.row) + dRow;
516
+ s.anchor = { col: s.anchor.col, row: (0, geometry_js_1.clamp)(raw, minRow, maxRow) };
517
+ s.virtualAnchorRow = raw < minRow || raw > maxRow ? raw : undefined;
518
+ // anchorSpan not virtual-tracked (word/line extend, irrelevant to
519
+ // keyboard-scroll round-trip) — plain clamp from current row.
520
+ if (s.anchorSpan) {
521
+ const shift = (p) => ({
522
+ col: p.col,
523
+ row: (0, geometry_js_1.clamp)(p.row + dRow, minRow, maxRow),
524
+ });
525
+ s.anchorSpan = {
526
+ lo: shift(s.anchorSpan.lo),
527
+ hi: shift(s.anchorSpan.hi),
528
+ kind: s.anchorSpan.kind,
529
+ };
530
+ }
531
+ }
532
+ /**
533
+ * Shift the whole selection (anchor + focus + anchorSpan) by dRow, clamped
534
+ * to [minRow, maxRow]. Used when sticky/auto-follow scrolls the ScrollBox
535
+ * while a selection is active — native terminal behavior is for the
536
+ * highlight to walk up the screen with the text (not stay at the same
537
+ * screen position).
538
+ *
539
+ * Differs from shiftAnchor: during drag-to-scroll, focus tracks the live
540
+ * mouse position and only anchor follows the text. During streaming-follow,
541
+ * the selection is text-anchored at both ends — both must move. The
542
+ * isDragging check in ink.tsx picks which shift to apply.
543
+ *
544
+ * If both ends would shift strictly BELOW minRow (unclamped), the selected
545
+ * text has scrolled entirely off the top. Clear it — otherwise a single
546
+ * inverted cell lingers at the viewport top as a ghost (native terminals
547
+ * drop the selection when it leaves scrollback). Landing AT minRow is
548
+ * still valid: that cell holds the correct text. Returns true if the
549
+ * selection was cleared so the caller can notify React-land subscribers
550
+ * (useHasSelection) — the caller is inside onRender so it can't use
551
+ * notifySelectionChange (recursion), must fire listeners directly.
552
+ */
553
+ function shiftSelectionForFollow(s, dRow, minRow, maxRow) {
554
+ if (!s.anchor)
555
+ return false;
556
+ // Mirror shiftSelection: compute raw (unclamped) positions from virtual
557
+ // if set, else current. This handles BOTH the update path (virtual already
558
+ // set from a prior keyboard scroll) AND the initialize path (first clamp
559
+ // happens HERE via follow-scroll, no prior keyboard scroll). Without the
560
+ // initialize path, follow-scroll-first leaves virtual undefined even
561
+ // though the clamp below occurred → a later PgUp computes debt from the
562
+ // clamped row instead of the true pre-clamp row and never pops the
563
+ // accumulator — getSelectedText double-counts the off-screen rows.
564
+ const rawAnchor = (s.virtualAnchorRow ?? s.anchor.row) + dRow;
565
+ const rawFocus = s.focus
566
+ ? (s.virtualFocusRow ?? s.focus.row) + dRow
567
+ : undefined;
568
+ if (rawAnchor < minRow && rawFocus !== undefined && rawFocus < minRow) {
569
+ clearSelection(s);
570
+ return true;
571
+ }
572
+ // Clamp from raw, not p.row+dRow — so a virtual position coming back
573
+ // in-bounds lands at the TRUE position, not the stale clamped one.
574
+ s.anchor = { col: s.anchor.col, row: (0, geometry_js_1.clamp)(rawAnchor, minRow, maxRow) };
575
+ if (s.focus && rawFocus !== undefined) {
576
+ s.focus = { col: s.focus.col, row: (0, geometry_js_1.clamp)(rawFocus, minRow, maxRow) };
577
+ }
578
+ s.virtualAnchorRow =
579
+ rawAnchor < minRow || rawAnchor > maxRow ? rawAnchor : undefined;
580
+ s.virtualFocusRow =
581
+ rawFocus !== undefined && (rawFocus < minRow || rawFocus > maxRow)
582
+ ? rawFocus
583
+ : undefined;
584
+ // anchorSpan not virtual-tracked (word/line extend, irrelevant to
585
+ // keyboard-scroll round-trip) — plain clamp from current row.
586
+ if (s.anchorSpan) {
587
+ const shift = (p) => ({
588
+ col: p.col,
589
+ row: (0, geometry_js_1.clamp)(p.row + dRow, minRow, maxRow),
590
+ });
591
+ s.anchorSpan = {
592
+ lo: shift(s.anchorSpan.lo),
593
+ hi: shift(s.anchorSpan.hi),
594
+ kind: s.anchorSpan.kind,
595
+ };
596
+ }
597
+ return false;
598
+ }
599
+ function hasSelection(s) {
600
+ return s.anchor !== null && s.focus !== null;
601
+ }
602
+ /**
603
+ * Normalized selection bounds: start is always before end in reading order.
604
+ * Returns null if no active selection.
605
+ */
606
+ function selectionBounds(s) {
607
+ if (!s.anchor || !s.focus)
608
+ return null;
609
+ return comparePoints(s.anchor, s.focus) <= 0
610
+ ? { start: s.anchor, end: s.focus }
611
+ : { start: s.focus, end: s.anchor };
612
+ }
613
+ /**
614
+ * Check if a cell at (col, row) is within the current selection range.
615
+ * Used by the renderer to apply inverse style.
616
+ */
617
+ function isCellSelected(s, col, row) {
618
+ const b = selectionBounds(s);
619
+ if (!b)
620
+ return false;
621
+ const { start, end } = b;
622
+ if (row < start.row || row > end.row)
623
+ return false;
624
+ if (row === start.row && col < start.col)
625
+ return false;
626
+ if (row === end.row && col > end.col)
627
+ return false;
628
+ return true;
629
+ }
630
+ /** Extract text from one screen row. When the next row is a soft-wrap
631
+ * continuation (screen.softWrap[row+1]>0), clamp to that content-end
632
+ * column and skip the trailing trim so the word-separator space survives
633
+ * the join. See Screen.softWrap for why the clamp is necessary. */
634
+ function extractRowText(screen, row, colStart, colEnd) {
635
+ const noSelect = screen.noSelect;
636
+ const rowOff = row * screen.width;
637
+ const contentEnd = row + 1 < screen.height ? screen.softWrap[row + 1] : 0;
638
+ const lastCol = contentEnd > 0 ? Math.min(colEnd, contentEnd - 1) : colEnd;
639
+ let line = '';
640
+ for (let col = colStart; col <= lastCol; col++) {
641
+ // Skip cells marked noSelect (gutters, line numbers, diff sigils).
642
+ // Check before cellAt to avoid the decode cost for excluded cells.
643
+ if (noSelect[rowOff + col] === 1)
644
+ continue;
645
+ const cell = (0, screen_js_1.cellAt)(screen, col, row);
646
+ if (!cell)
647
+ continue;
648
+ // Skip spacer tails (second half of wide chars) — the head already
649
+ // contains the full grapheme. SpacerHead is a blank at line-end.
650
+ if (cell.width === 2 /* CellWidth.SpacerTail */ ||
651
+ cell.width === 3 /* CellWidth.SpacerHead */) {
652
+ continue;
653
+ }
654
+ line += cell.char;
655
+ }
656
+ return contentEnd > 0 ? line : line.replace(/\s+$/, '');
657
+ }
658
+ /** Accumulator for selected text that merges soft-wrapped rows back
659
+ * into logical lines. push(text, sw) appends a newline before text
660
+ * only when sw=false (i.e. the row starts a new logical line). Rows
661
+ * with sw=true are concatenated onto the previous row. */
662
+ function joinRows(lines, text, sw) {
663
+ if (sw && lines.length > 0) {
664
+ lines[lines.length - 1] += text;
665
+ }
666
+ else {
667
+ lines.push(text);
668
+ }
669
+ }
670
+ /**
671
+ * Extract text from the screen buffer within the selection range.
672
+ * Rows are joined with newlines unless the screen's softWrap bitmap
673
+ * marks a row as a word-wrap continuation — those rows are concatenated
674
+ * onto the previous row so the copied text matches the logical source
675
+ * line, not the visual wrapped layout. Trailing whitespace on the last
676
+ * fragment of each logical line is trimmed. Wide-char spacer cells are
677
+ * skipped. Rows that scrolled out of the viewport during drag-to-scroll
678
+ * are joined back in from the scrolledOffAbove/Below accumulators along
679
+ * with their captured softWrap bits.
680
+ */
681
+ function getSelectedText(s, screen) {
682
+ const b = selectionBounds(s);
683
+ if (!b)
684
+ return '';
685
+ const { start, end } = b;
686
+ const sw = screen.softWrap;
687
+ const lines = [];
688
+ for (let i = 0; i < s.scrolledOffAbove.length; i++) {
689
+ joinRows(lines, s.scrolledOffAbove[i], s.scrolledOffAboveSW[i]);
690
+ }
691
+ for (let row = start.row; row <= end.row; row++) {
692
+ const rowStart = row === start.row ? start.col : 0;
693
+ const rowEnd = row === end.row ? end.col : screen.width - 1;
694
+ joinRows(lines, extractRowText(screen, row, rowStart, rowEnd), sw[row] > 0);
695
+ }
696
+ for (let i = 0; i < s.scrolledOffBelow.length; i++) {
697
+ joinRows(lines, s.scrolledOffBelow[i], s.scrolledOffBelowSW[i]);
698
+ }
699
+ return lines.join('\n');
700
+ }
701
+ /**
702
+ * Capture text from rows about to scroll out of the viewport during
703
+ * drag-to-scroll, BEFORE scrollBy overwrites them. Only the rows that
704
+ * intersect the selection are captured, using the selection's col bounds
705
+ * for the anchor-side boundary row. After capturing the anchor row, the
706
+ * anchor.col AND anchorSpan cols are reset to the full-width boundary so
707
+ * subsequent captures and the final getSelectedText don't re-apply a stale
708
+ * col constraint to content that's no longer under the original anchor.
709
+ * Both span cols are reset (not just the near side): after a blocked
710
+ * reversal the drag can flip direction, and extendSelection then reads the
711
+ * OPPOSITE span side — which would otherwise still hold the original word
712
+ * boundary and truncate one subsequently-captured row.
713
+ *
714
+ * side='above': rows scrolling out the top (dragging down, anchor=start).
715
+ * side='below': rows scrolling out the bottom (dragging up, anchor=end).
716
+ */
717
+ function captureScrolledRows(s, screen, firstRow, lastRow, side) {
718
+ const b = selectionBounds(s);
719
+ if (!b || firstRow > lastRow)
720
+ return;
721
+ const { start, end } = b;
722
+ // Intersect [firstRow, lastRow] with [start.row, end.row]. Rows outside
723
+ // the selection aren't captured — they weren't selected.
724
+ const lo = Math.max(firstRow, start.row);
725
+ const hi = Math.min(lastRow, end.row);
726
+ if (lo > hi)
727
+ return;
728
+ const width = screen.width;
729
+ const sw = screen.softWrap;
730
+ const captured = [];
731
+ const capturedSW = [];
732
+ for (let row = lo; row <= hi; row++) {
733
+ const colStart = row === start.row ? start.col : 0;
734
+ const colEnd = row === end.row ? end.col : width - 1;
735
+ captured.push(extractRowText(screen, row, colStart, colEnd));
736
+ capturedSW.push(sw[row] > 0);
737
+ }
738
+ if (side === 'above') {
739
+ // Newest rows go at the bottom of the above-accumulator (closest to
740
+ // the on-screen content in reading order).
741
+ s.scrolledOffAbove.push(...captured);
742
+ s.scrolledOffAboveSW.push(...capturedSW);
743
+ // We just captured the top of the selection. The anchor (=start when
744
+ // dragging down) is now pointing at content that will scroll out; its
745
+ // col constraint was applied to the captured row. Reset to col 0 so
746
+ // the NEXT tick and the final getSelectedText read the full row.
747
+ if (s.anchor && s.anchor.row === start.row && lo === start.row) {
748
+ s.anchor = { col: 0, row: s.anchor.row };
749
+ if (s.anchorSpan) {
750
+ s.anchorSpan = {
751
+ kind: s.anchorSpan.kind,
752
+ lo: { col: 0, row: s.anchorSpan.lo.row },
753
+ hi: { col: width - 1, row: s.anchorSpan.hi.row },
754
+ };
755
+ }
756
+ }
757
+ }
758
+ else {
759
+ // Newest rows go at the TOP of the below-accumulator — they're
760
+ // closest to the on-screen content.
761
+ s.scrolledOffBelow.unshift(...captured);
762
+ s.scrolledOffBelowSW.unshift(...capturedSW);
763
+ if (s.anchor && s.anchor.row === end.row && hi === end.row) {
764
+ s.anchor = { col: width - 1, row: s.anchor.row };
765
+ if (s.anchorSpan) {
766
+ s.anchorSpan = {
767
+ kind: s.anchorSpan.kind,
768
+ lo: { col: 0, row: s.anchorSpan.lo.row },
769
+ hi: { col: width - 1, row: s.anchorSpan.hi.row },
770
+ };
771
+ }
772
+ }
773
+ }
774
+ }
775
+ /**
776
+ * Apply the selection overlay directly to the screen buffer by changing
777
+ * the style of every cell in the selection range. Called after the
778
+ * renderer produces the Frame but before the diff — the normal diffEach
779
+ * then picks up the restyled cells as ordinary changes, so LogUpdate
780
+ * stays a pure diff engine with no selection awareness.
781
+ *
782
+ * Uses a SOLID selection background (theme-provided via StylePool.
783
+ * setSelectionBg) that REPLACES each cell's bg while PRESERVING its fg —
784
+ * matches native terminal selection. Previously SGR-7 inverse (swapped
785
+ * fg/bg per cell), which fragmented badly over syntax-highlighted text:
786
+ * every distinct fg color became a different bg stripe.
787
+ *
788
+ * Uses StylePool caches so on drag the only work per cell is a Map
789
+ * lookup + packed-int write.
790
+ */
791
+ function applySelectionOverlay(screen, selection, stylePool) {
792
+ const b = selectionBounds(selection);
793
+ if (!b)
794
+ return;
795
+ const { start, end } = b;
796
+ const width = screen.width;
797
+ const noSelect = screen.noSelect;
798
+ for (let row = start.row; row <= end.row && row < screen.height; row++) {
799
+ const colStart = row === start.row ? start.col : 0;
800
+ const colEnd = row === end.row ? Math.min(end.col, width - 1) : width - 1;
801
+ const rowOff = row * width;
802
+ for (let col = colStart; col <= colEnd; col++) {
803
+ const idx = rowOff + col;
804
+ // Skip noSelect cells — gutters stay visually unchanged so it's
805
+ // clear they're not part of the copy. Surrounding selectable cells
806
+ // still highlight so the selection extent remains visible.
807
+ if (noSelect[idx] === 1)
808
+ continue;
809
+ const cell = (0, screen_js_1.cellAtIndex)(screen, idx);
810
+ (0, screen_js_1.setCellStyleId)(screen, col, row, stylePool.withSelectionBg(cell.styleId));
811
+ }
812
+ }
813
+ }
814
+ //# sourceMappingURL=selection.js.map