@tyvm/knowhow 0.0.46 → 0.0.48

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 (461) 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 +30 -24
  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 +107 -64
  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/types.ts +1 -1
  40. package/src/clients/xai.ts +15 -5
  41. package/src/config.ts +17 -5
  42. package/src/dataset/diffs/generate.ts +2 -2
  43. package/src/dataset/diffs/jsonl.ts +0 -1
  44. package/src/embeddings.ts +6 -4
  45. package/src/index.ts +11 -5
  46. package/src/plugins/GitPlugin.ts +530 -0
  47. package/src/plugins/LinterPlugin.ts +89 -0
  48. package/src/plugins/PluginBase.ts +4 -2
  49. package/src/plugins/asana.ts +4 -2
  50. package/src/plugins/downloader/plugin.ts +5 -2
  51. package/src/plugins/embedding.ts +24 -4
  52. package/src/plugins/figma.ts +7 -3
  53. package/src/plugins/github.ts +4 -2
  54. package/src/plugins/jira.ts +4 -2
  55. package/src/plugins/language.ts +134 -27
  56. package/src/plugins/linear.ts +4 -2
  57. package/src/plugins/notion.ts +4 -2
  58. package/src/plugins/plugins.ts +27 -16
  59. package/src/plugins/tree-sitter/editor.ts +369 -0
  60. package/src/plugins/tree-sitter/lang-packs/index.ts +23 -0
  61. package/src/plugins/tree-sitter/lang-packs/java.ts +59 -0
  62. package/src/plugins/tree-sitter/lang-packs/javascript.ts +57 -0
  63. package/src/plugins/tree-sitter/lang-packs/python.ts +45 -0
  64. package/src/plugins/tree-sitter/lang-packs/types.ts +79 -0
  65. package/src/plugins/tree-sitter/lang-packs/typescript.ts +49 -0
  66. package/src/plugins/tree-sitter/parser.ts +444 -0
  67. package/src/plugins/tree-sitter/simple-paths.ts +467 -0
  68. package/src/plugins/types.ts +11 -0
  69. package/src/plugins/url.ts +5 -3
  70. package/src/plugins/vim.ts +8 -5
  71. package/src/processors/CustomVariables.ts +19 -7
  72. package/src/processors/TokenCompressor.ts +13 -13
  73. package/src/processors/ToolResponseCache.ts +15 -6
  74. package/src/services/EmbeddingService.ts +18 -9
  75. package/src/services/EventService.ts +80 -0
  76. package/src/services/Mcp.ts +5 -0
  77. package/src/services/S3.ts +4 -3
  78. package/src/services/Tools.ts +125 -53
  79. package/src/services/index.ts +16 -11
  80. package/src/services/types.ts +3 -3
  81. package/src/types.ts +7 -2
  82. package/src/worker.ts +14 -1
  83. package/test-comprehensive.ts +31 -0
  84. package/tests/clients/AIClient.test.ts +490 -0
  85. package/tests/manual/agent-events/run-test.ts +203 -0
  86. package/tests/{integration → manual/file-edits}/figma.test.ts +1 -1
  87. package/tests/{integration → manual/file-edits}/fileblocks/readwrite.test.ts +7 -3
  88. package/tests/{integration → manual/file-edits}/patching.test.ts +11 -8
  89. package/tests/plugins/language/languagePlugin-content-triggers.test.ts +332 -0
  90. package/tests/plugins/language/languagePlugin-integration.test.ts +456 -0
  91. package/tests/plugins/language/languagePlugin.test.ts +363 -0
  92. package/tests/processors/Base64ImageDetector.test.ts +403 -0
  93. package/tests/processors/CustomVariables.test.ts +430 -0
  94. package/tests/processors/HarmonyToolProcessor.test.ts +490 -0
  95. package/tests/processors/TokenCompressor.test.ts +391 -0
  96. package/tests/processors/ToolResponseCache.test.ts +688 -0
  97. package/tests/services/Tools.test.ts +1339 -0
  98. package/tests/test.spec.ts +162 -117
  99. package/tests/tree-sitter/editor.test.ts +113 -0
  100. package/tests/tree-sitter/invalid.test.ts +299 -0
  101. package/tests/tree-sitter/paths/common-edits.test.ts +564 -0
  102. package/tests/tree-sitter/paths/debug-exact-position.test.ts +44 -0
  103. package/tests/tree-sitter/paths/debug-line-indexing.test.ts +49 -0
  104. package/tests/tree-sitter/paths/debug-paths.test.ts +90 -0
  105. package/tests/tree-sitter/paths/paths.test.ts +170 -0
  106. package/tests/tree-sitter/paths/simple-paths.test.ts +367 -0
  107. package/tests/tree-sitter/sample-after.ts +48 -0
  108. package/tests/tree-sitter/sample-before.ts +25 -0
  109. package/tests/tree-sitter/test-files/completely-broken.ts +7 -0
  110. package/tests/tree-sitter/test-files/duplicate-braces.ts +39 -0
  111. package/tests/tree-sitter/test-files/invalid-nesting.ts +39 -0
  112. package/tests/tree-sitter/test-files/malformed-signature.ts +39 -0
  113. package/tests/tree-sitter/test-files/mismatched-parens.ts +39 -0
  114. package/tests/tree-sitter/test-files/missing-semicolon.ts +39 -0
  115. package/tests/tree-sitter/test-files/partially-broken.ts +20 -0
  116. package/tests/tree-sitter/test-files/specific-errors.ts +14 -0
  117. package/tests/tree-sitter/test-files/unclosed-string.ts +39 -0
  118. package/tests/tree-sitter/tree-sitter.test.ts +251 -0
  119. package/ts_build/package.json +8 -3
  120. package/ts_build/src/agents/base/base.d.ts +2 -2
  121. package/ts_build/src/agents/base/base.js +24 -20
  122. package/ts_build/src/agents/base/base.js.map +1 -1
  123. package/ts_build/src/agents/patcher/patcher.js +26 -5
  124. package/ts_build/src/agents/patcher/patcher.js.map +1 -1
  125. package/ts_build/src/agents/tools/agentCall.js +2 -1
  126. package/ts_build/src/agents/tools/agentCall.js.map +1 -1
  127. package/ts_build/src/agents/tools/aiClient.d.ts +7 -8
  128. package/ts_build/src/agents/tools/aiClient.js.map +1 -1
  129. package/ts_build/src/agents/tools/ast/astAppendNode.d.ts +1 -0
  130. package/ts_build/src/agents/tools/ast/astAppendNode.js +96 -0
  131. package/ts_build/src/agents/tools/ast/astAppendNode.js.map +1 -0
  132. package/ts_build/src/agents/tools/ast/astDeleteNode.d.ts +1 -0
  133. package/ts_build/src/agents/tools/ast/astDeleteNode.js +94 -0
  134. package/ts_build/src/agents/tools/ast/astDeleteNode.js.map +1 -0
  135. package/ts_build/src/agents/tools/ast/astEditNode.d.ts +1 -0
  136. package/ts_build/src/agents/tools/ast/astEditNode.js +96 -0
  137. package/ts_build/src/agents/tools/ast/astEditNode.js.map +1 -0
  138. package/ts_build/src/agents/tools/ast/astGetPathForLine.d.ts +1 -0
  139. package/ts_build/src/agents/tools/ast/astGetPathForLine.js +78 -0
  140. package/ts_build/src/agents/tools/ast/astGetPathForLine.js.map +1 -0
  141. package/ts_build/src/agents/tools/ast/astListPaths.d.ts +1 -0
  142. package/ts_build/src/agents/tools/ast/astListPaths.js +78 -0
  143. package/ts_build/src/agents/tools/ast/astListPaths.js.map +1 -0
  144. package/ts_build/src/agents/tools/ast/index.d.ts +5 -0
  145. package/ts_build/src/agents/tools/ast/index.js +14 -0
  146. package/ts_build/src/agents/tools/ast/index.js.map +1 -0
  147. package/ts_build/src/agents/tools/astAppendNode.d.ts +1 -0
  148. package/ts_build/src/agents/tools/astAppendNode.js +98 -0
  149. package/ts_build/src/agents/tools/astAppendNode.js.map +1 -0
  150. package/ts_build/src/agents/tools/astDeleteNode.d.ts +1 -0
  151. package/ts_build/src/agents/tools/astDeleteNode.js +95 -0
  152. package/ts_build/src/agents/tools/astDeleteNode.js.map +1 -0
  153. package/ts_build/src/agents/tools/astEditNode.d.ts +1 -0
  154. package/ts_build/src/agents/tools/astEditNode.js +98 -0
  155. package/ts_build/src/agents/tools/astEditNode.js.map +1 -0
  156. package/ts_build/src/agents/tools/astGetPathForLine.d.ts +1 -0
  157. package/ts_build/src/agents/tools/astGetPathForLine.js +89 -0
  158. package/ts_build/src/agents/tools/astGetPathForLine.js.map +1 -0
  159. package/ts_build/src/agents/tools/astListPaths.d.ts +1 -0
  160. package/ts_build/src/agents/tools/astListPaths.js +82 -0
  161. package/ts_build/src/agents/tools/astListPaths.js.map +1 -0
  162. package/ts_build/src/agents/tools/callPlugin.js +4 -2
  163. package/ts_build/src/agents/tools/callPlugin.js.map +1 -1
  164. package/ts_build/src/agents/tools/embeddingSearch.js +3 -2
  165. package/ts_build/src/agents/tools/embeddingSearch.js.map +1 -1
  166. package/ts_build/src/agents/tools/execCommand.d.ts +2 -2
  167. package/ts_build/src/agents/tools/execCommand.js +201 -67
  168. package/ts_build/src/agents/tools/execCommand.js.map +1 -1
  169. package/ts_build/src/agents/tools/fileSearch.d.ts +1 -1
  170. package/ts_build/src/agents/tools/fileSearch.js +11 -15
  171. package/ts_build/src/agents/tools/fileSearch.js.map +1 -1
  172. package/ts_build/src/agents/tools/github/index.d.ts +1 -1
  173. package/ts_build/src/agents/tools/index.d.ts +1 -0
  174. package/ts_build/src/agents/tools/index.js +1 -0
  175. package/ts_build/src/agents/tools/index.js.map +1 -1
  176. package/ts_build/src/agents/tools/language/definitions.js +11 -2
  177. package/ts_build/src/agents/tools/language/definitions.js.map +1 -1
  178. package/ts_build/src/agents/tools/language/index.js +4 -3
  179. package/ts_build/src/agents/tools/language/index.js.map +1 -1
  180. package/ts_build/src/agents/tools/lintFile.js +4 -2
  181. package/ts_build/src/agents/tools/lintFile.js.map +1 -1
  182. package/ts_build/src/agents/tools/list.js +185 -49
  183. package/ts_build/src/agents/tools/list.js.map +1 -1
  184. package/ts_build/src/agents/tools/patch.js +33 -10
  185. package/ts_build/src/agents/tools/patch.js.map +1 -1
  186. package/ts_build/src/agents/tools/readBlocks.js +23 -0
  187. package/ts_build/src/agents/tools/readBlocks.js.map +1 -1
  188. package/ts_build/src/agents/tools/readFile.js +14 -0
  189. package/ts_build/src/agents/tools/readFile.js.map +1 -1
  190. package/ts_build/src/agents/tools/stringReplace.js +19 -2
  191. package/ts_build/src/agents/tools/stringReplace.js.map +1 -1
  192. package/ts_build/src/agents/tools/writeFile.js +40 -0
  193. package/ts_build/src/agents/tools/writeFile.js.map +1 -1
  194. package/ts_build/src/agents/tools/ycmd/server.js +5 -0
  195. package/ts_build/src/agents/tools/ycmd/server.js.map +1 -1
  196. package/ts_build/src/chat/CliChatService.d.ts +1 -0
  197. package/ts_build/src/chat/CliChatService.js +6 -2
  198. package/ts_build/src/chat/CliChatService.js.map +1 -1
  199. package/ts_build/src/chat/modules/AgentModule.d.ts +5 -1
  200. package/ts_build/src/chat/modules/AgentModule.js +53 -31
  201. package/ts_build/src/chat/modules/AgentModule.js.map +1 -1
  202. package/ts_build/src/chat/modules/AskModule.js.map +1 -1
  203. package/ts_build/src/chat/modules/SetupModule.js +4 -3
  204. package/ts_build/src/chat/modules/SetupModule.js.map +1 -1
  205. package/ts_build/src/chat/modules/SystemModule.js +19 -4
  206. package/ts_build/src/chat/modules/SystemModule.js.map +1 -1
  207. package/ts_build/src/chat/modules/index.d.ts +5 -0
  208. package/ts_build/src/chat/modules/index.js +14 -0
  209. package/ts_build/src/chat/modules/index.js.map +1 -0
  210. package/ts_build/src/chat/types.d.ts +2 -0
  211. package/ts_build/src/chat-old.js +3 -3
  212. package/ts_build/src/chat-old.js.map +1 -1
  213. package/ts_build/src/clients/anthropic.d.ts +1 -0
  214. package/ts_build/src/clients/anthropic.js +22 -1
  215. package/ts_build/src/clients/anthropic.js.map +1 -1
  216. package/ts_build/src/clients/openai.js +1 -1
  217. package/ts_build/src/clients/openai.js.map +1 -1
  218. package/ts_build/src/clients/types.d.ts +1 -1
  219. package/ts_build/src/clients/xai.d.ts +7 -0
  220. package/ts_build/src/clients/xai.js +13 -4
  221. package/ts_build/src/clients/xai.js.map +1 -1
  222. package/ts_build/src/config.js +14 -3
  223. package/ts_build/src/config.js.map +1 -1
  224. package/ts_build/src/dataset/diffs/generate.js +2 -2
  225. package/ts_build/src/dataset/diffs/generate.js.map +1 -1
  226. package/ts_build/src/dataset/diffs/jsonl.js.map +1 -1
  227. package/ts_build/src/embeddings.js +7 -9
  228. package/ts_build/src/embeddings.js.map +1 -1
  229. package/ts_build/src/index.js +10 -10
  230. package/ts_build/src/index.js.map +1 -1
  231. package/ts_build/src/plugins/GitPlugin.d.ts +39 -0
  232. package/ts_build/src/plugins/GitPlugin.js +439 -0
  233. package/ts_build/src/plugins/GitPlugin.js.map +1 -0
  234. package/ts_build/src/plugins/LinterPlugin.d.ts +15 -0
  235. package/ts_build/src/plugins/LinterPlugin.js +65 -0
  236. package/ts_build/src/plugins/LinterPlugin.js.map +1 -0
  237. package/ts_build/src/plugins/PluginBase.d.ts +4 -3
  238. package/ts_build/src/plugins/PluginBase.js +3 -3
  239. package/ts_build/src/plugins/PluginBase.js.map +1 -1
  240. package/ts_build/src/plugins/asana.d.ts +3 -1
  241. package/ts_build/src/plugins/asana.js +3 -2
  242. package/ts_build/src/plugins/asana.js.map +1 -1
  243. package/ts_build/src/plugins/downloader/plugin.d.ts +3 -1
  244. package/ts_build/src/plugins/downloader/plugin.js +3 -2
  245. package/ts_build/src/plugins/downloader/plugin.js.map +1 -1
  246. package/ts_build/src/plugins/embedding.d.ts +5 -1
  247. package/ts_build/src/plugins/embedding.js +15 -3
  248. package/ts_build/src/plugins/embedding.js.map +1 -1
  249. package/ts_build/src/plugins/figma.d.ts +3 -1
  250. package/ts_build/src/plugins/figma.js +28 -4
  251. package/ts_build/src/plugins/figma.js.map +1 -1
  252. package/ts_build/src/plugins/github.d.ts +3 -1
  253. package/ts_build/src/plugins/github.js +3 -2
  254. package/ts_build/src/plugins/github.js.map +1 -1
  255. package/ts_build/src/plugins/jira.d.ts +3 -1
  256. package/ts_build/src/plugins/jira.js +3 -2
  257. package/ts_build/src/plugins/jira.js.map +1 -1
  258. package/ts_build/src/plugins/language.d.ts +7 -4
  259. package/ts_build/src/plugins/language.js +85 -20
  260. package/ts_build/src/plugins/language.js.map +1 -1
  261. package/ts_build/src/plugins/linear.d.ts +3 -1
  262. package/ts_build/src/plugins/linear.js +3 -2
  263. package/ts_build/src/plugins/linear.js.map +1 -1
  264. package/ts_build/src/plugins/notion.d.ts +3 -1
  265. package/ts_build/src/plugins/notion.js +3 -2
  266. package/ts_build/src/plugins/notion.js.map +1 -1
  267. package/ts_build/src/plugins/plugins.d.ts +4 -3
  268. package/ts_build/src/plugins/plugins.js +24 -14
  269. package/ts_build/src/plugins/plugins.js.map +1 -1
  270. package/ts_build/src/plugins/tree-sitter/editor.d.ts +34 -0
  271. package/ts_build/src/plugins/tree-sitter/editor.js +218 -0
  272. package/ts_build/src/plugins/tree-sitter/editor.js.map +1 -0
  273. package/ts_build/src/plugins/tree-sitter/human-readable-paths-new.d.ts +29 -0
  274. package/ts_build/src/plugins/tree-sitter/human-readable-paths-new.js +538 -0
  275. package/ts_build/src/plugins/tree-sitter/human-readable-paths-new.js.map +1 -0
  276. package/ts_build/src/plugins/tree-sitter/human-readable-paths.d.ts +22 -0
  277. package/ts_build/src/plugins/tree-sitter/human-readable-paths.js +332 -0
  278. package/ts_build/src/plugins/tree-sitter/human-readable-paths.js.map +1 -0
  279. package/ts_build/src/plugins/tree-sitter/lang-packs/index.d.ts +8 -0
  280. package/ts_build/src/plugins/tree-sitter/lang-packs/index.js +26 -0
  281. package/ts_build/src/plugins/tree-sitter/lang-packs/index.js.map +1 -0
  282. package/ts_build/src/plugins/tree-sitter/lang-packs/java.d.ts +2 -0
  283. package/ts_build/src/plugins/tree-sitter/lang-packs/java.js +61 -0
  284. package/ts_build/src/plugins/tree-sitter/lang-packs/java.js.map +1 -0
  285. package/ts_build/src/plugins/tree-sitter/lang-packs/javascript.d.ts +2 -0
  286. package/ts_build/src/plugins/tree-sitter/lang-packs/javascript.js +59 -0
  287. package/ts_build/src/plugins/tree-sitter/lang-packs/javascript.js.map +1 -0
  288. package/ts_build/src/plugins/tree-sitter/lang-packs/python.d.ts +2 -0
  289. package/ts_build/src/plugins/tree-sitter/lang-packs/python.js +47 -0
  290. package/ts_build/src/plugins/tree-sitter/lang-packs/python.js.map +1 -0
  291. package/ts_build/src/plugins/tree-sitter/lang-packs/types.d.ts +43 -0
  292. package/ts_build/src/plugins/tree-sitter/lang-packs/types.js +3 -0
  293. package/ts_build/src/plugins/tree-sitter/lang-packs/types.js.map +1 -0
  294. package/ts_build/src/plugins/tree-sitter/lang-packs/typescript.d.ts +2 -0
  295. package/ts_build/src/plugins/tree-sitter/lang-packs/typescript.js +50 -0
  296. package/ts_build/src/plugins/tree-sitter/lang-packs/typescript.js.map +1 -0
  297. package/ts_build/src/plugins/tree-sitter/parser.d.ts +75 -0
  298. package/ts_build/src/plugins/tree-sitter/parser.js +306 -0
  299. package/ts_build/src/plugins/tree-sitter/parser.js.map +1 -0
  300. package/ts_build/src/plugins/tree-sitter/simple-paths.d.ts +22 -0
  301. package/ts_build/src/plugins/tree-sitter/simple-paths.js +332 -0
  302. package/ts_build/src/plugins/tree-sitter/simple-paths.js.map +1 -0
  303. package/ts_build/src/plugins/types.d.ts +10 -0
  304. package/ts_build/src/plugins/url.d.ts +3 -2
  305. package/ts_build/src/plugins/url.js +3 -2
  306. package/ts_build/src/plugins/url.js.map +1 -1
  307. package/ts_build/src/plugins/vim.d.ts +4 -2
  308. package/ts_build/src/plugins/vim.js +6 -8
  309. package/ts_build/src/plugins/vim.js.map +1 -1
  310. package/ts_build/src/processors/CustomVariables.js +12 -3
  311. package/ts_build/src/processors/CustomVariables.js.map +1 -1
  312. package/ts_build/src/processors/TokenCompressor.js +8 -11
  313. package/ts_build/src/processors/TokenCompressor.js.map +1 -1
  314. package/ts_build/src/processors/ToolResponseCache.d.ts +2 -2
  315. package/ts_build/src/processors/ToolResponseCache.js +12 -2
  316. package/ts_build/src/processors/ToolResponseCache.js.map +1 -1
  317. package/ts_build/src/services/EmbeddingService.d.ts +10 -1
  318. package/ts_build/src/services/EmbeddingService.js +12 -12
  319. package/ts_build/src/services/EmbeddingService.js.map +1 -1
  320. package/ts_build/src/services/EventService.d.ts +7 -0
  321. package/ts_build/src/services/EventService.js +49 -0
  322. package/ts_build/src/services/EventService.js.map +1 -1
  323. package/ts_build/src/services/Mcp.js +8 -0
  324. package/ts_build/src/services/Mcp.js.map +1 -1
  325. package/ts_build/src/services/S3.js +4 -3
  326. package/ts_build/src/services/S3.js.map +1 -1
  327. package/ts_build/src/services/Tools.d.ts +1 -0
  328. package/ts_build/src/services/Tools.js +97 -35
  329. package/ts_build/src/services/Tools.js.map +1 -1
  330. package/ts_build/src/services/index.d.ts +4 -5
  331. package/ts_build/src/services/index.js +14 -9
  332. package/ts_build/src/services/index.js.map +1 -1
  333. package/ts_build/src/services/types.js +3 -3
  334. package/ts_build/src/services/types.js.map +1 -1
  335. package/ts_build/src/types.d.ts +7 -1
  336. package/ts_build/src/types.js +4 -0
  337. package/ts_build/src/types.js.map +1 -1
  338. package/ts_build/src/worker.js +12 -1
  339. package/ts_build/src/worker.js.map +1 -1
  340. package/ts_build/tests/clients/AIClient.test.d.ts +1 -0
  341. package/ts_build/tests/clients/AIClient.test.js +377 -0
  342. package/ts_build/tests/clients/AIClient.test.js.map +1 -0
  343. package/ts_build/tests/languagePlugin.test.js +217 -11
  344. package/ts_build/tests/languagePlugin.test.js.map +1 -1
  345. package/ts_build/tests/manual/agent-events/event-handler-reliability.test.d.ts +1 -0
  346. package/ts_build/tests/manual/agent-events/event-handler-reliability.test.js +315 -0
  347. package/ts_build/tests/manual/agent-events/event-handler-reliability.test.js.map +1 -0
  348. package/ts_build/tests/manual/agent-events/run-test.d.ts +2 -0
  349. package/ts_build/tests/manual/agent-events/run-test.js +148 -0
  350. package/ts_build/tests/manual/agent-events/run-test.js.map +1 -0
  351. package/ts_build/tests/manual/file-edits/figma.test.d.ts +1 -0
  352. package/ts_build/tests/manual/file-edits/figma.test.js +47 -0
  353. package/ts_build/tests/manual/file-edits/figma.test.js.map +1 -0
  354. package/ts_build/tests/manual/file-edits/fileblocks/readwrite.test.d.ts +1 -0
  355. package/ts_build/tests/manual/file-edits/fileblocks/readwrite.test.js +100 -0
  356. package/ts_build/tests/manual/file-edits/fileblocks/readwrite.test.js.map +1 -0
  357. package/ts_build/tests/manual/file-edits/patching.test.d.ts +1 -0
  358. package/ts_build/tests/manual/file-edits/patching.test.js +119 -0
  359. package/ts_build/tests/manual/file-edits/patching.test.js.map +1 -0
  360. package/ts_build/tests/plugins/language/languagePlugin-content-triggers.test.d.ts +1 -0
  361. package/ts_build/tests/plugins/language/languagePlugin-content-triggers.test.js +277 -0
  362. package/ts_build/tests/plugins/language/languagePlugin-content-triggers.test.js.map +1 -0
  363. package/ts_build/tests/plugins/language/languagePlugin-integration.test.d.ts +1 -0
  364. package/ts_build/tests/plugins/language/languagePlugin-integration.test.js +331 -0
  365. package/ts_build/tests/plugins/language/languagePlugin-integration.test.js.map +1 -0
  366. package/ts_build/tests/plugins/language/languagePlugin.test.d.ts +1 -0
  367. package/ts_build/tests/plugins/language/languagePlugin.test.js +286 -0
  368. package/ts_build/tests/plugins/language/languagePlugin.test.js.map +1 -0
  369. package/ts_build/tests/processors/Base64ImageDetector.test.d.ts +1 -0
  370. package/ts_build/tests/processors/Base64ImageDetector.test.js +351 -0
  371. package/ts_build/tests/processors/Base64ImageDetector.test.js.map +1 -0
  372. package/ts_build/tests/processors/CustomVariables.test.d.ts +1 -0
  373. package/ts_build/tests/processors/CustomVariables.test.js +351 -0
  374. package/ts_build/tests/processors/CustomVariables.test.js.map +1 -0
  375. package/ts_build/tests/processors/HarmonyToolProcessor.test.d.ts +1 -0
  376. package/ts_build/tests/processors/HarmonyToolProcessor.test.js +382 -0
  377. package/ts_build/tests/processors/HarmonyToolProcessor.test.js.map +1 -0
  378. package/ts_build/tests/processors/TokenCompressor.test.d.ts +1 -0
  379. package/ts_build/tests/processors/TokenCompressor.test.js +300 -0
  380. package/ts_build/tests/processors/TokenCompressor.test.js.map +1 -0
  381. package/ts_build/tests/processors/ToolResponseCache.test.d.ts +1 -0
  382. package/ts_build/tests/processors/ToolResponseCache.test.js +539 -0
  383. package/ts_build/tests/processors/ToolResponseCache.test.js.map +1 -0
  384. package/ts_build/tests/services/Plugins/plugin-event-integration.test.d.ts +1 -0
  385. package/ts_build/tests/services/Plugins/plugin-event-integration.test.js +232 -0
  386. package/ts_build/tests/services/Plugins/plugin-event-integration.test.js.map +1 -0
  387. package/ts_build/tests/services/Tools.test.d.ts +1 -0
  388. package/ts_build/tests/services/Tools.test.js +1059 -0
  389. package/ts_build/tests/services/Tools.test.js.map +1 -0
  390. package/ts_build/tests/test.spec.js +110 -68
  391. package/ts_build/tests/test.spec.js.map +1 -1
  392. package/ts_build/tests/tree-sitter/editor.test.d.ts +1 -0
  393. package/ts_build/tests/tree-sitter/editor.test.js +85 -0
  394. package/ts_build/tests/tree-sitter/editor.test.js.map +1 -0
  395. package/ts_build/tests/tree-sitter/invalid.test.d.ts +1 -0
  396. package/ts_build/tests/tree-sitter/invalid.test.js +198 -0
  397. package/ts_build/tests/tree-sitter/invalid.test.js.map +1 -0
  398. package/ts_build/tests/tree-sitter/paths/common-edits.test.d.ts +1 -0
  399. package/ts_build/tests/tree-sitter/paths/common-edits.test.js +347 -0
  400. package/ts_build/tests/tree-sitter/paths/common-edits.test.js.map +1 -0
  401. package/ts_build/tests/tree-sitter/paths/debug-exact-position.test.d.ts +1 -0
  402. package/ts_build/tests/tree-sitter/paths/debug-exact-position.test.js +35 -0
  403. package/ts_build/tests/tree-sitter/paths/debug-exact-position.test.js.map +1 -0
  404. package/ts_build/tests/tree-sitter/paths/debug-line-indexing.test.d.ts +1 -0
  405. package/ts_build/tests/tree-sitter/paths/debug-line-indexing.test.js +38 -0
  406. package/ts_build/tests/tree-sitter/paths/debug-line-indexing.test.js.map +1 -0
  407. package/ts_build/tests/tree-sitter/paths/debug-paths.test.d.ts +1 -0
  408. package/ts_build/tests/tree-sitter/paths/debug-paths.test.js +74 -0
  409. package/ts_build/tests/tree-sitter/paths/debug-paths.test.js.map +1 -0
  410. package/ts_build/tests/tree-sitter/paths/human-readable-paths.test.d.ts +1 -0
  411. package/ts_build/tests/tree-sitter/paths/human-readable-paths.test.js +302 -0
  412. package/ts_build/tests/tree-sitter/paths/human-readable-paths.test.js.map +1 -0
  413. package/ts_build/tests/tree-sitter/paths/paths.test.d.ts +1 -0
  414. package/ts_build/tests/tree-sitter/paths/paths.test.js +116 -0
  415. package/ts_build/tests/tree-sitter/paths/paths.test.js.map +1 -0
  416. package/ts_build/tests/tree-sitter/paths/simple-paths.test.d.ts +1 -0
  417. package/ts_build/tests/tree-sitter/paths/simple-paths.test.js +302 -0
  418. package/ts_build/tests/tree-sitter/paths/simple-paths.test.js.map +1 -0
  419. package/ts_build/tests/tree-sitter/sample-after.d.ts +11 -0
  420. package/ts_build/tests/tree-sitter/sample-after.js +44 -0
  421. package/ts_build/tests/tree-sitter/sample-after.js.map +1 -0
  422. package/ts_build/tests/tree-sitter/sample-before.d.ts +9 -0
  423. package/ts_build/tests/tree-sitter/sample-before.js +28 -0
  424. package/ts_build/tests/tree-sitter/sample-before.js.map +1 -0
  425. package/ts_build/tests/tree-sitter/test-files/completely-broken.d.ts +2 -0
  426. package/ts_build/tests/tree-sitter/test-files/completely-broken.js +17 -0
  427. package/ts_build/tests/tree-sitter/test-files/completely-broken.js.map +1 -0
  428. package/ts_build/tests/tree-sitter/test-files/duplicate-braces.d.ts +8 -0
  429. package/ts_build/tests/tree-sitter/test-files/duplicate-braces.js +38 -0
  430. package/ts_build/tests/tree-sitter/test-files/duplicate-braces.js.map +1 -0
  431. package/ts_build/tests/tree-sitter/test-files/invalid-nesting.d.ts +8 -0
  432. package/ts_build/tests/tree-sitter/test-files/invalid-nesting.js +38 -0
  433. package/ts_build/tests/tree-sitter/test-files/invalid-nesting.js.map +1 -0
  434. package/ts_build/tests/tree-sitter/test-files/malformed-signature.d.ts +8 -0
  435. package/ts_build/tests/tree-sitter/test-files/malformed-signature.js +38 -0
  436. package/ts_build/tests/tree-sitter/test-files/malformed-signature.js.map +1 -0
  437. package/ts_build/tests/tree-sitter/test-files/mismatched-parens.d.ts +10 -0
  438. package/ts_build/tests/tree-sitter/test-files/mismatched-parens.js +38 -0
  439. package/ts_build/tests/tree-sitter/test-files/mismatched-parens.js.map +1 -0
  440. package/ts_build/tests/tree-sitter/test-files/missing-semicolon.d.ts +8 -0
  441. package/ts_build/tests/tree-sitter/test-files/missing-semicolon.js +38 -0
  442. package/ts_build/tests/tree-sitter/test-files/missing-semicolon.js.map +1 -0
  443. package/ts_build/tests/tree-sitter/test-files/partially-broken.d.ts +6 -0
  444. package/ts_build/tests/tree-sitter/test-files/partially-broken.js +20 -0
  445. package/ts_build/tests/tree-sitter/test-files/partially-broken.js.map +1 -0
  446. package/ts_build/tests/tree-sitter/test-files/specific-errors.d.ts +7 -0
  447. package/ts_build/tests/tree-sitter/test-files/specific-errors.js +14 -0
  448. package/ts_build/tests/tree-sitter/test-files/specific-errors.js.map +1 -0
  449. package/ts_build/tests/tree-sitter/test-files/unclosed-string.d.ts +8 -0
  450. package/ts_build/tests/tree-sitter/test-files/unclosed-string.js +38 -0
  451. package/ts_build/tests/tree-sitter/test-files/unclosed-string.js.map +1 -0
  452. package/ts_build/tests/tree-sitter/tree-sitter.test.d.ts +1 -0
  453. package/ts_build/tests/tree-sitter/tree-sitter.test.js +185 -0
  454. package/ts_build/tests/tree-sitter/tree-sitter.test.js.map +1 -0
  455. package/tsconfig.json +2 -1
  456. package/tests/languagePlugin.test.ts +0 -74
  457. /package/src/chat/modules/{index.js → index.ts} +0 -0
  458. /package/tests/{integration → manual/file-edits}/patching/input.txt +0 -0
  459. /package/tests/{integration → manual/file-edits}/patching/output.txt +0 -0
  460. /package/tests/{integration → manual/file-edits}/patching/patch.txt +0 -0
  461. /package/tests/{integration → manual/file-edits}/patching/unseen.txt +0 -0
