lonny-agent 0.2.4 → 0.2.7

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 (509) hide show
  1. package/.github/workflows/ci.yml +21 -0
  2. package/AGENTS.md +106 -0
  3. package/CHANGELOG.md +24 -0
  4. package/README.md +326 -326
  5. package/dist/agent/__tests__/session-restore.test.d.ts +2 -0
  6. package/dist/agent/__tests__/session-restore.test.d.ts.map +1 -0
  7. package/dist/agent/__tests__/session-restore.test.js +260 -0
  8. package/dist/agent/__tests__/session-restore.test.js.map +1 -0
  9. package/dist/agent/commands.d.ts +26 -0
  10. package/dist/agent/commands.d.ts.map +1 -0
  11. package/dist/agent/commands.js +253 -0
  12. package/dist/agent/commands.js.map +1 -0
  13. package/dist/agent/compaction.js +8 -1
  14. package/dist/agent/compaction.js.map +1 -1
  15. package/dist/agent/index.d.ts +2 -1
  16. package/dist/agent/index.d.ts.map +1 -1
  17. package/dist/agent/index.js +2 -2
  18. package/dist/agent/index.js.map +1 -1
  19. package/dist/agent/llm.d.ts +4 -0
  20. package/dist/agent/llm.d.ts.map +1 -1
  21. package/dist/agent/memory.d.ts +12 -0
  22. package/dist/agent/memory.d.ts.map +1 -0
  23. package/dist/agent/memory.js +51 -0
  24. package/dist/agent/memory.js.map +1 -0
  25. package/dist/agent/prompt-builder.d.ts +6 -1
  26. package/dist/agent/prompt-builder.d.ts.map +1 -1
  27. package/dist/agent/prompt-builder.js +100 -33
  28. package/dist/agent/prompt-builder.js.map +1 -1
  29. package/dist/agent/providers/google.d.ts.map +1 -1
  30. package/dist/agent/providers/google.js.map +1 -1
  31. package/dist/agent/providers/openai.d.ts +1 -0
  32. package/dist/agent/providers/openai.d.ts.map +1 -1
  33. package/dist/agent/providers/openai.js +59 -6
  34. package/dist/agent/providers/openai.js.map +1 -1
  35. package/dist/agent/session-chat.d.ts +3 -0
  36. package/dist/agent/session-chat.d.ts.map +1 -0
  37. package/dist/agent/session-chat.js +384 -0
  38. package/dist/agent/session-chat.js.map +1 -0
  39. package/dist/agent/session-display.d.ts +29 -0
  40. package/dist/agent/session-display.d.ts.map +1 -0
  41. package/dist/agent/session-display.js +179 -0
  42. package/dist/agent/session-display.js.map +1 -0
  43. package/dist/agent/session-persistence.d.ts +55 -0
  44. package/dist/agent/session-persistence.d.ts.map +1 -0
  45. package/dist/agent/session-persistence.js +101 -0
  46. package/dist/agent/session-persistence.js.map +1 -0
  47. package/dist/agent/session-utils.d.ts +5 -0
  48. package/dist/agent/session-utils.d.ts.map +1 -0
  49. package/dist/agent/session-utils.js +51 -0
  50. package/dist/agent/session-utils.js.map +1 -0
  51. package/dist/agent/session.d.ts +19 -17
  52. package/dist/agent/session.d.ts.map +1 -1
  53. package/dist/agent/session.js +234 -578
  54. package/dist/agent/session.js.map +1 -1
  55. package/dist/cli/index.d.ts +4 -0
  56. package/dist/cli/index.d.ts.map +1 -1
  57. package/dist/cli/index.js +67 -2
  58. package/dist/cli/index.js.map +1 -1
  59. package/dist/config/index.d.ts +2 -2
  60. package/dist/config/index.d.ts.map +1 -1
  61. package/dist/config/index.js +7 -1
  62. package/dist/config/index.js.map +1 -1
  63. package/dist/index.js +24 -3
  64. package/dist/index.js.map +1 -1
  65. package/dist/tools/__tests__/bash.test.js +169 -2
  66. package/dist/tools/__tests__/bash.test.js.map +1 -1
  67. package/dist/tools/__tests__/edit.test.js +1091 -340
  68. package/dist/tools/__tests__/edit.test.js.map +1 -1
  69. package/dist/tools/__tests__/fetch.test.js +1 -1
  70. package/dist/tools/__tests__/fetch.test.js.map +1 -1
  71. package/dist/tools/__tests__/glob.test.js +1 -1
  72. package/dist/tools/__tests__/glob.test.js.map +1 -1
  73. package/dist/tools/__tests__/grep.test.js +33 -1
  74. package/dist/tools/__tests__/grep.test.js.map +1 -1
  75. package/dist/tools/__tests__/ls.test.js +1 -1
  76. package/dist/tools/__tests__/ls.test.js.map +1 -1
  77. package/dist/tools/__tests__/read.test.js +1 -1
  78. package/dist/tools/__tests__/read.test.js.map +1 -1
  79. package/dist/tools/__tests__/registry.test.js +313 -0
  80. package/dist/tools/__tests__/registry.test.js.map +1 -1
  81. package/dist/tools/__tests__/sed.test.d.ts +2 -0
  82. package/dist/tools/__tests__/sed.test.d.ts.map +1 -0
  83. package/dist/tools/__tests__/sed.test.js +228 -0
  84. package/dist/tools/__tests__/sed.test.js.map +1 -0
  85. package/dist/tools/__tests__/write_plan.test.js +1 -1
  86. package/dist/tools/__tests__/write_plan.test.js.map +1 -1
  87. package/dist/tools/bash.d.ts.map +1 -1
  88. package/dist/tools/bash.js +711 -18
  89. package/dist/tools/bash.js.map +1 -1
  90. package/dist/tools/codebase/ast/__tests__/ast-edit-demo.d.ts +2 -0
  91. package/dist/tools/codebase/ast/__tests__/ast-edit-demo.d.ts.map +1 -0
  92. package/dist/tools/codebase/ast/__tests__/ast-edit-demo.js +7 -0
  93. package/dist/tools/codebase/ast/__tests__/ast-edit-demo.js.map +1 -0
  94. package/dist/tools/codebase/ast/__tests__/ast-edit-final.d.ts +6 -0
  95. package/dist/tools/codebase/ast/__tests__/ast-edit-final.d.ts.map +1 -0
  96. package/dist/tools/codebase/ast/__tests__/ast-edit-final.js +11 -0
  97. package/dist/tools/codebase/ast/__tests__/ast-edit-final.js.map +1 -0
  98. package/dist/tools/codebase/ast/__tests__/ast-edit-test.d.ts +2 -0
  99. package/dist/tools/codebase/ast/__tests__/ast-edit-test.d.ts.map +1 -0
  100. package/dist/tools/codebase/ast/__tests__/ast-edit-test.js +9 -0
  101. package/dist/tools/codebase/ast/__tests__/ast-edit-test.js.map +1 -0
  102. package/dist/tools/codebase/ast/__tests__/integration.test.d.ts +2 -0
  103. package/dist/tools/codebase/ast/__tests__/integration.test.d.ts.map +1 -0
  104. package/dist/tools/codebase/ast/__tests__/integration.test.js +415 -0
  105. package/dist/tools/codebase/ast/__tests__/integration.test.js.map +1 -0
  106. package/dist/tools/codebase/ast/__tests__/tree-sitter.test.d.ts +2 -0
  107. package/dist/tools/codebase/ast/__tests__/tree-sitter.test.d.ts.map +1 -0
  108. package/dist/tools/codebase/ast/__tests__/tree-sitter.test.js +414 -0
  109. package/dist/tools/codebase/ast/__tests__/tree-sitter.test.js.map +1 -0
  110. package/dist/tools/codebase/ast/adapter.d.ts +23 -0
  111. package/dist/tools/codebase/ast/adapter.d.ts.map +1 -0
  112. package/dist/tools/codebase/ast/adapter.js +11 -0
  113. package/dist/tools/codebase/ast/adapter.js.map +1 -0
  114. package/dist/tools/codebase/ast/tools.d.ts +3 -0
  115. package/dist/tools/codebase/ast/tools.d.ts.map +1 -0
  116. package/dist/tools/codebase/ast/tools.js +286 -0
  117. package/dist/tools/codebase/ast/tools.js.map +1 -0
  118. package/dist/tools/codebase/ast/tree-sitter-adapter.d.ts +3 -0
  119. package/dist/tools/codebase/ast/tree-sitter-adapter.d.ts.map +1 -0
  120. package/dist/tools/codebase/ast/tree-sitter-adapter.js +412 -0
  121. package/dist/tools/codebase/ast/tree-sitter-adapter.js.map +1 -0
  122. package/dist/tools/codebase/ast/tree-sitter-converters.d.ts +4 -0
  123. package/dist/tools/codebase/ast/tree-sitter-converters.d.ts.map +1 -0
  124. package/dist/tools/codebase/ast/tree-sitter-converters.js +447 -0
  125. package/dist/tools/codebase/ast/tree-sitter-converters.js.map +1 -0
  126. package/dist/tools/codebase/ast/types.d.ts +103 -0
  127. package/dist/tools/codebase/ast/types.d.ts.map +1 -0
  128. package/dist/tools/codebase/ast/types.js +2 -0
  129. package/dist/tools/codebase/ast/types.js.map +1 -0
  130. package/dist/tools/codebase/ast/wasm/tree-sitter-python.wasm +0 -0
  131. package/dist/tools/codebase/ast/wasm/tree-sitter-tsx.wasm +0 -0
  132. package/dist/tools/codebase/ast/wasm/tree-sitter-typescript.wasm +0 -0
  133. package/dist/tools/codebase/ast/wasm/tree-sitter.wasm +0 -0
  134. package/dist/tools/codebase/ast/wasm/web-tree-sitter.wasm +0 -0
  135. package/dist/tools/codebase/find.d.ts +3 -0
  136. package/dist/tools/codebase/find.d.ts.map +1 -0
  137. package/dist/tools/codebase/find.js +61 -0
  138. package/dist/tools/codebase/find.js.map +1 -0
  139. package/dist/tools/codebase/glob.d.ts +3 -0
  140. package/dist/tools/codebase/glob.d.ts.map +1 -0
  141. package/dist/tools/codebase/glob.js +37 -0
  142. package/dist/tools/codebase/glob.js.map +1 -0
  143. package/dist/tools/codebase/grep.d.ts +3 -0
  144. package/dist/tools/codebase/grep.d.ts.map +1 -0
  145. package/dist/tools/codebase/grep.js +169 -0
  146. package/dist/tools/codebase/grep.js.map +1 -0
  147. package/dist/tools/codebase/ls.d.ts +3 -0
  148. package/dist/tools/codebase/ls.d.ts.map +1 -0
  149. package/dist/tools/codebase/ls.js +39 -0
  150. package/dist/tools/codebase/ls.js.map +1 -0
  151. package/dist/tools/codebase/read.d.ts +10 -0
  152. package/dist/tools/codebase/read.d.ts.map +1 -0
  153. package/dist/tools/codebase/read.js +81 -0
  154. package/dist/tools/codebase/read.js.map +1 -0
  155. package/dist/tools/delete_memory.d.ts +3 -0
  156. package/dist/tools/delete_memory.d.ts.map +1 -0
  157. package/dist/tools/delete_memory.js +46 -0
  158. package/dist/tools/delete_memory.js.map +1 -0
  159. package/dist/tools/edit/diff-compute.d.ts +4 -0
  160. package/dist/tools/edit/diff-compute.d.ts.map +1 -0
  161. package/dist/tools/edit/diff-compute.js +18 -0
  162. package/dist/tools/edit/diff-compute.js.map +1 -0
  163. package/dist/tools/edit/diff-render.d.ts +18 -0
  164. package/dist/tools/edit/diff-render.d.ts.map +1 -0
  165. package/dist/tools/edit/diff-render.js +128 -0
  166. package/dist/tools/edit/diff-render.js.map +1 -0
  167. package/dist/tools/edit/edit.d.ts +4 -0
  168. package/dist/tools/edit/edit.d.ts.map +1 -0
  169. package/dist/tools/edit/edit.js +440 -0
  170. package/dist/tools/edit/edit.js.map +1 -0
  171. package/dist/tools/edit/matcher.d.ts +24 -0
  172. package/dist/tools/edit/matcher.d.ts.map +1 -0
  173. package/dist/tools/edit/matcher.js +66 -0
  174. package/dist/tools/edit/matcher.js.map +1 -0
  175. package/dist/tools/edit/parser.d.ts +10 -0
  176. package/dist/tools/edit/parser.d.ts.map +1 -0
  177. package/dist/tools/edit/parser.js +120 -0
  178. package/dist/tools/edit/parser.js.map +1 -0
  179. package/dist/tools/edit/types.d.ts +16 -0
  180. package/dist/tools/edit/types.d.ts.map +1 -0
  181. package/dist/tools/edit/types.js +2 -0
  182. package/dist/tools/edit/types.js.map +1 -0
  183. package/dist/tools/edit/write_plan.d.ts +5 -0
  184. package/dist/tools/edit/write_plan.d.ts.map +1 -0
  185. package/dist/tools/edit/write_plan.js +98 -0
  186. package/dist/tools/edit/write_plan.js.map +1 -0
  187. package/dist/tools/edit.d.ts +50 -9
  188. package/dist/tools/edit.d.ts.map +1 -1
  189. package/dist/tools/edit.js +394 -159
  190. package/dist/tools/edit.js.map +1 -1
  191. package/dist/tools/execute/bash/constants.d.ts +24 -0
  192. package/dist/tools/execute/bash/constants.d.ts.map +1 -0
  193. package/dist/tools/execute/bash/constants.js +88 -0
  194. package/dist/tools/execute/bash/constants.js.map +1 -0
  195. package/dist/tools/execute/bash/errors.d.ts +39 -0
  196. package/dist/tools/execute/bash/errors.d.ts.map +1 -0
  197. package/dist/tools/execute/bash/errors.js +249 -0
  198. package/dist/tools/execute/bash/errors.js.map +1 -0
  199. package/dist/tools/execute/bash/execution.d.ts +18 -0
  200. package/dist/tools/execute/bash/execution.d.ts.map +1 -0
  201. package/dist/tools/execute/bash/execution.js +207 -0
  202. package/dist/tools/execute/bash/execution.js.map +1 -0
  203. package/dist/tools/execute/bash/index.d.ts +3 -0
  204. package/dist/tools/execute/bash/index.d.ts.map +1 -0
  205. package/dist/tools/execute/bash/index.js +117 -0
  206. package/dist/tools/execute/bash/index.js.map +1 -0
  207. package/dist/tools/execute/bash/platform.d.ts +6 -0
  208. package/dist/tools/execute/bash/platform.d.ts.map +1 -0
  209. package/dist/tools/execute/bash/platform.js +64 -0
  210. package/dist/tools/execute/bash/platform.js.map +1 -0
  211. package/dist/tools/execute/bash/security.d.ts +12 -0
  212. package/dist/tools/execute/bash/security.d.ts.map +1 -0
  213. package/dist/tools/execute/bash/security.js +26 -0
  214. package/dist/tools/execute/bash/security.js.map +1 -0
  215. package/dist/tools/execute/bash/validation.d.ts +16 -0
  216. package/dist/tools/execute/bash/validation.d.ts.map +1 -0
  217. package/dist/tools/execute/bash/validation.js +57 -0
  218. package/dist/tools/execute/bash/validation.js.map +1 -0
  219. package/dist/tools/execute/bash.d.ts +3 -0
  220. package/dist/tools/execute/bash.d.ts.map +1 -0
  221. package/dist/tools/execute/bash.js +728 -0
  222. package/dist/tools/execute/bash.js.map +1 -0
  223. package/dist/tools/execute/git.d.ts +3 -0
  224. package/dist/tools/execute/git.d.ts.map +1 -0
  225. package/dist/tools/execute/git.js +183 -0
  226. package/dist/tools/execute/git.js.map +1 -0
  227. package/dist/tools/execute/task_complete.d.ts +7 -0
  228. package/dist/tools/execute/task_complete.d.ts.map +1 -0
  229. package/dist/tools/execute/task_complete.js +38 -0
  230. package/dist/tools/execute/task_complete.js.map +1 -0
  231. package/dist/tools/fetch.d.ts.map +1 -1
  232. package/dist/tools/fetch.js +2 -0
  233. package/dist/tools/fetch.js.map +1 -1
  234. package/dist/tools/find.d.ts.map +1 -1
  235. package/dist/tools/find.js +2 -0
  236. package/dist/tools/find.js.map +1 -1
  237. package/dist/tools/git.d.ts.map +1 -1
  238. package/dist/tools/git.js +2 -0
  239. package/dist/tools/git.js.map +1 -1
  240. package/dist/tools/glob.d.ts.map +1 -1
  241. package/dist/tools/glob.js +2 -0
  242. package/dist/tools/glob.js.map +1 -1
  243. package/dist/tools/grep.d.ts.map +1 -1
  244. package/dist/tools/grep.js +56 -30
  245. package/dist/tools/grep.js.map +1 -1
  246. package/dist/tools/install/clawhub.d.ts +26 -0
  247. package/dist/tools/install/clawhub.d.ts.map +1 -0
  248. package/dist/tools/install/clawhub.js +182 -0
  249. package/dist/tools/install/clawhub.js.map +1 -0
  250. package/dist/tools/install/constants.d.ts +5 -0
  251. package/dist/tools/install/constants.d.ts.map +1 -0
  252. package/dist/tools/install/constants.js +5 -0
  253. package/dist/tools/install/constants.js.map +1 -0
  254. package/dist/tools/install/install_skill.d.ts +3 -0
  255. package/dist/tools/install/install_skill.d.ts.map +1 -0
  256. package/dist/tools/install/install_skill.js +132 -0
  257. package/dist/tools/install/install_skill.js.map +1 -0
  258. package/dist/tools/install/npm.d.ts +8 -0
  259. package/dist/tools/install/npm.d.ts.map +1 -0
  260. package/dist/tools/install/npm.js +52 -0
  261. package/dist/tools/install/npm.js.map +1 -0
  262. package/dist/tools/install/skill-content.d.ts +9 -0
  263. package/dist/tools/install/skill-content.d.ts.map +1 -0
  264. package/dist/tools/install/skill-content.js +89 -0
  265. package/dist/tools/install/skill-content.js.map +1 -0
  266. package/dist/tools/install_skill.d.ts.map +1 -1
  267. package/dist/tools/install_skill.js +2 -0
  268. package/dist/tools/install_skill.js.map +1 -1
  269. package/dist/tools/list_memory.d.ts +3 -0
  270. package/dist/tools/list_memory.d.ts.map +1 -0
  271. package/dist/tools/list_memory.js +55 -0
  272. package/dist/tools/list_memory.js.map +1 -0
  273. package/dist/tools/ls.d.ts.map +1 -1
  274. package/dist/tools/ls.js +2 -0
  275. package/dist/tools/ls.js.map +1 -1
  276. package/dist/tools/memory/delete_memory.d.ts +3 -0
  277. package/dist/tools/memory/delete_memory.d.ts.map +1 -0
  278. package/dist/tools/memory/delete_memory.js +46 -0
  279. package/dist/tools/memory/delete_memory.js.map +1 -0
  280. package/dist/tools/memory/list_memory.d.ts +3 -0
  281. package/dist/tools/memory/list_memory.d.ts.map +1 -0
  282. package/dist/tools/memory/list_memory.js +55 -0
  283. package/dist/tools/memory/list_memory.js.map +1 -0
  284. package/dist/tools/memory/save_memory.d.ts +3 -0
  285. package/dist/tools/memory/save_memory.d.ts.map +1 -0
  286. package/dist/tools/memory/save_memory.js +45 -0
  287. package/dist/tools/memory/save_memory.js.map +1 -0
  288. package/dist/tools/read.d.ts.map +1 -1
  289. package/dist/tools/read.js +2 -0
  290. package/dist/tools/read.js.map +1 -1
  291. package/dist/tools/registry.d.ts +7 -8
  292. package/dist/tools/registry.d.ts.map +1 -1
  293. package/dist/tools/registry.js +114 -46
  294. package/dist/tools/registry.js.map +1 -1
  295. package/dist/tools/save_memory.d.ts +3 -0
  296. package/dist/tools/save_memory.d.ts.map +1 -0
  297. package/dist/tools/save_memory.js +45 -0
  298. package/dist/tools/save_memory.js.map +1 -0
  299. package/dist/tools/search.d.ts.map +1 -1
  300. package/dist/tools/search.js +2 -0
  301. package/dist/tools/search.js.map +1 -1
  302. package/dist/tools/sed.d.ts +4 -0
  303. package/dist/tools/sed.d.ts.map +1 -0
  304. package/dist/tools/sed.js +121 -0
  305. package/dist/tools/sed.js.map +1 -0
  306. package/dist/tools/tree.d.ts +12 -0
  307. package/dist/tools/tree.d.ts.map +1 -0
  308. package/dist/tools/tree.js +87 -0
  309. package/dist/tools/tree.js.map +1 -0
  310. package/dist/tools/types.d.ts +12 -0
  311. package/dist/tools/types.d.ts.map +1 -1
  312. package/dist/tools/web/fetch.d.ts +3 -0
  313. package/dist/tools/web/fetch.d.ts.map +1 -0
  314. package/dist/tools/web/fetch.js +49 -0
  315. package/dist/tools/web/fetch.js.map +1 -0
  316. package/dist/tools/web/search.d.ts +3 -0
  317. package/dist/tools/web/search.d.ts.map +1 -0
  318. package/dist/tools/web/search.js +134 -0
  319. package/dist/tools/web/search.js.map +1 -0
  320. package/dist/tools/write_plan.d.ts.map +1 -1
  321. package/dist/tools/write_plan.js +2 -0
  322. package/dist/tools/write_plan.js.map +1 -1
  323. package/dist/tui/commands.d.ts +4 -0
  324. package/dist/tui/commands.d.ts.map +1 -0
  325. package/dist/tui/commands.js +118 -0
  326. package/dist/tui/commands.js.map +1 -0
  327. package/dist/tui/components/colors.d.ts +36 -0
  328. package/dist/tui/components/colors.d.ts.map +1 -0
  329. package/dist/tui/components/colors.js +48 -0
  330. package/dist/tui/components/colors.js.map +1 -0
  331. package/dist/tui/components/header-bar.d.ts +26 -0
  332. package/dist/tui/components/header-bar.d.ts.map +1 -0
  333. package/dist/tui/components/header-bar.js +78 -0
  334. package/dist/tui/components/header-bar.js.map +1 -0
  335. package/dist/tui/components/index.d.ts +9 -0
  336. package/dist/tui/components/index.d.ts.map +1 -0
  337. package/dist/tui/components/index.js +9 -0
  338. package/dist/tui/components/index.js.map +1 -0
  339. package/dist/tui/components/landing-screen.d.ts +12 -0
  340. package/dist/tui/components/landing-screen.d.ts.map +1 -0
  341. package/dist/tui/components/landing-screen.js +53 -0
  342. package/dist/tui/components/landing-screen.js.map +1 -0
  343. package/dist/tui/components/pixel-logo.d.ts +5 -0
  344. package/dist/tui/components/pixel-logo.d.ts.map +1 -0
  345. package/dist/tui/components/pixel-logo.js +27 -0
  346. package/dist/tui/components/pixel-logo.js.map +1 -0
  347. package/dist/tui/components/plan-utils.d.ts +11 -0
  348. package/dist/tui/components/plan-utils.d.ts.map +1 -0
  349. package/dist/tui/components/plan-utils.js +62 -0
  350. package/dist/tui/components/plan-utils.js.map +1 -0
  351. package/dist/tui/components/plans-list.d.ts +18 -0
  352. package/dist/tui/components/plans-list.d.ts.map +1 -0
  353. package/dist/tui/components/plans-list.js +46 -0
  354. package/dist/tui/components/plans-list.js.map +1 -0
  355. package/dist/tui/components/rich-footer.d.ts +29 -0
  356. package/dist/tui/components/rich-footer.d.ts.map +1 -0
  357. package/dist/tui/components/rich-footer.js +124 -0
  358. package/dist/tui/components/rich-footer.js.map +1 -0
  359. package/dist/tui/components/todo-panel.d.ts +14 -0
  360. package/dist/tui/components/todo-panel.d.ts.map +1 -0
  361. package/dist/tui/components/todo-panel.js +83 -0
  362. package/dist/tui/components/todo-panel.js.map +1 -0
  363. package/dist/tui/components.d.ts.map +1 -1
  364. package/dist/tui/components.js +14 -7
  365. package/dist/tui/components.js.map +1 -1
  366. package/dist/tui/index.d.ts +2 -1
  367. package/dist/tui/index.d.ts.map +1 -1
  368. package/dist/tui/index.js +99 -505
  369. package/dist/tui/index.js.map +1 -1
  370. package/dist/tui/overlays.d.ts +28 -0
  371. package/dist/tui/overlays.d.ts.map +1 -0
  372. package/dist/tui/overlays.js +154 -0
  373. package/dist/tui/overlays.js.map +1 -0
  374. package/dist/tui/themes.d.ts +5 -0
  375. package/dist/tui/themes.d.ts.map +1 -0
  376. package/dist/tui/themes.js +38 -0
  377. package/dist/tui/themes.js.map +1 -0
  378. package/dist/web/index.d.ts.map +1 -1
  379. package/dist/web/index.js +62 -101
  380. package/dist/web/index.js.map +1 -1
  381. package/dist/web/public/app.js +5 -855
  382. package/dist/web/public/confirm.js +70 -0
  383. package/dist/web/public/index.html +121 -120
  384. package/dist/web/public/input.js +107 -0
  385. package/dist/web/public/messages.js +411 -0
  386. package/dist/web/public/sidebar.js +82 -0
  387. package/dist/web/public/state.js +72 -0
  388. package/dist/web/public/style.css +247 -70
  389. package/dist/web/public/utils.js +37 -0
  390. package/dist/web/public/websocket.js +267 -0
  391. package/dist/web/public/ws.js +19 -0
  392. package/dist/web/session-bridge.d.ts.map +1 -1
  393. package/dist/web/session-bridge.js +85 -10
  394. package/dist/web/session-bridge.js.map +1 -1
  395. package/docs/ast-tools.md +117 -0
  396. package/package.json +11 -5
  397. package/scripts/check-line-count.mjs +53 -0
  398. package/scripts/copy-ast-wasm.mjs +32 -0
  399. package/scripts/copy-native.mjs +24 -0
  400. package/scripts/copy-web.mjs +15 -0
  401. package/src/agent/__tests__/session-restore.test.ts +284 -0
  402. package/src/agent/commands.ts +274 -0
  403. package/src/agent/compaction.ts +9 -2
  404. package/src/agent/index.ts +7 -2
  405. package/src/agent/llm.ts +4 -0
  406. package/src/agent/memory.ts +60 -0
  407. package/src/agent/prompt-builder.ts +111 -33
  408. package/src/agent/providers/google.ts +0 -1
  409. package/src/agent/providers/openai.ts +79 -8
  410. package/src/agent/session-chat.ts +480 -0
  411. package/src/agent/session-display.ts +195 -0
  412. package/src/agent/session-persistence.ts +146 -0
  413. package/src/agent/session-utils.ts +54 -0
  414. package/src/agent/session.ts +269 -670
  415. package/src/cli/index.ts +73 -4
  416. package/src/config/index.ts +14 -7
  417. package/src/index.ts +30 -3
  418. package/src/tools/__tests__/bash.test.ts +188 -2
  419. package/src/tools/__tests__/edit.test.ts +1216 -356
  420. package/src/tools/__tests__/fetch.test.ts +1 -1
  421. package/src/tools/__tests__/glob.test.ts +1 -1
  422. package/src/tools/__tests__/grep.test.ts +36 -1
  423. package/src/tools/__tests__/ls.test.ts +1 -1
  424. package/src/tools/__tests__/read.test.ts +1 -1
  425. package/src/tools/__tests__/registry.test.ts +332 -0
  426. package/src/tools/__tests__/write_plan.test.ts +1 -1
  427. package/src/tools/codebase/ast/__tests__/integration.test.ts +452 -0
  428. package/src/tools/codebase/ast/__tests__/tree-sitter.test.ts +466 -0
  429. package/src/tools/codebase/ast/adapter.ts +44 -0
  430. package/src/tools/codebase/ast/tools.ts +322 -0
  431. package/src/tools/codebase/ast/tree-sitter-adapter.ts +468 -0
  432. package/src/tools/codebase/ast/tree-sitter-converters.ts +480 -0
  433. package/src/tools/codebase/ast/types.ts +102 -0
  434. package/src/tools/codebase/ast/wasm/tree-sitter-python.wasm +0 -0
  435. package/src/tools/codebase/ast/wasm/tree-sitter-tsx.wasm +0 -0
  436. package/src/tools/codebase/ast/wasm/tree-sitter-typescript.wasm +0 -0
  437. package/src/tools/codebase/ast/wasm/tree-sitter.wasm +0 -0
  438. package/src/tools/codebase/ast/wasm/web-tree-sitter.wasm +0 -0
  439. package/src/tools/{find.ts → codebase/find.ts} +4 -2
  440. package/src/tools/{glob.ts → codebase/glob.ts} +4 -2
  441. package/src/tools/{grep.ts → codebase/grep.ts} +61 -32
  442. package/src/tools/{ls.ts → codebase/ls.ts} +4 -2
  443. package/src/tools/{read.ts → codebase/read.ts} +5 -3
  444. package/src/tools/edit/diff-compute.ts +21 -0
  445. package/src/tools/edit/diff-render.ts +145 -0
  446. package/src/tools/edit/edit.ts +468 -0
  447. package/src/tools/edit/matcher.ts +70 -0
  448. package/src/tools/edit/parser.ts +131 -0
  449. package/src/tools/edit/types.ts +19 -0
  450. package/src/tools/{write_plan.ts → edit/write_plan.ts} +4 -2
  451. package/src/tools/execute/bash/constants.ts +93 -0
  452. package/src/tools/execute/bash/errors.ts +304 -0
  453. package/src/tools/execute/bash/execution.ts +211 -0
  454. package/src/tools/execute/bash/index.ts +131 -0
  455. package/src/tools/execute/bash/platform.ts +65 -0
  456. package/src/tools/execute/bash/security.ts +28 -0
  457. package/src/tools/execute/bash/validation.ts +78 -0
  458. package/src/tools/execute/git.ts +209 -0
  459. package/src/tools/execute/task_complete.ts +40 -0
  460. package/src/tools/install/clawhub.ts +222 -0
  461. package/src/tools/install/constants.ts +4 -0
  462. package/src/tools/install/install_skill.ts +150 -0
  463. package/src/tools/install/npm.ts +60 -0
  464. package/src/tools/install/skill-content.ts +108 -0
  465. package/src/tools/memory/delete_memory.ts +46 -0
  466. package/src/tools/memory/list_memory.ts +53 -0
  467. package/src/tools/memory/save_memory.ts +45 -0
  468. package/src/tools/registry.ts +121 -50
  469. package/src/tools/tree.ts +103 -0
  470. package/src/tools/types.ts +13 -0
  471. package/src/tools/{fetch.ts → web/fetch.ts} +4 -2
  472. package/src/tools/{search.ts → web/search.ts} +4 -2
  473. package/src/tui/commands.ts +135 -0
  474. package/src/tui/components/colors.ts +52 -0
  475. package/src/tui/components/header-bar.ts +88 -0
  476. package/src/tui/components/index.ts +8 -0
  477. package/src/tui/components/landing-screen.ts +67 -0
  478. package/src/tui/components/pixel-logo.ts +33 -0
  479. package/src/tui/components/plan-utils.ts +69 -0
  480. package/src/tui/components/plans-list.ts +55 -0
  481. package/src/tui/components/rich-footer.ts +146 -0
  482. package/src/tui/components/todo-panel.ts +95 -0
  483. package/src/tui/index.ts +110 -561
  484. package/src/tui/overlays.ts +203 -0
  485. package/src/tui/themes.ts +41 -0
  486. package/src/web/index.ts +66 -107
  487. package/src/web/public/app.js +5 -855
  488. package/src/web/public/confirm.js +70 -0
  489. package/src/web/public/index.html +121 -120
  490. package/src/web/public/input.js +107 -0
  491. package/src/web/public/messages.js +411 -0
  492. package/src/web/public/sidebar.js +82 -0
  493. package/src/web/public/state.js +72 -0
  494. package/src/web/public/style.css +247 -70
  495. package/src/web/public/utils.js +37 -0
  496. package/src/web/public/websocket.js +267 -0
  497. package/src/web/public/ws.js +19 -0
  498. package/src/web/session-bridge.ts +90 -12
  499. package/.claude/settings.local.json +0 -14
  500. package/.kilo/plans/1780064105789-mighty-pixel.md +0 -171
  501. package/.kilo/plans/1780293725888-quick-wizard.md +0 -62
  502. package/.lonny/plan-web-cwd-status.md +0 -38
  503. package/AGENT.md +0 -99
  504. package/src/tools/bash.ts +0 -39
  505. package/src/tools/edit.ts +0 -554
  506. package/src/tools/exec.ts +0 -348
  507. package/src/tools/git.ts +0 -76
  508. package/src/tools/install_skill.ts +0 -539
  509. package/src/tui/components.ts +0 -635
