@tyvm/knowhow 0.0.47 → 0.0.49

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 (459) hide show
  1. package/benchmarks/results/27b0a06/2025-09-27/xai/xai-grok-code-fast-1.json +2909 -0
  2. package/benchmarks/results/4057aed/2025-08-14/anthropic/anthropic-claude-sonnet-4-20250514.json +1671 -0
  3. package/jest.config.js +2 -2
  4. package/package.json +8 -3
  5. package/src/agents/base/base.ts +39 -25
  6. package/src/agents/patcher/patcher.ts +26 -5
  7. package/src/agents/tools/agentCall.ts +4 -2
  8. package/src/agents/tools/aiClient.ts +3 -11
  9. package/src/agents/tools/ast/astAppendNode.ts +90 -0
  10. package/src/agents/tools/ast/astDeleteNode.ts +88 -0
  11. package/src/agents/tools/ast/astEditNode.ts +95 -0
  12. package/src/agents/tools/ast/astGetPathForLine.ts +73 -0
  13. package/src/agents/tools/ast/astListPaths.ts +66 -0
  14. package/src/agents/tools/ast/index.ts +7 -0
  15. package/src/agents/tools/callPlugin.ts +8 -2
  16. package/src/agents/tools/embeddingSearch.ts +2 -1
  17. package/src/agents/tools/execCommand.ts +239 -94
  18. package/src/agents/tools/fileSearch.ts +15 -17
  19. package/src/agents/tools/index.ts +1 -0
  20. package/src/agents/tools/language/definitions.ts +10 -2
  21. package/src/agents/tools/language/index.ts +3 -2
  22. package/src/agents/tools/lintFile.ts +4 -2
  23. package/src/agents/tools/list.ts +203 -62
  24. package/src/agents/tools/patch.ts +48 -14
  25. package/src/agents/tools/readBlocks.ts +34 -0
  26. package/src/agents/tools/readFile.ts +23 -0
  27. package/src/agents/tools/stringReplace.ts +33 -9
  28. package/src/agents/tools/writeFile.ts +55 -0
  29. package/src/agents/tools/ycmd/server.ts +14 -4
  30. package/src/chat/CliChatService.ts +6 -1
  31. package/src/chat/modules/AgentModule.ts +129 -67
  32. package/src/chat/modules/AskModule.ts +0 -1
  33. package/src/chat/modules/SetupModule.ts +4 -4
  34. package/src/chat/modules/SystemModule.ts +28 -5
  35. package/src/chat/types.ts +2 -0
  36. package/src/chat-old.ts +2 -2
  37. package/src/clients/anthropic.ts +22 -1
  38. package/src/clients/openai.ts +1 -1
  39. package/src/clients/xai.ts +15 -5
  40. package/src/config.ts +17 -5
  41. package/src/dataset/diffs/generate.ts +2 -2
  42. package/src/dataset/diffs/jsonl.ts +0 -1
  43. package/src/embeddings.ts +8 -8
  44. package/src/index.ts +11 -5
  45. package/src/plugins/GitPlugin.ts +530 -0
  46. package/src/plugins/LinterPlugin.ts +89 -0
  47. package/src/plugins/PluginBase.ts +4 -2
  48. package/src/plugins/asana.ts +4 -2
  49. package/src/plugins/downloader/plugin.ts +5 -2
  50. package/src/plugins/embedding.ts +24 -4
  51. package/src/plugins/figma.ts +7 -3
  52. package/src/plugins/github.ts +4 -2
  53. package/src/plugins/jira.ts +4 -2
  54. package/src/plugins/language.ts +134 -27
  55. package/src/plugins/linear.ts +4 -2
  56. package/src/plugins/notion.ts +4 -2
  57. package/src/plugins/plugins.ts +27 -16
  58. package/src/plugins/tree-sitter/editor.ts +369 -0
  59. package/src/plugins/tree-sitter/lang-packs/index.ts +23 -0
  60. package/src/plugins/tree-sitter/lang-packs/java.ts +59 -0
  61. package/src/plugins/tree-sitter/lang-packs/javascript.ts +57 -0
  62. package/src/plugins/tree-sitter/lang-packs/python.ts +45 -0
  63. package/src/plugins/tree-sitter/lang-packs/types.ts +79 -0
  64. package/src/plugins/tree-sitter/lang-packs/typescript.ts +49 -0
  65. package/src/plugins/tree-sitter/parser.ts +444 -0
  66. package/src/plugins/tree-sitter/simple-paths.ts +467 -0
  67. package/src/plugins/types.ts +11 -0
  68. package/src/plugins/url.ts +5 -3
  69. package/src/plugins/vim.ts +8 -5
  70. package/src/processors/CustomVariables.ts +60 -70
  71. package/src/processors/TokenCompressor.ts +15 -14
  72. package/src/processors/ToolResponseCache.ts +20 -14
  73. package/src/services/EmbeddingService.ts +18 -9
  74. package/src/services/EventService.ts +80 -0
  75. package/src/services/Mcp.ts +5 -0
  76. package/src/services/S3.ts +4 -3
  77. package/src/services/Tools.ts +125 -53
  78. package/src/services/index.ts +16 -11
  79. package/src/services/types.ts +3 -3
  80. package/src/types.ts +7 -2
  81. package/src/worker.ts +14 -1
  82. package/test-comprehensive.ts +31 -0
  83. package/tests/clients/AIClient.test.ts +490 -0
  84. package/tests/manual/agent-events/run-test.ts +203 -0
  85. package/tests/{integration → manual/file-edits}/figma.test.ts +1 -1
  86. package/tests/{integration → manual/file-edits}/fileblocks/readwrite.test.ts +7 -3
  87. package/tests/{integration → manual/file-edits}/patching.test.ts +11 -8
  88. package/tests/plugins/language/languagePlugin-content-triggers.test.ts +332 -0
  89. package/tests/plugins/language/languagePlugin-integration.test.ts +456 -0
  90. package/tests/plugins/language/languagePlugin.test.ts +363 -0
  91. package/tests/processors/Base64ImageDetector.test.ts +403 -0
  92. package/tests/processors/CustomVariables.test.ts +485 -0
  93. package/tests/processors/HarmonyToolProcessor.test.ts +490 -0
  94. package/tests/processors/TokenCompressor.test.ts +390 -0
  95. package/tests/processors/ToolResponseCache.test.ts +736 -0
  96. package/tests/services/Tools.test.ts +1339 -0
  97. package/tests/test.spec.ts +162 -117
  98. package/tests/tree-sitter/editor.test.ts +113 -0
  99. package/tests/tree-sitter/invalid.test.ts +299 -0
  100. package/tests/tree-sitter/paths/common-edits.test.ts +564 -0
  101. package/tests/tree-sitter/paths/debug-exact-position.test.ts +44 -0
  102. package/tests/tree-sitter/paths/debug-line-indexing.test.ts +49 -0
  103. package/tests/tree-sitter/paths/debug-paths.test.ts +90 -0
  104. package/tests/tree-sitter/paths/paths.test.ts +170 -0
  105. package/tests/tree-sitter/paths/simple-paths.test.ts +367 -0
  106. package/tests/tree-sitter/sample-after.ts +48 -0
  107. package/tests/tree-sitter/sample-before.ts +25 -0
  108. package/tests/tree-sitter/test-files/completely-broken.ts +7 -0
  109. package/tests/tree-sitter/test-files/duplicate-braces.ts +39 -0
  110. package/tests/tree-sitter/test-files/invalid-nesting.ts +39 -0
  111. package/tests/tree-sitter/test-files/malformed-signature.ts +39 -0
  112. package/tests/tree-sitter/test-files/mismatched-parens.ts +39 -0
  113. package/tests/tree-sitter/test-files/missing-semicolon.ts +39 -0
  114. package/tests/tree-sitter/test-files/partially-broken.ts +20 -0
  115. package/tests/tree-sitter/test-files/specific-errors.ts +14 -0
  116. package/tests/tree-sitter/test-files/unclosed-string.ts +39 -0
  117. package/tests/tree-sitter/tree-sitter.test.ts +251 -0
  118. package/ts_build/package.json +8 -3
  119. package/ts_build/src/agents/base/base.d.ts +7 -2
  120. package/ts_build/src/agents/base/base.js +27 -21
  121. package/ts_build/src/agents/base/base.js.map +1 -1
  122. package/ts_build/src/agents/patcher/patcher.js +26 -5
  123. package/ts_build/src/agents/patcher/patcher.js.map +1 -1
  124. package/ts_build/src/agents/tools/agentCall.js +2 -1
  125. package/ts_build/src/agents/tools/agentCall.js.map +1 -1
  126. package/ts_build/src/agents/tools/aiClient.d.ts +7 -8
  127. package/ts_build/src/agents/tools/aiClient.js.map +1 -1
  128. package/ts_build/src/agents/tools/ast/astAppendNode.d.ts +1 -0
  129. package/ts_build/src/agents/tools/ast/astAppendNode.js +96 -0
  130. package/ts_build/src/agents/tools/ast/astAppendNode.js.map +1 -0
  131. package/ts_build/src/agents/tools/ast/astDeleteNode.d.ts +1 -0
  132. package/ts_build/src/agents/tools/ast/astDeleteNode.js +94 -0
  133. package/ts_build/src/agents/tools/ast/astDeleteNode.js.map +1 -0
  134. package/ts_build/src/agents/tools/ast/astEditNode.d.ts +1 -0
  135. package/ts_build/src/agents/tools/ast/astEditNode.js +96 -0
  136. package/ts_build/src/agents/tools/ast/astEditNode.js.map +1 -0
  137. package/ts_build/src/agents/tools/ast/astGetPathForLine.d.ts +1 -0
  138. package/ts_build/src/agents/tools/ast/astGetPathForLine.js +78 -0
  139. package/ts_build/src/agents/tools/ast/astGetPathForLine.js.map +1 -0
  140. package/ts_build/src/agents/tools/ast/astListPaths.d.ts +1 -0
  141. package/ts_build/src/agents/tools/ast/astListPaths.js +78 -0
  142. package/ts_build/src/agents/tools/ast/astListPaths.js.map +1 -0
  143. package/ts_build/src/agents/tools/ast/index.d.ts +5 -0
  144. package/ts_build/src/agents/tools/ast/index.js +14 -0
  145. package/ts_build/src/agents/tools/ast/index.js.map +1 -0
  146. package/ts_build/src/agents/tools/astAppendNode.d.ts +1 -0
  147. package/ts_build/src/agents/tools/astAppendNode.js +98 -0
  148. package/ts_build/src/agents/tools/astAppendNode.js.map +1 -0
  149. package/ts_build/src/agents/tools/astDeleteNode.d.ts +1 -0
  150. package/ts_build/src/agents/tools/astDeleteNode.js +95 -0
  151. package/ts_build/src/agents/tools/astDeleteNode.js.map +1 -0
  152. package/ts_build/src/agents/tools/astEditNode.d.ts +1 -0
  153. package/ts_build/src/agents/tools/astEditNode.js +98 -0
  154. package/ts_build/src/agents/tools/astEditNode.js.map +1 -0
  155. package/ts_build/src/agents/tools/astGetPathForLine.d.ts +1 -0
  156. package/ts_build/src/agents/tools/astGetPathForLine.js +89 -0
  157. package/ts_build/src/agents/tools/astGetPathForLine.js.map +1 -0
  158. package/ts_build/src/agents/tools/astListPaths.d.ts +1 -0
  159. package/ts_build/src/agents/tools/astListPaths.js +82 -0
  160. package/ts_build/src/agents/tools/astListPaths.js.map +1 -0
  161. package/ts_build/src/agents/tools/callPlugin.js +4 -2
  162. package/ts_build/src/agents/tools/callPlugin.js.map +1 -1
  163. package/ts_build/src/agents/tools/embeddingSearch.js +3 -2
  164. package/ts_build/src/agents/tools/embeddingSearch.js.map +1 -1
  165. package/ts_build/src/agents/tools/execCommand.d.ts +2 -2
  166. package/ts_build/src/agents/tools/execCommand.js +201 -67
  167. package/ts_build/src/agents/tools/execCommand.js.map +1 -1
  168. package/ts_build/src/agents/tools/fileSearch.d.ts +1 -1
  169. package/ts_build/src/agents/tools/fileSearch.js +11 -15
  170. package/ts_build/src/agents/tools/fileSearch.js.map +1 -1
  171. package/ts_build/src/agents/tools/github/index.d.ts +1 -1
  172. package/ts_build/src/agents/tools/index.d.ts +1 -0
  173. package/ts_build/src/agents/tools/index.js +1 -0
  174. package/ts_build/src/agents/tools/index.js.map +1 -1
  175. package/ts_build/src/agents/tools/language/definitions.js +11 -2
  176. package/ts_build/src/agents/tools/language/definitions.js.map +1 -1
  177. package/ts_build/src/agents/tools/language/index.js +4 -3
  178. package/ts_build/src/agents/tools/language/index.js.map +1 -1
  179. package/ts_build/src/agents/tools/lintFile.js +4 -2
  180. package/ts_build/src/agents/tools/lintFile.js.map +1 -1
  181. package/ts_build/src/agents/tools/list.js +185 -49
  182. package/ts_build/src/agents/tools/list.js.map +1 -1
  183. package/ts_build/src/agents/tools/patch.js +33 -10
  184. package/ts_build/src/agents/tools/patch.js.map +1 -1
  185. package/ts_build/src/agents/tools/readBlocks.js +23 -0
  186. package/ts_build/src/agents/tools/readBlocks.js.map +1 -1
  187. package/ts_build/src/agents/tools/readFile.js +14 -0
  188. package/ts_build/src/agents/tools/readFile.js.map +1 -1
  189. package/ts_build/src/agents/tools/stringReplace.js +19 -2
  190. package/ts_build/src/agents/tools/stringReplace.js.map +1 -1
  191. package/ts_build/src/agents/tools/writeFile.js +40 -0
  192. package/ts_build/src/agents/tools/writeFile.js.map +1 -1
  193. package/ts_build/src/agents/tools/ycmd/server.js +5 -0
  194. package/ts_build/src/agents/tools/ycmd/server.js.map +1 -1
  195. package/ts_build/src/chat/CliChatService.d.ts +1 -0
  196. package/ts_build/src/chat/CliChatService.js +6 -2
  197. package/ts_build/src/chat/CliChatService.js.map +1 -1
  198. package/ts_build/src/chat/modules/AgentModule.d.ts +5 -1
  199. package/ts_build/src/chat/modules/AgentModule.js +62 -32
  200. package/ts_build/src/chat/modules/AgentModule.js.map +1 -1
  201. package/ts_build/src/chat/modules/AskModule.js.map +1 -1
  202. package/ts_build/src/chat/modules/SetupModule.js +4 -3
  203. package/ts_build/src/chat/modules/SetupModule.js.map +1 -1
  204. package/ts_build/src/chat/modules/SystemModule.js +19 -4
  205. package/ts_build/src/chat/modules/SystemModule.js.map +1 -1
  206. package/ts_build/src/chat/modules/index.d.ts +5 -0
  207. package/ts_build/src/chat/modules/index.js +14 -0
  208. package/ts_build/src/chat/modules/index.js.map +1 -0
  209. package/ts_build/src/chat/types.d.ts +2 -0
  210. package/ts_build/src/chat-old.js +3 -3
  211. package/ts_build/src/chat-old.js.map +1 -1
  212. package/ts_build/src/clients/anthropic.d.ts +1 -0
  213. package/ts_build/src/clients/anthropic.js +22 -1
  214. package/ts_build/src/clients/anthropic.js.map +1 -1
  215. package/ts_build/src/clients/openai.js +1 -1
  216. package/ts_build/src/clients/openai.js.map +1 -1
  217. package/ts_build/src/clients/xai.d.ts +7 -0
  218. package/ts_build/src/clients/xai.js +13 -4
  219. package/ts_build/src/clients/xai.js.map +1 -1
  220. package/ts_build/src/config.js +14 -3
  221. package/ts_build/src/config.js.map +1 -1
  222. package/ts_build/src/dataset/diffs/generate.js +2 -2
  223. package/ts_build/src/dataset/diffs/generate.js.map +1 -1
  224. package/ts_build/src/dataset/diffs/jsonl.js.map +1 -1
  225. package/ts_build/src/embeddings.js +9 -13
  226. package/ts_build/src/embeddings.js.map +1 -1
  227. package/ts_build/src/index.js +10 -10
  228. package/ts_build/src/index.js.map +1 -1
  229. package/ts_build/src/plugins/GitPlugin.d.ts +39 -0
  230. package/ts_build/src/plugins/GitPlugin.js +439 -0
  231. package/ts_build/src/plugins/GitPlugin.js.map +1 -0
  232. package/ts_build/src/plugins/LinterPlugin.d.ts +15 -0
  233. package/ts_build/src/plugins/LinterPlugin.js +65 -0
  234. package/ts_build/src/plugins/LinterPlugin.js.map +1 -0
  235. package/ts_build/src/plugins/PluginBase.d.ts +4 -3
  236. package/ts_build/src/plugins/PluginBase.js +3 -3
  237. package/ts_build/src/plugins/PluginBase.js.map +1 -1
  238. package/ts_build/src/plugins/asana.d.ts +3 -1
  239. package/ts_build/src/plugins/asana.js +3 -2
  240. package/ts_build/src/plugins/asana.js.map +1 -1
  241. package/ts_build/src/plugins/downloader/plugin.d.ts +3 -1
  242. package/ts_build/src/plugins/downloader/plugin.js +3 -2
  243. package/ts_build/src/plugins/downloader/plugin.js.map +1 -1
  244. package/ts_build/src/plugins/embedding.d.ts +5 -1
  245. package/ts_build/src/plugins/embedding.js +15 -3
  246. package/ts_build/src/plugins/embedding.js.map +1 -1
  247. package/ts_build/src/plugins/figma.d.ts +3 -1
  248. package/ts_build/src/plugins/figma.js +28 -4
  249. package/ts_build/src/plugins/figma.js.map +1 -1
  250. package/ts_build/src/plugins/github.d.ts +3 -1
  251. package/ts_build/src/plugins/github.js +3 -2
  252. package/ts_build/src/plugins/github.js.map +1 -1
  253. package/ts_build/src/plugins/jira.d.ts +3 -1
  254. package/ts_build/src/plugins/jira.js +3 -2
  255. package/ts_build/src/plugins/jira.js.map +1 -1
  256. package/ts_build/src/plugins/language.d.ts +7 -4
  257. package/ts_build/src/plugins/language.js +85 -20
  258. package/ts_build/src/plugins/language.js.map +1 -1
  259. package/ts_build/src/plugins/linear.d.ts +3 -1
  260. package/ts_build/src/plugins/linear.js +3 -2
  261. package/ts_build/src/plugins/linear.js.map +1 -1
  262. package/ts_build/src/plugins/notion.d.ts +3 -1
  263. package/ts_build/src/plugins/notion.js +3 -2
  264. package/ts_build/src/plugins/notion.js.map +1 -1
  265. package/ts_build/src/plugins/plugins.d.ts +4 -3
  266. package/ts_build/src/plugins/plugins.js +24 -14
  267. package/ts_build/src/plugins/plugins.js.map +1 -1
  268. package/ts_build/src/plugins/tree-sitter/editor.d.ts +34 -0
  269. package/ts_build/src/plugins/tree-sitter/editor.js +218 -0
  270. package/ts_build/src/plugins/tree-sitter/editor.js.map +1 -0
  271. package/ts_build/src/plugins/tree-sitter/human-readable-paths-new.d.ts +29 -0
  272. package/ts_build/src/plugins/tree-sitter/human-readable-paths-new.js +538 -0
  273. package/ts_build/src/plugins/tree-sitter/human-readable-paths-new.js.map +1 -0
  274. package/ts_build/src/plugins/tree-sitter/human-readable-paths.d.ts +22 -0
  275. package/ts_build/src/plugins/tree-sitter/human-readable-paths.js +332 -0
  276. package/ts_build/src/plugins/tree-sitter/human-readable-paths.js.map +1 -0
  277. package/ts_build/src/plugins/tree-sitter/lang-packs/index.d.ts +8 -0
  278. package/ts_build/src/plugins/tree-sitter/lang-packs/index.js +26 -0
  279. package/ts_build/src/plugins/tree-sitter/lang-packs/index.js.map +1 -0
  280. package/ts_build/src/plugins/tree-sitter/lang-packs/java.d.ts +2 -0
  281. package/ts_build/src/plugins/tree-sitter/lang-packs/java.js +61 -0
  282. package/ts_build/src/plugins/tree-sitter/lang-packs/java.js.map +1 -0
  283. package/ts_build/src/plugins/tree-sitter/lang-packs/javascript.d.ts +2 -0
  284. package/ts_build/src/plugins/tree-sitter/lang-packs/javascript.js +59 -0
  285. package/ts_build/src/plugins/tree-sitter/lang-packs/javascript.js.map +1 -0
  286. package/ts_build/src/plugins/tree-sitter/lang-packs/python.d.ts +2 -0
  287. package/ts_build/src/plugins/tree-sitter/lang-packs/python.js +47 -0
  288. package/ts_build/src/plugins/tree-sitter/lang-packs/python.js.map +1 -0
  289. package/ts_build/src/plugins/tree-sitter/lang-packs/types.d.ts +43 -0
  290. package/ts_build/src/plugins/tree-sitter/lang-packs/types.js +3 -0
  291. package/ts_build/src/plugins/tree-sitter/lang-packs/types.js.map +1 -0
  292. package/ts_build/src/plugins/tree-sitter/lang-packs/typescript.d.ts +2 -0
  293. package/ts_build/src/plugins/tree-sitter/lang-packs/typescript.js +50 -0
  294. package/ts_build/src/plugins/tree-sitter/lang-packs/typescript.js.map +1 -0
  295. package/ts_build/src/plugins/tree-sitter/parser.d.ts +75 -0
  296. package/ts_build/src/plugins/tree-sitter/parser.js +306 -0
  297. package/ts_build/src/plugins/tree-sitter/parser.js.map +1 -0
  298. package/ts_build/src/plugins/tree-sitter/simple-paths.d.ts +22 -0
  299. package/ts_build/src/plugins/tree-sitter/simple-paths.js +332 -0
  300. package/ts_build/src/plugins/tree-sitter/simple-paths.js.map +1 -0
  301. package/ts_build/src/plugins/types.d.ts +10 -0
  302. package/ts_build/src/plugins/url.d.ts +3 -2
  303. package/ts_build/src/plugins/url.js +3 -2
  304. package/ts_build/src/plugins/url.js.map +1 -1
  305. package/ts_build/src/plugins/vim.d.ts +4 -2
  306. package/ts_build/src/plugins/vim.js +6 -8
  307. package/ts_build/src/plugins/vim.js.map +1 -1
  308. package/ts_build/src/processors/CustomVariables.js +45 -47
  309. package/ts_build/src/processors/CustomVariables.js.map +1 -1
  310. package/ts_build/src/processors/TokenCompressor.js +10 -13
  311. package/ts_build/src/processors/TokenCompressor.js.map +1 -1
  312. package/ts_build/src/processors/ToolResponseCache.d.ts +2 -2
  313. package/ts_build/src/processors/ToolResponseCache.js +18 -10
  314. package/ts_build/src/processors/ToolResponseCache.js.map +1 -1
  315. package/ts_build/src/services/EmbeddingService.d.ts +10 -1
  316. package/ts_build/src/services/EmbeddingService.js +12 -12
  317. package/ts_build/src/services/EmbeddingService.js.map +1 -1
  318. package/ts_build/src/services/EventService.d.ts +7 -0
  319. package/ts_build/src/services/EventService.js +49 -0
  320. package/ts_build/src/services/EventService.js.map +1 -1
  321. package/ts_build/src/services/Mcp.js +8 -0
  322. package/ts_build/src/services/Mcp.js.map +1 -1
  323. package/ts_build/src/services/S3.js +4 -3
  324. package/ts_build/src/services/S3.js.map +1 -1
  325. package/ts_build/src/services/Tools.d.ts +1 -0
  326. package/ts_build/src/services/Tools.js +97 -35
  327. package/ts_build/src/services/Tools.js.map +1 -1
  328. package/ts_build/src/services/index.d.ts +4 -5
  329. package/ts_build/src/services/index.js +14 -9
  330. package/ts_build/src/services/index.js.map +1 -1
  331. package/ts_build/src/services/types.js +3 -3
  332. package/ts_build/src/services/types.js.map +1 -1
  333. package/ts_build/src/types.d.ts +7 -1
  334. package/ts_build/src/types.js +4 -0
  335. package/ts_build/src/types.js.map +1 -1
  336. package/ts_build/src/worker.js +12 -1
  337. package/ts_build/src/worker.js.map +1 -1
  338. package/ts_build/tests/clients/AIClient.test.d.ts +1 -0
  339. package/ts_build/tests/clients/AIClient.test.js +377 -0
  340. package/ts_build/tests/clients/AIClient.test.js.map +1 -0
  341. package/ts_build/tests/languagePlugin.test.js +217 -11
  342. package/ts_build/tests/languagePlugin.test.js.map +1 -1
  343. package/ts_build/tests/manual/agent-events/event-handler-reliability.test.d.ts +1 -0
  344. package/ts_build/tests/manual/agent-events/event-handler-reliability.test.js +315 -0
  345. package/ts_build/tests/manual/agent-events/event-handler-reliability.test.js.map +1 -0
  346. package/ts_build/tests/manual/agent-events/run-test.d.ts +2 -0
  347. package/ts_build/tests/manual/agent-events/run-test.js +148 -0
  348. package/ts_build/tests/manual/agent-events/run-test.js.map +1 -0
  349. package/ts_build/tests/manual/file-edits/figma.test.d.ts +1 -0
  350. package/ts_build/tests/manual/file-edits/figma.test.js +47 -0
  351. package/ts_build/tests/manual/file-edits/figma.test.js.map +1 -0
  352. package/ts_build/tests/manual/file-edits/fileblocks/readwrite.test.d.ts +1 -0
  353. package/ts_build/tests/manual/file-edits/fileblocks/readwrite.test.js +100 -0
  354. package/ts_build/tests/manual/file-edits/fileblocks/readwrite.test.js.map +1 -0
  355. package/ts_build/tests/manual/file-edits/patching.test.d.ts +1 -0
  356. package/ts_build/tests/manual/file-edits/patching.test.js +119 -0
  357. package/ts_build/tests/manual/file-edits/patching.test.js.map +1 -0
  358. package/ts_build/tests/plugins/language/languagePlugin-content-triggers.test.d.ts +1 -0
  359. package/ts_build/tests/plugins/language/languagePlugin-content-triggers.test.js +277 -0
  360. package/ts_build/tests/plugins/language/languagePlugin-content-triggers.test.js.map +1 -0
  361. package/ts_build/tests/plugins/language/languagePlugin-integration.test.d.ts +1 -0
  362. package/ts_build/tests/plugins/language/languagePlugin-integration.test.js +331 -0
  363. package/ts_build/tests/plugins/language/languagePlugin-integration.test.js.map +1 -0
  364. package/ts_build/tests/plugins/language/languagePlugin.test.d.ts +1 -0
  365. package/ts_build/tests/plugins/language/languagePlugin.test.js +286 -0
  366. package/ts_build/tests/plugins/language/languagePlugin.test.js.map +1 -0
  367. package/ts_build/tests/processors/Base64ImageDetector.test.d.ts +1 -0
  368. package/ts_build/tests/processors/Base64ImageDetector.test.js +351 -0
  369. package/ts_build/tests/processors/Base64ImageDetector.test.js.map +1 -0
  370. package/ts_build/tests/processors/CustomVariables.test.d.ts +1 -0
  371. package/ts_build/tests/processors/CustomVariables.test.js +354 -0
  372. package/ts_build/tests/processors/CustomVariables.test.js.map +1 -0
  373. package/ts_build/tests/processors/HarmonyToolProcessor.test.d.ts +1 -0
  374. package/ts_build/tests/processors/HarmonyToolProcessor.test.js +382 -0
  375. package/ts_build/tests/processors/HarmonyToolProcessor.test.js.map +1 -0
  376. package/ts_build/tests/processors/TokenCompressor.test.d.ts +1 -0
  377. package/ts_build/tests/processors/TokenCompressor.test.js +299 -0
  378. package/ts_build/tests/processors/TokenCompressor.test.js.map +1 -0
  379. package/ts_build/tests/processors/ToolResponseCache.test.d.ts +1 -0
  380. package/ts_build/tests/processors/ToolResponseCache.test.js +550 -0
  381. package/ts_build/tests/processors/ToolResponseCache.test.js.map +1 -0
  382. package/ts_build/tests/services/Plugins/plugin-event-integration.test.d.ts +1 -0
  383. package/ts_build/tests/services/Plugins/plugin-event-integration.test.js +232 -0
  384. package/ts_build/tests/services/Plugins/plugin-event-integration.test.js.map +1 -0
  385. package/ts_build/tests/services/Tools.test.d.ts +1 -0
  386. package/ts_build/tests/services/Tools.test.js +1059 -0
  387. package/ts_build/tests/services/Tools.test.js.map +1 -0
  388. package/ts_build/tests/test.spec.js +110 -68
  389. package/ts_build/tests/test.spec.js.map +1 -1
  390. package/ts_build/tests/tree-sitter/editor.test.d.ts +1 -0
  391. package/ts_build/tests/tree-sitter/editor.test.js +85 -0
  392. package/ts_build/tests/tree-sitter/editor.test.js.map +1 -0
  393. package/ts_build/tests/tree-sitter/invalid.test.d.ts +1 -0
  394. package/ts_build/tests/tree-sitter/invalid.test.js +198 -0
  395. package/ts_build/tests/tree-sitter/invalid.test.js.map +1 -0
  396. package/ts_build/tests/tree-sitter/paths/common-edits.test.d.ts +1 -0
  397. package/ts_build/tests/tree-sitter/paths/common-edits.test.js +347 -0
  398. package/ts_build/tests/tree-sitter/paths/common-edits.test.js.map +1 -0
  399. package/ts_build/tests/tree-sitter/paths/debug-exact-position.test.d.ts +1 -0
  400. package/ts_build/tests/tree-sitter/paths/debug-exact-position.test.js +35 -0
  401. package/ts_build/tests/tree-sitter/paths/debug-exact-position.test.js.map +1 -0
  402. package/ts_build/tests/tree-sitter/paths/debug-line-indexing.test.d.ts +1 -0
  403. package/ts_build/tests/tree-sitter/paths/debug-line-indexing.test.js +38 -0
  404. package/ts_build/tests/tree-sitter/paths/debug-line-indexing.test.js.map +1 -0
  405. package/ts_build/tests/tree-sitter/paths/debug-paths.test.d.ts +1 -0
  406. package/ts_build/tests/tree-sitter/paths/debug-paths.test.js +74 -0
  407. package/ts_build/tests/tree-sitter/paths/debug-paths.test.js.map +1 -0
  408. package/ts_build/tests/tree-sitter/paths/human-readable-paths.test.d.ts +1 -0
  409. package/ts_build/tests/tree-sitter/paths/human-readable-paths.test.js +302 -0
  410. package/ts_build/tests/tree-sitter/paths/human-readable-paths.test.js.map +1 -0
  411. package/ts_build/tests/tree-sitter/paths/paths.test.d.ts +1 -0
  412. package/ts_build/tests/tree-sitter/paths/paths.test.js +116 -0
  413. package/ts_build/tests/tree-sitter/paths/paths.test.js.map +1 -0
  414. package/ts_build/tests/tree-sitter/paths/simple-paths.test.d.ts +1 -0
  415. package/ts_build/tests/tree-sitter/paths/simple-paths.test.js +302 -0
  416. package/ts_build/tests/tree-sitter/paths/simple-paths.test.js.map +1 -0
  417. package/ts_build/tests/tree-sitter/sample-after.d.ts +11 -0
  418. package/ts_build/tests/tree-sitter/sample-after.js +44 -0
  419. package/ts_build/tests/tree-sitter/sample-after.js.map +1 -0
  420. package/ts_build/tests/tree-sitter/sample-before.d.ts +9 -0
  421. package/ts_build/tests/tree-sitter/sample-before.js +28 -0
  422. package/ts_build/tests/tree-sitter/sample-before.js.map +1 -0
  423. package/ts_build/tests/tree-sitter/test-files/completely-broken.d.ts +2 -0
  424. package/ts_build/tests/tree-sitter/test-files/completely-broken.js +17 -0
  425. package/ts_build/tests/tree-sitter/test-files/completely-broken.js.map +1 -0
  426. package/ts_build/tests/tree-sitter/test-files/duplicate-braces.d.ts +8 -0
  427. package/ts_build/tests/tree-sitter/test-files/duplicate-braces.js +38 -0
  428. package/ts_build/tests/tree-sitter/test-files/duplicate-braces.js.map +1 -0
  429. package/ts_build/tests/tree-sitter/test-files/invalid-nesting.d.ts +8 -0
  430. package/ts_build/tests/tree-sitter/test-files/invalid-nesting.js +38 -0
  431. package/ts_build/tests/tree-sitter/test-files/invalid-nesting.js.map +1 -0
  432. package/ts_build/tests/tree-sitter/test-files/malformed-signature.d.ts +8 -0
  433. package/ts_build/tests/tree-sitter/test-files/malformed-signature.js +38 -0
  434. package/ts_build/tests/tree-sitter/test-files/malformed-signature.js.map +1 -0
  435. package/ts_build/tests/tree-sitter/test-files/mismatched-parens.d.ts +10 -0
  436. package/ts_build/tests/tree-sitter/test-files/mismatched-parens.js +38 -0
  437. package/ts_build/tests/tree-sitter/test-files/mismatched-parens.js.map +1 -0
  438. package/ts_build/tests/tree-sitter/test-files/missing-semicolon.d.ts +8 -0
  439. package/ts_build/tests/tree-sitter/test-files/missing-semicolon.js +38 -0
  440. package/ts_build/tests/tree-sitter/test-files/missing-semicolon.js.map +1 -0
  441. package/ts_build/tests/tree-sitter/test-files/partially-broken.d.ts +6 -0
  442. package/ts_build/tests/tree-sitter/test-files/partially-broken.js +20 -0
  443. package/ts_build/tests/tree-sitter/test-files/partially-broken.js.map +1 -0
  444. package/ts_build/tests/tree-sitter/test-files/specific-errors.d.ts +7 -0
  445. package/ts_build/tests/tree-sitter/test-files/specific-errors.js +14 -0
  446. package/ts_build/tests/tree-sitter/test-files/specific-errors.js.map +1 -0
  447. package/ts_build/tests/tree-sitter/test-files/unclosed-string.d.ts +8 -0
  448. package/ts_build/tests/tree-sitter/test-files/unclosed-string.js +38 -0
  449. package/ts_build/tests/tree-sitter/test-files/unclosed-string.js.map +1 -0
  450. package/ts_build/tests/tree-sitter/tree-sitter.test.d.ts +1 -0
  451. package/ts_build/tests/tree-sitter/tree-sitter.test.js +185 -0
  452. package/ts_build/tests/tree-sitter/tree-sitter.test.js.map +1 -0
  453. package/tsconfig.json +2 -1
  454. package/tests/languagePlugin.test.ts +0 -74
  455. /package/src/chat/modules/{index.js → index.ts} +0 -0
  456. /package/tests/{integration → manual/file-edits}/patching/input.txt +0 -0
  457. /package/tests/{integration → manual/file-edits}/patching/output.txt +0 -0
  458. /package/tests/{integration → manual/file-edits}/patching/patch.txt +0 -0
  459. /package/tests/{integration → manual/file-edits}/patching/unseen.txt +0 -0
