lonny-agent 0.2.6 → 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 (475) hide show
  1. package/.github/workflows/ci.yml +21 -0
  2. package/AGENTS.md +106 -0
  3. package/CHANGELOG.md +24 -0
  4. package/dist/agent/__tests__/session-restore.test.d.ts +2 -0
  5. package/dist/agent/__tests__/session-restore.test.d.ts.map +1 -0
  6. package/dist/agent/__tests__/session-restore.test.js +260 -0
  7. package/dist/agent/__tests__/session-restore.test.js.map +1 -0
  8. package/dist/agent/commands.d.ts +26 -0
  9. package/dist/agent/commands.d.ts.map +1 -0
  10. package/dist/agent/commands.js +253 -0
  11. package/dist/agent/commands.js.map +1 -0
  12. package/dist/agent/compaction.js +8 -1
  13. package/dist/agent/compaction.js.map +1 -1
  14. package/dist/agent/index.d.ts +2 -1
  15. package/dist/agent/index.d.ts.map +1 -1
  16. package/dist/agent/index.js +2 -2
  17. package/dist/agent/index.js.map +1 -1
  18. package/dist/agent/memory.d.ts +12 -0
  19. package/dist/agent/memory.d.ts.map +1 -0
  20. package/dist/agent/memory.js +51 -0
  21. package/dist/agent/memory.js.map +1 -0
  22. package/dist/agent/prompt-builder.d.ts +6 -1
  23. package/dist/agent/prompt-builder.d.ts.map +1 -1
  24. package/dist/agent/prompt-builder.js +89 -26
  25. package/dist/agent/prompt-builder.js.map +1 -1
  26. package/dist/agent/providers/openai.d.ts +1 -0
  27. package/dist/agent/providers/openai.d.ts.map +1 -1
  28. package/dist/agent/providers/openai.js +16 -3
  29. package/dist/agent/providers/openai.js.map +1 -1
  30. package/dist/agent/session-chat.d.ts +3 -0
  31. package/dist/agent/session-chat.d.ts.map +1 -0
  32. package/dist/agent/session-chat.js +384 -0
  33. package/dist/agent/session-chat.js.map +1 -0
  34. package/dist/agent/session-display.d.ts +29 -0
  35. package/dist/agent/session-display.d.ts.map +1 -0
  36. package/dist/agent/session-display.js +179 -0
  37. package/dist/agent/session-display.js.map +1 -0
  38. package/dist/agent/session-persistence.d.ts +55 -0
  39. package/dist/agent/session-persistence.d.ts.map +1 -0
  40. package/dist/agent/session-persistence.js +101 -0
  41. package/dist/agent/session-persistence.js.map +1 -0
  42. package/dist/agent/session-utils.d.ts +5 -0
  43. package/dist/agent/session-utils.d.ts.map +1 -0
  44. package/dist/agent/session-utils.js +51 -0
  45. package/dist/agent/session-utils.js.map +1 -0
  46. package/dist/agent/session.d.ts +15 -17
  47. package/dist/agent/session.d.ts.map +1 -1
  48. package/dist/agent/session.js +226 -608
  49. package/dist/agent/session.js.map +1 -1
  50. package/dist/cli/index.d.ts +4 -0
  51. package/dist/cli/index.d.ts.map +1 -1
  52. package/dist/cli/index.js +67 -2
  53. package/dist/cli/index.js.map +1 -1
  54. package/dist/config/index.d.ts +2 -2
  55. package/dist/config/index.d.ts.map +1 -1
  56. package/dist/index.js +24 -3
  57. package/dist/index.js.map +1 -1
  58. package/dist/tools/__tests__/bash.test.js +168 -1
  59. package/dist/tools/__tests__/bash.test.js.map +1 -1
  60. package/dist/tools/__tests__/edit.test.js +253 -6
  61. package/dist/tools/__tests__/edit.test.js.map +1 -1
  62. package/dist/tools/__tests__/fetch.test.js +1 -1
  63. package/dist/tools/__tests__/fetch.test.js.map +1 -1
  64. package/dist/tools/__tests__/glob.test.js +1 -1
  65. package/dist/tools/__tests__/glob.test.js.map +1 -1
  66. package/dist/tools/__tests__/grep.test.js +1 -1
  67. package/dist/tools/__tests__/grep.test.js.map +1 -1
  68. package/dist/tools/__tests__/ls.test.js +1 -1
  69. package/dist/tools/__tests__/ls.test.js.map +1 -1
  70. package/dist/tools/__tests__/read.test.js +1 -1
  71. package/dist/tools/__tests__/read.test.js.map +1 -1
  72. package/dist/tools/__tests__/registry.test.js +313 -0
  73. package/dist/tools/__tests__/registry.test.js.map +1 -1
  74. package/dist/tools/__tests__/write_plan.test.js +1 -1
  75. package/dist/tools/__tests__/write_plan.test.js.map +1 -1
  76. package/dist/tools/bash.d.ts.map +1 -1
  77. package/dist/tools/bash.js +659 -39
  78. package/dist/tools/bash.js.map +1 -1
  79. package/dist/tools/codebase/ast/__tests__/ast-edit-demo.d.ts +2 -0
  80. package/dist/tools/codebase/ast/__tests__/ast-edit-demo.d.ts.map +1 -0
  81. package/dist/tools/codebase/ast/__tests__/ast-edit-demo.js +7 -0
  82. package/dist/tools/codebase/ast/__tests__/ast-edit-demo.js.map +1 -0
  83. package/dist/tools/codebase/ast/__tests__/ast-edit-final.d.ts +6 -0
  84. package/dist/tools/codebase/ast/__tests__/ast-edit-final.d.ts.map +1 -0
  85. package/dist/tools/codebase/ast/__tests__/ast-edit-final.js +11 -0
  86. package/dist/tools/codebase/ast/__tests__/ast-edit-final.js.map +1 -0
  87. package/dist/tools/codebase/ast/__tests__/ast-edit-test.d.ts +2 -0
  88. package/dist/tools/codebase/ast/__tests__/ast-edit-test.d.ts.map +1 -0
  89. package/dist/tools/codebase/ast/__tests__/ast-edit-test.js +9 -0
  90. package/dist/tools/codebase/ast/__tests__/ast-edit-test.js.map +1 -0
  91. package/dist/tools/codebase/ast/__tests__/integration.test.d.ts +2 -0
  92. package/dist/tools/codebase/ast/__tests__/integration.test.d.ts.map +1 -0
  93. package/dist/tools/codebase/ast/__tests__/integration.test.js +415 -0
  94. package/dist/tools/codebase/ast/__tests__/integration.test.js.map +1 -0
  95. package/dist/tools/codebase/ast/__tests__/tree-sitter.test.d.ts +2 -0
  96. package/dist/tools/codebase/ast/__tests__/tree-sitter.test.d.ts.map +1 -0
  97. package/dist/tools/codebase/ast/__tests__/tree-sitter.test.js +414 -0
  98. package/dist/tools/codebase/ast/__tests__/tree-sitter.test.js.map +1 -0
  99. package/dist/tools/codebase/ast/adapter.d.ts +23 -0
  100. package/dist/tools/codebase/ast/adapter.d.ts.map +1 -0
  101. package/dist/tools/codebase/ast/adapter.js +11 -0
  102. package/dist/tools/codebase/ast/adapter.js.map +1 -0
  103. package/dist/tools/codebase/ast/tools.d.ts +3 -0
  104. package/dist/tools/codebase/ast/tools.d.ts.map +1 -0
  105. package/dist/tools/codebase/ast/tools.js +286 -0
  106. package/dist/tools/codebase/ast/tools.js.map +1 -0
  107. package/dist/tools/codebase/ast/tree-sitter-adapter.d.ts +3 -0
  108. package/dist/tools/codebase/ast/tree-sitter-adapter.d.ts.map +1 -0
  109. package/dist/tools/codebase/ast/tree-sitter-adapter.js +412 -0
  110. package/dist/tools/codebase/ast/tree-sitter-adapter.js.map +1 -0
  111. package/dist/tools/codebase/ast/tree-sitter-converters.d.ts +4 -0
  112. package/dist/tools/codebase/ast/tree-sitter-converters.d.ts.map +1 -0
  113. package/dist/tools/codebase/ast/tree-sitter-converters.js +447 -0
  114. package/dist/tools/codebase/ast/tree-sitter-converters.js.map +1 -0
  115. package/dist/tools/codebase/ast/types.d.ts +103 -0
  116. package/dist/tools/codebase/ast/types.d.ts.map +1 -0
  117. package/dist/tools/codebase/ast/types.js +2 -0
  118. package/dist/tools/codebase/ast/types.js.map +1 -0
  119. package/dist/tools/codebase/ast/wasm/tree-sitter-python.wasm +0 -0
  120. package/dist/tools/codebase/ast/wasm/tree-sitter-tsx.wasm +0 -0
  121. package/dist/tools/codebase/ast/wasm/tree-sitter-typescript.wasm +0 -0
  122. package/dist/tools/codebase/ast/wasm/tree-sitter.wasm +0 -0
  123. package/dist/tools/codebase/ast/wasm/web-tree-sitter.wasm +0 -0
  124. package/dist/tools/codebase/find.d.ts +3 -0
  125. package/dist/tools/codebase/find.d.ts.map +1 -0
  126. package/dist/tools/codebase/find.js +61 -0
  127. package/dist/tools/codebase/find.js.map +1 -0
  128. package/dist/tools/codebase/glob.d.ts +3 -0
  129. package/dist/tools/codebase/glob.d.ts.map +1 -0
  130. package/dist/tools/codebase/glob.js +37 -0
  131. package/dist/tools/codebase/glob.js.map +1 -0
  132. package/dist/tools/codebase/grep.d.ts +3 -0
  133. package/dist/tools/codebase/grep.d.ts.map +1 -0
  134. package/dist/tools/codebase/grep.js +169 -0
  135. package/dist/tools/codebase/grep.js.map +1 -0
  136. package/dist/tools/codebase/ls.d.ts +3 -0
  137. package/dist/tools/codebase/ls.d.ts.map +1 -0
  138. package/dist/tools/codebase/ls.js +39 -0
  139. package/dist/tools/codebase/ls.js.map +1 -0
  140. package/dist/tools/codebase/read.d.ts +10 -0
  141. package/dist/tools/codebase/read.d.ts.map +1 -0
  142. package/dist/tools/codebase/read.js +81 -0
  143. package/dist/tools/codebase/read.js.map +1 -0
  144. package/dist/tools/delete_memory.d.ts +3 -0
  145. package/dist/tools/delete_memory.d.ts.map +1 -0
  146. package/dist/tools/delete_memory.js +46 -0
  147. package/dist/tools/delete_memory.js.map +1 -0
  148. package/dist/tools/edit/diff-compute.d.ts +4 -0
  149. package/dist/tools/edit/diff-compute.d.ts.map +1 -0
  150. package/dist/tools/edit/diff-compute.js +18 -0
  151. package/dist/tools/edit/diff-compute.js.map +1 -0
  152. package/dist/tools/edit/diff-render.d.ts +18 -0
  153. package/dist/tools/edit/diff-render.d.ts.map +1 -0
  154. package/dist/tools/edit/diff-render.js +128 -0
  155. package/dist/tools/edit/diff-render.js.map +1 -0
  156. package/dist/tools/edit/edit.d.ts +4 -0
  157. package/dist/tools/edit/edit.d.ts.map +1 -0
  158. package/dist/tools/edit/edit.js +440 -0
  159. package/dist/tools/edit/edit.js.map +1 -0
  160. package/dist/tools/edit/matcher.d.ts +24 -0
  161. package/dist/tools/edit/matcher.d.ts.map +1 -0
  162. package/dist/tools/edit/matcher.js +66 -0
  163. package/dist/tools/edit/matcher.js.map +1 -0
  164. package/dist/tools/edit/parser.d.ts +10 -0
  165. package/dist/tools/edit/parser.d.ts.map +1 -0
  166. package/dist/tools/edit/parser.js +120 -0
  167. package/dist/tools/edit/parser.js.map +1 -0
  168. package/dist/tools/edit/types.d.ts +16 -0
  169. package/dist/tools/edit/types.d.ts.map +1 -0
  170. package/dist/tools/edit/types.js +2 -0
  171. package/dist/tools/edit/types.js.map +1 -0
  172. package/dist/tools/edit/write_plan.d.ts +5 -0
  173. package/dist/tools/edit/write_plan.d.ts.map +1 -0
  174. package/dist/tools/edit/write_plan.js +98 -0
  175. package/dist/tools/edit/write_plan.js.map +1 -0
  176. package/dist/tools/edit.d.ts.map +1 -1
  177. package/dist/tools/edit.js +66 -1
  178. package/dist/tools/edit.js.map +1 -1
  179. package/dist/tools/execute/bash/constants.d.ts +24 -0
  180. package/dist/tools/execute/bash/constants.d.ts.map +1 -0
  181. package/dist/tools/execute/bash/constants.js +88 -0
  182. package/dist/tools/execute/bash/constants.js.map +1 -0
  183. package/dist/tools/execute/bash/errors.d.ts +39 -0
  184. package/dist/tools/execute/bash/errors.d.ts.map +1 -0
  185. package/dist/tools/execute/bash/errors.js +249 -0
  186. package/dist/tools/execute/bash/errors.js.map +1 -0
  187. package/dist/tools/execute/bash/execution.d.ts +18 -0
  188. package/dist/tools/execute/bash/execution.d.ts.map +1 -0
  189. package/dist/tools/execute/bash/execution.js +207 -0
  190. package/dist/tools/execute/bash/execution.js.map +1 -0
  191. package/dist/tools/execute/bash/index.d.ts +3 -0
  192. package/dist/tools/execute/bash/index.d.ts.map +1 -0
  193. package/dist/tools/execute/bash/index.js +117 -0
  194. package/dist/tools/execute/bash/index.js.map +1 -0
  195. package/dist/tools/execute/bash/platform.d.ts +6 -0
  196. package/dist/tools/execute/bash/platform.d.ts.map +1 -0
  197. package/dist/tools/execute/bash/platform.js +64 -0
  198. package/dist/tools/execute/bash/platform.js.map +1 -0
  199. package/dist/tools/execute/bash/security.d.ts +12 -0
  200. package/dist/tools/execute/bash/security.d.ts.map +1 -0
  201. package/dist/tools/execute/bash/security.js +26 -0
  202. package/dist/tools/execute/bash/security.js.map +1 -0
  203. package/dist/tools/execute/bash/validation.d.ts +16 -0
  204. package/dist/tools/execute/bash/validation.d.ts.map +1 -0
  205. package/dist/tools/execute/bash/validation.js +57 -0
  206. package/dist/tools/execute/bash/validation.js.map +1 -0
  207. package/dist/tools/execute/bash.d.ts +3 -0
  208. package/dist/tools/execute/bash.d.ts.map +1 -0
  209. package/dist/tools/execute/bash.js +728 -0
  210. package/dist/tools/execute/bash.js.map +1 -0
  211. package/dist/tools/execute/git.d.ts +3 -0
  212. package/dist/tools/execute/git.d.ts.map +1 -0
  213. package/dist/tools/execute/git.js +183 -0
  214. package/dist/tools/execute/git.js.map +1 -0
  215. package/dist/tools/execute/task_complete.d.ts +7 -0
  216. package/dist/tools/execute/task_complete.d.ts.map +1 -0
  217. package/dist/tools/execute/task_complete.js +38 -0
  218. package/dist/tools/execute/task_complete.js.map +1 -0
  219. package/dist/tools/fetch.d.ts.map +1 -1
  220. package/dist/tools/fetch.js +2 -0
  221. package/dist/tools/fetch.js.map +1 -1
  222. package/dist/tools/find.d.ts.map +1 -1
  223. package/dist/tools/find.js +2 -0
  224. package/dist/tools/find.js.map +1 -1
  225. package/dist/tools/git.d.ts.map +1 -1
  226. package/dist/tools/git.js +2 -0
  227. package/dist/tools/git.js.map +1 -1
  228. package/dist/tools/glob.d.ts.map +1 -1
  229. package/dist/tools/glob.js +2 -0
  230. package/dist/tools/glob.js.map +1 -1
  231. package/dist/tools/grep.d.ts.map +1 -1
  232. package/dist/tools/grep.js +2 -0
  233. package/dist/tools/grep.js.map +1 -1
  234. package/dist/tools/install/clawhub.d.ts +26 -0
  235. package/dist/tools/install/clawhub.d.ts.map +1 -0
  236. package/dist/tools/install/clawhub.js +182 -0
  237. package/dist/tools/install/clawhub.js.map +1 -0
  238. package/dist/tools/install/constants.d.ts +5 -0
  239. package/dist/tools/install/constants.d.ts.map +1 -0
  240. package/dist/tools/install/constants.js +5 -0
  241. package/dist/tools/install/constants.js.map +1 -0
  242. package/dist/tools/install/install_skill.d.ts +3 -0
  243. package/dist/tools/install/install_skill.d.ts.map +1 -0
  244. package/dist/tools/install/install_skill.js +132 -0
  245. package/dist/tools/install/install_skill.js.map +1 -0
  246. package/dist/tools/install/npm.d.ts +8 -0
  247. package/dist/tools/install/npm.d.ts.map +1 -0
  248. package/dist/tools/install/npm.js +52 -0
  249. package/dist/tools/install/npm.js.map +1 -0
  250. package/dist/tools/install/skill-content.d.ts +9 -0
  251. package/dist/tools/install/skill-content.d.ts.map +1 -0
  252. package/dist/tools/install/skill-content.js +89 -0
  253. package/dist/tools/install/skill-content.js.map +1 -0
  254. package/dist/tools/install_skill.d.ts.map +1 -1
  255. package/dist/tools/install_skill.js +2 -0
  256. package/dist/tools/install_skill.js.map +1 -1
  257. package/dist/tools/list_memory.d.ts +3 -0
  258. package/dist/tools/list_memory.d.ts.map +1 -0
  259. package/dist/tools/list_memory.js +55 -0
  260. package/dist/tools/list_memory.js.map +1 -0
  261. package/dist/tools/ls.d.ts.map +1 -1
  262. package/dist/tools/ls.js +2 -0
  263. package/dist/tools/ls.js.map +1 -1
  264. package/dist/tools/memory/delete_memory.d.ts +3 -0
  265. package/dist/tools/memory/delete_memory.d.ts.map +1 -0
  266. package/dist/tools/memory/delete_memory.js +46 -0
  267. package/dist/tools/memory/delete_memory.js.map +1 -0
  268. package/dist/tools/memory/list_memory.d.ts +3 -0
  269. package/dist/tools/memory/list_memory.d.ts.map +1 -0
  270. package/dist/tools/memory/list_memory.js +55 -0
  271. package/dist/tools/memory/list_memory.js.map +1 -0
  272. package/dist/tools/memory/save_memory.d.ts +3 -0
  273. package/dist/tools/memory/save_memory.d.ts.map +1 -0
  274. package/dist/tools/memory/save_memory.js +45 -0
  275. package/dist/tools/memory/save_memory.js.map +1 -0
  276. package/dist/tools/read.d.ts.map +1 -1
  277. package/dist/tools/read.js +2 -0
  278. package/dist/tools/read.js.map +1 -1
  279. package/dist/tools/registry.d.ts +7 -2
  280. package/dist/tools/registry.d.ts.map +1 -1
  281. package/dist/tools/registry.js +112 -17
  282. package/dist/tools/registry.js.map +1 -1
  283. package/dist/tools/save_memory.d.ts +3 -0
  284. package/dist/tools/save_memory.d.ts.map +1 -0
  285. package/dist/tools/save_memory.js +45 -0
  286. package/dist/tools/save_memory.js.map +1 -0
  287. package/dist/tools/search.d.ts.map +1 -1
  288. package/dist/tools/search.js +2 -0
  289. package/dist/tools/search.js.map +1 -1
  290. package/dist/tools/tree.d.ts +12 -0
  291. package/dist/tools/tree.d.ts.map +1 -0
  292. package/dist/tools/tree.js +87 -0
  293. package/dist/tools/tree.js.map +1 -0
  294. package/dist/tools/types.d.ts +12 -0
  295. package/dist/tools/types.d.ts.map +1 -1
  296. package/dist/tools/web/fetch.d.ts +3 -0
  297. package/dist/tools/web/fetch.d.ts.map +1 -0
  298. package/dist/tools/web/fetch.js +49 -0
  299. package/dist/tools/web/fetch.js.map +1 -0
  300. package/dist/tools/web/search.d.ts +3 -0
  301. package/dist/tools/web/search.d.ts.map +1 -0
  302. package/dist/tools/web/search.js +134 -0
  303. package/dist/tools/web/search.js.map +1 -0
  304. package/dist/tools/write_plan.d.ts.map +1 -1
  305. package/dist/tools/write_plan.js +2 -0
  306. package/dist/tools/write_plan.js.map +1 -1
  307. package/dist/tui/commands.d.ts +4 -0
  308. package/dist/tui/commands.d.ts.map +1 -0
  309. package/dist/tui/commands.js +118 -0
  310. package/dist/tui/commands.js.map +1 -0
  311. package/dist/tui/components/colors.d.ts +36 -0
  312. package/dist/tui/components/colors.d.ts.map +1 -0
  313. package/dist/tui/components/colors.js +48 -0
  314. package/dist/tui/components/colors.js.map +1 -0
  315. package/dist/tui/components/header-bar.d.ts +26 -0
  316. package/dist/tui/components/header-bar.d.ts.map +1 -0
  317. package/dist/tui/components/header-bar.js +78 -0
  318. package/dist/tui/components/header-bar.js.map +1 -0
  319. package/dist/tui/components/index.d.ts +9 -0
  320. package/dist/tui/components/index.d.ts.map +1 -0
  321. package/dist/tui/components/index.js +9 -0
  322. package/dist/tui/components/index.js.map +1 -0
  323. package/dist/tui/components/landing-screen.d.ts +12 -0
  324. package/dist/tui/components/landing-screen.d.ts.map +1 -0
  325. package/dist/tui/components/landing-screen.js +53 -0
  326. package/dist/tui/components/landing-screen.js.map +1 -0
  327. package/dist/tui/components/pixel-logo.d.ts +5 -0
  328. package/dist/tui/components/pixel-logo.d.ts.map +1 -0
  329. package/dist/tui/components/pixel-logo.js +27 -0
  330. package/dist/tui/components/pixel-logo.js.map +1 -0
  331. package/dist/tui/components/plan-utils.d.ts +11 -0
  332. package/dist/tui/components/plan-utils.d.ts.map +1 -0
  333. package/dist/tui/components/plan-utils.js +62 -0
  334. package/dist/tui/components/plan-utils.js.map +1 -0
  335. package/dist/tui/components/plans-list.d.ts +18 -0
  336. package/dist/tui/components/plans-list.d.ts.map +1 -0
  337. package/dist/tui/components/plans-list.js +46 -0
  338. package/dist/tui/components/plans-list.js.map +1 -0
  339. package/dist/tui/components/rich-footer.d.ts +29 -0
  340. package/dist/tui/components/rich-footer.d.ts.map +1 -0
  341. package/dist/tui/components/rich-footer.js +124 -0
  342. package/dist/tui/components/rich-footer.js.map +1 -0
  343. package/dist/tui/components/todo-panel.d.ts +14 -0
  344. package/dist/tui/components/todo-panel.d.ts.map +1 -0
  345. package/dist/tui/components/todo-panel.js +83 -0
  346. package/dist/tui/components/todo-panel.js.map +1 -0
  347. package/dist/tui/components.d.ts.map +1 -1
  348. package/dist/tui/components.js +14 -7
  349. package/dist/tui/components.js.map +1 -1
  350. package/dist/tui/index.d.ts +2 -1
  351. package/dist/tui/index.d.ts.map +1 -1
  352. package/dist/tui/index.js +99 -505
  353. package/dist/tui/index.js.map +1 -1
  354. package/dist/tui/overlays.d.ts +28 -0
  355. package/dist/tui/overlays.d.ts.map +1 -0
  356. package/dist/tui/overlays.js +154 -0
  357. package/dist/tui/overlays.js.map +1 -0
  358. package/dist/tui/themes.d.ts +5 -0
  359. package/dist/tui/themes.d.ts.map +1 -0
  360. package/dist/tui/themes.js +38 -0
  361. package/dist/tui/themes.js.map +1 -0
  362. package/dist/web/index.d.ts.map +1 -1
  363. package/dist/web/index.js +60 -122
  364. package/dist/web/index.js.map +1 -1
  365. package/dist/web/public/index.html +1 -1
  366. package/dist/web/public/messages.js +41 -25
  367. package/dist/web/public/state.js +72 -72
  368. package/dist/web/public/style.css +1126 -996
  369. package/dist/web/public/websocket.js +267 -267
  370. package/dist/web/session-bridge.d.ts.map +1 -1
  371. package/dist/web/session-bridge.js +82 -3
  372. package/dist/web/session-bridge.js.map +1 -1
  373. package/docs/ast-tools.md +117 -0
  374. package/package.json +60 -55
  375. package/scripts/check-line-count.mjs +53 -0
  376. package/scripts/copy-ast-wasm.mjs +32 -0
  377. package/src/agent/__tests__/session-restore.test.ts +284 -0
  378. package/src/agent/commands.ts +274 -0
  379. package/src/agent/compaction.ts +9 -2
  380. package/src/agent/index.ts +30 -25
  381. package/src/agent/memory.ts +60 -0
  382. package/src/agent/prompt-builder.ts +100 -26
  383. package/src/agent/providers/anthropic.ts +179 -179
  384. package/src/agent/providers/google.ts +210 -210
  385. package/src/agent/providers/ollama.ts +186 -186
  386. package/src/agent/providers/openai.ts +18 -3
  387. package/src/agent/session-chat.ts +480 -0
  388. package/src/agent/session-display.ts +195 -0
  389. package/src/agent/session-persistence.ts +146 -0
  390. package/src/agent/session-utils.ts +54 -0
  391. package/src/agent/session.ts +261 -718
  392. package/src/cli/index.ts +73 -4
  393. package/src/config/index.ts +342 -342
  394. package/src/index.ts +30 -3
  395. package/src/tools/__tests__/bash.test.ts +187 -1
  396. package/src/tools/__tests__/edit.test.ts +275 -11
  397. package/src/tools/__tests__/fetch.test.ts +1 -1
  398. package/src/tools/__tests__/glob.test.ts +1 -1
  399. package/src/tools/__tests__/grep.test.ts +1 -1
  400. package/src/tools/__tests__/ls.test.ts +1 -1
  401. package/src/tools/__tests__/read.test.ts +1 -1
  402. package/src/tools/__tests__/registry.test.ts +332 -0
  403. package/src/tools/__tests__/write_plan.test.ts +1 -1
  404. package/src/tools/codebase/ast/__tests__/integration.test.ts +452 -0
  405. package/src/tools/codebase/ast/__tests__/tree-sitter.test.ts +466 -0
  406. package/src/tools/codebase/ast/adapter.ts +44 -0
  407. package/src/tools/codebase/ast/tools.ts +322 -0
  408. package/src/tools/codebase/ast/tree-sitter-adapter.ts +468 -0
  409. package/src/tools/codebase/ast/tree-sitter-converters.ts +480 -0
  410. package/src/tools/codebase/ast/types.ts +102 -0
  411. package/src/tools/codebase/ast/wasm/tree-sitter-python.wasm +0 -0
  412. package/src/tools/codebase/ast/wasm/tree-sitter-tsx.wasm +0 -0
  413. package/src/tools/codebase/ast/wasm/tree-sitter-typescript.wasm +0 -0
  414. package/src/tools/codebase/ast/wasm/tree-sitter.wasm +0 -0
  415. package/src/tools/codebase/ast/wasm/web-tree-sitter.wasm +0 -0
  416. package/src/tools/{find.ts → codebase/find.ts} +4 -2
  417. package/src/tools/{glob.ts → codebase/glob.ts} +4 -2
  418. package/src/tools/{grep.ts → codebase/grep.ts} +4 -2
  419. package/src/tools/{ls.ts → codebase/ls.ts} +4 -2
  420. package/src/tools/{read.ts → codebase/read.ts} +5 -3
  421. package/src/tools/edit/diff-compute.ts +21 -0
  422. package/src/tools/edit/diff-render.ts +145 -0
  423. package/src/tools/edit/edit.ts +468 -0
  424. package/src/tools/edit/matcher.ts +70 -0
  425. package/src/tools/edit/parser.ts +131 -0
  426. package/src/tools/edit/types.ts +19 -0
  427. package/src/tools/{write_plan.ts → edit/write_plan.ts} +4 -2
  428. package/src/tools/execute/bash/constants.ts +93 -0
  429. package/src/tools/execute/bash/errors.ts +304 -0
  430. package/src/tools/execute/bash/execution.ts +211 -0
  431. package/src/tools/execute/bash/index.ts +131 -0
  432. package/src/tools/execute/bash/platform.ts +65 -0
  433. package/src/tools/execute/bash/security.ts +28 -0
  434. package/src/tools/execute/bash/validation.ts +78 -0
  435. package/src/tools/execute/git.ts +209 -0
  436. package/src/tools/execute/task_complete.ts +40 -0
  437. package/src/tools/install/clawhub.ts +222 -0
  438. package/src/tools/install/constants.ts +4 -0
  439. package/src/tools/install/install_skill.ts +150 -0
  440. package/src/tools/install/npm.ts +60 -0
  441. package/src/tools/install/skill-content.ts +108 -0
  442. package/src/tools/memory/delete_memory.ts +46 -0
  443. package/src/tools/memory/list_memory.ts +53 -0
  444. package/src/tools/memory/save_memory.ts +45 -0
  445. package/src/tools/registry.ts +119 -19
  446. package/src/tools/tree.ts +103 -0
  447. package/src/tools/types.ts +13 -0
  448. package/src/tools/{fetch.ts → web/fetch.ts} +4 -2
  449. package/src/tools/{search.ts → web/search.ts} +4 -2
  450. package/src/tui/commands.ts +135 -0
  451. package/src/tui/components/colors.ts +52 -0
  452. package/src/tui/components/header-bar.ts +88 -0
  453. package/src/tui/components/index.ts +8 -0
  454. package/src/tui/components/landing-screen.ts +67 -0
  455. package/src/tui/components/pixel-logo.ts +33 -0
  456. package/src/tui/components/plan-utils.ts +69 -0
  457. package/src/tui/components/plans-list.ts +55 -0
  458. package/src/tui/components/rich-footer.ts +146 -0
  459. package/src/tui/components/todo-panel.ts +95 -0
  460. package/src/tui/index.ts +335 -786
  461. package/src/tui/overlays.ts +203 -0
  462. package/src/tui/themes.ts +41 -0
  463. package/src/web/index.ts +64 -127
  464. package/src/web/public/index.html +1 -1
  465. package/src/web/public/messages.js +41 -25
  466. package/src/web/public/state.js +72 -72
  467. package/src/web/public/style.css +1126 -996
  468. package/src/web/public/websocket.js +267 -267
  469. package/src/web/session-bridge.ts +272 -193
  470. package/AGENT.md +0 -99
  471. package/src/tools/bash.ts +0 -125
  472. package/src/tools/edit.ts +0 -747
  473. package/src/tools/git.ts +0 -76
  474. package/src/tools/install_skill.ts +0 -539
  475. package/src/tui/components.ts +0 -635