@@ -0,0 +1,267 @@
1
+ /* ── WebSocket Connection & Message Handler ── */
2
+
3
+ import { closeConfirmDialog, showConfirmDialog } from './confirm.js'
4
+ import {
5
+ addErrorMessage,
6
+ addSystemMessage,
7
+ addTokenStats,
8
+ addToolCall,
9
+ addToolResult,
10
+ appendChunk,
11
+ finalizeAssistantMessage,
12
+ hideThinking,
13
+ renderSessionHistory,
14
+ showThinking,
15
+ startAssistantMessage,
16
+ } from './messages.js'
17
+ import { updatePlansAndTodos } from './sidebar.js'
18
+ import {
19
+ balanceDisplay,
20
+ balanceSep,
21
+ connectionOverlay,
22
+ cwdDisplay,
23
+ MAX_RECONNECT_ATTEMPTS,
24
+ messagesEl,
25
+ modeDisplay,
26
+ modelDisplay,
27
+ pendingToolCalls,
28
+ RECONNECT_DELAY,
29
+ setStatus,
30
+ state,
31
+ tokenCache,
32
+ tokenCalls,
33
+ tokenIn,
34
+ tokenOut,
35
+ } from './state.js'
36
+ import { formatTokenCount, getWsUrl, scrollToBottom } from './utils.js'
37
+ import { setWs } from './ws.js'
38
+
39
+ function handleMessage(msg) {
40
+ switch (msg.type) {
41
+ case 'hello':
42
+ state.currentMode = msg.mode || 'code'
43
+ state.currentModel = msg.model || ''
44
+ state.currentProvider = msg.provider || ''
45
+ modeDisplay.textContent = state.currentMode
46
+ modelDisplay.textContent = `${state.currentProvider}/${state.currentModel}`
47
+ if (msg.totalIn !== undefined) {
48
+ tokenIn.textContent = formatTokenCount(msg.totalIn || 0)
49
+ tokenOut.textContent = formatTokenCount(msg.totalOut || 0)
50
+ tokenCalls.textContent = `(${msg.totalApi || 0})`
51
+ const cacheHit = msg.totalCacheHit ?? 0
52
+ const cacheMiss = msg.totalCacheMiss ?? 0
53
+ const cacheTotal = cacheHit + cacheMiss
54
+ if (cacheTotal > 0) {
55
+ const pct = Math.round((cacheHit / cacheTotal) * 100)
56
+ tokenCache.textContent = `| 缓存 ${pct}%`
57
+ tokenCache.classList.remove('hidden')
58
+ }
59
+ }
60
+ if (msg.webBalance) {
61
+ balanceDisplay.textContent = `余额:${msg.webBalance}`
62
+ balanceDisplay.style.display = ''
63
+ balanceSep.style.display = ''
64
+ } else if (msg.balance) {
65
+ balanceDisplay.textContent = `余额:${msg.balance}`
66
+ balanceDisplay.style.display = ''
67
+ balanceSep.style.display = ''
68
+ } else {
69
+ balanceDisplay.style.display = 'none'
70
+ balanceSep.style.display = 'none'
71
+ }
72
+ if (msg.cwd) {
73
+ const maxLen = 35
74
+ cwdDisplay.textContent = msg.cwd.length > maxLen ? `...${msg.cwd.slice(-maxLen)}` : msg.cwd
75
+ }
76
+ break
77
+
78
+ case 'chunk':
79
+ appendChunk(msg.text || '')
80
+ break
81
+
82
+ case 'thinking':
83
+ showThinking(msg.text || '')
84
+ break
85
+
86
+ case 'thinking_end':
87
+ hideThinking()
88
+ break
89
+
90
+ case 'tool_call':
91
+ addToolCall(msg.name, msg.input, msg.id)
92
+ break
93
+
94
+ case 'tool_result':
95
+ if (msg.success) {
96
+ addToolResult(msg.name, true, msg.output || '', msg.id)
97
+ } else {
98
+ addToolResult(msg.name, false, msg.error || 'Unknown error', msg.id)
99
+ }
100
+ break
101
+
102
+ case 'turn_start':
103
+ setStatus(true)
104
+ startAssistantMessage()
105
+ break
106
+
107
+ case 'turn_end':
108
+ hideThinking()
109
+ for (const [, el] of pendingToolCalls) el.classList.remove('executing')
110
+ pendingToolCalls.clear()
111
+ finalizeAssistantMessage()
112
+ break
113
+
114
+ case 'done':
115
+ setStatus(false)
116
+ hideThinking()
117
+ for (const [, el] of pendingToolCalls) el.classList.remove('executing')
118
+ pendingToolCalls.clear()
119
+ finalizeAssistantMessage()
120
+ if (msg.reason === 'error') {
121
+ addErrorMessage('An error occurred during processing.')
122
+ }
123
+ break
124
+
125
+ case 'mode_changed':
126
+ state.currentMode = msg.mode
127
+ modeDisplay.textContent = state.currentMode
128
+ addSystemMessage(`Switched to ${state.currentMode} mode`)
129
+ break
130
+
131
+ case 'model_changed':
132
+ state.currentModel = msg.model
133
+ modelDisplay.textContent = `${state.currentProvider}/${state.currentModel}`
134
+ addSystemMessage(`Model switched to ${state.currentModel}`)
135
+ break
136
+
137
+ case 'session_cleared':
138
+ messagesEl.innerHTML = ''
139
+ addSystemMessage('Session cleared. Starting fresh.')
140
+ break
141
+
142
+ case 'help':
143
+ if (Array.isArray(msg.commands)) {
144
+ addSystemMessage('Available commands:')
145
+ msg.commands.forEach(cmd => addSystemMessage(cmd))
146
+ }
147
+ break
148
+
149
+ case 'compaction':
150
+ addSystemMessage(`📦 Compressed context: ${msg.before} → ${msg.after} messages`)
151
+ break
152
+
153
+ case 'plan_written':
154
+ addSystemMessage(`📝 Plan written: ${msg.display || ''}`)
155
+ break
156
+
157
+ case 'session_history':
158
+ renderSessionHistory(msg.messages)
159
+ setTimeout(scrollToBottom, 50)
160
+ break
161
+
162
+ case 'plan_data':
163
+ state.plans = msg.plans || []
164
+ state.currentPlanName = msg.currentPlanName || ''
165
+ state.todos = msg.todos || []
166
+ updatePlansAndTodos()
167
+ break
168
+
169
+ case 'balance_update':
170
+ if (msg.webBalance) {
171
+ balanceDisplay.textContent = `余额:${msg.webBalance}`
172
+ balanceDisplay.style.display = ''
173
+ balanceSep.style.display = ''
174
+ } else if (msg.balance) {
175
+ balanceDisplay.textContent = `余额:${msg.balance}`
176
+ balanceDisplay.style.display = ''
177
+ balanceSep.style.display = ''
178
+ }
179
+ break
180
+
181
+ case 'token_stats':
182
+ addTokenStats(
183
+ msg.turnIn,
184
+ msg.turnOut,
185
+ msg.totalIn,
186
+ msg.totalOut,
187
+ msg.turnApi,
188
+ msg.totalApi,
189
+ msg.totalCacheHit,
190
+ msg.totalCacheMiss,
191
+ )
192
+ break
193
+
194
+ case 'tool_confirm_request': {
195
+ if (!msg.toolCalls || msg.toolCalls.length === 0) break
196
+ showConfirmDialog(msg.toolCalls)
197
+ break
198
+ }
199
+
200
+ case 'error':
201
+ closeConfirmDialog()
202
+ addErrorMessage(msg.message || 'Unknown error')
203
+ break
204
+
205
+ case 'pong':
206
+ break
207
+
208
+ default:
209
+ console.log('Unknown message type:', msg.type)
210
+ }
211
+ }
212
+
213
+ export function connect() {
214
+ connectionOverlay.classList.remove('hidden')
215
+
216
+ let ws
217
+ try {
218
+ ws = new WebSocket(getWsUrl())
219
+ setWs(ws)
220
+ } catch (err) {
221
+ connectionOverlay.classList.add('hidden')
222
+ addErrorMessage(`Connection failed: ${err.message}`)
223
+ return
224
+ }
225
+
226
+ ws.onopen = () => {
227
+ connectionOverlay.classList.add('hidden')
228
+ state.reconnectAttempts = 0
229
+ addSystemMessage('Connected to Lonny')
230
+ }
231
+
232
+ ws.onmessage = event => {
233
+ try {
234
+ const msg = JSON.parse(event.data)
235
+ handleMessage(msg)
236
+ } catch (err) {
237
+ console.error('Failed to parse message:', err)
238
+ }
239
+ }
240
+
241
+ ws.onclose = () => {
242
+ setStatus(false)
243
+ hideThinking()
244
+ for (const [, el] of pendingToolCalls) el.classList.remove('executing')
245
+ pendingToolCalls.clear()
246
+ if (state.streamingMsgEl) {
247
+ finalizeAssistantMessage()
248
+ }
249
+
250
+ if (state.reconnectAttempts < MAX_RECONNECT_ATTEMPTS) {
251
+ state.reconnectAttempts++
252
+ const delay = RECONNECT_DELAY * Math.min(state.reconnectAttempts, 5)
253
+ connectionOverlay.querySelector('p').textContent =
254
+ `Reconnecting in ${delay / 1000}s... (attempt ${state.reconnectAttempts}/${MAX_RECONNECT_ATTEMPTS})`
255
+ connectionOverlay.classList.remove('hidden')
256
+ setTimeout(connect, delay)
257
+ } else {
258
+ connectionOverlay.querySelector('p').textContent = 'Connection lost. Please refresh the page.'
259
+ connectionOverlay.classList.remove('hidden')
260
+ addErrorMessage('Connection lost. Refresh the page to reconnect.')
261
+ }
262
+ }
263
+
264
+ ws.onerror = () => {
265
+ // onclose will fire after this
266
+ }
267
+ }
@@ -0,0 +1,19 @@
1
+ /* ── WebSocket Reference & Send ── */
2
+
3
+ let ws = null
4
+
5
+ export function getWs() {
6
+ return ws
7
+ }
8
+
9
+ export function setWs(newWs) {
10
+ ws = newWs
11
+ }
12
+
13
+ export function sendWsMsg(data) {
14
+ if (ws && ws.readyState === WebSocket.OPEN) {
15
+ ws.send(JSON.stringify(data))
16
+ return true
17
+ }
18
+ return false
19
+ }
@@ -28,16 +28,20 @@ export function startSessionBridge(
28
28
  ): { close: () => void; sendMessage: (text: string) => Promise<void> } {
29
29
  const bus = getGlobalEventBus()
30
30
 
31
- // Send initial handshake with current token stats
31
+ // Send initial handshake with current token stats and session info
32
32
  send({
33
33
  type: 'hello',
34
34
  version: WS_PROTOCOL_VERSION,
35
+ sessionId: session.sessionId,
36
+ sessionTitle: session.sessionTitle || undefined,
35
37
  mode: config.mode,
36
38
  model: config.model,
37
39
  provider: config.provider,
38
40
  totalIn: session.totalInputTokens,
39
41
  totalOut: session.totalOutputTokens,
40
42
  totalApi: session.totalApiCalls,
43
+ totalCacheHit: session.totalCacheHitTokens || undefined,
44
+ totalCacheMiss: session.totalCacheMissTokens || undefined,
41
45
  })
42
46
 
43
47
  // ── Subscribe to EventBus ──
@@ -59,7 +63,7 @@ export function startSessionBridge(
59
63
  name: d.name,
60
64
  id: d.id,
61
65
  success: true,
62
- output: stripAnsi(d.output),
66
+ output: d.name === 'edit' ? d.output : stripAnsi(d.output),
63
67
  })