@@ -0,0 +1,203 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Simple test runner for the event handler reliability test
5
+ * This runs the test cases manually since they're in the manual test directory
6
+ */
7
+
8
+ import { EventEmitter } from "events";
9
+
10
+ // Mock the imports that might not be available
11
+ const mockMessage = { role: "user", content: "test" };
12
+ const mockContext = {
13
+ Tools: {
14
+ getTools: () => [],
15
+ callTool: async (name: string, params: any) => ({ name, content: "mock result" })
16
+ },
17
+ Events: { registerAgent: () => {} },
18
+ messageProcessor: { process: async () => "processed" }
19
+ };
20
+
21
+ // Simplified BaseAgent mock
22
+ class MockBaseAgent extends EventEmitter {
23
+ name = "MockAgent";
24
+ agentEvents = new EventEmitter();
25
+ eventTypes = { done: "done" };
26
+
27
+ constructor(context: any) {
28
+ super();
29
+ }
30
+
31
+ async call(userInput: string): Promise<string> {
32
+ // Simulate agent processing
33
+ console.log(`🤖 Agent processing: "${userInput}"`);
34
+
35
+ // Simulate async work
36
+ await new Promise(resolve => setTimeout(resolve, 50));
37
+
38
+ // Simulate finalAnswer tool call
39
+ const result = "Task completed successfully";
40
+
41
+ // Emit done event (this is what we're testing)
42
+ setTimeout(() => {
43
+ console.log("📡 Emitting done event...");
44
+ this.agentEvents.emit(this.eventTypes.done, result);
45
+ }, 10);
46
+
47
+ return result;
48
+ }
49
+ }
50
+
51
+ // Test cases
52
+ async function runTests() {
53
+ console.log("🧪 Starting Agent Event Handler Reliability Tests\n");
54
+
55
+ let passedTests = 0;
56
+ let totalTests = 0;
57
+
58
+ // Test 1: Normal event handler
59
+ try {
60
+ totalTests++;
61
+ console.log("Test 1: Normal event handler flow");
62
+
63
+ const agent = new MockBaseAgent(mockContext);
64
+ let eventFired = false;
65
+ let eventMessage = "";
66
+
67
+ // Register event handler
68
+ const eventPromise = new Promise<void>((resolve, reject) => {
69
+ const timeout = setTimeout(() => {
70
+ reject(new Error("Event handler timeout"));
71
+ }, 1000);
72
+
73
+ agent.agentEvents.once(agent.eventTypes.done, (message) => {
74
+ clearTimeout(timeout);
75
+ console.log("✅ Agent has finished."); // This should log
76
+ eventFired = true;
77
+ eventMessage = message;
78
+ resolve();
79
+ });
80
+ });
81
+
82
+ const result = await agent.call("Complete normal test");
83
+
84
+ await eventPromise;
85
+
86
+ if (eventFired && eventMessage === result) {
87
+ console.log("✅ Test 1 PASSED - Event handler fired correctly\n");
88
+ passedTests++;
89
+ } else {
90
+ console.log("❌ Test 1 FAILED - Event handler didn't fire properly\n");
91
+ }
92
+
93
+ } catch (error: any) {
94
+ console.log(`❌ Test 1 FAILED - ${error.message}\n`);
95
+ }
96
+
97
+ // Test 2: Race condition - late event handler registration
98
+ try {
99
+ totalTests++;
100
+ console.log("Test 2: Race condition - late event handler");
101
+
102
+ const agent = new MockBaseAgent(mockContext);
103
+
104
+ // Start agent immediately
105
+ const agentPromise = agent.call("Race condition test");
106
+
107
+ // Wait a bit before registering event handler (simulating race condition)
108
+ await new Promise(resolve => setTimeout(resolve, 100));
109
+
110
+ let eventFired = false;
111
+
112
+ // Register event handler LATE
113
+ const lateEventPromise = new Promise<void>((resolve, reject) => {
114
+ const timeout = setTimeout(() => {
115
+ reject(new Error("Late event handler timeout - demonstrates the bug"));
116
+ }, 500);
117
+
118
+ agent.agentEvents.once(agent.eventTypes.done, (message) => {
119
+ clearTimeout(timeout);
120
+ console.log("✅ Agent has finished (late handler).");
121
+ eventFired = true;
122
+ resolve();
123
+ });
124
+ });
125
+
126
+ const result = await agentPromise;
127
+
128
+ try {
129
+ await lateEventPromise;
130
+ console.log("✅ Test 2 PASSED - Late event handler worked (no race condition)\n");
131
+ passedTests++;
132
+ } catch (error: any) {
133
+ console.log("❌ Test 2 DEMONSTRATED BUG - Race condition detected!");
134
+ console.log(" This shows the event handler was registered too late\n");
135
+ // This is actually the expected failure that demonstrates the bug
136
+ }
137
+
138
+ } catch (error: any) {
139
+ console.log(`❌ Test 2 ERROR - ${error.message}\n`);
140
+ }
141
+
142
+ // Test 3: Multiple event handlers
143
+ try {
144
+ totalTests++;
145
+ console.log("Test 3: Multiple event handlers");
146
+
147
+ const agent = new MockBaseAgent(mockContext);
148
+ let handler1Fired = false;
149
+ let handler2Fired = false;
150
+
151
+ // Register multiple handlers
152
+ const promise1 = new Promise<void>((resolve) => {
153
+ agent.agentEvents.once(agent.eventTypes.done, () => {
154
+ console.log("✅ Handler 1: Agent has finished.");
155
+ handler1Fired = true;
156
+ resolve();
157
+ });
158
+ });
159
+
160
+ const promise2 = new Promise<void>((resolve) => {
161
+ agent.agentEvents.once(agent.eventTypes.done, () => {
162
+ console.log("✅ Handler 2: Agent has completed the task.");
163
+ handler2Fired = true;
164
+ resolve();
165
+ });
166
+ });
167
+
168
+ const result = await agent.call("Multiple handlers test");
169
+
170
+ await Promise.race([
171
+ Promise.all([promise1, promise2]),
172
+ new Promise((_, reject) =>
173
+ setTimeout(() => reject(new Error("Multiple handlers timeout")), 1000)
174
+ )
175
+ ]);
176
+
177
+ if (handler1Fired && handler2Fired) {
178
+ console.log("✅ Test 3 PASSED - All event handlers fired\n");
179
+ passedTests++;
180
+ } else {
181
+ console.log("❌ Test 3 FAILED - Not all handlers fired\n");
182
+ }
183
+
184
+ } catch (error: any) {
185
+ console.log(`❌ Test 3 FAILED - ${error.message}\n`);
186
+ }
187
+
188
+ // Summary
189
+ console.log("📊 Test Results:");
190
+ console.log(` Passed: ${passedTests}/${totalTests} tests`);
191
+
192
+ if (passedTests < totalTests) {
193
+ console.log("\n🔍 Event Handler Issues Detected:");
194
+ console.log(" - Race conditions when handlers are registered late");
195
+ console.log(" - Timing issues in event emission");
196
+ console.log(" - This demonstrates the reliability issues in AgentModule.ts");
197
+ } else {
198
+ console.log("\n✅ All tests passed - Event handlers are working reliably");
199
+ }
200
+ }
201
+
202
+ // Run the tests
203
+ runTests().catch(console.error);
@@ -1,4 +1,4 @@
1
- import { FigmaPlugin } from "../../src/plugins/figma";
1
+ import { FigmaPlugin } from "../../../src/plugins/figma";
2
2
 