@@ -1,342 +1,342 @@
1
- import * as fs from 'node:fs'
2
- import * as os from 'node:os'
3
- import * as path from 'node:path'
4
-
5
- export interface Config {
6
- apiKey: string
7
- baseUrl?: string
8
- mode: 'code' | 'plan' | 'ask'
9
- provider: 'openai' | 'anthropic' | 'google' | 'ollama'
10
- model: string
11
- contextWindow: number
12
- cwd: string
13
- autoApprove: boolean
14
- thinking?: boolean
15
- reasoningEffort?: string
16
- enableCache?: boolean
17
- strictTools?: boolean
18
- temperature?: number
19
- maxTokens?: number
20
- tavilyApiKey?: string
21
- }
22
-
23
- /**
24
- * 模型上下文窗口大小映射表(基于 2026 年最新数据)
25
- * 单位:tokens
26
- */
27
- const MODEL_CONTEXT_WINDOWS: Record<string, number> = {
28
- // Doubao 系列
29
- 'doubao-seed-2.0-code': 256_000,
30
- 'doubao-seed-2.0-pro': 256_000,
31
- 'doubao-seed-2.0-lite': 256_000,
32
- 'doubao-seed-2.0-mini': 256_000,
33
- 'doubao-seed-2.0-code-preview-260215': 256_000,
34
- 'doubao-seed-1.8': 256_000,
35
- 'doubao-seed-1.6': 256_000,
36
-
37
- // DeepSeek 系列
38
- 'deepseek-v4-pro': 1_000_000,
39
- 'deepseek-v4-flash': 256_000,
40
- 'deepseek-v3.2': 160_000,
41
- 'deepseek-r1': 128_000,
42
- 'deepseek-chat': 128_000,
43
- 'deepseek-reasoner': 128_000,
44
-
45
- // Kimi 系列
46
- 'kimi-k2.5': 262_144,
47
- 'kimi-k2.6': 262_144,
48
- 'kimi-k2-thinking': 256_000,
49
-
50
- // MiniMax 系列
51
- 'minimax-m2.5': 200_000,
52
- 'minimax-m2.7': 200_000,
53
- 'minimax-m2': 205_000,
54
-
55
- // GLM 系列
56
- 'glm-5': 200_000,
57
- 'glm-5.1': 200_000,
58
- 'glm-4.7-flashx': 200_000,
59
- 'glm-4-flash': 128_000,
60
- 'glm-4': 128_000,
61
-
62
- // Qwen 系列
63
- 'qwen3.6-plus': 1_000_000,
64
- 'qwen3.7-max': 1_000_000,
65
- 'qwen3-max': 256_000,
66
- 'qwen3.5-plus': 1_000_000,
67
- 'qwen-flash': 1_000_000,
68
-
69
- // Claude 系列
70
- 'claude-opus-4.7': 1_000_000,
71
- 'claude-opus-4.6': 1_000_000,
72
- 'claude-sonnet-4.6': 1_000_000,
73
- 'claude-haiku-4.5': 200_000,
74
-
75
- // GPT 系列
76
- 'gpt-5.5': 1_000_000,
77
- 'gpt-5.4': 1_000_000,
78
- 'gpt-5.1': 1_000_000,
79
- 'gpt-5.2-codex': 512_000,
80
- 'gpt-4.1': 1_000_000,
81
- 'gpt-4.1-mini': 1_000_000,
82
- 'gpt-4o': 128_000,
83
- 'gpt-4': 128_000,
84
-
85
- // Gemini 系列
86
- 'gemini-2.5-pro': 1_000_000,
87
- 'gemini-2.5-flash': 1_000_000,
88
- 'gemini-3.1-pro': 1_000_000,
89
- 'gemini-3.1-flash': 1_000_000,
90
-
91
- // Llama 系列
92
- 'llama-4-maverick': 1_000_000,
93
- 'llama-4-scout': 10_000_000,
94
- 'llama-3.1': 128_000,
95
- 'llama-3': 128_000,
96
-
97
- // Mistral 系列
98
- 'mistral-small-3.1': 128_000,
99
- 'mistral-small-3.2': 128_000,
100
- }
101
-
102
- /**
103
- * 模糊匹配规则
104
- */
105
- interface FuzzyMatchRule {
106
- keywords: string[]
107
- windowSize: number
108
- }
109
-
110
- /**
111
- * 模糊匹配规则列表(从高优先级到低优先级)
112
- */
113
- const fuzzyMatchRules: FuzzyMatchRule[] = [
114
- // 首先匹配 128K 模型(防止 gpt-4 匹配到 gpt-5 规则)
115
- {
116
- keywords: [
117
- 'gpt-4o',
118
- 'gpt 4o',
119
- 'gpt-4',
120
- 'gpt 4',
121
- 'llama-3',
122
- 'llama 3',
123
- 'mistral-small',
124
- 'mistral small',
125
- 'glm-4-flash',
126
- 'glm 4 flash',
127
- 'glm-4',
128
- ],
129
- windowSize: 128_000,
130
- },
131
- // 百万上下文模型 - 更高优先级(更精确的关键词)
132
- {
133
- keywords: [
134
- 'deepseek-v4',
135
- 'deepseek v4',
136
- 'qwen3.6',
137
- 'qwen 3.6',
138
- 'qwen3.7',
139
- 'qwen 3.7',
140
- 'qwen3.5',
141
- 'qwen 3.5',
142
- 'qwen-flash',
143
- 'qwen flash',
144
- ],
145
- windowSize: 1_000_000,
146
- },
147
- {
148
- keywords: [
149
- 'claude-opus',
150
- 'claude sonnet',
151
- 'claude-sonnet',
152
- 'gpt-5.',
153
- 'gpt 5',
154
- 'gpt-4.1',
155
- 'gpt 4.1',
156
- 'gemini-2.5',
157
- 'gemini 2.5',
158
- 'gemini-3.1',
159
- 'gemini 3.1',
160
- 'llama-4',
161
- 'llama 4',
162
- ],
163
- windowSize: 1_000_000,
164
- },
165
- // 256K 上下文模型
166
- {
167
- keywords: [
168
- 'doubao-seed-2.0',
169
- 'doubao seed 2.0',
170
- 'doubao-seed-1',
171
- 'doubao seed 1',
172
- 'kimi-k2',
173
- 'kimi k2',
174
- 'kimi-k2.5',
175
- 'kimi k2.5',
176
- 'kimi-k2.6',
177
- 'kimi k2.6',
178
- 'qwen3',
179
- 'qwen 3',
180
- 'qwen3-max',
181
- 'qwen3 max',
182
- ],
183
- windowSize: 256_000,
184
- },
185
- // 200K 上下文模型
186
- {
187
- keywords: [
188
- 'minimax',
189
- 'glm-5',
190
- 'glm 5',
191
- 'glm-5.1',
192
- 'glm 5.1',
193
- 'glm-4.7',
194
- 'glm 4.7',
195
- 'claude-haiku',
196
- 'claude haiku',
197
- ],
198
- windowSize: 200_000,
199
- },
200
- // 160K 上下文模型
201
- {
202
- keywords: ['deepseek-v3', 'deepseek v3', 'deepseek-v3.2', 'deepseek v3.2'],
203
- windowSize: 160_000,
204
- },
205
- // 最后匹配通用关键词(deepseek)
206
- {
207
- keywords: ['deepseek'],
208
- windowSize: 128_000,
209
- },
210
- ]
211
-
212
- /**
213
- * 根据模型名称获取上下文窗口大小(改进的模糊匹配)
214
- * @param modelName 模型名称(不区分大小写)
215
- * @returns 上下文窗口大小(tokens)
216
- */
217
- export function getContextWindowForModel(modelName: string): number {
218
- // 处理空字符串
219
- if (!modelName) {
220
- return 128_000
221
- }
222
-
223
- const normalizedModelName = modelName.toLowerCase().replace(/[-_]/g, ' ')
224
-
225
- // 1. 精确匹配(原始键名)
226
- if (MODEL_CONTEXT_WINDOWS[modelName]) {
227
- return MODEL_CONTEXT_WINDOWS[modelName]
228
- }
229
-
230
- // 2. 精确匹配(小写键名)
231
- if (MODEL_CONTEXT_WINDOWS[modelName.toLowerCase()]) {
232
- return MODEL_CONTEXT_WINDOWS[modelName.toLowerCase()]
233
- }
234
-
235
- // 3. 前缀匹配(支持部分匹配)
236
- for (const [pattern, size] of Object.entries(MODEL_CONTEXT_WINDOWS)) {
237
- const normalizedPattern = pattern.toLowerCase().replace(/[-_]/g, ' ')
238
- if (
239
- normalizedModelName.includes(normalizedPattern) ||
240
- normalizedPattern.includes(normalizedModelName)
241
- ) {
242
- return size
243
- }
244
- }
245
-
246
- // 4. 模糊匹配(关键词匹配)- 按照规则顺序(优先级)处理
247
- for (const rule of fuzzyMatchRules) {
248
- for (const keyword of rule.keywords) {
249
- const normalizedKeyword = keyword.toLowerCase().replace(/[-_]/g, ' ')
250
- if (normalizedModelName.includes(normalizedKeyword)) {
251
- return rule.windowSize
252
- }
253
- }
254
- }
255
-
256
- // 5. 兜底默认值
257
- return 128_000
258
- }
259
-
260
- interface JsonConfig {
261
- apiKey?: string
262
- baseUrl?: string
263
- provider?: string
264
- model?: string
265
- thinking?: boolean
266
- reasoningEffort?: string
267
- autoApprove?: boolean
268
- enableCache?: boolean
269
- strictTools?: boolean
270
- contextWindow?: number
271
- temperature?: number
272
- maxTokens?: number
273
- tavilyApiKey?: string
274
- }
275
-
276
- let cachedJsonConfig: JsonConfig | null = null
277
-
278
- function loadJsonConfig(): JsonConfig {
279
- if (cachedJsonConfig) return cachedJsonConfig
280
- const configPath = path.join(os.homedir(), '.lonny', 'config.json')
281
- try {
282
- const raw = fs.readFileSync(configPath, 'utf-8')
283
- cachedJsonConfig = JSON.parse(raw) as JsonConfig
284
- return cachedJsonConfig
285
- } catch {
286
- cachedJsonConfig = {}
287
- return cachedJsonConfig
288
- }
289
- }
290
-
291
- function saveJsonConfig(config: JsonConfig): void {
292
- const configPath = path.join(os.homedir(), '.lonny', 'config.json')
293
- fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8')
294
- cachedJsonConfig = config
295
- }
296
-
297
- /** Check if the model is a DeepSeek model (supports enable_cache). */
298
- function isDeepSeekModel(model: string, baseUrl?: string): boolean {
299
- if (/deepseek/i.test(model)) return true
300
- if (baseUrl && /deepseek/i.test(baseUrl)) return true
301
- return false
302
- }
303
-
304
- export function loadConfig(options?: {
305
- mode?: 'code' | 'plan' | 'ask'
306
- autoApprove?: boolean
307
- cwd?: string
308
- }): Config {
309
- const jsonConfig = loadJsonConfig()
310
-
311
- const model = jsonConfig.model || 'deepseek-v4-flash'
312
- const baseUrl = process.env.LONNY_BASE_URL || jsonConfig.baseUrl || undefined
313
- const provider = (process.env.LONNY_PROVIDER || jsonConfig.provider || 'openai') as
314
- | 'openai'
315
- | 'anthropic'
316
- | 'google'
317
- | 'ollama'
318
-
319
- // Auto-enable cache for DeepSeek models unless explicitly disabled
320
- const enableCache = jsonConfig.enableCache ?? (isDeepSeekModel(model, baseUrl) || undefined)
321
-
322
- // 根据模型名称获取上下文窗口大小,如果配置中有则优先使用配置值
323
- const contextWindow = jsonConfig.contextWindow || getContextWindowForModel(model)
324
-
325
- return {
326
- apiKey: jsonConfig.apiKey || '',
327
- baseUrl,
328
- provider,
329
- mode: options?.mode || 'code',
330
- model,
331
- contextWindow,
332
- cwd: options?.cwd || process.cwd(),
333
- autoApprove: options?.autoApprove ?? jsonConfig.autoApprove ?? false,
334
- thinking: jsonConfig.thinking,
335
- reasoningEffort: jsonConfig.reasoningEffort,
336
- enableCache,
337
- strictTools: jsonConfig.strictTools,
338
- temperature: jsonConfig.temperature,
339
- maxTokens: jsonConfig.maxTokens,
340
- tavilyApiKey: jsonConfig.tavilyApiKey,
341
- }
342
- }
1
+ import * as fs from 'node:fs'
2
+ import * as os from 'node:os'
3
+ import * as path from 'node:path'
4
+
5
+ export interface Config {
6
+ apiKey: string
7
+ baseUrl?: string
8
+ mode: 'code' | 'plan' | 'ask' | 'loop'
9
+ provider: 'openai' | 'anthropic' | 'google' | 'ollama'
10
+ model: string
11
+ contextWindow: number
12
+ cwd: string
13
+ autoApprove: boolean
14
+ thinking?: boolean
15
+ reasoningEffort?: string
16
+ enableCache?: boolean
17
+ strictTools?: boolean
18
+ temperature?: number
19
+ maxTokens?: number
20
+ tavilyApiKey?: string
21
+ }
22
+
23
+ /**
24
+ * 模型上下文窗口大小映射表(基于 2026 年最新数据)
25
+ * 单位:tokens
26
+ */
27
+ const MODEL_CONTEXT_WINDOWS: Record<string, number> = {
28
+ // Doubao 系列
29
+ 'doubao-seed-2.0-code': 256_000,
30
+ 'doubao-seed-2.0-pro': 256_000,
31
+ 'doubao-seed-2.0-lite': 256_000,
32
+ 'doubao-seed-2.0-mini': 256_000,
33
+ 'doubao-seed-2.0-code-preview-260215': 256_000,
34
+ 'doubao-seed-1.8': 256_000,
35
+ 'doubao-seed-1.6': 256_000,
36
+
37
+ // DeepSeek 系列
38
+ 'deepseek-v4-pro': 1_000_000,
39
+ 'deepseek-v4-flash': 256_000,
40
+ 'deepseek-v3.2': 160_000,
41
+ 'deepseek-r1': 128_000,
42
+ 'deepseek-chat': 128_000,
43
+ 'deepseek-reasoner': 128_000,
44
+
45
+ // Kimi 系列
46
+ 'kimi-k2.5': 262_144,
47
+ 'kimi-k2.6': 262_144,
48
+ 'kimi-k2-thinking': 256_000,
49
+
50
+ // MiniMax 系列
51
+ 'minimax-m2.5': 200_000,
52
+ 'minimax-m2.7': 200_000,
53
+ 'minimax-m2': 205_000,
54
+
55
+ // GLM 系列
56
+ 'glm-5': 200_000,
57
+ 'glm-5.1': 200_000,
58
+ 'glm-4.7-flashx': 200_000,
59
+ 'glm-4-flash': 128_000,
60
+ 'glm-4': 128_000,
61
+
62
+ // Qwen 系列
63
+ 'qwen3.6-plus': 1_000_000,
64
+ 'qwen3.7-max': 1_000_000,
65
+ 'qwen3-max': 256_000,
66
+ 'qwen3.5-plus': 1_000_000,
67
+ 'qwen-flash': 1_000_000,
68
+
69
+ // Claude 系列
70
+ 'claude-opus-4.7': 1_000_000,
71
+ 'claude-opus-4.6': 1_000_000,
72
+ 'claude-sonnet-4.6': 1_000_000,
73
+ 'claude-haiku-4.5': 200_000,
74
+
75
+ // GPT 系列
76
+ 'gpt-5.5': 1_000_000,
77
+ 'gpt-5.4': 1_000_000,
78
+ 'gpt-5.1': 1_000_000,
79
+ 'gpt-5.2-codex': 512_000,
80
+ 'gpt-4.1': 1_000_000,
81
+ 'gpt-4.1-mini': 1_000_000,
82
+ 'gpt-4o': 128_000,
83
+ 'gpt-4': 128_000,
84
+
85
+ // Gemini 系列
86
+ 'gemini-2.5-pro': 1_000_000,
87
+ 'gemini-2.5-flash': 1_000_000,
88
+ 'gemini-3.1-pro': 1_000_000,
89
+ 'gemini-3.1-flash': 1_000_000,
90
+
91
+ // Llama 系列
92
+ 'llama-4-maverick': 1_000_000,
93
+ 'llama-4-scout': 10_000_000,
94
+ 'llama-3.1': 128_000,
95
+ 'llama-3': 128_000,
96
+
97
+ // Mistral 系列
98
+ 'mistral-small-3.1': 128_000,
99
+ 'mistral-small-3.2': 128_000,
100
+ }
101
+
102
+ /**
103
+ * 模糊匹配规则
104
+ */
105
+ interface FuzzyMatchRule {
106
+ keywords: string[]
107
+ windowSize: number
108
+ }
109
+
110
+ /**
111
+ * 模糊匹配规则列表(从高优先级到低优先级)
112
+ */
113
+ const fuzzyMatchRules: FuzzyMatchRule[] = [
114
+ // 首先匹配 128K 模型(防止 gpt-4 匹配到 gpt-5 规则)
115
+ {
116
+ keywords: [
117
+ 'gpt-4o',
118
+ 'gpt 4o',
119
+ 'gpt-4',
120
+ 'gpt 4',
121
+ 'llama-3',
122
+ 'llama 3',
123
+ 'mistral-small',
124
+ 'mistral small',
125
+ 'glm-4-flash',
126
+ 'glm 4 flash',
127
+ 'glm-4',
128
+ ],
129
+ windowSize: 128_000,
130
+ },
131
+ // 百万上下文模型 - 更高优先级(更精确的关键词)
132
+ {
133
+ keywords: [
134
+ 'deepseek-v4',
135
+ 'deepseek v4',
136
+ 'qwen3.6',
137
+ 'qwen 3.6',
138
+ 'qwen3.7',
139
+ 'qwen 3.7',
140
+ 'qwen3.5',
141
+ 'qwen 3.5',
142
+ 'qwen-flash',
143
+ 'qwen flash',
144
+ ],
145
+ windowSize: 1_000_000,
146
+ },
147
+ {
148
+ keywords: [
149
+ 'claude-opus',
150
+ 'claude sonnet',
151
+ 'claude-sonnet',
152
+ 'gpt-5.',
153
+ 'gpt 5',
154
+ 'gpt-4.1',
155
+ 'gpt 4.1',
156
+ 'gemini-2.5',
157
+ 'gemini 2.5',
158
+ 'gemini-3.1',
159
+ 'gemini 3.1',
160
+ 'llama-4',
161
+ 'llama 4',
162
+ ],
163
+ windowSize: 1_000_000,
164
+ },
165
+ // 256K 上下文模型
166
+ {
167
+ keywords: [
168
+ 'doubao-seed-2.0',
169
+ 'doubao seed 2.0',
170
+ 'doubao-seed-1',
171
+ 'doubao seed 1',
172
+ 'kimi-k2',
173
+ 'kimi k2',
174
+ 'kimi-k2.5',
175
+ 'kimi k2.5',
176
+ 'kimi-k2.6',
177
+ 'kimi k2.6',
178
+ 'qwen3',
179
+ 'qwen 3',
180
+ 'qwen3-max',
181
+ 'qwen3 max',
182
+ ],
183
+ windowSize: 256_000,
184
+ },
185
+ // 200K 上下文模型
186
+ {
187
+ keywords: [
188
+ 'minimax',
189
+ 'glm-5',
190
+ 'glm 5',
191
+ 'glm-5.1',
192
+ 'glm 5.1',
193
+ 'glm-4.7',
194
+ 'glm 4.7',
195
+ 'claude-haiku',
196
+ 'claude haiku',
197
+ ],
198
+ windowSize: 200_000,
199
+ },
200
+ // 160K 上下文模型
201
+ {
202
+ keywords: ['deepseek-v3', 'deepseek v3', 'deepseek-v3.2', 'deepseek v3.2'],
203
+ windowSize: 160_000,
204
+ },
205
+ // 最后匹配通用关键词(deepseek)
206
+ {
207
+ keywords: ['deepseek'],
208
+ windowSize: 128_000,
209
+ },
210
+ ]
211
+
212
+ /**
213
+ * 根据模型名称获取上下文窗口大小(改进的模糊匹配)
214
+ * @param modelName 模型名称(不区分大小写)
215
+ * @returns 上下文窗口大小(tokens)
216
+ */
217
+ export function getContextWindowForModel(modelName: string): number {
218
+ // 处理空字符串
219
+ if (!modelName) {
220
+ return 128_000
221
+ }
222
+
223
+ const normalizedModelName = modelName.toLowerCase().replace(/[-_]/g, ' ')
224
+
225
+ // 1. 精确匹配(原始键名)
226
+ if (MODEL_CONTEXT_WINDOWS[modelName]) {
227
+ return MODEL_CONTEXT_WINDOWS[modelName]
228
+ }
229
+
230
+ // 2. 精确匹配(小写键名)
231
+ if (MODEL_CONTEXT_WINDOWS[modelName.toLowerCase()]) {
232
+ return MODEL_CONTEXT_WINDOWS[modelName.toLowerCase()]
233
+ }
234
+
235
+ // 3. 前缀匹配(支持部分匹配)
236
+ for (const [pattern, size] of Object.entries(MODEL_CONTEXT_WINDOWS)) {
237
+ const normalizedPattern = pattern.toLowerCase().replace(/[-_]/g, ' ')
238
+ if (
239
+ normalizedModelName.includes(normalizedPattern) ||
240
+ normalizedPattern.includes(normalizedModelName)
241
+ ) {
242
+ return size
243
+ }
244
+ }
245
+
246
+ // 4. 模糊匹配(关键词匹配)- 按照规则顺序(优先级)处理
247
+ for (const rule of fuzzyMatchRules) {
248
+ for (const keyword of rule.keywords) {
249
+ const normalizedKeyword = keyword.toLowerCase().replace(/[-_]/g, ' ')
250
+ if (normalizedModelName.includes(normalizedKeyword)) {
251
+ return rule.windowSize
252
+ }
253
+ }
254
+ }
255
+
256
+ // 5. 兜底默认值
257
+ return 128_000
258
+ }
259
+
260
+ interface JsonConfig {
261
+ apiKey?: string
262
+ baseUrl?: string
263
+ provider?: string
264
+ model?: string
265
+ thinking?: boolean
266
+ reasoningEffort?: string
267
+ autoApprove?: boolean
268
+ enableCache?: boolean
269
+ strictTools?: boolean
270
+ contextWindow?: number
271
+ temperature?: number
272
+ maxTokens?: number
273
+ tavilyApiKey?: string
274
+ }
275
+
276
+ let cachedJsonConfig: JsonConfig | null = null
277
+
278
+ function loadJsonConfig(): JsonConfig {
279
+ if (cachedJsonConfig) return cachedJsonConfig
280
+ const configPath = path.join(os.homedir(), '.lonny', 'config.json')
281
+ try {
282
+ const raw = fs.readFileSync(configPath, 'utf-8')
283
+ cachedJsonConfig = JSON.parse(raw) as JsonConfig
284
+ return cachedJsonConfig
285
+ } catch {
286
+ cachedJsonConfig = {}
287
+ return cachedJsonConfig
288
+ }
289
+ }
290
+
291
+ function saveJsonConfig(config: JsonConfig): void {
292
+ const configPath = path.join(os.homedir(), '.lonny', 'config.json')
293
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8')
294
+ cachedJsonConfig = config
295
+ }
296
+
297
+ /** Check if the model is a DeepSeek model (supports enable_cache). */
298
+ function isDeepSeekModel(model: string, baseUrl?: string): boolean {
299
+ if (/deepseek/i.test(model)) return true
300
+ if (baseUrl && /deepseek/i.test(baseUrl)) return true
301
+ return false
302
+ }
303
+
304
+ export function loadConfig(options?: {
305
+ mode?: 'code' | 'plan' | 'ask' | 'loop'
306
+ autoApprove?: boolean
307
+ cwd?: string
308
+ }): Config {
309
+ const jsonConfig = loadJsonConfig()
310
+
311
+ const model = jsonConfig.model || 'deepseek-v4-flash'
312
+ const baseUrl = process.env.LONNY_BASE_URL || jsonConfig.baseUrl || undefined
313
+ const provider = (process.env.LONNY_PROVIDER || jsonConfig.provider || 'openai') as
314
+ | 'openai'
315
+ | 'anthropic'
316
+ | 'google'
317
+ | 'ollama'
318
+
319
+ // Auto-enable cache for DeepSeek models unless explicitly disabled
320
+ const enableCache = jsonConfig.enableCache ?? (isDeepSeekModel(model, baseUrl) || undefined)
321
+
322
+ // 根据模型名称获取上下文窗口大小,如果配置中有则优先使用配置值
323
+ const contextWindow = jsonConfig.contextWindow || getContextWindowForModel(model)
324
+
325
+ return {
326
+ apiKey: jsonConfig.apiKey || '',
327
+ baseUrl,
328
+ provider,
329
+ mode: options?.mode || 'code',
330
+ model,
331
+ contextWindow,
332
+ cwd: options?.cwd || process.cwd(),
333
+ autoApprove: options?.autoApprove ?? jsonConfig.autoApprove ?? false,
334
+ thinking: jsonConfig.thinking,
335
+ reasoningEffort: jsonConfig.reasoningEffort,
336
+ enableCache,
337
+ strictTools: jsonConfig.strictTools,
338
+ temperature: jsonConfig.temperature,
339
+ maxTokens: jsonConfig.maxTokens,
340
+ tavilyApiKey: jsonConfig.tavilyApiKey,
341
+ }
342
+ }