64
68
  })
65
69
 
@@ -95,6 +99,10 @@ export function startSessionBridge(
95
99
  totalOut: number
96
100
  turnApi: number
97
101
  totalApi: number
102
+ turnCacheHit?: number
103
+ turnCacheMiss?: number
104
+ totalCacheHit?: number
105
+ totalCacheMiss?: number
98
106
  }
99
107
  send({ type: 'token_stats', ...d })
100
108
  })
@@ -113,8 +121,11 @@ export function startSessionBridge(
113
121
  const cmd = parts[0]
114
122
  const arg = parts.slice(1).join(' ')
115
123
 
116
- if (cmd === 'mode' && (arg === 'code' || arg === 'plan' || arg === 'ask')) {
117
- session.setMode(arg as 'code' | 'plan' | 'ask')
124
+ if (
125
+ cmd === 'mode' &&
126
+ (arg === 'code' || arg === 'plan' || arg === 'ask' || arg === 'loop')
127
+ ) {
128
+ session.setMode(arg as 'code' | 'plan' | 'ask' | 'loop')
118
129
  send({ type: 'mode_changed', mode: arg })
119
130
  return
120
131
  }
@@ -126,19 +137,17 @@ export function startSessionBridge(
126
137
  return
127
138
  }
128
139
 
129
- if (cmd === 'new') {
130
- const { Session } = await import('../agent/session.js')
131
- Session.clearSavedSession(config.cwd)
132
- send({ type: 'session_cleared' })
133
- return
134
- }
135
-
136
140
  if (cmd === 'help') {
137
141
  send({
138
142
  type: 'help',
139
143
  commands: [
140
- '/mode code|plan|ask - Switch mode',
144
+ '/mode code|plan|ask|loop - Switch mode',
141
145
  '/model <name> - Switch model',
146
+ '/sessions - List saved sessions',
147
+ '/session - Show current session info',
148
+ '/session title <name> - Name current session',
149
+ '/session delete <id> - Delete a session',
150
+ '/fork - Fork a new session from current context',
142
151
  '/new - Start a new session',
143
152
  '/help - Show this help',
144
153
  ],
@@ -146,6 +155,75 @@ export function startSessionBridge(
146
155
  return
147
156
  }
148
157
 
158
+ if (cmd === 'sessions') {
159
+ const { Session } = await import('../agent/session.js')
160
+ const allSessions = Session.listSessions()
161
+ send({
162
+ type: 'sessions',
163
+ sessions: allSessions.map(s => ({
164
+ id: s.id,
165
+ cwd: s.cwd,
166
+ title: s.title,
167
+ messageCount: s.messageCount,
168
+ mode: s.mode,
169
+ model: s.model,
170
+ provider: s.provider,
171
+ totalInputTokens: s.totalInputTokens,
172
+ totalOutputTokens: s.totalOutputTokens,
173
+ totalApiCalls: s.totalApiCalls,
174
+ createdAt: s.createdAt,
175
+ updatedAt: s.updatedAt,
176
+ })),
177
+ })
178
+ return
179
+ }
180
+
181
+ if (cmd === 'session') {
182
+ if (arg === 'delete' || arg.startsWith('delete ')) {
183
+ const { Session } = await import('../agent/session.js')
184
+ const id = arg.slice(arg.startsWith('delete ') ? 7 : 6).trim()
185
+ const deleted = id ? Session.deleteSession(id) : false
186
+ send({ type: 'session_deleted', id, success: deleted })
187
+ } else if (arg.startsWith('title ')) {
188
+ const title = arg.slice(6).trim()
189
+ if (title) {
190
+ session.sessionTitle = title
191
+ session.save()
192
+ send({ type: 'session_titled', title })
193
+ } else {
194
+ send({ type: 'error', message: 'Usage: /session title <name>' })
195
+ }
196
+ } else if (arg === 'export') {
197
+ try {
198
+ const filePath = session.exportSession()
199
+ send({ type: 'session_exported', filePath })
200
+ } catch (err) {
201
+ send({ type: 'error', message: `Export failed: ${err}` })
202
+ }
203
+ } else {
204
+ send({
205
+ type: 'session_info',
206
+ id: session.sessionId,
207
+ title: session.sessionTitle || '(untitled)',
208
+ mode: session.config.mode,
209
+ model: session.config.model,
210
+ provider: session.config.provider,
211
+ messageCount: session.messages.length,
212
+ totalInputTokens: session.totalInputTokens,
213
+ totalOutputTokens: session.totalOutputTokens,
214
+ totalApiCalls: session.totalApiCalls,
215
+ createdAt: session.sessionCreatedAt,
216
+ })
217
+ }
218
+ return
219
+ }
220
+
221
+ if (cmd === 'fork') {
222
+ const forked = session.fork()
223
+ send({ type: 'session_forked', id: forked.sessionId, title: forked.sessionTitle })
224
+ return
225
+ }
226
+
149
227
  send({ type: 'error', message: `Unknown command: ${cmd}` })
150
228
  return
151
229
  }
@@ -1,14 +0,0 @@
1
- {
2
- "permissions": {
3
- "allow": [
4
- "Bash(npm run:*)",
5
- "Bash(grep:*)",
6
- "Bash(npx tsc:*)",
7
- "Bash(npm test:*)",
8
- "Bash(gh release:*)",
9
- "Read(//c/Program Files/GitHub CLI//**)",
10
- "Read(//c/Program Files \\(x86\\)/**)",
11
- "Bash(\"/c/Program Files/GitHub CLI/gh.exe\" release create 0.2.4 --title \"v0.2.4\" --generate-notes)"
12
- ]
13
- }
14
- }
@@ -1,171 +0,0 @@
1
- # Plan: Vendor `@earendil-works/pi-tui` source
2
-
3
- ## Objective
4
-
5
- Replace the `@earendil-works/pi-tui` npm dependency with vendored source code from [pi/packages/tui](https://github.com/earendil-works/pi/tree/main/packages/tui), so the project no longer depends on that npm package.
6
-
7
- ## Current state
8
-
9
- - `package.json` depends on `"@earendil-works/pi-tui": "0.75.5"`
10
- - A patch file `patches/@earendil-works+pi-tui+0.75.5.patch` applies 2 modifications (autocomplete above editor, alternate screen buffer on start/stop)
11
- - `patch-package` is in devDependencies for applying the patch
12
- - Only 2 source files import from `@earendil-works/pi-tui`:
13
- - `src/tui/index.ts` (type imports + 11 class exports)
14
- - `src/tui/components.ts` (Component type + SelectList class)
15
- - Internal Editor access: `(editor as any).killRing`, `.undoStack`, `.history`
16
-
17
- ## Steps
18
-
19
- ### 1. Download pi-tui source from GitHub
20
-
21
- Clone a shallow copy of the repo to get the source at the matching version or the main branch:
22
-
23
- ```bash
24
- # From project root temp dir
25
- git clone --depth 1 --branch main https://github.com/earendil-works/pi.git /tmp/pi-source
26
- ```
27
-
28
- Alternatively, if git clone is not feasible, download each file individually from GitHub.
29
-
30
- Source files needed from `packages/tui/src/`:
31
- ```
32
- src/
33
- index.ts - barrel exports
34
- autocomplete.ts - CombinedAutocompleteProvider, AutocompleteProvider, etc.
35
- editor-component.ts - EditorComponent type
36
- fuzzy.ts - fuzzyFilter, fuzzyMatch
37
- keybindings.ts - KeybindingsManager, TUI_KEYBINDINGS, etc.
38
- keys.ts - Key, matchesKey, parseKey, etc.
39
- kill-ring.ts - KillRing
40
- native-modifiers.ts - native keyboard modifiers
41
- stdin-buffer.ts - StdinBuffer
42
- terminal-image.ts - image rendering
43
- terminal.ts - ProcessTerminal, Terminal interface
44
- tui.ts - TUI, Container, Component, OverlayHandle, OverlayOptions, Focusable, CURSOR_MARKER, etc.
45
- undo-stack.ts - UndoStack
46
- utils.ts - visibleWidth, truncateToWidth, wrapTextWithAnsi, etc.
47
- word-navigation.ts - word boundary navigation
48
- components/
49
- box.ts
50
- cancellable-loader.ts
51
- editor.ts
52
- image.ts
53
- input.ts
54
- loader.ts
55
- markdown.ts
56
- select-list.ts
57
- settings-list.ts
58
- spacer.ts
59
- text.ts
60
- truncated-text.ts
61
- ```
62
-
63
- Also copy `native/` directory (Windows VT input helper):
64
- ```
65
- native/win32/prebuilds/win32-x64/win32-console-mode.node
66
- native/win32/prebuilds/win32-arm64/win32-console-mode.node
67
- ```
68
-
69
- ### 2. Place vendored code at `src/pi-tui/`
70
-
71
- ```
72
- src/
73
- pi-tui/
74
- index.ts
75
- autocomplete.ts
76
- editor-component.ts
77
- fuzzy.ts
78
- keybindings.ts
79
- keys.ts
80
- kill-ring.ts
81
- native-modifiers.ts
82
- stdin-buffer.ts
83
- terminal-image.ts
84
- terminal.ts
85
- tui.ts
86
- undo-stack.ts
87
- utils.ts
88
- word-navigation.ts
89
- components/
90
- box.ts
91
- cancellable-loader.ts
92
- editor.ts
93
- image.ts
94
- input.ts
95
- loader.ts
96
- markdown.ts
97
- select-list.ts
98
- settings-list.ts
99
- spacer.ts
100
- text.ts
101
- truncated-text.ts
102
- native/
103
- win32/prebuilds/win32-x64/win32-console-mode.node
104
- win32/prebuilds/win32-arm64/win32-console-mode.node
105
- ```
106
-
107
- ### 3. Apply the two manual patches to the vendored source
108
-
109
- The patch file modifies the **compiled dist JS**, but we need to apply equivalent changes to the **TypeScript source**:
110
-
111
- **Patch 1** — `components/editor.ts`: Move autocomplete rendering above the editor
112
- - Find the `render()` method where autocomplete lines are appended
113
- - Change `result.push(...acLines)` → `result.unshift(...acLines)` (or equivalent logic)
114
-
115
- **Patch 2** — `tui.ts`: Add alternate screen buffer on start/stop
116
- - In `start()`: add `this.terminal.write("\x1b[?1049h");` before `this.terminal.start(…)`
117
- - In `stop()`: add `this.terminal.write("\x1b[?1049l");` before cursor/timer cleanup
118
-
119
- ### 4. Update import paths
120
-
121
- **`src/tui/index.ts`** — change:
122
- ```ts
123
- import type { EditorTheme, MarkdownTheme, OverlayHandle, SelectItem, SelectListTheme, SlashCommand } from '@earendil-works/pi-tui'
124
- import { Box, CombinedAutocompleteProvider, Container, Editor, Loader, Markdown, ProcessTerminal, Text, TUI } from '@earendil-works/pi-tui'
125
- ```
126
- to:
127
- ```ts
128
- import type { EditorTheme, MarkdownTheme, OverlayHandle, SelectItem, SelectListTheme, SlashCommand } from '../pi-tui/index.js'
129
- import { Box, CombinedAutocompleteProvider, Container, Editor, Loader, Markdown, ProcessTerminal, Text, TUI } from '../pi-tui/index.js'
130
- ```
131
-
132
- **`src/tui/components.ts`** — change:
133
- ```ts
134
- import type { Component, SelectItem, SelectListTheme } from '@earendil-works/pi-tui'
135
- import { SelectList } from '@earendil-works/pi-tui'
136
- ```
137
- to:
138
- ```ts
139
- import type { Component, SelectItem, SelectListTheme } from '../pi-tui/index.js'
140
- import { SelectList } from '../pi-tui/index.js'
141
- ```
142
-
143
- ### 5. Keep `marked` and `get-east-asian-width` as runtime dependencies
144
-
145
- These are pi-tui's own runtime dependencies used by `Markdown` and `visibleWidth` respectively. They remain in `dependencies`.
146
-
147
- ### 6. Remove pi-tui-related npm setup
148
-
149
- - `package.json`: Remove `"@earendil-works/pi-tui": "0.75.5"` from `dependencies`
150
- - `package.json`: Remove `"patch-package": "^8.0.1"` from `devDependencies` (only existed for pi-tui patching)
151
- - `package.json`: Change `"postinstall": "npx patch-package"` to `"postinstall": "husky"` (or remove entirely if not needed)
152
- - Delete `patches/@earendil-works+pi-tui+0.75.5.patch`
153
- - Delete `patches/` directory if empty
154
- - Run `npm uninstall @earendil-works/pi-tui` and `npm uninstall patch-package` to update lockfile
155
-
156
- ### 7. Update `package-lock.json`
157
-
158
- Run `npm install` to regenerate `package-lock.json` without pi-tui/patch-package.
159
-
160
- ### 8. Verify
161
-
162
- - `npm run build` — tsc should compile successfully
163
- - `npm run lint` — biome should pass
164
- - `npm test` — vitest tests should pass
165
- - Verify the TUI starts correctly with `npm run dev`
166
-
167
- ## Open questions
168
-
169
- 1. Should we use the exact version `0.75.5` source (may need to checkout a tag) or the latest `main` branch source? **Answer: main branch is fine unless it introduces breaking changes.**
170
- 2. The `native-modifiers.ts` file on GitHub may export functions used by `terminal.ts`. If unavailable, we can stub it or inline the native module loading logic.
171
- 3. If the GitHub raw URLs are flaky, alternative: download from npm tarball and reverse-engineer from dist JS (less ideal).
@@ -1,62 +0,0 @@
1
- # Plan: Optimize edit tool error handling for model
2
-
3
- ## Problem
4
- The model calls the `edit` tool with errors very frequently. The most common failures:
5
- 1. `old_string not found` (whitespace issues, stale content, hallucinated content)
6
- 2. `old_string appears MULTIPLE times` (insufficient context)
7
- 3. File doesn't exist / already exists
8
- 4. Input format misuse (already mostly auto-corrected)
9
-
10
- Error messages are returned to the model (via `session.ts:687` as `ERROR: ${result.error}`), but they lack actionable recovery guidance, and noise obscures the core issue.
11
-
12
- ## Changes
13
-
14
- ### 1. Use `FileReadTracker.checkModified()` to detect stale content
15
- The `FileReadTracker` has a `checkModified()` method that is never called in production code. The edit tool should call it before attempting edits to detect:
16
- - File was never read in this session → suggest `read` first
17
- - File was externally modified since last read → suggest re-reading
18
-
19
- This catches a major source of `old_string not found` errors — the model editing content it hasn't read, or editing stale content.
20
-
21
- **Location**: `edit.ts`, in the `for (const [resolved, group] of fileGroups)` loop, before processing edits.
22
-
23
- ### 2. Include proximity hint in `firstError`
24
- Currently the hint (near-line snippet / file content) is only in `results.push()` but NOT in `firstError`. This means the compact "First error:" line at the bottom of the batch error message lacks the most useful context.
25
-
26
- **Fix**: Update lines ~339-342 to include hint in `firstError`.
27
-
28
- ### 3. Add actionable "Suggestion:" line to failure messages
29
- When `old_string not found`, the error should tell the model what to do:
30
- - "Suggestion: Read the file again with `read({ paths: [...] })` to get current content, then retry with exact matching text. Include 2-3 lines of surrounding context for uniqueness."
31
- - "Suggestion: Whitespace-tolerant matching was attempted but no match found. The text content differs — not just whitespace."
32
-
33
- When `old_string appears MULTIPLE times`:
34
- - "Suggestion: Include more surrounding context lines (2-3 lines before and after) in old_string to make the match unique."
35
-
36
- When `File not found`:
37
- - "Suggestion: Check the file path or create the file first with old_string: '' (empty string)."
38
-
39
- When `File already exists` (on create):
40
- - "Suggestion: Use edit with old_string to replace existing content, or use a different file path."
41
-
42
- ### 4. Clean up batch failure output
43
- When a batch fails, the current output includes ALL results (even successful edits that were rolled back). This is noisy.
44
-
45
- **Fix**: Only show FAIL lines in the batch error, plus a brief summary like "N edit(s) before failure were rolled back."
46
-
47
- ### 5. Improve "multiple matches" error with location hints
48
- When old_string matches multiple times, show the file content at each match location (similar to the "near line" hint for not-found).
49
-
50
- ### 6. Better `edits` format error
51
- Tighten the "edits array required" error to be more compact.
52
-
53
- ## Files to modify
54
- - `src/tools/edit.ts` — all the above changes
55
-
56
- ## Tests
57
- - All existing tests in `src/tools/__tests__/edit.test.ts` must pass
58
- - Some test assertions may need updating if error message content changes
59
- - Specifically:
60
- - `expect(r.error).toContain('rolled back')` — still valid since rolled-back summary stays
61
- - `expect(r.error).toContain('hello')` — still valid since hint stays in error
62
- - Other `toContain('not found')`, `toContain('MULTIPLE times')` — still valid