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
@@ -1,23 +1,33 @@
1
1
  import type { FileReadTracker } from '../diff/apply.js'
2
- import { bashTool } from './bash.js'
3
- import { createEditTool } from './edit.js'
2
+ import { createAstTools } from './codebase/ast/tools.js'
3
+ import { createFindTool } from './codebase/find.js'
4
+ import { globTool } from './codebase/glob.js'
5
+ import { createGrepTool } from './codebase/grep.js'
6
+ import { createLsTool } from './codebase/ls.js'
7
+ import { createReadTool } from './codebase/read.js'
8
+ import { createEditTool } from './edit/edit.js'
9
+ import { createWritePlanTool } from './edit/write_plan.js'
4
10
  import { fmtErr } from './errors.js'
5
- import { createExecTool, updateExecToolDefinition } from './exec.js'
6
- import { fetchTool } from './fetch.js'
7
- import { createFindTool } from './find.js'
8
- import { createGitTool } from './git.js'
9
- import { globTool } from './glob.js'
10
- import { createGrepTool } from './grep.js'
11
- import { createInstallSkillTool } from './install_skill.js'
12
- import { createLsTool } from './ls.js'
13
- import { createReadTool } from './read.js'
14
- import { searchTool } from './search.js'
11
+ import { bashTool } from './execute/bash/index.js'
12
+ import { createGitTool } from './execute/git.js'
13
+ import { taskCompleteTool } from './execute/task_complete.js'
14
+ import { createInstallSkillTool } from './install/install_skill.js'
15
+ import { createDeleteMemoryTool } from './memory/delete_memory.js'
16
+ import { createListMemoryTool } from './memory/list_memory.js'
17
+ import { createSaveMemoryTool } from './memory/save_memory.js'
15
18
  import type { Tool, ToolCall, ToolDefinition, ToolResult } from './types.js'
16
- import { createWritePlanTool } from './write_plan.js'
19
+ import { fetchTool } from './web/fetch.js'
20
+ import { searchTool } from './web/search.js'
21
+
22
+ /**
23
+ * Tools in this set are passed directly to the LLM API's `tools` parameter.
24
+ * All other tools must be invoked via the `tool()` gateway.
25
+ */
26
+ const CORE_TOOL_NAMES = new Set(['read', 'edit', 'bash', 'glob', 'grep', 'task_complete'])
17
27
 
18
28
  /**
19
29
  * Normalize tool input to prevent common LLM call misuses.
20
- * The LLM sometimes passes parameters in the wrong format this function
30
+ * The LLM sometimes passes parameters in the wrong format �?this function
21
31
  * auto-corrects those patterns so tools work reliably.
22
32
  *
23
33
  * Common misuses handled:
@@ -50,9 +60,6 @@ function normalizeToolInput(
50
60
  if (toolName === 'write_plan') {
51
61
  return { filename: input, content: input }
52
62
  }
53
- if (toolName === 'exec') {
54
- return { code: input }
55
- }
56
63
  // For tools that take a single string param, guess from the definition
57
64
  const params = Object.keys(_definition.parameters)
58
65
  if (params.length === 1) {
@@ -79,7 +86,7 @@ export interface ToolContext {
79
86
  cwd: string
80
87
  autoApprove: boolean
81
88
  applier: FileReadTracker
82
- mode: 'code' | 'plan' | 'ask'
89
+ mode: 'code' | 'plan' | 'ask' | 'loop'
83
90
  onPlanWritten?: (display: string) => void
84
91
  }
85
92
 
@@ -97,17 +104,67 @@ export class ToolRegistry {
97
104
  private tools: Map<string, Tool> = new Map()
98
105
  private context: ToolContext
99
106
  private plugins: Map<string, ToolPlugin> = new Map()
100
- /** Reference to the exec tool for dynamic description updates */
101
- private execTool: Tool | null = null
107
+ private gatewayTool: Tool
102
108
 
103
109
  constructor(context: ToolContext) {
104
110
  this.context = context
111
+ this.gatewayTool = this.createGatewayTool()
105
112
  this.registerBuiltins()
106
113
  }
107
114
 