package/jest.config.js CHANGED
@@ -12,8 +12,8 @@ module.exports = {
12
12
  ],
13
13
  },
14
14
  testEnvironment: 'node',
15
- testRegex: '/tests/.*\.(test|spec)?\.(ts|tsx|js)$',
15
+ testRegex: '/tests/.*\.(test|spec)\.(ts|tsx|js)$',
16
16
  moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
17
17
  modulePathIgnorePatterns: ["ts_build", "benchmarks"],
18
- testPathIgnorePatterns: ["<rootDir>/benchmarks/"]
18
+ testPathIgnorePatterns: ["<rootDir>/benchmarks/", "<rootDir>/tests/manual/"],
19
19
  };
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@tyvm/knowhow",
3
- "version": "0.0.47",
3
+ "version": "0.0.49",
4
4
  "description": "ai cli with plugins and agents",
5
5
  "main": "ts_build/src/index.js",
6
6
  "bin": {
7
7
  "knowhow": "ts_build/src/cli.js"
8
8
  },
9
9
  "scripts": {
10
- "test": "jest --detectOpenHandles --forceExit --testTimeout 300000",
10
+ "test": "jest --testTimeout 300000",
11
11
  "test:debug": "node --inspect-brk ../../node_modules/jest/bin/jest.js --detectOpenHandles --forceExit --testTimeout 300000",
12
12
  "compile": "tsc",
13
13
  "start": "npm run compile && node ts_build/src/server/index.js",
@@ -41,7 +41,7 @@
41
41
  "@anthropic-ai/sdk": "^0.39.0",
42
42
  "@aws-sdk/client-s3": "^3.588.0",
43
43
  "@google/genai": "^0.14.1",
44
- "@inquirer/editor": "^1.2.13",
44
+ "@inquirer/editor": "^4.2.18",
45
45
  "@linear/sdk": "^12.0.0",
46
46
  "@modelcontextprotocol/sdk": "^1.13.3",
47
47
  "@notionhq/client": "^2.2.14",
@@ -56,11 +56,13 @@
56
56
  "express": "^4.19.2",
57
57
  "figma-js": "^1.16.1-0",
58
58
  "gitignore-to-glob": "^0.3.0",
59
+ "glob": "11.0.3",
59
60
  "ink": "^6.0.1",
60
61
  "isolated-vm": "^5.0.4",
61
62
  "jira-client": "^8.2.2",
62
63
  "marked": "^10.0.0",
63
64
  "marked-terminal": "^6.2.0",
65
+ "minimatch": "^10.0.3",
64
66
  "morgan": "^1.10.0",
65
67
  "node-fetch": "^3.2.3",
66
68
  "node-jq": "^6.0.1",
@@ -77,6 +79,9 @@
77
79
  "puppeteer-extra-plugin-stealth": "^2.11.2",
78
80
  "react": "^19.1.0",
79
81
  "source-map-support": "^0.5.21",
82
+ "tree-sitter": "^0.21.1",
83
+ "tree-sitter-javascript": "^0.23.1",
84
+ "tree-sitter-typescript": "^0.23.1",
80
85
  "typescript": "^4.6.3",
81
86
  "ws": "^8.18.1",
82
87
  "youtube-dl-exec": "^2.5.5",
@@ -31,6 +31,11 @@ export interface AgentContext {
31
31
  Clients?: AIClient;
32
32
  }
33
33
 
34
+ export interface ToolCallEvent {
35
+ toolCall: ToolCall;
36
+ functionResp: any;
37
+ }
38
+
34
39
  export abstract class BaseAgent implements IAgent {
35
40
  abstract name: string;
36
41
  abstract description: string;
@@ -55,13 +60,15 @@ export abstract class BaseAgent implements IAgent {
55
60
  protected pendingUserMessages = [] as Message[];
56
61
  protected taskBreakdown = "";
57
62
  protected summaries = [] as string[];
63
+ protected currentTaskId: string | null = null;
58
64
 
59
65
  public agentEvents = new EventEmitter();
60
66
  public eventTypes = {
61
67
  newThread: "new_thread",
62
68
  threadUpdate: "thread_update",
63
69
  costUpdate: "cost_update",
64
- toolUsed: "tool_used",
70
+ toolCall: "tool:pre_call",
71
+ toolUsed: "tool:post_call",
65
72
  done: "done",
66
73
  pause: "pause",
67
74
  kill: "kill",
@@ -87,6 +94,15 @@ export abstract class BaseAgent implements IAgent {
87
94
  if (!this.events) {
88
95
  throw new Error("EventService is required for BaseAgent");
89
96
  }
97
+
98
+ // Subscribe to "agent:msg" events for dynamic context loading
99
+ this.events.on("agent:msg", (eventData: any) => {
100
+ const message = {
101
+ role: "user",
102
+ content: JSON.stringify(eventData),
103
+ } as Message;
104
+ this.addPendingUserMessage(message);
105
+ });
90
106
  }
91
107
 
92
108
  setMaxTurns(maxTurns: number | null) {
@@ -101,7 +117,7 @@ export abstract class BaseAgent implements IAgent {
101
117
  this.maxRunTimeMs = maxRunTimeMs;
102
118
  }
103
119
 
104
- newTask() {
120
+ newTask(taskId?: string) {
105
121
  this.currentThread = 0;
106
122
  this.threads = [];
107
123
  this.taskBreakdown = "";
@@ -110,6 +126,13 @@ export abstract class BaseAgent implements IAgent {
110
126
  this.status = "in_progress";
111
127
  this.turnCount = 0;
112
128
  this.startTimeMs = Date.now();
129
+ this.currentTaskId = taskId || this.startTimeMs.toString();
130
+
131
+ // Emit event for plugin integration
132
+ const id = taskId || this.startTimeMs.toString();
133
+ this.events.emit("agent:newTask", {
134
+ taskId: id,
135
+ });
113
136
  }
114
137
 
115
138
  register() {
@@ -143,6 +166,7 @@ export abstract class BaseAgent implements IAgent {
143
166
 
144
167
  setModel(value: string) {
145
168
  this.modelName = value;
169
+ this.client = null; // Reset client to force re-fetch
146
170
  }
147
171
 
148
172
  getProvider() {
@@ -151,6 +175,7 @@ export abstract class BaseAgent implements IAgent {
151
175
 
152
176
  setProvider(value: keyof typeof Clients.clients) {
153
177
  this.provider = value;
178
+ this.client = null; // Reset client to force re-fetch
154
179
  }
155
180
 
156
181
  getClient() {
@@ -275,6 +300,8 @@ export abstract class BaseAgent implements IAgent {
275
300
  abstract getInitialMessages(userInput: string): Promise<Message[]>;
276
301
 
277
302
  async processToolMessages(toolCall: ToolCall) {
303
+ this.agentEvents.emit(this.eventTypes.toolCall, { toolCall });
304
+
278
305
  const { functionResp, toolMessages } = await this.tools.callTool(
279
306
  toolCall,
280
307
  this.getEnabledToolNames()
@@ -416,27 +443,6 @@ export abstract class BaseAgent implements IAgent {
416
443
  });
417
444
  }
418
445
 
419
- async resume(resumeReason: string) {
420
- const reason = resumeReason ? `Reason for resuming: ${resumeReason}` : "";
421
-
422
- // Create resume prompt
423
- const resumePrompt = `We are resuming a previously started task. Here's the context:
424
- ORIGINAL REQUEST:
425
- ${this.taskBreakdown}
426
-
427
- LAST Progress State:
428
- ${JSON.stringify(this.threads[this.currentThread], null, 2)}
429
-
430
- Please continue from where you left off and complete the original request.
431
- ${reason}
432
-
433
- `;
434
-
435
- const lastThread = this.threads[this.currentThread] || [];
436
- this.status = "in_progress";
437
- this.call(resumePrompt, lastThread);
438
- }
439
-
440
446
  async kill() {
441
447
  console.log("Killing agent");
442
448
  this.agentEvents.emit(this.eventTypes.kill, this);
@@ -564,6 +570,14 @@ ${reason}
564
570
  );
565
571
 
566
572
  if (finalMessage) {
573
+ // Emit task completion event for plugins (like GitPlugin)
574
+ this.events.emit("agent:taskComplete", {
575
+ taskId:
576
+ this.currentTaskId ||
577
+ this.startTimeMs?.toString() ||
578
+ Date.now().toString(),
579
+ result: finalMessage.content || "Done",
580
+ });
567
581
  const doneMsg = finalMessage.content || "Done";
568
582
  this.agentEvents.emit(this.eventTypes.done, doneMsg);
569
583
  this.status = this.eventTypes.done;
@@ -620,7 +634,7 @@ ${reason}
620
634
 
621
635
  if (
622
636
  this.getMessagesLength(messages) > compressThreshold &&
623
- messages.length > 10
637
+ messages.length > 20
624
638
  ) {
625
639
  const taskBreakdown = await this.getTaskBreakdown(messages);
626
640
  console.log(
@@ -702,7 +716,7 @@ ${reason}
702
716
 
703
717
  addPendingUserMessage(message: Message) {
704
718
  if (this.status === this.eventTypes.done) {
705
- this.resume(JSON.stringify(message.content));
719
+ console.warn("Agent is done, cannot take more messages");
706
720
  } else {
707
721
  this.pendingUserMessages.push(message);
708
722
  }
@@ -79,11 +79,9 @@ export class PatchingAgent extends BaseAgent {
79
79
  super(context);
80
80
 
81
81
  this.setModelPreferences([
82
- { model: Models.anthropic.Sonnet4, provider: "anthropic" },
83
- {
84
- model: Models.openai.GPT_41_Mini,
85
- provider: "openai",
86
- },
82
+ { model: Models.anthropic.Sonnet4_5, provider: "anthropic" },
83
+ { model: Models.xai.GrokCodeFast, provider: "xai" },
84
+ { model: Models.openai.GPT_5, provider: "openai" },
87
85
  ]);
88
86
  }
89
87
 
@@ -102,6 +100,29 @@ export class PatchingAgent extends BaseAgent {
102
100
  This helps ensure accurate modifications and can suggest fixes for compilation errors.
103
101
 
104
102
  IF you fail twice to patch a file, you may switch using writeFileChunk to rewrite the whole file.
103
+
104
+ If you need to know about a type, you should use the ycmd completion tool to discovery the properties, and fallback to reading the source files if the ycmd tools are not available.
105
+
106
+ # Debugging Workflow
107
+ If a build or test command fails due to compilation errors:
108
+
109
+ ALWAYS start by running ycmdDiagnostics on the file with errors to get a structured list of issues.
110
+
111
+ Address the errors one at a time, from top to bottom.
112
+
113
+ For each error, use ycmdGoTo to find the correct definition or readFile on the relevant source file to understand the correct implementation.
114
+
115
+ If an error is related to properties not being named correctly, you can use ycmdCompletion to get suggestions for the correct property or method names.
116
+
117
+ Apply a small, targeted patch to fix only that single error.
118
+
119
+ After every 2-3 fixes, run ycmdDiagnostics again to confirm progress.
120
+
121
+ # Test Writing Workflow
122
+ When writing tests, you proceed incrementally, writing one test, verifying it compiles and works before moving on to the next test.
123
+ You ALWAYS get to a stable state with tests compiling / running before adding the next test.
124
+ When writing tests, you never change the source code to pass the test, you always change the test to match the existing source code.
125
+
105
126
  `,
106
127
  },
107
128
  { role: "user", content: userInput },
@@ -1,10 +1,12 @@
1
1
  import { getConfig } from "../../config";
2
- import { ToolsService } from "../../services";
2
+ import { services, ToolsService } from "../../services";
3
3
 
4
4
  export async function agentCall(agentName: string, userInput: string) {
5
5
  return new Promise(async (resolve, reject) => {
6
6
  const config = await getConfig();
7
- const toolService = this as ToolsService;
7
+ const toolService = (
8
+ this instanceof ToolsService ? this : services().Tools
9
+ ) as ToolsService;
8
10
 
9
11
  const { Events, Plugins } = toolService.getContext();
10
12
 
@@ -9,7 +9,6 @@ import {
9
9
  import { services } from "../../services";
10
10
 
11
11
  export function createAiCompletion(
12
- this: ToolsService,
13
12
  provider: string,
14
13
  options: CompletionOptions
15
14
  ): Promise<CompletionResponse> {
@@ -29,7 +28,6 @@ export function createAiCompletion(
29
28
  }
30
29
 
31
30
  export function createEmbedding(
32
- this: ToolsService,
33
31
  provider: string,
34
32
  options: EmbeddingOptions
35
33
  ): Promise<EmbeddingResponse> {
@@ -49,7 +47,6 @@ export function createEmbedding(
49
47
  }
50
48
 
51
49
  export async function listModelsForProvider(
52
- this: ToolsService,
53
50
  provider: string
54
51
  ): Promise<string[]> {
55
52
  // Get context from bound ToolsService
@@ -68,7 +65,6 @@ export async function listModelsForProvider(
68
65
  }
69
66
 
70
67
  export async function listAllModels(
71
- this: ToolsService
72
68
  ): Promise<Record<string, string[]>> {
73
69
  // Get context from bound ToolsService
74
70
  const toolService = (
@@ -85,7 +81,7 @@ export async function listAllModels(
85
81
  return contextClients.listAllModels();
86
82
  }
87
83
 
88
- export async function listAllProviders(this: ToolsService): Promise<string[]> {
84
+ export async function listAllProviders(): Promise<string[]> {
89
85
  // Get context from bound ToolsService
90
86
  const toolService = (
91
87
  this instanceof ToolsService ? this : services().Tools
@@ -101,9 +97,7 @@ export async function listAllProviders(this: ToolsService): Promise<string[]> {
101
97
  return contextClients.listAllProviders();
102
98
  }
103
99
 
104
- export async function listAllCompletionModels(
105
- this: ToolsService
106
- ): Promise<Record<string, string[]>> {
100
+ export async function listAllCompletionModels(): Promise<Record<string, string[]>> {
107
101
  // Get context from bound ToolsService
108
102
  const toolService = (
109
103
  this instanceof ToolsService ? this : services().Tools
@@ -119,9 +113,7 @@ export async function listAllCompletionModels(
119
113
  return contextClients.listAllCompletionModels();
120
114
  }
121
115
 
122
- export async function listAllEmbeddingModels(
123
- this: ToolsService
124
- ): Promise<Record<string, string[]>> {
116
+ export async function listAllEmbeddingModels(): Promise<Record<string, string[]>> {
125
117
  // Get context from bound ToolsService
126
118
  const toolService = (
127
119
  this instanceof ToolsService ? this : services().Tools
@@ -0,0 +1,90 @@
1
+ import * as fs from "fs";
2
+ import { fileExists } from "../../../utils";
3
+ import { services, ToolsService } from "../../../services";
4
+ import { LanguageAgnosticParser } from "../../../plugins/tree-sitter/parser";
5
+ import { TreeEditor } from "../../../plugins/tree-sitter/editor";
6
+
7
+ /**
8
+ * Append a child node to a specific path in a file using tree-sitter AST parsing
9
+ */
10
+ export async function astAppendNode(filePath: string, parentPath: string, newContent: string): Promise<string> {
11
+ // Get context from bound ToolsService
12
+ const toolService = (
13
+ this instanceof ToolsService ? this : services().Tools
14
+ ) as ToolsService;
15
+
16
+ const context = toolService.getContext();
17
+
18
+ const exists = await fileExists(filePath);
19
+ if (!exists) {
20
+ throw new Error(`File not found: ${filePath}`);
21
+ }
22
+
23
+ // Read original content for event emission
24
+ let originalContent = "";
25
+ try {
26
+ originalContent = fs.readFileSync(filePath, "utf8");
27
+ } catch (error) {
28
+ throw new Error(`Failed to read file ${filePath}: ${error.message}`);
29
+ }
30
+
31
+ // Emit pre-edit blocking event
32
+ if (context.Events) {
33
+ await context.Events.emitBlocking("file:pre-edit", {
34
+ filePath,
35
+ operation: "ast-append-node",
36
+ content: newContent,
37
+ originalContent,
38
+ astParentPath: parentPath,
39
+ });
40
+ }
41
+
42
+ try {
43
+ if (!LanguageAgnosticParser.supportsFile(filePath)) {
44
+ throw new Error(`Unsupported file type for AST parsing: ${filePath}`);
45
+ }
46
+
47
+ const parser = LanguageAgnosticParser.createParserForFile(filePath);
48
+ const editor = new TreeEditor(parser, originalContent);
49
+ const updatedEditor = editor.appendChild(parentPath, newContent);
50
+ const updatedContent = updatedEditor.getCurrentText();
51
+
52
+ // Write the updated content back to the file
53
+ fs.writeFileSync(filePath, updatedContent, "utf8");
54
+
55
+ // Emit post-edit blocking event (only on success)
56
+ let eventResults: any[] = [];
57
+ if (context.Events) {
58
+ eventResults = await context.Events.emitBlocking("file:post-edit", {
59
+ filePath,
60
+ operation: "ast-append-node",
61
+ content: newContent,
62
+ originalContent,
63
+ updatedContent,
64
+ astParentPath: parentPath,
65
+ success: true,
66
+ });
67
+ }
68
+
69
+ const result = {
70
+ file: filePath,
71
+ parentPath,
72
+ action: "appendChild",
73
+ success: true,
74
+ message: `Successfully appended child node to path: ${parentPath}`,
75
+ };
76
+
77
+ // Format event results
78
+ let eventResultsText = "";
79
+ if (eventResults && eventResults.length > 0) {
80
+ eventResultsText =
81
+ "\n\nAdditional Information:\n" +
82
+ JSON.stringify(eventResults, null, 2);
83
+ }
84
+
85
+ return JSON.stringify(result, null, 2) + eventResultsText;
86
+ } catch (error: any) {
87
+ // Do NOT emit post-edit event on error
88
+ throw new Error(`Failed to append node in ${filePath}: ${error.message}`);
89
+ }
90
+ }
@@ -0,0 +1,88 @@
1
+ import * as fs from "fs";
2
+ import { fileExists } from "../../../utils";
3
+ import { services, ToolsService } from "../../../services";
4
+ import { LanguageAgnosticParser } from "../../../plugins/tree-sitter/parser";
5
+ import { TreeEditor } from "../../../plugins/tree-sitter/editor";
6
+
7
+ /**
8
+ * Delete a node at a specific path in a file using tree-sitter AST parsing
9
+ */
10
+ export async function astDeleteNode(filePath: string, path: string): Promise<string> {
11
+ // Get context from bound ToolsService
12
+ const toolService = (
13
+ this instanceof ToolsService ? this : services().Tools
14
+ ) as ToolsService;
15
+
16
+ const context = toolService.getContext();
17
+
18
+ const exists = await fileExists(filePath);
19
+ if (!exists) {
20
+ throw new Error(`File not found: ${filePath}`);
21
+ }
22
+
23
+ // Read original content for event emission
24
+ let originalContent = "";
25
+ try {
26
+ originalContent = fs.readFileSync(filePath, "utf8");
27
+ } catch (error) {
28
+ throw new Error(`Failed to read file ${filePath}: ${error.message}`);
29
+ }
30
+
31
+ // Emit pre-edit blocking event
32
+ if (context.Events) {
33
+ await context.Events.emitBlocking("file:pre-edit", {
34
+ filePath,
35
+ operation: "ast-delete-node",
36
+ originalContent,
37
+ astPath: path,
38
+ });
39
+ }
40
+
41
+ try {
42
+ if (!LanguageAgnosticParser.supportsFile(filePath)) {
43
+ throw new Error(`Unsupported file type for AST parsing: ${filePath}`);
44
+ }
45
+
46
+ const parser = LanguageAgnosticParser.createParserForFile(filePath);
47
+ const editor = new TreeEditor(parser, originalContent);
48
+ const updatedEditor = editor.deleteNodeByPath(path);
49
+ const updatedContent = updatedEditor.getCurrentText();
50
+
51
+ // Write the updated content back to the file
52
+ fs.writeFileSync(filePath, updatedContent, "utf8");
53
+
54
+ // Emit post-edit blocking event (only on success)
55
+ let eventResults: any[] = [];
56
+ if (context.Events) {
57
+ eventResults = await context.Events.emitBlocking("file:post-edit", {
58
+ filePath,
59
+ operation: "ast-delete-node",
60
+ originalContent,
61
+ updatedContent,
62
+ astPath: path,
63
+ success: true,
64
+ });
65
+ }
66
+
67
+ const result = {
68
+ file: filePath,
69
+ path,
70
+ action: "delete",
71
+ success: true,
72
+ message: `Successfully deleted node at path: ${path}`,
73
+ };
74
+
75
+ // Format event results
76
+ let eventResultsText = "";
77
+ if (eventResults && eventResults.length > 0) {
78
+ eventResultsText =
79
+ "\n\nAdditional Information:\n" +
80
+ JSON.stringify(eventResults, null, 2);
81
+ }
82
+
83
+ return JSON.stringify(result, null, 2) + eventResultsText;
84
+ } catch (error: any) {
85
+ // Do NOT emit post-edit event on error
86
+ throw new Error(`Failed to delete node in ${filePath}: ${error.message}`);
87
+ }
88
+ }
@@ -0,0 +1,95 @@
1
+ import * as fs from "fs";
2
+ import { fileExists } from "../../../utils";
3
+ import { services, ToolsService } from "../../../services";
4
+ import { LanguageAgnosticParser } from "../../../plugins/tree-sitter/parser";
5
+ import { TreeEditor } from "../../../plugins/tree-sitter/editor";
6
+
7
+ /**
8
+ * Update a node at a specific path in a file using tree-sitter AST parsing
9
+ */
10
+ export async function astEditNode(
11
+ filePath: string,
12
+ path: string,
13
+ newContent: string
14
+ ): Promise<string> {
15
+ // Get context from bound ToolsService
16
+ const toolService = (
17
+ this instanceof ToolsService ? this : services().Tools
18
+ ) as ToolsService;
19
+
20
+ const context = toolService.getContext();
21
+
22
+ const exists = await fileExists(filePath);
23
+ if (!exists) {
24
+ throw new Error(`File not found: ${filePath}`);
25
+ }
26
+
27
+ // Read original content for event emission
28
+ let originalContent = "";
29
+ try {
30
+ originalContent = fs.readFileSync(filePath, "utf8");
31
+ } catch (error) {
32
+ throw new Error(`Failed to read file ${filePath}: ${error.message}`);
33
+ }
34
+
35
+ // Emit pre-edit blocking event
36
+ if (context.Events) {
37
+ await context.Events.emitBlocking("file:pre-edit", {
38
+ filePath,
39
+ operation: "ast-edit-node",
40
+ content: newContent,
41
+ originalContent,
42
+ astPath: path,
43
+ });
44
+ }
45
+
46
+ try {
47
+ if (!LanguageAgnosticParser.supportsFile(filePath)) {
48
+ throw new Error(`Unsupported file type for AST parsing: ${filePath}`);
49
+ }
50
+
51
+ const parser = LanguageAgnosticParser.createParserForFile(filePath);
52
+ const editor = new TreeEditor(parser, originalContent);
53
+ const updatedEditor = editor.updateNodeByPath(path, newContent);
54
+ const updatedContent = updatedEditor.getCurrentText();
55
+
56
+ // Write the updated content back to the file
57
+ fs.writeFileSync(filePath, updatedContent, "utf8");
58
+
59
+ // Emit post-edit blocking event
60
+ let eventResults: any[] = [];
61
+ if (context.Events) {
62
+ eventResults = await context.Events.emitBlocking("file:post-edit", {
63
+ filePath,
64
+ operation: "ast-edit-node",
65
+ content: newContent,
66
+ originalContent,
67
+ updatedContent,
68
+ astPath: path,
69
+ success: true,
70
+ });
71
+ }
72
+
73
+ const result = {
74
+ file: filePath,
75
+ path,
76
+ action: "update",
77
+ success: true,
78
+ message: `Successfully updated node at path: ${path}`,
79
+ };
80
+
81
+ // Format event results
82
+ let eventResultsText = "";
83
+ if (eventResults && eventResults.length > 0) {
84
+ eventResultsText =
85
+ "\n\nAdditional Information:\n" +
86
+ JSON.stringify(eventResults, null, 2);
87
+ }
88
+
89
+ return JSON.stringify(result, null, 2) + eventResultsText;
90
+ } catch (error: any) {
91
+ // Do NOT emit post-edit event on error
92
+
93
+ throw new Error(`Failed to edit node in ${filePath}: ${error.message}`);
94
+ }
95
+ }
@@ -0,0 +1,73 @@
1
+ import * as fs from "fs";
2
+ import { fileExists } from "../../../utils";
3
+ import { services, ToolsService } from "../../../services";
4
+ import { LanguageAgnosticParser } from "../../../plugins/tree-sitter/parser";
5
+ import { TreeEditor } from "../../../plugins/tree-sitter/editor";
6
+
7
+ /**
8
+ * Get the AST path for a specific line of text in a file using tree-sitter parsing
9
+ */
10
+ export async function astGetPathForLine(
11
+ filePath: string,
12
+ searchText: string
13
+ ): Promise<string> {
14
+ // Get context from bound ToolsService
15
+ const toolService = (
16
+ this instanceof ToolsService ? this : services().Tools
17
+ ) as ToolsService;
18
+
19
+ const context = toolService.getContext();
20
+
21
+ // Emit pre-action event
22
+ if (context.Events) {
23
+ await context.Events.emitBlocking("ast:pre-get-path-for-line", {
24
+ filePath,
25
+ searchText,
26
+ });
27
+ }
28
+
29
+ const exists = await fileExists(filePath);
30
+ if (!exists) {
31
+ throw new Error(`File not found: ${filePath}`);
32
+ }
33
+
34
+ try {
35
+ const content = fs.readFileSync(filePath, "utf8");
36
+
37
+ if (!LanguageAgnosticParser.supportsFile(filePath)) {
38
+ throw new Error(`Unsupported file type for AST parsing: ${filePath}`);
39
+ }
40
+
41
+ const parser = LanguageAgnosticParser.createParserForFile(filePath);
42
+ const tree = parser.parseString(content);
43
+ const pathLocations = parser.findPathsForLine(tree, searchText);
44
+
45
+ // Emit post-action event
46
+ if (context.Events) {
47
+ await context.Events.emitNonBlocking("ast:post-get-path-for-line", {
48
+ filePath,
49
+ searchText,
50
+ pathCount: pathLocations.length,
51
+ });
52
+ }
53
+
54
+ const result = {
55
+ file: filePath,
56
+ searchText,
57
+ language: parser.getLanguage(),
58
+ totalMatches: pathLocations.length,
59
+ matches: pathLocations.map((loc) => ({
60
+ path: loc.path,
61
+ line: loc.row + 1, // Convert from 0-based to 1-based line numbering
62
+ column: loc.column + 1, // Convert from 0-based to 1-based column numbering
63
+ text: loc.text,
64
+ })),
65
+ };
66
+
67
+ return JSON.stringify(result, null, 2);
68
+ } catch (error: any) {
69
+ throw new Error(
70
+ `Failed to get path for line in ${filePath}: ${error.message}`
71
+ );
72
+ }
73
+ }