indusagi 0.12.18 → 0.12.20

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 (518) hide show
  1. package/README.md +17 -37
  2. package/dist/agent/agent-loop.d.ts +3 -9
  3. package/dist/agent/agent-loop.d.ts.map +1 -1
  4. package/dist/agent/agent-loop.js +19 -58
  5. package/dist/agent/agent-loop.js.map +1 -1
  6. package/dist/agent/agent.d.ts +9 -10
  7. package/dist/agent/agent.d.ts.map +1 -1
  8. package/dist/agent/agent.js +182 -129
  9. package/dist/agent/agent.js.map +1 -1
  10. package/dist/agent/error-handler.d.ts.map +1 -1
  11. package/dist/agent/error-handler.js.map +1 -1
  12. package/dist/agent/event-bus.d.ts.map +1 -1
  13. package/dist/agent/event-bus.js +1 -3
  14. package/dist/agent/event-bus.js.map +1 -1
  15. package/dist/agent/index.d.ts.map +1 -1
  16. package/dist/agent/index.js +0 -6
  17. package/dist/agent/index.js.map +1 -1
  18. package/dist/agent/messages.d.ts +1 -1
  19. package/dist/agent/messages.d.ts.map +1 -1
  20. package/dist/agent/proxy.d.ts +1 -14
  21. package/dist/agent/proxy.d.ts.map +1 -1
  22. package/dist/agent/proxy.js +67 -148
  23. package/dist/agent/proxy.js.map +1 -1
  24. package/dist/agent/session-manager.d.ts +10 -10
  25. package/dist/agent/session-manager.d.ts.map +1 -1
  26. package/dist/agent/session-manager.js +20 -16
  27. package/dist/agent/session-manager.js.map +1 -1
  28. package/dist/agent/state-manager.d.ts +1 -1
  29. package/dist/agent/state-manager.d.ts.map +1 -1
  30. package/dist/agent/state-manager.js +1 -0
  31. package/dist/agent/state-manager.js.map +1 -1
  32. package/dist/agent/telemetry.d.ts.map +1 -1
  33. package/dist/agent/telemetry.js +1 -3
  34. package/dist/agent/telemetry.js.map +1 -1
  35. package/dist/agent/tools/bash.d.ts.map +1 -1
  36. package/dist/agent/tools/bash.js +143 -118
  37. package/dist/agent/tools/bash.js.map +1 -1
  38. package/dist/agent/tools/edit-diff.d.ts +1 -1
  39. package/dist/agent/tools/edit-diff.d.ts.map +1 -1
  40. package/dist/agent/tools/edit-diff.js +189 -175
  41. package/dist/agent/tools/edit-diff.js.map +1 -1
  42. package/dist/agent/tools/edit.d.ts.map +1 -1
  43. package/dist/agent/tools/edit.js +137 -121
  44. package/dist/agent/tools/edit.js.map +1 -1
  45. package/dist/agent/tools/find.d.ts.map +1 -1
  46. package/dist/agent/tools/find.js +100 -65
  47. package/dist/agent/tools/find.js.map +1 -1
  48. package/dist/agent/tools/grep.d.ts.map +1 -1
  49. package/dist/agent/tools/grep.js +126 -97
  50. package/dist/agent/tools/grep.js.map +1 -1
  51. package/dist/agent/tools/index.d.ts +53 -40
  52. package/dist/agent/tools/index.d.ts.map +1 -1
  53. package/dist/agent/tools/index.js +19 -12
  54. package/dist/agent/tools/index.js.map +1 -1
  55. package/dist/agent/tools/ls.d.ts +2 -1
  56. package/dist/agent/tools/ls.d.ts.map +1 -1
  57. package/dist/agent/tools/ls.js +145 -94
  58. package/dist/agent/tools/ls.js.map +1 -1
  59. package/dist/agent/tools/path-utils.d.ts.map +1 -1
  60. package/dist/agent/tools/path-utils.js +48 -29
  61. package/dist/agent/tools/path-utils.js.map +1 -1
  62. package/dist/agent/tools/process-controller.d.ts +15 -0
  63. package/dist/agent/tools/process-controller.d.ts.map +1 -0
  64. package/dist/agent/tools/process-controller.js +39 -0
  65. package/dist/agent/tools/process-controller.js.map +1 -0
  66. package/dist/agent/tools/process-manager.d.ts +60 -0
  67. package/dist/agent/tools/process-manager.d.ts.map +1 -0
  68. package/dist/agent/tools/process-manager.js +485 -0
  69. package/dist/agent/tools/process-manager.js.map +1 -0
  70. package/dist/agent/tools/process-types.d.ts +74 -0
  71. package/dist/agent/tools/process-types.d.ts.map +1 -0
  72. package/dist/agent/tools/process-types.js +7 -0
  73. package/dist/agent/tools/process-types.js.map +1 -0
  74. package/dist/agent/tools/process.d.ts +38 -0
  75. package/dist/agent/tools/process.d.ts.map +1 -0
  76. package/dist/agent/tools/process.js +360 -0
  77. package/dist/agent/tools/process.js.map +1 -0
  78. package/dist/agent/tools/read.d.ts.map +1 -1
  79. package/dist/agent/tools/read.js +157 -135
  80. package/dist/agent/tools/read.js.map +1 -1
  81. package/dist/agent/tools/registry.js +2 -4
  82. package/dist/agent/tools/registry.js.map +1 -1
  83. package/dist/agent/tools/teams/activity-tracker.d.ts +66 -0
  84. package/dist/agent/tools/teams/activity-tracker.d.ts.map +1 -0
  85. package/dist/agent/tools/teams/activity-tracker.js +480 -0
  86. package/dist/agent/tools/teams/activity-tracker.js.map +1 -0
  87. package/dist/agent/tools/teams/cleanup.d.ts +51 -0
  88. package/dist/agent/tools/teams/cleanup.d.ts.map +1 -0
  89. package/dist/agent/tools/teams/cleanup.js +219 -0
  90. package/dist/agent/tools/teams/cleanup.js.map +1 -0
  91. package/dist/agent/tools/teams/fs-lock.d.ts +12 -0
  92. package/dist/agent/tools/teams/fs-lock.d.ts.map +1 -0
  93. package/dist/agent/tools/teams/fs-lock.js +74 -0
  94. package/dist/agent/tools/teams/fs-lock.js.map +1 -0
  95. package/dist/agent/tools/teams/index.d.ts +12 -0
  96. package/dist/agent/tools/teams/index.d.ts.map +1 -0
  97. package/dist/agent/tools/teams/index.js +12 -0
  98. package/dist/agent/tools/teams/index.js.map +1 -0
  99. package/dist/agent/tools/teams/mailbox.d.ts +21 -0
  100. package/dist/agent/tools/teams/mailbox.d.ts.map +1 -0
  101. package/dist/agent/tools/teams/mailbox.js +106 -0
  102. package/dist/agent/tools/teams/mailbox.js.map +1 -0
  103. package/dist/agent/tools/teams/model-policy.d.ts +23 -0
  104. package/dist/agent/tools/teams/model-policy.d.ts.map +1 -0
  105. package/dist/agent/tools/teams/model-policy.js +113 -0
  106. package/dist/agent/tools/teams/model-policy.js.map +1 -0
  107. package/dist/agent/tools/teams/names.d.ts +28 -0
  108. package/dist/agent/tools/teams/names.d.ts.map +1 -0
  109. package/dist/agent/tools/teams/names.js +109 -0
  110. package/dist/agent/tools/teams/names.js.map +1 -0
  111. package/dist/agent/tools/teams/protocol.d.ts +75 -0
  112. package/dist/agent/tools/teams/protocol.d.ts.map +1 -0
  113. package/dist/agent/tools/teams/protocol.js +205 -0
  114. package/dist/agent/tools/teams/protocol.js.map +1 -0
  115. package/dist/agent/tools/teams/task-store.d.ts +89 -0
  116. package/dist/agent/tools/teams/task-store.d.ts.map +1 -0
  117. package/dist/agent/tools/teams/task-store.js +445 -0
  118. package/dist/agent/tools/teams/task-store.js.map +1 -0
  119. package/dist/agent/tools/teams/team-attach-claim.d.ts +36 -0
  120. package/dist/agent/tools/teams/team-attach-claim.d.ts.map +1 -0
  121. package/dist/agent/tools/teams/team-attach-claim.js +144 -0
  122. package/dist/agent/tools/teams/team-attach-claim.js.map +1 -0
  123. package/dist/agent/tools/teams/team-config.d.ts +55 -0
  124. package/dist/agent/tools/teams/team-config.d.ts.map +1 -0
  125. package/dist/agent/tools/teams/team-config.js +252 -0
  126. package/dist/agent/tools/teams/team-config.js.map +1 -0
  127. package/dist/agent/tools/teams/worktree.d.ts +40 -0
  128. package/dist/agent/tools/teams/worktree.d.ts.map +1 -0
  129. package/dist/agent/tools/teams/worktree.js +213 -0
  130. package/dist/agent/tools/teams/worktree.js.map +1 -0
  131. package/dist/agent/tools/todo-store.js +2 -1
  132. package/dist/agent/tools/todo-store.js.map +1 -1
  133. package/dist/agent/tools/todo.d.ts +2 -2
  134. package/dist/agent/tools/todo.js +2 -2
  135. package/dist/agent/tools/truncate.d.ts.map +1 -1
  136. package/dist/agent/tools/truncate.js +150 -134
  137. package/dist/agent/tools/truncate.js.map +1 -1
  138. package/dist/agent/tools/utils/hook-runner.d.ts +9 -10
  139. package/dist/agent/tools/utils/hook-runner.d.ts.map +1 -1
  140. package/dist/agent/tools/utils/hook-runner.js +18 -16
  141. package/dist/agent/tools/utils/hook-runner.js.map +1 -1
  142. package/dist/agent/tools/utils/image-resize.d.ts +1 -14
  143. package/dist/agent/tools/utils/image-resize.d.ts.map +1 -1
  144. package/dist/agent/tools/utils/image-resize.js +80 -34
  145. package/dist/agent/tools/utils/image-resize.js.map +1 -1
  146. package/dist/agent/tools/utils/mime.d.ts +0 -8
  147. package/dist/agent/tools/utils/mime.d.ts.map +1 -1
  148. package/dist/agent/tools/utils/mime.js +43 -32
  149. package/dist/agent/tools/utils/mime.js.map +1 -1
  150. package/dist/agent/tools/utils/shell.d.ts +1 -23
  151. package/dist/agent/tools/utils/shell.d.ts.map +1 -1
  152. package/dist/agent/tools/utils/shell.js +43 -86
  153. package/dist/agent/tools/utils/shell.js.map +1 -1
  154. package/dist/agent/tools/write.d.ts.map +1 -1
  155. package/dist/agent/tools/write.js +105 -62
  156. package/dist/agent/tools/write.js.map +1 -1
  157. package/dist/agent/types.d.ts +69 -64
  158. package/dist/agent/types.d.ts.map +1 -1
  159. package/dist/agent/types.js +38 -23
  160. package/dist/agent/types.js.map +1 -1
  161. package/dist/agent.d.ts +4 -0
  162. package/dist/agent.d.ts.map +1 -1
  163. package/dist/agent.js +4 -0
  164. package/dist/agent.js.map +1 -1
  165. package/dist/ai/api-registry.d.ts.map +1 -1
  166. package/dist/ai/api-registry.js +3 -4
  167. package/dist/ai/api-registry.js.map +1 -1
  168. package/dist/ai/cli.js +62 -82
  169. package/dist/ai/cli.js.map +1 -1
  170. package/dist/ai/env-api-keys.d.ts.map +1 -1
  171. package/dist/ai/env-api-keys.js +78 -81
  172. package/dist/ai/env-api-keys.js.map +1 -1
  173. package/dist/ai/index.d.ts +6 -0
  174. package/dist/ai/index.d.ts.map +1 -1
  175. package/dist/ai/index.js +6 -0
  176. package/dist/ai/index.js.map +1 -1
  177. package/dist/ai/models.d.ts +7 -17
  178. package/dist/ai/models.d.ts.map +1 -1
  179. package/dist/ai/models.generated.d.ts +87 -244
  180. package/dist/ai/models.generated.d.ts.map +1 -1
  181. package/dist/ai/models.generated.js +82 -241
  182. package/dist/ai/models.generated.js.map +1 -1
  183. package/dist/ai/models.js +17 -11
  184. package/dist/ai/models.js.map +1 -1
  185. package/dist/ai/providers/amazon-bedrock.d.ts.map +1 -1
  186. package/dist/ai/providers/amazon-bedrock.js +319 -248
  187. package/dist/ai/providers/amazon-bedrock.js.map +1 -1
  188. package/dist/ai/providers/anthropic.d.ts.map +1 -1
  189. package/dist/ai/providers/anthropic.js +378 -324
  190. package/dist/ai/providers/anthropic.js.map +1 -1
  191. package/dist/ai/providers/azure-openai-responses.d.ts.map +1 -1
  192. package/dist/ai/providers/azure-openai-responses.js +164 -123
  193. package/dist/ai/providers/azure-openai-responses.js.map +1 -1
  194. package/dist/ai/providers/google-shared.d.ts +0 -18
  195. package/dist/ai/providers/google-shared.d.ts.map +1 -1
  196. package/dist/ai/providers/google-shared.js +224 -225
  197. package/dist/ai/providers/google-shared.js.map +1 -1
  198. package/dist/ai/providers/google-vertex.d.ts.map +1 -1
  199. package/dist/ai/providers/google-vertex.js +244 -226
  200. package/dist/ai/providers/google-vertex.js.map +1 -1
  201. package/dist/ai/providers/google.d.ts +3 -0
  202. package/dist/ai/providers/google.d.ts.map +1 -1
  203. package/dist/ai/providers/google.js +232 -210
  204. package/dist/ai/providers/google.js.map +1 -1
  205. package/dist/ai/providers/kimi.js +1 -0
  206. package/dist/ai/providers/kimi.js.map +1 -1
  207. package/dist/ai/providers/mock.d.ts +10 -0
  208. package/dist/ai/providers/mock.d.ts.map +1 -0
  209. package/dist/ai/providers/mock.js +64 -0
  210. package/dist/ai/providers/mock.js.map +1 -0
  211. package/dist/ai/providers/openai-codex-responses.d.ts.map +1 -1
  212. package/dist/ai/providers/openai-codex-responses.js +178 -133
  213. package/dist/ai/providers/openai-codex-responses.js.map +1 -1
  214. package/dist/ai/providers/openai-completions.d.ts.map +1 -1
  215. package/dist/ai/providers/openai-completions.js +468 -387
  216. package/dist/ai/providers/openai-completions.js.map +1 -1
  217. package/dist/ai/providers/openai-responses-shared.d.ts.map +1 -1
  218. package/dist/ai/providers/openai-responses-shared.js +187 -166
  219. package/dist/ai/providers/openai-responses-shared.js.map +1 -1
  220. package/dist/ai/providers/openai-responses.d.ts.map +1 -1
  221. package/dist/ai/providers/openai-responses.js +108 -85
  222. package/dist/ai/providers/openai-responses.js.map +1 -1
  223. package/dist/ai/providers/openai-scaffold.d.ts +4 -0
  224. package/dist/ai/providers/openai-scaffold.d.ts.map +1 -0
  225. package/dist/ai/providers/openai-scaffold.js +33 -0
  226. package/dist/ai/providers/openai-scaffold.js.map +1 -0
  227. package/dist/ai/providers/register-builtins.d.ts.map +1 -1
  228. package/dist/ai/providers/register-builtins.js +109 -42
  229. package/dist/ai/providers/register-builtins.js.map +1 -1
  230. package/dist/ai/providers/simple-options.js +2 -0
  231. package/dist/ai/providers/simple-options.js.map +1 -1
  232. package/dist/ai/providers/transform-messages.js +3 -9
  233. package/dist/ai/providers/transform-messages.js.map +1 -1
  234. package/dist/ai/stream.d.ts +4 -14
  235. package/dist/ai/stream.d.ts.map +1 -1
  236. package/dist/ai/stream.js +0 -36
  237. package/dist/ai/stream.js.map +1 -1
  238. package/dist/ai/types.d.ts +22 -3
  239. package/dist/ai/types.d.ts.map +1 -1
  240. package/dist/ai/types.js +154 -77
  241. package/dist/ai/types.js.map +1 -1
  242. package/dist/ai/utils/base-stream-handler.js +1 -0
  243. package/dist/ai/utils/base-stream-handler.js.map +1 -1
  244. package/dist/ai/utils/event-stream.d.ts +2 -0
  245. package/dist/ai/utils/event-stream.d.ts.map +1 -1
  246. package/dist/ai/utils/event-stream.js +22 -5
  247. package/dist/ai/utils/event-stream.js.map +1 -1
  248. package/dist/ai/utils/json-parse.d.ts +3 -0
  249. package/dist/ai/utils/json-parse.d.ts.map +1 -1
  250. package/dist/ai/utils/json-parse.js +8 -5
  251. package/dist/ai/utils/json-parse.js.map +1 -1
  252. package/dist/ai/utils/oauth/anthropic.d.ts.map +1 -1
  253. package/dist/ai/utils/oauth/anthropic.js +110 -65
  254. package/dist/ai/utils/oauth/anthropic.js.map +1 -1
  255. package/dist/ai/utils/oauth/github-copilot.d.ts +8 -16
  256. package/dist/ai/utils/oauth/github-copilot.d.ts.map +1 -1
  257. package/dist/ai/utils/oauth/github-copilot.js +218 -227
  258. package/dist/ai/utils/oauth/github-copilot.js.map +1 -1
  259. package/dist/ai/utils/oauth/openai-codex.d.ts +4 -2
  260. package/dist/ai/utils/oauth/openai-codex.d.ts.map +1 -1
  261. package/dist/ai/utils/oauth/openai-codex.js +221 -236
  262. package/dist/ai/utils/oauth/openai-codex.js.map +1 -1
  263. package/dist/ai/utils/oauth/pkce.d.ts +6 -5
  264. package/dist/ai/utils/oauth/pkce.d.ts.map +1 -1
  265. package/dist/ai/utils/oauth/pkce.js +24 -21
  266. package/dist/ai/utils/oauth/pkce.js.map +1 -1
  267. package/dist/ai/utils/oauth/types.d.ts +31 -12
  268. package/dist/ai/utils/oauth/types.d.ts.map +1 -1
  269. package/dist/ai/utils/oauth/types.js +10 -1
  270. package/dist/ai/utils/oauth/types.js.map +1 -1
  271. package/dist/ai/utils/overflow.d.ts.map +1 -1
  272. package/dist/ai/utils/overflow.js +49 -21
  273. package/dist/ai/utils/overflow.js.map +1 -1
  274. package/dist/ai/utils/provider-adapter.js +9 -0
  275. package/dist/ai/utils/provider-adapter.js.map +1 -1
  276. package/dist/ai/utils/provider-client-builder.js +1 -1
  277. package/dist/ai/utils/provider-client-builder.js.map +1 -1
  278. package/dist/ai/utils/provider-errors.js +2 -0
  279. package/dist/ai/utils/provider-errors.js.map +1 -1
  280. package/dist/ai/utils/sanitize-unicode.d.ts +0 -20
  281. package/dist/ai/utils/sanitize-unicode.d.ts.map +1 -1
  282. package/dist/ai/utils/sanitize-unicode.js +35 -17
  283. package/dist/ai/utils/sanitize-unicode.js.map +1 -1
  284. package/dist/ai/utils/stream-event-helper.js +3 -0
  285. package/dist/ai/utils/stream-event-helper.js.map +1 -1
  286. package/dist/ai/utils/stream-handler-types.js +5 -0
  287. package/dist/ai/utils/stream-handler-types.js.map +1 -1
  288. package/dist/ai/utils/streaming-state-manager.js +4 -2
  289. package/dist/ai/utils/streaming-state-manager.js.map +1 -1
  290. package/dist/ai/utils/typebox-helpers.d.ts +6 -4
  291. package/dist/ai/utils/typebox-helpers.d.ts.map +1 -1
  292. package/dist/ai/utils/typebox-helpers.js +25 -7
  293. package/dist/ai/utils/typebox-helpers.js.map +1 -1
  294. package/dist/ai/utils/validation.d.ts.map +1 -1
  295. package/dist/ai/utils/validation.js +67 -34
  296. package/dist/ai/utils/validation.js.map +1 -1
  297. package/dist/ai.d.ts +4 -0
  298. package/dist/ai.d.ts.map +1 -1
  299. package/dist/ai.js +4 -0
  300. package/dist/ai.js.map +1 -1
  301. package/dist/cli.d.ts +3 -0
  302. package/dist/cli.d.ts.map +1 -0
  303. package/dist/cli.js +3 -0
  304. package/dist/cli.js.map +1 -0
  305. package/dist/index.d.ts +1 -0
  306. package/dist/index.d.ts.map +1 -1
  307. package/dist/index.js +1 -0
  308. package/dist/index.js.map +1 -1
  309. package/dist/mcp/client-pool.js +3 -2
  310. package/dist/mcp/client-pool.js.map +1 -1
  311. package/dist/mcp/client.js +19 -6
  312. package/dist/mcp/client.js.map +1 -1
  313. package/dist/mcp/config.d.ts +6 -6
  314. package/dist/mcp/config.js +17 -17
  315. package/dist/mcp/config.js.map +1 -1
  316. package/dist/mcp/errors.js +8 -0
  317. package/dist/mcp/errors.js.map +1 -1
  318. package/dist/mcp/index.d.ts +5 -5
  319. package/dist/mcp/index.js +5 -5
  320. package/dist/mcp/schema-converter.d.ts +1 -1
  321. package/dist/mcp/schema-converter.js +1 -1
  322. package/dist/mcp/server.d.ts +4 -4
  323. package/dist/mcp/server.js +12 -7
  324. package/dist/mcp/server.js.map +1 -1
  325. package/dist/mcp/tool-factory.d.ts +2 -2
  326. package/dist/mcp/tool-factory.js +2 -2
  327. package/dist/mcp.d.ts +0 -4
  328. package/dist/mcp.d.ts.map +1 -1
  329. package/dist/mcp.js +0 -4
  330. package/dist/mcp.js.map +1 -1
  331. package/dist/observability.d.ts +2 -0
  332. package/dist/observability.d.ts.map +1 -0
  333. package/dist/observability.js +2 -0
  334. package/dist/observability.js.map +1 -0
  335. package/dist/tui/autocomplete.d.ts +14 -18
  336. package/dist/tui/autocomplete.d.ts.map +1 -1
  337. package/dist/tui/autocomplete.js +290 -402
  338. package/dist/tui/autocomplete.js.map +1 -1
  339. package/dist/tui/components/box.d.ts +1 -6
  340. package/dist/tui/components/box.d.ts.map +1 -1
  341. package/dist/tui/components/box.js +98 -67
  342. package/dist/tui/components/box.js.map +1 -1
  343. package/dist/tui/components/cancellable-loader.d.ts +6 -3
  344. package/dist/tui/components/cancellable-loader.d.ts.map +1 -1
  345. package/dist/tui/components/cancellable-loader.js +8 -9
  346. package/dist/tui/components/cancellable-loader.js.map +1 -1
  347. package/dist/tui/components/editor.d.ts +18 -0
  348. package/dist/tui/components/editor.d.ts.map +1 -1
  349. package/dist/tui/components/editor.js +356 -354
  350. package/dist/tui/components/editor.js.map +1 -1
  351. package/dist/tui/components/image.d.ts +2 -0
  352. package/dist/tui/components/image.d.ts.map +1 -1
  353. package/dist/tui/components/image.js +79 -37
  354. package/dist/tui/components/image.js.map +1 -1
  355. package/dist/tui/components/input.d.ts +4 -8
  356. package/dist/tui/components/input.d.ts.map +1 -1
  357. package/dist/tui/components/input.js +236 -232
  358. package/dist/tui/components/input.js.map +1 -1
  359. package/dist/tui/components/loader.d.ts +5 -5
  360. package/dist/tui/components/loader.d.ts.map +1 -1
  361. package/dist/tui/components/loader.js +22 -19
  362. package/dist/tui/components/loader.js.map +1 -1
  363. package/dist/tui/components/markdown.d.ts +2 -32
  364. package/dist/tui/components/markdown.d.ts.map +1 -1
  365. package/dist/tui/components/markdown.js +338 -357
  366. package/dist/tui/components/markdown.js.map +1 -1
  367. package/dist/tui/components/select-list.d.ts +1 -0
  368. package/dist/tui/components/select-list.d.ts.map +1 -1
  369. package/dist/tui/components/select-list.js +83 -82
  370. package/dist/tui/components/select-list.js.map +1 -1
  371. package/dist/tui/components/settings-list.d.ts +10 -10
  372. package/dist/tui/components/settings-list.d.ts.map +1 -1
  373. package/dist/tui/components/settings-list.js +48 -40
  374. package/dist/tui/components/settings-list.js.map +1 -1
  375. package/dist/tui/components/spacer.d.ts +1 -0
  376. package/dist/tui/components/spacer.d.ts.map +1 -1
  377. package/dist/tui/components/spacer.js +20 -5
  378. package/dist/tui/components/spacer.js.map +1 -1
  379. package/dist/tui/components/text.d.ts.map +1 -1
  380. package/dist/tui/components/text.js +47 -20
  381. package/dist/tui/components/text.js.map +1 -1
  382. package/dist/tui/components/truncated-text.d.ts +8 -4
  383. package/dist/tui/components/truncated-text.d.ts.map +1 -1
  384. package/dist/tui/components/truncated-text.js +15 -12
  385. package/dist/tui/components/truncated-text.js.map +1 -1
  386. package/dist/tui/editor-component.d.ts +87 -23
  387. package/dist/tui/editor-component.d.ts.map +1 -1
  388. package/dist/tui/fuzzy.d.ts.map +1 -1
  389. package/dist/tui/fuzzy.js +101 -50
  390. package/dist/tui/fuzzy.js.map +1 -1
  391. package/dist/tui/keybindings.d.ts +3 -3
  392. package/dist/tui/keybindings.d.ts.map +1 -1
  393. package/dist/tui/keybindings.js +137 -111
  394. package/dist/tui/keybindings.js.map +1 -1
  395. package/dist/tui/keys.d.ts +46 -43
  396. package/dist/tui/keys.d.ts.map +1 -1
  397. package/dist/tui/keys.js +493 -411
  398. package/dist/tui/keys.js.map +1 -1
  399. package/dist/tui/stdin-buffer.d.ts.map +1 -1
  400. package/dist/tui/stdin-buffer.js +162 -159
  401. package/dist/tui/stdin-buffer.js.map +1 -1
  402. package/dist/tui/terminal-image.d.ts +10 -5
  403. package/dist/tui/terminal-image.d.ts.map +1 -1
  404. package/dist/tui/terminal-image.js +53 -51
  405. package/dist/tui/terminal-image.js.map +1 -1
  406. package/dist/tui/terminal.d.ts +4 -27
  407. package/dist/tui/terminal.d.ts.map +1 -1
  408. package/dist/tui/terminal.js +123 -121
  409. package/dist/tui/terminal.js.map +1 -1
  410. package/dist/tui/tui.d.ts +14 -1
  411. package/dist/tui/tui.d.ts.map +1 -1
  412. package/dist/tui/tui.js +185 -145
  413. package/dist/tui/tui.js.map +1 -1
  414. package/dist/tui/utils.d.ts.map +1 -1
  415. package/dist/tui/utils.js +235 -216
  416. package/dist/tui/utils.js.map +1 -1
  417. package/dist/tui.d.ts +4 -0
  418. package/dist/tui.d.ts.map +1 -1
  419. package/dist/tui.js +4 -0
  420. package/dist/tui.js.map +1 -1
  421. package/package.json +23 -43
  422. package/LICENSE.md +0 -22
  423. package/dist/agent/tools/task-types.d.ts +0 -74
  424. package/dist/agent/tools/task-types.d.ts.map +0 -1
  425. package/dist/agent/tools/task-types.js +0 -8
  426. package/dist/agent/tools/task-types.js.map +0 -1
  427. package/dist/agent/tools/task.d.ts +0 -84
  428. package/dist/agent/tools/task.d.ts.map +0 -1
  429. package/dist/agent/tools/task.js +0 -184
  430. package/dist/agent/tools/task.js.map +0 -1
  431. package/dist/memory/embedder/base.d.ts +0 -41
  432. package/dist/memory/embedder/base.d.ts.map +0 -1
  433. package/dist/memory/embedder/base.js +0 -10
  434. package/dist/memory/embedder/base.js.map +0 -1
  435. package/dist/memory/embedder/index.d.ts +0 -8
  436. package/dist/memory/embedder/index.d.ts.map +0 -1
  437. package/dist/memory/embedder/index.js +0 -6
  438. package/dist/memory/embedder/index.js.map +0 -1
  439. package/dist/memory/embedder/openai.d.ts +0 -35
  440. package/dist/memory/embedder/openai.d.ts.map +0 -1
  441. package/dist/memory/embedder/openai.js +0 -103
  442. package/dist/memory/embedder/openai.js.map +0 -1
  443. package/dist/memory/index.d.ts +0 -33
  444. package/dist/memory/index.d.ts.map +0 -1
  445. package/dist/memory/index.js +0 -31
  446. package/dist/memory/index.js.map +0 -1
  447. package/dist/memory/memory.d.ts +0 -126
  448. package/dist/memory/memory.d.ts.map +0 -1
  449. package/dist/memory/memory.js +0 -280
  450. package/dist/memory/memory.js.map +0 -1
  451. package/dist/memory/processors/base.d.ts +0 -42
  452. package/dist/memory/processors/base.d.ts.map +0 -1
  453. package/dist/memory/processors/base.js +0 -6
  454. package/dist/memory/processors/base.js.map +0 -1
  455. package/dist/memory/processors/index.d.ts +0 -16
  456. package/dist/memory/processors/index.d.ts.map +0 -1
  457. package/dist/memory/processors/index.js +0 -18
  458. package/dist/memory/processors/index.js.map +0 -1
  459. package/dist/memory/processors/message-history.d.ts +0 -35
  460. package/dist/memory/processors/message-history.d.ts.map +0 -1
  461. package/dist/memory/processors/message-history.js +0 -51
  462. package/dist/memory/processors/message-history.js.map +0 -1
  463. package/dist/memory/processors/observational-memory/index.d.ts +0 -82
  464. package/dist/memory/processors/observational-memory/index.d.ts.map +0 -1
  465. package/dist/memory/processors/observational-memory/index.js +0 -234
  466. package/dist/memory/processors/observational-memory/index.js.map +0 -1
  467. package/dist/memory/processors/observational-memory/observer-agent.d.ts +0 -64
  468. package/dist/memory/processors/observational-memory/observer-agent.d.ts.map +0 -1
  469. package/dist/memory/processors/observational-memory/observer-agent.js +0 -362
  470. package/dist/memory/processors/observational-memory/observer-agent.js.map +0 -1
  471. package/dist/memory/processors/observational-memory/reflector-agent.d.ts +0 -38
  472. package/dist/memory/processors/observational-memory/reflector-agent.d.ts.map +0 -1
  473. package/dist/memory/processors/observational-memory/reflector-agent.js +0 -213
  474. package/dist/memory/processors/observational-memory/reflector-agent.js.map +0 -1
  475. package/dist/memory/processors/observational-memory/token-counter.d.ts +0 -35
  476. package/dist/memory/processors/observational-memory/token-counter.d.ts.map +0 -1
  477. package/dist/memory/processors/observational-memory/token-counter.js +0 -90
  478. package/dist/memory/processors/observational-memory/token-counter.js.map +0 -1
  479. package/dist/memory/processors/semantic-recall.d.ts +0 -55
  480. package/dist/memory/processors/semantic-recall.d.ts.map +0 -1
  481. package/dist/memory/processors/semantic-recall.js +0 -143
  482. package/dist/memory/processors/semantic-recall.js.map +0 -1
  483. package/dist/memory/processors/working-memory.d.ts +0 -41
  484. package/dist/memory/processors/working-memory.d.ts.map +0 -1
  485. package/dist/memory/processors/working-memory.js +0 -82
  486. package/dist/memory/processors/working-memory.js.map +0 -1
  487. package/dist/memory/storage/base.d.ts +0 -288
  488. package/dist/memory/storage/base.d.ts.map +0 -1
  489. package/dist/memory/storage/base.js +0 -211
  490. package/dist/memory/storage/base.js.map +0 -1
  491. package/dist/memory/storage/index.d.ts +0 -9
  492. package/dist/memory/storage/index.d.ts.map +0 -1
  493. package/dist/memory/storage/index.js +0 -7
  494. package/dist/memory/storage/index.js.map +0 -1
  495. package/dist/memory/storage/inmemory.d.ts +0 -93
  496. package/dist/memory/storage/inmemory.d.ts.map +0 -1
  497. package/dist/memory/storage/inmemory.js +0 -646
  498. package/dist/memory/storage/inmemory.js.map +0 -1
  499. package/dist/memory/tools/working-memory.d.ts +0 -100
  500. package/dist/memory/tools/working-memory.d.ts.map +0 -1
  501. package/dist/memory/tools/working-memory.js +0 -237
  502. package/dist/memory/tools/working-memory.js.map +0 -1
  503. package/dist/memory/types.d.ts +0 -386
  504. package/dist/memory/types.d.ts.map +0 -1
  505. package/dist/memory/types.js +0 -58
  506. package/dist/memory/types.js.map +0 -1
  507. package/dist/memory/vector/base.d.ts +0 -145
  508. package/dist/memory/vector/base.d.ts.map +0 -1
  509. package/dist/memory/vector/base.js +0 -83
  510. package/dist/memory/vector/base.js.map +0 -1
  511. package/dist/memory/vector/index.d.ts +0 -8
  512. package/dist/memory/vector/index.d.ts.map +0 -1
  513. package/dist/memory/vector/index.js +0 -7
  514. package/dist/memory/vector/index.js.map +0 -1
  515. package/dist/memory/vector/inmemory.d.ts +0 -47
  516. package/dist/memory/vector/inmemory.d.ts.map +0 -1
  517. package/dist/memory/vector/inmemory.js +0 -234
  518. package/dist/memory/vector/inmemory.js.map +0 -1