115
+ /** Create the `tool()` gateway that proxies calls to extended (non-core) tools */
116
+ private createGatewayTool(): Tool {
117
+ const dispatch = this.dispatch.bind(this)
118
+ return {
119
+ definition: {
120
+ name: 'tool',
121
+ description: `Invoke an extended tool. Use this for tools not in the direct-access core set.
122
+
123
+ The core tools are: read, edit, bash, glob, grep �?use them directly.
124
+ For everything else, call tool() with the tool name and its parameters.
125
+
126
+ Examples:
127
+ tool({ name: "git", params: { command: "status" } })
128
+ tool({ name: "ls", params: { path: "src" } })
129
+ tool({ name: "find", params: { pattern: "*.ts" } })
130
+ tool({ name: "fetch", params: { url: "https://example.com" } })`,
131
+ parameters: {
132
+ name: {
133
+ type: 'string',
134
+ description: 'The extended tool name to invoke',
135
+ required: true,
136
+ },
137
+ params: {
138
+ type: 'object',
139
+ description: 'Tool-specific parameters as a JSON object',
140
+ required: true,
141
+ },
142
+ },
143
+ },
144
+ async execute(input) {
145
+ const name = input.name as string | undefined
146
+ if (!name || typeof name !== 'string') {
147
+ return { success: false, output: '', error: 'tool() requires a "name" field (string)' }
148
+ }
149
+ if (name === 'tool') {
150
+ return { success: false, output: '', error: 'Cannot call tool() recursively' }
151
+ }
152
+ const call: ToolCall = {
153
+ id: `gateway-${Date.now()}`,
154
+ name,
155
+ input: (input.params || {}) as Record<string, unknown>,
156
+ }
157
+ return dispatch(call)
158
+ },
159
+ }
160
+ }
161
+
108
162
  /** Register all built-in tools */