3
3
  const figmaToken = "test_token"; // This should be the actual testing token
4
4
  const figmaPlugin = new FigmaPlugin();
@@ -1,11 +1,15 @@
1
1
  import * as fs from "fs";
2
- import { readFile, writeFile } from "../../../src/utils";
3
- import { agents } from "../../../src/agents";
4
- import { FlagsService } from "../../../src/services/flags";
2
+ import { readFile, writeFile } from "../../../../src/utils";
3
+ import { agents } from "../../../../src/agents";
4
+ import { services } from "../../../../src/services";
5
+ import { includedTools } from "../../../../src/agents/tools/list";
6
+ import { FlagsService } from "../../../../src/services/flags";
5
7
 
6
8
  describe("Developer", () => {
7
9
  const { Patcher } = agents();
8
10
  beforeAll(() => {
11
+ const { Tools } = services();
12
+ Tools.addTools(includedTools);
9
13
  Patcher.disableTool("searchFiles");
10
14
  Patcher.disableTool("execCommand");
11
15
  Patcher.enableTool("modifyFile");
@@ -1,11 +1,11 @@
1
- import { readFile, writeFile } from "../../src/utils";
1
+ import { readFile, writeFile } from "../../../src/utils";
2
2
  import { createPatch, applyPatch } from "diff";
3
- import { scanFile } from "../../src/agents/tools";
4
- import { patchFile } from "../../src/agents/tools/patch";
5
- import { agents } from "../../src/agents";
6
- import { services } from "../../src/services";
7
- import { includedTools } from "../../src/agents/tools/list";
8
- import * as allTools from "../../src/agents/tools";
3
+ import { scanFile } from "../../../src/agents/tools";
4
+ import { patchFile } from "../../../src/agents/tools/patch";
5
+ import { agents } from "../../../src/agents";
6
+ import { services } from "../../../src/services";
7
+ import { includedTools } from "../../../src/agents/tools/list";
8
+ import * as allTools from "../../../src/agents/tools";
9
9
 
10
10
  const inputPath = "tests/integration/patching/input.txt";
11
11
  const outputPath = "tests/integration/patching/output.txt";
@@ -28,8 +28,11 @@ const brokenPatch = `Index: tests/integration/patching/input.txt
28
28
  }\n`;
29
29
 
30
30
  describe("Patcher", () => {
31
- const { Agents, Tools } = beforeAll(async () => {
31
+ let Agents: any, Tools: any;
32
+
33
+ beforeAll(async () => {
32
34
  const { Patcher } = agents();
35
+ ({ Agents, Tools } = services());
33
36
  Agents.registerAgent(Patcher);
34
37
  Tools.addTools(includedTools);
35
38
  const toolFunctions = Object.entries(allTools)
@@ -0,0 +1,332 @@
1
+ import { LanguagePlugin } from "../../../src/plugins/language";
2
+ import { EventService } from "../../../src/services/EventService";
3
+ import { PluginService } from "../../../src/plugins/plugins";
4
+ import * as utils from "../../../src/utils";
5
+ import { getConfig, getLanguageConfig } from "../../../src/config";
6
+
7
+ jest.mock("../../../src/utils", () => ({
8
+ readFile: jest.fn(),
9
+ fileExists: jest.fn().mockReturnValue(true),
10
+ fileStat: jest.fn(),
11
+ }));
12
+
13
+ jest.mock("../../../src/services/EventService", () => ({
14
+ EventService: jest.fn().mockImplementation(() => ({
15
+ on: jest.fn(),
16
+ emit: jest.fn(),
17
+ })),
18
+ }));
19
+
20
+ jest.mock("../../../src/config", () => ({
21
+ getConfig: jest.fn(),
22
+ getConfigSync: jest.fn(),
23
+ getLanguageConfig: jest.fn(),
24
+ }));
25
+
26
+ jest.mock("../../../src/plugins/plugins", () => ({
27
+ PluginService: jest.fn().mockImplementation(() => ({
28
+ listPlugins: jest.fn(),
29
+ call: jest.fn(),
30
+ })),
31
+ }));
32
+
33
+ const mockedConfig = getConfig as jest.MockedFunction<typeof getConfig>;
34
+ const mockedLanguageConfig = getLanguageConfig as jest.MockedFunction<
35
+ typeof getLanguageConfig
36
+ >;
37
+ const mockedReadFile = utils.readFile as jest.MockedFunction<
38
+ typeof utils.readFile
39
+ >;
40
+
41
+ describe("LanguagePlugin - Content-Based Triggering", () => {
42
+ let mockEventService: any;
43
+ let mockPluginService: any;
44
+ let eventHandlers: Map<string, Function>;
45
+
46
+ beforeEach(() => {
47
+ eventHandlers = new Map();
48
+ mockEventService = {
49
+ on: jest.fn((event: string, handler: Function) => {
50
+ eventHandlers.set(event, handler);
51
+ }),
52
+ emit: jest.fn(),
53
+ };
54
+
55
+ mockPluginService = {
56
+ listPlugins: jest.fn().mockReturnValue(["github"]),
57
+ call: jest.fn().mockResolvedValue(["plugin context data"]),
58
+ };
59
+
60
+ jest.clearAllMocks();
61
+ });
62
+
63
+ test("should trigger on file content containing test functions", async () => {
64
+ // Mock file content that contains test functions
65
+ const fileContentWithTests = `
66
+ import { expect } from 'jest';
67
+
68
+ describe('MyComponent', () => {
69
+ test('should render correctly', () => {
70
+ expect(component).toBeTruthy();
71
+ });
72
+
73
+ it('should handle click events', () => {
74
+ // test implementation
75
+ });
76
+ });
77
+ `;
78
+
79
+ mockedReadFile.mockResolvedValue(Buffer.from(fileContentWithTests));
80
+ mockedConfig.mockResolvedValue({
81
+ plugins: [],
82
+ modules: [],
83
+ promptsDir: ".knowhow/prompts",
84
+ sources: [],
85
+ embedSources: [],
86
+ embeddingModel: "text-embedding-ada-002",
87
+ agents: [],
88
+ mcps: [],
89
+ modelProviders: [],
90
+ });
91
+ mockedLanguageConfig.mockResolvedValue({
92
+ "test(": {
93
+ events: ["file:post-read"],
94
+ sources: [
95
+ { kind: "text", data: ["Jest testing best practices"] },
96
+ { kind: "file", data: ["docs/testing-guidelines.md"] },
97
+ ],
98
+ },
99
+ });
100
+
101
+ new LanguagePlugin({
102
+ Events: mockEventService,
103
+ Plugins: mockPluginService,
104
+ } as any);
105
+
106
+ await new Promise((resolve) => setTimeout(resolve, 0));
107
+
108
+ // Trigger file:post-read event
109
+ const fileReadHandler = eventHandlers.get("file:post-read");
110
+ expect(fileReadHandler).toBeDefined();
111
+
112
+ await fileReadHandler!({
113
+ filePath: "src/components/MyComponent.spec.ts",
114
+ operation: "read",
115
+ });
116
+
117
+ await new Promise((resolve) => setTimeout(resolve, 10));
118
+
119
+ // Verify that the content-based trigger was activated
120
+ expect(mockEventService.emit).toHaveBeenCalledWith(
121
+ "agent:msg",
122
+ expect.stringContaining("language_context_trigger")
123
+ );
124
+
125
+ const emitCall = mockEventService.emit.mock.calls.find(
126
+ (call) => call[0] === "agent:msg"
127
+ );
128
+ expect(emitCall).toBeDefined();
129
+
130
+ const eventData = JSON.parse(emitCall![1]);
131
+ expect(eventData.type).toBe("language_context_trigger");
132
+ expect(eventData.filePath).toBe("src/components/MyComponent.spec.ts");
133
+ expect(eventData.matchingTerms).toContain("test(");
134
+ expect(eventData.contextMessage).toContain("Jest testing best practices");
135
+ });
136
+
137
+ test("should not trigger when file content doesn't match", async () => {
138
+ // Mock file content without trigger terms
139
+ const fileContent = `
140
+ const config = {
141
+ database: 'postgresql',
142
+ port: 5432
143
+ };
144
+ `;
145
+
146
+ mockedReadFile.mockResolvedValue(Buffer.from(fileContent));
147
+ mockedConfig.mockResolvedValue({
148
+ plugins: [],
149
+ modules: [],
150
+ promptsDir: ".knowhow/prompts",
151
+ sources: [],
152
+ embedSources: [],
153
+ embeddingModel: "text-embedding-ada-002",
154
+ agents: [],
155
+ mcps: [],
156
+ modelProviders: [],
157
+ });
158
+ mockedLanguageConfig.mockResolvedValue({
159
+ "test(": {
160
+ events: ["file:post-read"],
161
+ sources: [{ kind: "text", data: ["Jest testing best practices"] }],
162
+ },
163
+ });
164
+
165
+ new LanguagePlugin({
166
+ Events: mockEventService,
167
+ Plugins: mockPluginService,
168
+ } as any);
169
+
170
+ await new Promise((resolve) => setTimeout(resolve, 0));
171
+
172
+ // Trigger file:post-read event
173
+ const fileReadHandler = eventHandlers.get("file:post-read");
174
+ expect(fileReadHandler).toBeDefined();
175
+
176
+ await fileReadHandler!({
177
+ filePath: "src/config.js",
178
+ operation: "read",
179
+ });
180
+
181
+ await new Promise((resolve) => setTimeout(resolve, 10));
182
+
183
+ // Verify no trigger was activated
184
+ expect(mockEventService.emit).not.toHaveBeenCalled();
185
+ });
186
+
187
+ test("should handle file read errors gracefully", async () => {
188
+ // Mock readFile to throw an error
189
+ mockedReadFile.mockRejectedValue(new Error("File not found"));
190
+ mockedConfig.mockResolvedValue({
191
+ plugins: [],
192
+ modules: [],
193
+ promptsDir: ".knowhow/prompts",
194
+ sources: [],
195
+ embedSources: [],
196
+ embeddingModel: "text-embedding-ada-002",
197
+ agents: [],
198
+ mcps: [],
199
+ modelProviders: [],
200
+ });
201
+ mockedLanguageConfig.mockResolvedValue({
202
+ "test(": {
203
+ events: ["file:post-read"],
204
+ sources: [{ kind: "text", data: ["Jest testing best practices"] }],
205
+ },
206
+ });
207
+
208
+ new LanguagePlugin({
209
+ Events: mockEventService,
210
+ Plugins: mockPluginService,
211
+ } as any);
212
+
213
+ await new Promise((resolve) => setTimeout(resolve, 0));
214
+
215
+ // Trigger file:post-read event
216
+ const fileReadHandler = eventHandlers.get("file:post-read");
217
+ expect(fileReadHandler).toBeDefined();
218
+
219
+ await fileReadHandler!({
220
+ filePath: "src/nonexistent.test.js",
221
+ operation: "read",
222
+ });
223
+
224
+ await new Promise((resolve) => setTimeout(resolve, 10));
225
+
226
+ // Verify no crash occurred and no trigger was activated
227
+ expect(mockEventService.emit).not.toHaveBeenCalled();
228
+ });
229
+
230
+ test("should work with case-insensitive matching", async () => {
231
+ // Mock file content with uppercase TEST
232
+ const fileContent = `
233
+ function myTEST() {
234
+ return true;
235
+ }
236
+ `;
237
+
238
+ mockedReadFile.mockResolvedValue(Buffer.from(fileContent));
239
+ mockedConfig.mockResolvedValue({
240
+ plugins: [],
241
+ modules: [],
242
+ promptsDir: ".knowhow/prompts",
243
+ sources: [],
244
+ embedSources: [],
245
+ embeddingModel: "text-embedding-ada-002",
246
+ agents: [],
247
+ mcps: [],
248
+ modelProviders: [],
249
+ });
250
+ mockedLanguageConfig.mockResolvedValue({
251
+ "test(": {
252
+ events: ["file:post-read"],
253
+ sources: [{ kind: "text", data: ["Jest testing best practices"] }],
254
+ },
255
+ });
256
+
257
+ new LanguagePlugin({
258
+ Events: mockEventService,
259
+ Plugins: mockPluginService,
260
+ } as any);
261
+
262
+ await new Promise((resolve) => setTimeout(resolve, 0));
263
+
264
+ // Trigger file:post-read event
265
+ const fileReadHandler = eventHandlers.get("file:post-read");
266
+ expect(fileReadHandler).toBeDefined();
267
+
268
+ await fileReadHandler!({
269
+ filePath: "src/utils.js",
270
+ operation: "read",
271
+ });
272
+
273
+ await new Promise((resolve) => setTimeout(resolve, 10));
274
+
275
+ // Verify that case-insensitive matching worked
276
+ expect(mockEventService.emit).toHaveBeenCalledWith(
277
+ "agent:msg",
278
+ expect.stringContaining("language_context_trigger")
279
+ );
280
+ });
281
+
282
+ test("should trigger on file:post-edit events", async () => {
283
+ const fileContent = `
284
+ test('new test case', () => {
285
+ expect(true).toBe(true);
286
+ });
287
+ `;
288
+
289
+ mockedReadFile.mockResolvedValue(Buffer.from(fileContent));
290
+ mockedConfig.mockResolvedValue({
291
+ plugins: [],
292
+ modules: [],
293
+ promptsDir: ".knowhow/prompts",
294
+ sources: [],
295
+ embedSources: [],
296
+ embeddingModel: "text-embedding-ada-002",
297
+ agents: [],
298
+ mcps: [],
299
+ modelProviders: [],
300
+ });
301
+ mockedLanguageConfig.mockResolvedValue({
302
+ "test(": {
303
+ events: ["file:post-read", "file:post-edit"],
304
+ sources: [{ kind: "text", data: ["Jest testing best practices"] }],
305
+ },
306
+ });
307
+
308
+ new LanguagePlugin({
309
+ Events: mockEventService,
310
+ Plugins: mockPluginService,
311
+ } as any);
312
+
313
+ await new Promise((resolve) => setTimeout(resolve, 0));
314
+
315
+ // Trigger file:post-edit event instead of read
316
+ const fileEditHandler = eventHandlers.get("file:post-edit");
317
+ expect(fileEditHandler).toBeDefined();
318
+
319
+ await fileEditHandler!({
320
+ filePath: "src/newFeature.test.js",
321
+ operation: "edit",
322
+ });
323
+
324
+ await new Promise((resolve) => setTimeout(resolve, 10));
325
+
326
+ // Verify that edit events also trigger content analysis
327
+ expect(mockEventService.emit).toHaveBeenCalledWith(
328
+ "agent:msg",
329
+ expect.stringContaining("language_context_trigger")
330
+ );
331
+ });
332
+ });