@@ -102,40 +102,94 @@ function decodeKittyPrintable(data) {
102
102
  return undefined;
103
103
  }
104
104
  }
105
+ class EditorLayoutProjector {
106
+ static buildVisualLineMap(lines, width) {
107
+ const visualLines = [];
108
+ for (let logicalIndex = 0; logicalIndex < lines.length; logicalIndex++) {
109
+ const line = lines[logicalIndex] || "";
110
+ if (line.length === 0) {
111
+ visualLines.push({ logicalLine: logicalIndex, startCol: 0, length: 0 });
112
+ continue;
113
+ }
114
+ if (visibleWidth(line) <= width) {
115
+ visualLines.push({ logicalLine: logicalIndex, startCol: 0, length: line.length });
116
+ continue;
117
+ }
118
+ for (const chunk of wordWrapLine(line, width)) {
119
+ visualLines.push({
120
+ logicalLine: logicalIndex,
121
+ startCol: chunk.startIndex,
122
+ length: chunk.endIndex - chunk.startIndex,
123
+ });
124
+ }
125
+ }
126
+ return visualLines;
127
+ }
128
+ static findCurrentVisualLine(visualLines, cursorLine, cursorCol) {
129
+ for (let visualIndex = 0; visualIndex < visualLines.length; visualIndex++) {
130
+ const segment = visualLines[visualIndex];
131
+ if (!segment || segment.logicalLine !== cursorLine)
132
+ continue;
133
+ const offset = cursorCol - segment.startCol;
134
+ const lastSegment = visualIndex === visualLines.length - 1 || visualLines[visualIndex + 1]?.logicalLine !== segment.logicalLine;
135
+ if (offset >= 0 && (offset < segment.length || (lastSegment && offset <= segment.length))) {
136
+ return visualIndex;
137
+ }
138
+ }
139
+ return visualLines.length - 1;
140
+ }
141
+ static resolveCursorAtVisualLine(visualLines, visualIndex, visualCol, lines) {
142
+ const segment = visualLines[visualIndex];
143
+ if (!segment)
144
+ return null;
145
+ const line = segment.logicalLine;
146
+ const targetCol = segment.startCol + Math.min(visualCol, segment.length);
147
+ return { line, col: Math.min(targetCol, (lines[line] || "").length) };
148
+ }
149
+ }
105
150
  export class Editor extends ComponentBase {
151
+ state = {
152
+ lines: [""],
153
+ cursorLine: 0,
154
+ cursorCol: 0,
155
+ };
156
+ /** Focusable interface - set by TUI when focus changes */
157
+ focused = false;
158
+ tui;
159
+ theme;
160
+ paddingX = 0;
161
+ // Store last render width for cursor navigation
162
+ lastWidth = 80;
163
+ // Vertical scrolling support
164
+ scrollOffset = 0;
165
+ // Border color (can be changed dynamically)
166
+ borderColor;
167
+ // Autocomplete support
168
+ autocompleteProvider;
169
+ autocompleteList;
170
+ isAutocompleting = false;
171
+ autocompletePrefix = "";
172
+ // Paste tracking for large pastes
173
+ pastes = new Map();
174
+ pasteCounter = 0;
175
+ // Bracketed paste mode buffering
176
+ pasteBuffer = "";
177
+ isInPaste = false;
178
+ pendingShiftEnter = false;
179
+ // Prompt history for up/down navigation
180
+ history = [];
181
+ historyIndex = -1; // -1 = not browsing, 0 = most recent, 1 = older, etc.
182
+ // Kill ring for Emacs-style kill/yank operations
183
+ // Also tracks undo coalescing: "type-word" means we're mid-word (coalescing)
184
+ killRing = [];
185
+ lastAction = null;
186
+ // Undo support
187
+ undoStack = [];
188
+ onSubmit;
189
+ onChange;
190
+ disableSubmit = false;
106
191
  constructor(tui, theme, options = {}) {
107
192
  super();
108
- this.state = {
109
- lines: [""],
110
- cursorLine: 0,
111
- cursorCol: 0,
112
- };
113
- /** Focusable interface - set by TUI when focus changes */
114
- this.focused = false;
115
- this.paddingX = 0;
116
- // Store last render width for cursor navigation
117
- this.lastWidth = 80;
118
- // Vertical scrolling support
119
- this.scrollOffset = 0;
120
- this.isAutocompleting = false;
121
- this.autocompletePrefix = "";
122
- // Paste tracking for large pastes
123
- this.pastes = new Map();
124
- this.pasteCounter = 0;
125
- // Bracketed paste mode buffering
126
- this.pasteBuffer = "";
127
- this.isInPaste = false;
128
- this.pendingShiftEnter = false;
129
- // Prompt history for up/down navigation
130
- this.history = [];
131
- this.historyIndex = -1; // -1 = not browsing, 0 = most recent, 1 = older, etc.
132
- // Kill ring for Emacs-style kill/yank operations
133
- // Also tracks undo coalescing: "type-word" means we're mid-word (coalescing)
134
- this.killRing = [];
135
- this.lastAction = null;
136
- // Undo support
137
- this.undoStack = [];
138
- this.disableSubmit = false;
139
193
  this.tui = tui;
140
194
  this.theme = theme;
141
195
  this.borderColor = theme.borderColor;
@@ -223,294 +277,274 @@ export class Editor extends ComponentBase {
223
277
  this.autocompleteList?.invalidate?.();
224
278
  }
225
279
  render(width) {
280
+ const state = this.prepareRenderState(width);
281
+ const out = [];
282
+ out.push(this.renderTopBorder(width, state.horizontal));
283
+ const emitCursorMarker = this.focused && !this.isAutocompleting;
284
+ for (const layoutLine of state.visibleLines) {
285
+ out.push(this.renderVisibleLine(layoutLine, state.contentWidth, state.leftPadding, state.rightPadding, emitCursorMarker));
286
+ }
287
+ const linesBelow = state.layoutLines.length - (this.scrollOffset + state.visibleLines.length);
288
+ out.push(this.renderBottomBorder(width, state.horizontal, linesBelow));
289
+ if (this.isAutocompleting && this.autocompleteList) {
290
+ this.appendAutocompleteLines(out, state.contentWidth, state.leftPadding, state.rightPadding);
291
+ }
292
+ return out;
293
+ }
294
+ prepareRenderState(width) {
226
295
  const maxPadding = Math.max(0, Math.floor((width - 1) / 2));
227
296
  const paddingX = Math.min(this.paddingX, maxPadding);
228
297
  const contentWidth = Math.max(1, width - paddingX * 2);
229
- // Layout width: with padding the cursor can overflow into it,
230
- // without padding we reserve 1 column for the cursor.
231
298
  const layoutWidth = Math.max(1, contentWidth - (paddingX ? 0 : 1));
232
- // Store for cursor navigation (must match wrapping width)
233
299
  this.lastWidth = layoutWidth;
234
- const horizontal = this.borderColor("─");
235
- // Layout the text
236
300
  const layoutLines = this.layoutText(layoutWidth);
237
- // Calculate max visible lines: 30% of terminal height, minimum 5 lines
238
- const terminalRows = this.tui.terminal.rows;
239
- const maxVisibleLines = Math.max(5, Math.floor(terminalRows * 0.3));
240
- // Find the cursor line index in layoutLines
241
- let cursorLineIndex = layoutLines.findIndex((line) => line.hasCursor);
242
- if (cursorLineIndex === -1)
243
- cursorLineIndex = 0;
244
- // Adjust scroll offset to keep cursor visible
301
+ const maxVisibleLines = Math.max(5, Math.floor(this.tui.terminal.rows * 0.3));
302
+ const cursorLineIndex = Math.max(0, layoutLines.findIndex((line) => line.hasCursor));
303
+ this.syncScrollOffset(cursorLineIndex, maxVisibleLines, layoutLines.length);
304
+ const visibleLines = layoutLines.slice(this.scrollOffset, this.scrollOffset + maxVisibleLines);
305
+ const sidePadding = " ".repeat(paddingX);
306
+ return {
307
+ horizontal: this.borderColor("─"),
308
+ contentWidth,
309
+ leftPadding: sidePadding,
310
+ rightPadding: sidePadding,
311
+ layoutLines,
312
+ visibleLines,
313
+ };
314
+ }
315
+ syncScrollOffset(cursorLineIndex, maxVisibleLines, totalLayoutLines) {
245
316
  if (cursorLineIndex < this.scrollOffset) {
246
317
  this.scrollOffset = cursorLineIndex;
247
318
  }
248
319
  else if (cursorLineIndex >= this.scrollOffset + maxVisibleLines) {
249
320
  this.scrollOffset = cursorLineIndex - maxVisibleLines + 1;
250
321
  }
251
- // Clamp scroll offset to valid range
252
- const maxScrollOffset = Math.max(0, layoutLines.length - maxVisibleLines);
322
+ const maxScrollOffset = Math.max(0, totalLayoutLines - maxVisibleLines);
253
323
  this.scrollOffset = Math.max(0, Math.min(this.scrollOffset, maxScrollOffset));
254
- // Get visible lines slice
255
- const visibleLines = layoutLines.slice(this.scrollOffset, this.scrollOffset + maxVisibleLines);
256
- const result = [];
257
- const leftPadding = " ".repeat(paddingX);
258
- const rightPadding = leftPadding;
259
- // Render top border (with scroll indicator if scrolled down)
260
- if (this.scrollOffset > 0) {
261
- const indicator = `─── ↑ ${this.scrollOffset} more `;
262
- const remaining = width - visibleWidth(indicator);
263
- result.push(this.borderColor(indicator + "─".repeat(Math.max(0, remaining))));
264
- }
265
- else {
266
- result.push(horizontal.repeat(width));
267
- }
268
- // Render each visible layout line
269
- // Emit hardware cursor marker only when focused and not showing autocomplete
270
- const emitCursorMarker = this.focused && !this.isAutocompleting;
271
- for (const layoutLine of visibleLines) {
272
- let displayText = layoutLine.text;
273
- let lineVisibleWidth = visibleWidth(layoutLine.text);
274
- let cursorInPadding = false;
275
- // Add cursor if this line has it
276
- if (layoutLine.hasCursor && layoutLine.cursorPos !== undefined) {
277
- const before = displayText.slice(0, layoutLine.cursorPos);
278
- const after = displayText.slice(layoutLine.cursorPos);
279
- // Hardware cursor marker (zero-width, emitted before fake cursor for IME positioning)
280
- const marker = emitCursorMarker ? CURSOR_MARKER : "";
281
- if (after.length > 0) {
282
- // Cursor is on a character (grapheme) - replace it with highlighted version
283
- // Get the first grapheme from 'after'
284
- const afterGraphemes = [...segmenter.segment(after)];
285
- const firstGrapheme = afterGraphemes[0]?.segment || "";
286
- const restAfter = after.slice(firstGrapheme.length);
287
- const cursor = `\x1b[7m${firstGrapheme}\x1b[0m`;
288
- displayText = before + marker + cursor + restAfter;
289
- // lineVisibleWidth stays the same - we're replacing, not adding
290
- }
291
- else {
292
- // Cursor is at the end - add highlighted space
293
- const cursor = "\x1b[7m \x1b[0m";
294
- displayText = before + marker + cursor;
295
- lineVisibleWidth = lineVisibleWidth + 1;
296
- // If cursor overflows content width into the padding, flag it
297
- if (lineVisibleWidth > contentWidth && paddingX > 0) {
298
- cursorInPadding = true;
299
- }
300
- }
324
+ }
325
+ renderTopBorder(width, horizontal) {
326
+ if (this.scrollOffset <= 0)
327
+ return horizontal.repeat(width);
328
+ const indicator = `─── ↑ ${this.scrollOffset} more `;
329
+ const remaining = width - visibleWidth(indicator);
330
+ return this.borderColor(indicator + "─".repeat(Math.max(0, remaining)));
331
+ }
332
+ renderBottomBorder(width, horizontal, linesBelow) {
333
+ if (linesBelow <= 0)
334
+ return horizontal.repeat(width);
335
+ const indicator = `─── ↓ ${linesBelow} more `;
336
+ const remaining = width - visibleWidth(indicator);
337
+ return this.borderColor(indicator + "─".repeat(Math.max(0, remaining)));
338
+ }
339
+ renderVisibleLine(layoutLine, contentWidth, leftPadding, rightPadding, emitCursorMarker) {
340
+ let displayText = layoutLine.text;
341
+ let measuredWidth = visibleWidth(layoutLine.text);
342
+ let cursorInPadding = false;
343
+ if (layoutLine.hasCursor && layoutLine.cursorPos !== undefined) {
344
+ const before = displayText.slice(0, layoutLine.cursorPos);
345
+ const after = displayText.slice(layoutLine.cursorPos);
346
+ const marker = emitCursorMarker ? CURSOR_MARKER : "";
347
+ if (after.length > 0) {
348
+ const first = [...segmenter.segment(after)][0]?.segment || "";
349
+ const highlighted = `\x1b[7m${first}\x1b[0m`;
350
+ displayText = before + marker + highlighted + after.slice(first.length);
301
351
  }
302
- // Calculate padding based on actual visible width
303
- const padding = " ".repeat(Math.max(0, contentWidth - lineVisibleWidth));
304
- const lineRightPadding = cursorInPadding ? rightPadding.slice(1) : rightPadding;
305
- // Render the line (no side borders, just horizontal lines above and below)
306
- result.push(`${leftPadding}${displayText}${padding}${lineRightPadding}`);
307
- }
308
- // Render bottom border (with scroll indicator if more content below)
309
- const linesBelow = layoutLines.length - (this.scrollOffset + visibleLines.length);
310
- if (linesBelow > 0) {
311
- const indicator = `─── ↓ ${linesBelow} more `;
312
- const remaining = width - visibleWidth(indicator);
313
- result.push(this.borderColor(indicator + "─".repeat(Math.max(0, remaining))));
314
- }
315
- else {
316
- result.push(horizontal.repeat(width));
317
- }
318
- // Add autocomplete list if active
319
- if (this.isAutocompleting && this.autocompleteList) {
320
- const autocompleteResult = this.autocompleteList.render(contentWidth);
321
- for (const line of autocompleteResult) {
322
- const lineWidth = visibleWidth(line);
323
- const linePadding = " ".repeat(Math.max(0, contentWidth - lineWidth));
324
- result.push(`${leftPadding}${line}${linePadding}${rightPadding}`);
352
+ else {
353
+ displayText = before + marker + "\x1b[7m \x1b[0m";
354
+ measuredWidth += 1;
355
+ cursorInPadding = measuredWidth > contentWidth && rightPadding.length > 0;
325
356
  }
326
357
  }
327
- return result;
358
+ const fill = " ".repeat(Math.max(0, contentWidth - measuredWidth));
359
+ const adjustedRightPadding = cursorInPadding ? rightPadding.slice(1) : rightPadding;
360
+ return `${leftPadding}${displayText}${fill}${adjustedRightPadding}`;
361
+ }
362
+ appendAutocompleteLines(target, contentWidth, leftPadding, rightPadding) {
363
+ const autocompleteResult = this.autocompleteList?.render(contentWidth) ?? [];
364
+ for (const line of autocompleteResult) {
365
+ const linePadding = " ".repeat(Math.max(0, contentWidth - visibleWidth(line)));
366
+ target.push(`${leftPadding}${line}${linePadding}${rightPadding}`);
367
+ }
328
368
  }
329
369
  handleInput(data) {
330
370
  const kb = getEditorKeybindings();
331
- // Handle bracketed paste mode
332
- if (data.includes("\x1b[200~")) {
333
- this.isInPaste = true;
334
- this.pasteBuffer = "";
335
- data = data.replace("\x1b[200~", "");
336
- }
337
- if (this.isInPaste) {
338
- this.pasteBuffer += data;
339
- const endIndex = this.pasteBuffer.indexOf("\x1b[201~");
340
- if (endIndex !== -1) {
341
- const pasteContent = this.pasteBuffer.substring(0, endIndex);
342
- if (pasteContent.length > 0) {
343
- this.handlePaste(pasteContent);
344
- }
345
- this.isInPaste = false;
346
- const remaining = this.pasteBuffer.substring(endIndex + 6);
347
- this.pasteBuffer = "";
348
- if (remaining.length > 0) {
349
- this.handleInput(remaining);
350
- }
351
- return;
352
- }
371
+ const pasteResult = this.consumePasteInput(data);
372
+ if (!pasteResult)
353
373
  return;
354
- }
355
- if (this.pendingShiftEnter) {
356
- if (data === "\r") {
357
- this.pendingShiftEnter = false;
358
- this.addNewLine();
359
- return;
360
- }
361
- this.pendingShiftEnter = false;
362
- this.insertCharacter("\\");
363
- }
374
+ data = pasteResult;
375
+ const pendingResult = this.consumePendingShiftEnter(data);
376
+ if (!pendingResult)
377
+ return;
378
+ data = pendingResult;
364
379
  if (data === "\\") {
365
380
  this.pendingShiftEnter = true;
366
381
  return;
367
382
  }
368
- // Ctrl+C - let parent handle (exit/clear)
369
- if (kb.matches(data, "copy")) {
383
+ if (this.runEarlyActions(data, kb))
370
384
  return;
371
- }
372
- // Undo
373
- if (kb.matches(data, "undo")) {
374
- this.undo();
385
+ const autocompleteResult = this.handleAutocompleteInput(data, kb);
386
+ if (autocompleteResult === "handled")
375
387
  return;
376
- }
377
- // Handle autocomplete mode
378
- if (this.isAutocompleting && this.autocompleteList) {
379
- if (kb.matches(data, "selectCancel")) {
380
- this.cancelAutocomplete();
381
- return;
382
- }
383
- if (kb.matches(data, "selectUp") || kb.matches(data, "selectDown")) {
384
- this.autocompleteList.handleInput(data);
385
- return;
386
- }
387
- if (kb.matches(data, "tab")) {
388
- const selected = this.autocompleteList.getSelectedItem();
389
- if (selected && this.autocompleteProvider) {
390
- this.pushUndoSnapshot();
391
- this.lastAction = null;
392
- const result = this.autocompleteProvider.applyCompletion(this.state.lines, this.state.cursorLine, this.state.cursorCol, selected, this.autocompletePrefix);
393
- this.state.lines = result.lines;
394
- this.state.cursorLine = result.cursorLine;
395
- this.state.cursorCol = result.cursorCol;
396
- this.cancelAutocomplete();
397
- if (this.onChange)
398
- this.onChange(this.getText());
399
- }
400
- return;
401
- }
402
- if (kb.matches(data, "selectConfirm")) {
403
- const selected = this.autocompleteList.getSelectedItem();
404
- if (selected && this.autocompleteProvider) {
405
- this.pushUndoSnapshot();
406
- this.lastAction = null;
407
- const result = this.autocompleteProvider.applyCompletion(this.state.lines, this.state.cursorLine, this.state.cursorCol, selected, this.autocompletePrefix);
408
- this.state.lines = result.lines;
409
- this.state.cursorLine = result.cursorLine;
410
- this.state.cursorCol = result.cursorCol;
411
- if (this.autocompletePrefix.startsWith("/")) {
412
- this.cancelAutocomplete();
413
- // Fall through to submit
414
- }
415
- else {
416
- this.cancelAutocomplete();
417
- if (this.onChange)
418
- this.onChange(this.getText());
419
- return;
420
- }
421
- }
422
- }
423
- }
424
- // Tab - trigger completion
425
- if (kb.matches(data, "tab") && !this.isAutocompleting) {
388
+ if (!this.isAutocompleting && kb.matches(data, "tab")) {
426
389
  this.handleTabCompletion();
427
390
  return;
428
391
  }
429
- // Deletion actions
430
- if (kb.matches(data, "deleteToLineEnd")) {
431
- this.deleteToEndOfLine();
392
+ if (this.runDeleteActions(data, kb))
432
393
  return;
433
- }
434
- if (kb.matches(data, "deleteToLineStart")) {
435
- this.deleteToStartOfLine();
394
+ if (this.runKillRingActions(data, kb))
436
395
  return;
437
- }
438
- if (kb.matches(data, "deleteWordBackward")) {
439
- this.deleteWordBackwards();
396
+ if (this.runCursorActions(data, kb))
440
397
  return;
441
- }
442
- if (kb.matches(data, "deleteWordForward")) {
443
- this.deleteWordForward();
398
+ if (this.isNewLineInput(data, kb)) {
399
+ this.addNewLine();
444
400
  return;
445
401
  }
446
- if (kb.matches(data, "deleteCharBackward") || matchesKey(data, "shift+backspace")) {
447
- this.handleBackspace();
402
+ if (kb.matches(data, "submit")) {
403
+ this.submitEditor();
448
404
  return;
449
405
  }
450
- if (kb.matches(data, "deleteCharForward") || matchesKey(data, "shift+delete")) {
451
- this.handleForwardDelete();
406
+ if (this.runArrowActions(data, kb))
452
407
  return;
453
- }
454
- // Kill ring actions
455
- if (kb.matches(data, "yank")) {
456
- this.yank();
408
+ if (this.runPagingActions(data, kb))
457
409
  return;
458
- }
459
- if (kb.matches(data, "yankPop")) {
460
- this.yankPop();
410
+ if (matchesKey(data, "shift+space")) {
411
+ this.insertCharacter(" ");
461
412
  return;
462
413
  }
463
- // Cursor movement actions
464
- if (kb.matches(data, "cursorLineStart")) {
465
- this.moveToLineStart();
414
+ const kittyPrintable = decodeKittyPrintable(data);
415
+ if (kittyPrintable !== undefined) {
416
+ this.insertCharacter(kittyPrintable);
466
417
  return;
467
418
  }
468
- if (kb.matches(data, "cursorLineEnd")) {
469
- this.moveToLineEnd();
470
- return;
419
+ if (data.charCodeAt(0) >= 32) {
420
+ this.insertCharacter(data);
471
421
  }
472
- if (kb.matches(data, "cursorWordLeft")) {
473
- this.moveWordBackwards();
474
- return;
422
+ }
423
+ consumePasteInput(data) {
424
+ if (data.includes("\x1b[200~")) {
425
+ this.isInPaste = true;
426
+ this.pasteBuffer = "";
427
+ data = data.replace("\x1b[200~", "");
475
428
  }
476
- if (kb.matches(data, "cursorWordRight")) {
477
- this.moveWordForwards();
478
- return;
429
+ if (!this.isInPaste)
430
+ return data;
431
+ this.pasteBuffer += data;
432
+ const endIndex = this.pasteBuffer.indexOf("\x1b[201~");
433
+ if (endIndex === -1)
434
+ return null;
435
+ const pasteContent = this.pasteBuffer.substring(0, endIndex);
436
+ if (pasteContent.length > 0) {
437
+ this.handlePaste(pasteContent);
479
438
  }
480
- // New line (Shift+Enter, Alt+Enter, etc.)
481
- if (kb.matches(data, "newLine") ||
482
- (data.charCodeAt(0) === 10 && data.length > 1) ||
483
- data === "\x1b\r" ||
484
- data === "\x1b[13;2~" ||
485
- (data.length > 1 && data.includes("\x1b") && data.includes("\r")) ||
486
- (data === "\n" && data.length === 1) ||
487
- data === "\\\r") {
439
+ this.isInPaste = false;
440
+ const remaining = this.pasteBuffer.substring(endIndex + 6);
441
+ this.pasteBuffer = "";
442
+ if (remaining.length > 0) {
443
+ this.handleInput(remaining);
444
+ }
445
+ return null;
446
+ }
447
+ consumePendingShiftEnter(data) {
448
+ if (!this.pendingShiftEnter)
449
+ return data;
450
+ if (data === "\r") {
451
+ this.pendingShiftEnter = false;
488
452
  this.addNewLine();
489
- return;
453
+ return null;
490
454
  }
491
- // Submit (Enter)
492
- if (kb.matches(data, "submit")) {
493
- if (this.disableSubmit)
494
- return;
495
- let result = this.state.lines.join("\n").trim();
496
- for (const [pasteId, pasteContent] of this.pastes) {
497
- const markerRegex = new RegExp(`\\[paste #${pasteId}( (\\+\\d+ lines|\\d+ chars))?\\]`, "g");
498
- result = result.replace(markerRegex, pasteContent);
499
- }
500
- this.state = { lines: [""], cursorLine: 0, cursorCol: 0 };
501
- this.pastes.clear();
502
- this.pasteCounter = 0;
503
- this.historyIndex = -1;
504
- this.scrollOffset = 0;
505
- this.undoStack.length = 0;
506
- this.lastAction = null;
507
- if (this.onChange)
508
- this.onChange("");
509
- if (this.onSubmit)
510
- this.onSubmit(result);
511
- return;
455
+ this.pendingShiftEnter = false;
456
+ this.insertCharacter("\\");
457
+ return data;
458
+ }
459
+ runEarlyActions(data, kb) {
460
+ if (kb.matches(data, "copy")) {
461
+ return true;
462
+ }
463
+ if (kb.matches(data, "undo")) {
464
+ this.undo();
465
+ return true;
466
+ }
467
+ return false;
468
+ }
469
+ handleAutocompleteInput(data, kb) {
470
+ if (!this.isAutocompleting || !this.autocompleteList)
471
+ return "none";
472
+ if (kb.matches(data, "selectCancel")) {
473
+ this.cancelAutocomplete();
474
+ return "handled";
475
+ }
476
+ if (kb.matches(data, "selectUp") || kb.matches(data, "selectDown")) {
477
+ this.autocompleteList.handleInput(data);
478
+ return "handled";
479
+ }
480
+ if (kb.matches(data, "tab")) {
481
+ this.applySelectedAutocompleteItem(true);
482
+ return "handled";
483
+ }
484
+ if (kb.matches(data, "selectConfirm")) {
485
+ const applied = this.applySelectedAutocompleteItem(false);
486
+ if (!applied)
487
+ return "handled";
488
+ return this.autocompletePrefix.startsWith("/") ? "continue" : "handled";
489
+ }
490
+ return "none";
491
+ }
492
+ applySelectedAutocompleteItem(notifyOnSlash) {
493
+ const selected = this.autocompleteList?.getSelectedItem();
494
+ if (!selected || !this.autocompleteProvider)
495
+ return false;
496
+ this.pushUndoSnapshot();
497
+ this.lastAction = null;
498
+ const result = this.autocompleteProvider.applyCompletion(this.state.lines, this.state.cursorLine, this.state.cursorCol, selected, this.autocompletePrefix);
499
+ this.state.lines = result.lines;
500
+ this.state.cursorLine = result.cursorLine;
501
+ this.state.cursorCol = result.cursorCol;
502
+ this.cancelAutocomplete();
503
+ if (this.onChange && (notifyOnSlash || !this.autocompletePrefix.startsWith("/"))) {
504
+ this.onChange(this.getText());
505
+ }
506
+ return true;
507
+ }
508
+ runDeleteActions(data, kb) {
509
+ const actions = [
510
+ { match: kb.matches(data, "deleteToLineEnd"), run: () => this.deleteToEndOfLine() },
511
+ { match: kb.matches(data, "deleteToLineStart"), run: () => this.deleteToStartOfLine() },
512
+ { match: kb.matches(data, "deleteWordBackward"), run: () => this.deleteWordBackwards() },
513
+ { match: kb.matches(data, "deleteWordForward"), run: () => this.deleteWordForward() },
514
+ { match: kb.matches(data, "deleteCharBackward") || matchesKey(data, "shift+backspace"), run: () => this.handleBackspace() },
515
+ { match: kb.matches(data, "deleteCharForward") || matchesKey(data, "shift+delete"), run: () => this.handleForwardDelete() },
516
+ ];
517
+ const route = actions.find((entry) => entry.match);
518
+ if (!route)
519
+ return false;
520
+ route.run();
521
+ return true;
522
+ }
523
+ runKillRingActions(data, kb) {
524
+ if (kb.matches(data, "yank")) {
525
+ this.yank();
526
+ return true;
527
+ }
528
+ if (kb.matches(data, "yankPop")) {
529
+ this.yankPop();
530
+ return true;
512
531
  }
513
- // Arrow key navigation (with history support)
532
+ return false;
533
+ }
534
+ runCursorActions(data, kb) {
535
+ const routes = [
536
+ { match: kb.matches(data, "cursorLineStart"), run: () => this.moveToLineStart() },
537
+ { match: kb.matches(data, "cursorLineEnd"), run: () => this.moveToLineEnd() },
538
+ { match: kb.matches(data, "cursorWordLeft"), run: () => this.moveWordBackwards() },
539
+ { match: kb.matches(data, "cursorWordRight"), run: () => this.moveWordForwards() },
540
+ ];
541
+ const route = routes.find((entry) => entry.match);
542
+ if (!route)
543
+ return false;
544
+ route.run();
545
+ return true;
546
+ }
547
+ runArrowActions(data, kb) {
514
548
  if (kb.matches(data, "cursorUp")) {
515
549
  if (this.isEditorEmpty()) {
516
550
  this.navigateHistory(-1);
@@ -521,7 +555,7 @@ export class Editor extends ComponentBase {
521
555
  else {
522
556
  this.moveCursor(-1, 0);
523
557
  }
524
- return;
558
+ return true;
525
559
  }
526
560
  if (kb.matches(data, "cursorDown")) {
527
561
  if (this.historyIndex > -1 && this.isOnLastVisualLine()) {
@@ -530,39 +564,57 @@ export class Editor extends ComponentBase {
530
564
  else {
531
565
  this.moveCursor(1, 0);
532
566
  }
533
- return;
567
+ return true;
534
568
  }
535
569
  if (kb.matches(data, "cursorRight")) {
536
570
  this.moveCursor(0, 1);
537
- return;
571
+ return true;
538
572
  }
539
573
  if (kb.matches(data, "cursorLeft")) {
540
574
  this.moveCursor(0, -1);
541
- return;
575
+ return true;
542
576
  }
543
- // Page up/down - scroll by page and move cursor
577
+ return false;
578
+ }
579
+ runPagingActions(data, kb) {
544
580
  if (kb.matches(data, "pageUp")) {
545
581
  this.pageScroll(-1);
546
- return;
582
+ return true;
547
583
  }
548
584
  if (kb.matches(data, "pageDown")) {
549
585
  this.pageScroll(1);
550
- return;
586
+ return true;
551
587
  }
552
- // Shift+Space - insert regular space
553
- if (matchesKey(data, "shift+space")) {
554
- this.insertCharacter(" ");
555
- return;
556
- }
557
- const kittyPrintable = decodeKittyPrintable(data);
558
- if (kittyPrintable !== undefined) {
559
- this.insertCharacter(kittyPrintable);
588
+ return false;
589
+ }
590
+ isNewLineInput(data, kb) {
591
+ return (kb.matches(data, "newLine") ||
592
+ (data.charCodeAt(0) === 10 && data.length > 1) ||
593
+ data === "\x1b\r" ||
594
+ data === "\x1b[13;2~" ||
595
+ (data.length > 1 && data.includes("\x1b") && data.includes("\r")) ||
596
+ (data === "\n" && data.length === 1) ||
597
+ data === "\\\r");
598
+ }
599
+ submitEditor() {
600
+ if (this.disableSubmit)
560
601
  return;
602
+ let result = this.state.lines.join("\n").trim();
603
+ for (const [pasteId, pasteContent] of this.pastes) {
604
+ const markerRegex = new RegExp(`\\[paste #${pasteId}( (\\+\\d+ lines|\\d+ chars))?\\]`, "g");
605
+ result = result.replace(markerRegex, pasteContent);
561
606
  }
562
- // Regular characters
563
- if (data.charCodeAt(0) >= 32) {
564
- this.insertCharacter(data);
565
- }
607
+ this.state = { lines: [""], cursorLine: 0, cursorCol: 0 };
608
+ this.pastes.clear();
609
+ this.pasteCounter = 0;
610
+ this.historyIndex = -1;
611
+ this.scrollOffset = 0;
612
+ this.undoStack.length = 0;
613
+ this.lastAction = null;
614
+ if (this.onChange)
615
+ this.onChange("");
616
+ if (this.onSubmit)
617
+ this.onSubmit(result);
566
618
  }
567
619
  layoutText(contentWidth) {
568
620
  const layoutLines = [];
@@ -1085,72 +1137,28 @@ export class Editor extends ComponentBase {
1085
1137
  * - length: length of this visual line segment
1086
1138
  */
1087
1139
  buildVisualLineMap(width) {
1088
- const visualLines = [];
1089
- for (let i = 0; i < this.state.lines.length; i++) {
1090
- const line = this.state.lines[i] || "";
1091
- const lineVisWidth = visibleWidth(line);
1092
- if (line.length === 0) {
1093
- // Empty line still takes one visual line
1094
- visualLines.push({ logicalLine: i, startCol: 0, length: 0 });
1095
- }
1096
- else if (lineVisWidth <= width) {
1097
- visualLines.push({ logicalLine: i, startCol: 0, length: line.length });
1098
- }
1099
- else {
1100
- // Line needs wrapping - use word-aware wrapping
1101
- const chunks = wordWrapLine(line, width);
1102
- for (const chunk of chunks) {
1103
- visualLines.push({
1104
- logicalLine: i,
1105
- startCol: chunk.startIndex,
1106
- length: chunk.endIndex - chunk.startIndex,
1107
- });
1108
- }
1109
- }
1110
- }
1111
- return visualLines;
1140
+ return EditorLayoutProjector.buildVisualLineMap(this.state.lines, width);
1112
1141
  }
1113
1142
  /**
1114
1143
  * Find the visual line index for the current cursor position.
1115
1144
  */
1116
1145
  findCurrentVisualLine(visualLines) {
1117
- for (let i = 0; i < visualLines.length; i++) {
1118
- const vl = visualLines[i];
1119
- if (!vl)
1120
- continue;
1121
- if (vl.logicalLine === this.state.cursorLine) {
1122
- const colInSegment = this.state.cursorCol - vl.startCol;
1123
- // Cursor is in this segment if it's within range
1124
- // For the last segment of a logical line, cursor can be at length (end position)
1125
- const isLastSegmentOfLine = i === visualLines.length - 1 || visualLines[i + 1]?.logicalLine !== vl.logicalLine;
1126
- if (colInSegment >= 0 && (colInSegment < vl.length || (isLastSegmentOfLine && colInSegment <= vl.length))) {
1127
- return i;
1128
- }
1129
- }
1130
- }
1131
- // Fallback: return last visual line
1132
- return visualLines.length - 1;
1146
+ return EditorLayoutProjector.findCurrentVisualLine(visualLines, this.state.cursorLine, this.state.cursorCol);
1133
1147
  }
1134
1148
  moveCursor(deltaLine, deltaCol) {
1135
1149
  this.lastAction = null;
1136
1150
  const width = this.lastWidth;
1137
1151
  if (deltaLine !== 0) {
1138
- // Build visual line map for navigation
1139
1152
  const visualLines = this.buildVisualLineMap(width);
1140
1153
  const currentVisualLine = this.findCurrentVisualLine(visualLines);
1141
- // Calculate column position within current visual line
1142
- const currentVL = visualLines[currentVisualLine];
1143
- const visualCol = currentVL ? this.state.cursorCol - currentVL.startCol : 0;
1144
- // Move to target visual line
1154
+ const currentSegment = visualLines[currentVisualLine];
1155
+ const visualCol = currentSegment ? this.state.cursorCol - currentSegment.startCol : 0;
1145
1156
  const targetVisualLine = currentVisualLine + deltaLine;
1146
1157
  if (targetVisualLine >= 0 && targetVisualLine < visualLines.length) {
1147
- const targetVL = visualLines[targetVisualLine];
1148
- if (targetVL) {
1149
- this.state.cursorLine = targetVL.logicalLine;
1150
- // Try to maintain visual column position, clamped to line length
1151
- const targetCol = targetVL.startCol + Math.min(visualCol, targetVL.length);
1152
- const logicalLine = this.state.lines[targetVL.logicalLine] || "";
1153
- this.state.cursorCol = Math.min(targetCol, logicalLine.length);
1158
+ const target = EditorLayoutProjector.resolveCursorAtVisualLine(visualLines, targetVisualLine, visualCol, this.state.lines);
1159
+ if (target) {
1160
+ this.state.cursorLine = target.line;
1161
+ this.state.cursorCol = target.col;
1154
1162
  }
1155
1163
  }
1156
1164
  }
@@ -1196,21 +1204,15 @@ export class Editor extends ComponentBase {
1196
1204
  const width = this.lastWidth;
1197
1205
  const terminalRows = this.tui.terminal.rows;
1198
1206
  const pageSize = Math.max(5, Math.floor(terminalRows * 0.3));
1199
- // Build visual line map
1200
1207
  const visualLines = this.buildVisualLineMap(width);
1201
1208
  const currentVisualLine = this.findCurrentVisualLine(visualLines);
1202
- // Calculate target visual line
1203
1209
  const targetVisualLine = Math.max(0, Math.min(visualLines.length - 1, currentVisualLine + direction * pageSize));
1204
- // Move cursor to target visual line
1205
- const targetVL = visualLines[targetVisualLine];
1206
- if (targetVL) {
1207
- // Preserve column position within the line
1208
- const currentVL = visualLines[currentVisualLine];
1209
- const visualCol = currentVL ? this.state.cursorCol - currentVL.startCol : 0;
1210
- this.state.cursorLine = targetVL.logicalLine;
1211
- const targetCol = targetVL.startCol + Math.min(visualCol, targetVL.length);
1212
- const logicalLine = this.state.lines[targetVL.logicalLine] || "";
1213
- this.state.cursorCol = Math.min(targetCol, logicalLine.length);
1210
+ const currentSegment = visualLines[currentVisualLine];
1211
+ const visualCol = currentSegment ? this.state.cursorCol - currentSegment.startCol : 0;
1212
+ const target = EditorLayoutProjector.resolveCursorAtVisualLine(visualLines, targetVisualLine, visualCol, this.state.lines);
1213
+ if (target) {
1214
+ this.state.cursorLine = target.line;
1215
+ this.state.cursorCol = target.col;
1214
1216
  }
1215
1217
  }
1216
1218
  moveWordBackwards() {