109
163
  private registerBuiltins(): void {
110
- // ask mode: only fetch and search + exec (exec works with any toolset)
164
+ // Register the gateway tool first so it's always available
165
+ this.register(this.gatewayTool)
166
+
167
+ // ask mode: only fetch and search
111
168
  if (this.context.mode === 'ask') {
112
169
  this.register(fetchTool)
113
170
  this.register(searchTool)
@@ -122,56 +179,54 @@ export class ToolRegistry {
122
179
  this.register(fetchTool)
123
180
  this.register(searchTool)
124
181
 
125
- if (this.context.mode === 'code') {
126
- // Code mode: full toolset including write operations
182
+ if (this.context.mode === 'code' || this.context.mode === 'loop') {
183
+ // Code/Loop mode: full toolset including write operations
127
184
  this.register(bashTool)
128
185
  this.register(createGitTool(this.context.cwd))
129
186
  this.register(createInstallSkillTool(this.context.cwd))
130
187
  this.register(createEditTool(this.context.applier, this.context.cwd))
131
- this.registerExecTool()
188
+ // Register save_memory tool (simple on-disk writer)
189
+ try {
190
+ this.register(createSaveMemoryTool(this.context.cwd))
191
+ this.register(createListMemoryTool(this.context.cwd))
192
+ this.register(createDeleteMemoryTool(this.context.cwd))
193
+ } catch (err) {
194
+ // If for some reason the tool can't be created, ignore — not critical
195
+ console.error('[ToolRegistry] Failed to register memory tools:', err)
196
+ }
197
+ // Register AST tools (ast_query, ast_edit)
198
+ for (const tool of createAstTools()) {
199
+ this.register(tool)
200
+ }
201
+
202
+ // Register task_complete tool so the model can explicitly signal completion
203
+ // (most useful in loop mode, but available in code mode too)
204
+ this.register(taskCompleteTool)
132
205
  } else {
133
206
  // Plan mode: read-only investigation + write_plan
134
207
  this.register(createWritePlanTool(this.context.cwd, this.context.onPlanWritten))
135
208
  }
136
209
  }
137
210
 
138
- /** Register the exec tool with dynamic type declarations for all registered tools */
139
- private registerExecTool(): void {
140
- const execTool = createExecTool(() => Array.from(this.tools.values()))
141
- this.execTool = execTool
142
- this.register(execTool)
143
- }
144
-
145
- /** Refresh the exec tool's description to include current tool type declarations */
146
- private refreshExecDescription(): void {
147
- if (this.execTool) {
148
- updateExecToolDefinition(this.execTool, this.getDefinitions())
149
- }
150
- }
151
-
152
- setMode(mode: 'code' | 'plan' | 'ask'): void {
211
+ setMode(mode: 'code' | 'plan' | 'ask' | 'loop'): void {
153
212
  // Update context.mode FIRST so registerBuiltins() and mode-based logic
154
213
  // use the NEW mode, not the stale one (fixes bug when switching from
155
214
  // ask→code or plan→code where all tools would be missing)
156
215
  this.context.mode = mode
157
216
 
158
- if (mode === 'code') {
159
- // Re-register all built-in tools for code mode
217
+ if (mode === 'code' || mode === 'loop') {
218
+ // Code/Loop mode: Re-register all built-in tools for full toolset
160
219
  this.tools.clear()
161
- this.execTool = null
162
220
  this.registerBuiltins()
163
221
  } else if (mode === 'plan') {
164
- // Keep existing tools but swap edit/write_plan, remove exec
222
+ // Keep existing tools but swap edit/write_plan
165
223
  if (!this.tools.has('write_plan')) {
166
224
  this.register(createWritePlanTool(this.context.cwd, this.context.onPlanWritten))
167
225
  }
168
226
  this.tools.delete('edit')
169
- this.tools.delete('exec')
170
- this.execTool = null
171
227
  } else if (mode === 'ask') {
172
228
  // Ask mode: only fetch and search
173
229
  this.tools.clear()
174
- this.execTool = null
175
230
  this.register(fetchTool)
176
231
  this.register(searchTool)
177
232
  }
@@ -180,10 +235,6 @@ export class ToolRegistry {
180
235
  /** Register a single tool */
181
236
  register(tool: Tool): void {
182
237
  this.tools.set(tool.definition.name, tool)
183
- // Refresh exec tool description to include the new tool's type declarations
184
- if (this.execTool && tool.definition.name !== 'exec') {
185
- this.refreshExecDescription()
186
- }
187
238
  }
188
239
 
189
240
  /** Register a tool plugin (lazy creation pattern) */
@@ -228,6 +279,26 @@ export class ToolRegistry {
228
279
  return Array.from(this.tools.values()).map(t => t.definition)
229
280
  }
230
281
 
282
+ /** Get definitions for the core tool set + gateway (for LLM API's tools parameter) */
283
+ getCoreDefinitions(): ToolDefinition[] {
284
+ // Ask mode has only 2 tools �?pass them directly, no gateway needed
285
+ if (this.context.mode === 'ask') {
286
+ return Array.from(this.tools.values())
287
+ .filter(t => t.definition.name !== 'tool')
288
+ .map(t => t.definition)
289
+ }
290
+
291
+ const core: ToolDefinition[] = []
292
+ for (const [name, tool] of this.tools) {
293
+ if (CORE_TOOL_NAMES.has(name)) {
294
+ core.push(tool.definition)
295
+ }
296
+ }
297
+ // Always include the gateway tool so the model can reach extended tools
298
+ core.push(this.gatewayTool.definition)
299
+ return core
300
+ }
301
+
231
302
  async dispatch(call: ToolCall): Promise<ToolResult> {
232
303
  const tool = this.tools.get(call.name)
233
304
  if (!tool) {
@@ -0,0 +1,103 @@
1
+ import type { ToolDefinition, ToolTreeNode } from './types.js'
2
+
3
+ function normalizeLabel(value: string | undefined, fallback: string): string {
4
+ const trimmed = value?.trim()
5
+ return trimmed && trimmed !== 'Unclassified' ? trimmed : fallback
6
+ }
7
+
8
+ function createToolNode(def: ToolDefinition, depth: number): ToolTreeNode {
9
+ return {
10
+ type: 'tool',
11
+ name: def.name,
12
+ description: def.description,
13
+ toolName: def.name,
14
+ depth,
15
+ }
16
+ }
17
+
18
+ export function buildToolTree(definitions: ToolDefinition[]): ToolTreeNode[] {
19
+ const root: ToolTreeNode[] = []
20
+ const groups = new Map<string, ToolTreeNode>()
21
+
22
+ function getOrCreate(parts: string[], depth: number): ToolTreeNode {
23
+ const key = parts.join('/')
24
+ let node = groups.get(key)
25
+ if (!node) {
26
+ node = {
27
+ type: 'group',
28
+ name: parts[parts.length - 1] || 'Other',
29
+ children: [],
30
+ depth,
31
+ }
32
+ groups.set(key, node)
33
+
34
+ if (parts.length === 1) {
35
+ root.push(node)
36
+ } else {
37
+ const parent = groups.get(parts.slice(0, -1).join('/'))
38
+ parent?.children?.push(node)
39
+ }
40
+ }
41
+ return node
42
+ }
43
+
44
+ for (const def of definitions) {
45
+ const category = normalizeLabel(def.category, 'Other')
46
+ const rawGroup = normalizeLabel(def.group, 'Unclassified')
47
+
48
+ // Build path: category first, then split group by '/' for multi-level nesting
49
+ const parts = [category]
50
+ if (rawGroup && rawGroup !== 'Unclassified') {
51
+ parts.push(
52
+ ...rawGroup
53
+ .split('/')
54
+ .map(p => p.trim())
55
+ .filter(Boolean),
56
+ )
57
+ }
58
+
59
+ // Create all intermediate group nodes (parents before children)
60
+ for (let i = 1; i <= parts.length; i++) {
61
+ const node = getOrCreate(parts.slice(0, i), i - 1)
62
+ if (i === parts.length) {
63
+ node.children?.push(createToolNode(def, i))
64
+ }
65
+ }
66
+ }
67
+
68
+ return root
69
+ }
70
+
71
+ /**
72
+ * Format the tool tree for inclusion in the system prompt.
73
+ *
74
+ * @param definitions - All tool definitions (for building the full tree)
75
+ * @param coreNames - Optional set of core tool names. When provided, tools NOT
76
+ * in this set are annotated with "(via tool)" to indicate they require the
77
+ * `tool()` gateway.
78
+ */
79
+ export function formatToolTreeForPrompt(
80
+ definitions: ToolDefinition[],
81
+ coreNames?: Set<string>,
82
+ ): string {
83
+ const lines: string[] = []
84
+
85
+ function render(node: ToolTreeNode, level: number): void {
86
+ const indent = ' '.repeat(level)
87
+ if (node.type === 'group') {
88
+ lines.push(`${indent}- ${node.name}`)
89
+ } else {
90
+ const suffix = coreNames && !coreNames.has(node.name) ? ' (via tool gateway)' : ''
91
+ lines.push(`${indent}- \`${node.name}\`: ${node.description || ''}${suffix}`)
92
+ }
93
+ for (const child of node.children || []) {
94
+ render(child, level + 1)
95
+ }
96
+ }
97
+
98
+ for (const node of buildToolTree(definitions)) {
99
+ render(node, 0)
100
+ }
101
+
102
+ return lines.join('\n')
103
+ }
@@ -9,6 +9,10 @@ export interface ToolDefinition {
9
9
  name: string
10
10
  description: string
11
11
  parameters: Record<string, ToolParameter>
12
+ /** Top-level category used for hierarchical tool trees, e.g. "File I/O". */
13
+ category?: string
14
+ /** Second-level group used for hierarchical tool trees, e.g. "Read". */
15
+ group?: string
12
16
  }
13
17
 
14
18
  export interface ToolCall {
@@ -27,3 +31,12 @@ export interface Tool {
27
31
  definition: ToolDefinition
28
32
  execute(input: Record<string, unknown>): Promise<ToolResult>
29
33
  }
34
+
35
+ export interface ToolTreeNode {
36
+ type: 'group' | 'tool'
37
+ name: string
38
+ description?: string
39
+ children?: ToolTreeNode[]
40
+ toolName?: string
41
+ depth: number
42
+ }
@@ -1,9 +1,11 @@
1
- import { fmtErr } from './errors.js'
2
- import type { Tool, ToolResult } from './types.js'
1
+ import { fmtErr } from '../errors.js'
2
+ import type { Tool, ToolResult } from '../types.js'
3
3
 
4
4
  export const fetchTool: Tool = {
5
5
  definition: {
6
6
  name: 'fetch',
7
+ category: 'Web',
8
+ group: 'Fetch',
7
9
  description: 'Fetch content from a URL. Returns the response body as text.',
8
10
  parameters: {
9
11
  url: { type: 'string', description: 'URL to fetch', required: true },
@@ -1,8 +1,8 @@
1
1
  import * as fs from 'node:fs'
2
2
  import * as os from 'node:os'
3
3
  import * as path from 'node:path'
4
- import { fmtErr } from './errors.js'
5
- import type { Tool, ToolResult } from './types.js'
4
+ import { fmtErr } from '../errors.js'
5
+ import type { Tool, ToolResult } from '../types.js'
6
6
 
7
7
  interface TavilyConfig {
8
8
  tavilyApiKey?: string
@@ -30,6 +30,8 @@ const TAVILY_API_URL = 'https://api.tavily.com/search'
30
30
  export const searchTool: Tool = {
31
31
  definition: {
32
32
  name: 'search',
33
+ category: 'Web',
34
+ group: 'Search Engine',
33
35
  description:
34
36
  'Search the web using the Tavily search engine. Returns a summary answer and a list of relevant results with titles, URLs, and content snippets.',
35
37
  parameters: {
@@ -0,0 +1,135 @@
1
+ import type { CommandUI } from '../agent/commands.js'
2
+ import { dispatchCommand } from '../agent/commands.js'
3
+ import { fmtErr } from '../tools/errors.js'
4
+ import { colors } from './components/index.js'
5
+ import type { TuiContext } from './overlays.js'
6
+ import {
7
+ refreshBalance,
8
+ refreshPlans,
9
+ showHelpOverlay,
10
+ showPlansOverlay,
11
+ updateFooter,
12
+ } from './overlays.js'
13
+
14
+ export function handleConfirmInput(ctx: TuiContext, data: string): boolean {
15
+ if (!ctx.pendingConfirmResolve) return false
16
+ const key = data.trim().toLowerCase()
17
+ if (key === 'y' || key === 'yes') {
18
+ ctx.pendingConfirmResolve(true)
19
+ ctx.pendingConfirmResolve = null
20
+ ctx.chatContent += 'y\n'
21
+ ctx.chatMarkdown.setText(ctx.chatContent)
22
+ ctx.tui.requestRender(true)
23
+ return true
24
+ } else if (key === 'n' || key === 'no' || key === '\r' || key === '') {
25
+ ctx.pendingConfirmResolve(false)
26
+ ctx.pendingConfirmResolve = null
27
+ ctx.chatContent += 'N\n'
28
+ ctx.chatMarkdown.setText(ctx.chatContent)
29
+ ctx.tui.requestRender(true)
30
+ return true
31
+ }
32
+ return false
33
+ }
34
+
35
+ function makeCommandUI(ctx: TuiContext): CommandUI {
36
+ return {
37
+ write: (text: string) => {
38
+ ctx.chatContent += '\n' + text + '\n'
39
+ ctx.chatMarkdown.setText(ctx.chatContent)
40
+ },
41
+ replaceContent: (text: string) => {
42
+ ctx.chatContent = text
43
+ ctx.chatMarkdown.setText(text)
44
+ },
45
+ onStateChange: () => {
46
+ updateFooter(ctx)
47
+ },
48
+ onNewSession: (session: any) => {
49
+ ctx.session = session
50
+ ctx.session.onPlanWritten = ctx.planCb
51
+ ctx.plansList.clearFilter()
52
+ ;(ctx.editor as any).undoStack.clear()
53
+ ;(ctx.editor as any).history = []
54
+ ;(ctx.editor as any).killRing.ring = []
55
+ },
56
+ }
57
+ }
58
+
59
+ export async function sendMessage(ctx: TuiContext, text: string): Promise<void> {
60
+ const trimmed = text.trim()
61
+ if (!trimmed) return
62
+ ctx.editor.setText('')
63
+ ctx.editor.addToHistory(trimmed)
64
+
65
+ if (trimmed.startsWith('/')) {
66
+ const parts = trimmed.slice(1).split(/\s+/)
67
+ const cmd = parts[0]
68
+ const arg = parts.slice(1).join(' ')
69
+
70
+ // TUI-specific commands
71
+ if (cmd === 'exit' || cmd === 'quit') {
72
+ ctx.chatContent += `\n${colors.dim('Goodbye!')}\n`
73
+ ctx.chatMarkdown.setText(ctx.chatContent)
74
+ ctx.tui.stop()
75
+ process.exit(0)
76
+ return
77
+ }
78
+ if (cmd === 'plans') {
79
+ showPlansOverlay(ctx)
80
+ return
81
+ }
82
+ if (cmd === 'filter') {
83
+ ctx.plansList.setFilter(arg)
84
+ ctx.tui.requestRender(true)
85
+ return
86
+ }
87
+ if (cmd === 'help' || cmd === '?') {
88
+ showHelpOverlay(ctx)
89
+ return
90
+ }
91
+
92
+ // Shared commands
93
+ const ui = makeCommandUI(ctx)
94
+ const handled = await dispatchCommand(
95
+ { session: ctx.session, config: ctx.config, ui, isRunning: ctx.isRunning },
96
+ cmd,
97
+ arg,
98
+ )
99
+ if (handled) {
100
+ ctx.tui.requestRender(true)
101
+ return
102
+ }
103
+
104
+ ctx.chatContent += `\n${colors.error('\u2716')} Unknown command: /${cmd}. ${colors.dim('Type /help for available commands.')}\n`
105
+ ctx.chatMarkdown.setText(ctx.chatContent)
106
+ return
107
+ }
108
+
109
+ if (ctx.isRunning) return
110
+
111
+ ctx.isRunning = true
112
+ ctx.loader.setMessage('thinking...')
113
+ ctx.tui.setShowHardwareCursor(false)
114
+ updateFooter(ctx)
115
+
116
+ ctx.session
117
+ .chat(trimmed)
118
+ .then(() => {
119
+ ctx.isRunning = false
120
+ ctx.loader.setMessage('')
121
+ refreshPlans(ctx)
122
+ ctx.tui.setShowHardwareCursor(true)
123
+ updateFooter(ctx)
124
+ refreshBalance(ctx)
125
+ })
126
+ .catch((err: unknown) => {
127
+ ctx.isRunning = false
128
+ ctx.loader.setMessage('')
129
+ const errMsg = fmtErr(err)
130
+ ctx.chatContent += `\n${colors.error('\u2716 Error:')} ${errMsg}\n`
131
+ ctx.chatMarkdown.setText(ctx.chatContent)
132
+ ctx.tui.setShowHardwareCursor(true)
133
+ updateFooter(ctx)
134
+ })
135
+ }
@@ -0,0 +1,52 @@
1
+ import * as fs from 'node:fs'
2
+
3
+ function safeBg(text: string, bg: string): string {
4
+ return `\x1b[${bg}m${text.replace(/\x1b\[0m/g, `\x1b[0m\x1b[${bg}m`)}\x1b[0m`
5
+ }
6
+
7
+ export { safeBg }
8
+
9
+ export const colors = {
10
+ bgDark: (text: string) => safeBg(text, '48;2;30;30;30'),
11
+ bgDim: (text: string) => safeBg(text, '48;2;25;25;25'),
12
+ headerBg: (text: string) => safeBg(text, '48;2;170;170;170'),
13
+ separator: (text: string) => `\x1b[38;2;60;60;60m${text}\x1b[0m`,
14
+ statusBg: (text: string) => safeBg(text, '48;2;25;25;35'),
15
+ running: (text: string) => `\x1b[38;2;0;255;100m${text}\x1b[0m`,
16
+ idle: (text: string) => `\x1b[38;2;150;150;150m${text}\x1b[0m`,
17
+ doneTodo: (text: string) => `\x1b[38;2;100;200;100m${text}\x1b[0m`,
18
+ todo: (text: string) => `\x1b[38;2;150;150;150m${text}\x1b[0m`,
19
+ accent: (text: string) => `\x1b[38;2;0;170;255m${text}\x1b[0m`,
20
+ dim: (text: string) => `\x1b[38;2;90;90;90m${text}\x1b[0m`,
21
+ userLabel: (text: string) => `\x1b[38;2;255;200;50m${text}\x1b[0m`,
22
+ assistantLabel: (text: string) => `\x1b[38;2;0;255;150m${text}\x1b[0m`,
23
+ error: (text: string) => `\x1b[38;2;255;80;80m${text}\x1b[0m`,
24
+ success: (text: string) => `\x1b[38;2;0;200;100m${text}\x1b[0m`,
25
+ inputPrompt: (text: string) => `\x1b[38;2;0;170;255m${text}\x1b[0m`,
26
+ warn: (text: string) => `\x1b[38;2;255;200;50m${text}\x1b[0m`,
27
+ }
28
+
29
+ const APP_VERSION: string = (() => {
30
+ try {
31
+ const pkgPath = new URL('../../package.json', import.meta.url)
32
+ const raw = fs.readFileSync(pkgPath, 'utf-8')
33
+ return JSON.parse(raw).version || '0.1.0'
34
+ } catch {
35
+ return '0.1.0'
36
+ }
37
+ })()
38
+
39
+ export { APP_VERSION }
40
+
41
+ export const landingColors = {
42
+ inputBg: '\x1b[48;2;35;35;35m',
43
+ inputBorder: '\x1b[38;2;60;60;60m',
44
+ cyanBar: '\x1b[38;2;0;200;255m',
45
+ placeholderDim: '\x1b[38;2;130;130;130m',
46
+ placeholderQuote: '\x1b[38;2;160;160;160m',
47
+ inputText: '\x1b[38;2;220;220;220m',
48
+ statusBg: '\x1b[48;2;18;18;18m',
49
+ statusText: '\x1b[38;2;110;110;110m',
50
+ statusAccent: '\x1b[38;2;0;170;255m',
51
+ reset: '\x1b[0m',
52
+ }