@tyvm/knowhow 0.0.33 → 0.0.35

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 (504) hide show
  1. package/autodoc/plugins/downloader/downloader.mdx +2 -2
  2. package/benchmarks/.dockerignore +7 -0
  3. package/benchmarks/README.md +166 -0
  4. package/benchmarks/docker/Dockerfile +68 -0
  5. package/benchmarks/example-config.yml +27 -0
  6. package/benchmarks/jest.config.js +13 -0
  7. package/benchmarks/package-lock.json +4297 -0
  8. package/benchmarks/package.json +39 -0
  9. package/benchmarks/results/4542435/2025-08-05/lms/lms-openai-gpt-oss-20b.json +2814 -0
  10. package/benchmarks/results/4542435/2025-08-05/lms/lms-qwen-qwen3-30b-a3b-2507.json +2014 -0
  11. package/benchmarks/results/4fb9125/2025-08-07/anthropic/anthropic-claude-sonnet-4-20250514.json +3121 -0
  12. package/benchmarks/results/5766aee/2025-08-02/lms-qwen/qwen3-coder-30b.json +98 -0
  13. package/benchmarks/results/6d73808/2025-08-07/openai/openai-gpt-5.json +3256 -0
  14. package/benchmarks/results/77bf0a6/2025-08-02/lms-qwen/qwen3-30b-a3b-2507.json +4298 -0
  15. package/benchmarks/results/8c0d445/2025-08-03/anthropic/anthropic-claude-sonnet-4-20250514.json +3031 -0
  16. package/benchmarks/results/8c0d445/2025-08-03/openai/openai-gpt-4.1-2025-04-14.json +2990 -0
  17. package/benchmarks/results/ac6b2ab/2025-08-03/anthropic/anthropic-claude-sonnet-4-20250514.json +3256 -0
  18. package/benchmarks/results/ac6b2ab/2025-08-03/lms/lms-qwen-qwen3-coder-30b.json +3007 -0
  19. package/benchmarks/results/ac6b2ab/2025-08-03/openai/openai-gpt-4.1-2025-04-14.json +3256 -0
  20. package/benchmarks/results/ac6b2ab/2025-08-03/openai/openai-gpt-4.1-mini-2025-04-14.json +3036 -0
  21. package/benchmarks/results/ac6b2ab/2025-08-03/openai/openai-gpt-4.1-nano-2025-04-14.json +3280 -0
  22. package/benchmarks/results/adff675/2025-08-04/lms/lms-qwen-qwen3-30b-a3b-2507.json +1920 -0
  23. package/benchmarks/results/adff675/2025-08-04/lms/lms-qwen-qwen3-coder-30b.json +3281 -0
  24. package/benchmarks/results/b502ed9/2025-08-03/lms-qwen/qwen3-coder-30b.json +2896 -0
  25. package/benchmarks/results/d1a8129/2025-08-03/lms/lms-qwen-qwen3-coder-30b.json +3011 -0
  26. package/benchmarks/results/e60471c/2025-08-03/lms/qwen3-30b-a3b-2507.json +3003 -0
  27. package/benchmarks/scripts/build-and-run.sh +47 -0
  28. package/benchmarks/scripts/clone-exercism.sh +92 -0
  29. package/benchmarks/scripts/validate.sh +48 -0
  30. package/benchmarks/src/__tests__/runner.test.ts +27 -0
  31. package/benchmarks/src/cli.ts +90 -0
  32. package/benchmarks/src/evaluators/EvaluatorRegistry.ts +64 -0
  33. package/benchmarks/src/evaluators/JavaScriptEvaluator.ts +183 -0
  34. package/benchmarks/src/evaluators/index.ts +3 -0
  35. package/benchmarks/src/evaluators/types.ts +22 -0
  36. package/benchmarks/src/index.ts +3 -0
  37. package/benchmarks/src/providers.ts +13 -0
  38. package/benchmarks/src/runner.ts +824 -0
  39. package/benchmarks/src/types.ts +63 -0
  40. package/benchmarks/tsconfig.json +19 -0
  41. package/jest.config.js +2 -1
  42. package/leaderboard/README.md +148 -0
  43. package/leaderboard/app/api/benchmark-data/route.ts +131 -0
  44. package/leaderboard/app/api/benchmark-detail/route.ts +172 -0
  45. package/leaderboard/app/details/[model]/[provider]/[language]/page.tsx +501 -0
  46. package/leaderboard/app/exercise/[model]/[provider]/[language]/[exercise]/page.tsx +375 -0
  47. package/leaderboard/app/globals.css +27 -0
  48. package/leaderboard/app/layout.tsx +21 -0
  49. package/leaderboard/app/page.tsx +170 -0
  50. package/leaderboard/components/LeaderboardTable.tsx +168 -0
  51. package/leaderboard/components/PerformanceChart.tsx +109 -0
  52. package/leaderboard/next-env.d.ts +5 -0
  53. package/leaderboard/next.config.js +4 -0
  54. package/leaderboard/package-lock.json +6363 -0
  55. package/leaderboard/package.json +28 -0
  56. package/leaderboard/postcss.config.js +6 -0
  57. package/leaderboard/tailwind.config.js +17 -0
  58. package/leaderboard/tsconfig.json +28 -0
  59. package/leaderboard/types/benchmark.ts +67 -0
  60. package/leaderboard/utils/dataProcessor.ts +33 -0
  61. package/package.json +2 -1
  62. package/src/agents/base/base.ts +182 -24
  63. package/src/agents/base/prompt.ts +28 -0
  64. package/src/agents/index.ts +3 -0
  65. package/src/agents/patcher/patcher.ts +6 -4
  66. package/src/agents/setup/setup.ts +56 -0
  67. package/src/agents/tools/agentCall.ts +6 -2
  68. package/src/agents/tools/aiClient.ts +74 -8
  69. package/src/agents/tools/execCommand.ts +13 -14
  70. package/src/agents/tools/executeScript/README.md +16 -0
  71. package/src/agents/tools/index.ts +2 -0
  72. package/src/agents/tools/list.ts +73 -16
  73. package/src/agents/tools/startAgentTask.ts +109 -0
  74. package/src/agents/tools/textSearch.ts +1 -1
  75. package/src/agents/tools/visionTool.ts +31 -2
  76. package/src/agents/tools/ycmd/client.ts +608 -0
  77. package/src/agents/tools/ycmd/definitions.ts +294 -0
  78. package/src/agents/tools/ycmd/detection.ts +211 -0
  79. package/src/agents/tools/ycmd/index.ts +11 -0
  80. package/src/agents/tools/ycmd/installer.ts +251 -0
  81. package/src/agents/tools/ycmd/server.ts +535 -0
  82. package/src/agents/tools/ycmd/serverManager.ts +316 -0
  83. package/src/agents/tools/ycmd/tools/completion.ts +113 -0
  84. package/src/agents/tools/ycmd/tools/diagnostics.ts +155 -0
  85. package/src/agents/tools/ycmd/tools/getLocations.ts +173 -0
  86. package/src/agents/tools/ycmd/tools/goto.ts +169 -0
  87. package/src/agents/tools/ycmd/tools/refactor.ts +204 -0
  88. package/src/agents/tools/ycmd/tools/signature.ts +174 -0
  89. package/src/agents/tools/ycmd/tools/start.ts +95 -0
  90. package/src/agents/tools/ycmd/utils/pathUtils.ts +59 -0
  91. package/src/ai.ts +15 -0
  92. package/src/chat/CliChatService.ts +277 -0
  93. package/src/chat/modules/AgentModule.ts +985 -0
  94. package/src/chat/modules/AskModule.ts +98 -0
  95. package/src/chat/modules/BaseChatModule.ts +66 -0
  96. package/src/chat/modules/InternalChatModule.ts +174 -0
  97. package/src/chat/modules/SearchModule.ts +166 -0
  98. package/src/chat/modules/SetupModule.ts +185 -0
  99. package/src/chat/modules/SystemModule.ts +120 -0
  100. package/src/chat/modules/VoiceModule.ts +70 -0
  101. package/src/chat/modules/index.js +5 -0
  102. package/src/chat/types.ts +97 -0
  103. package/src/chat.ts +9 -1
  104. package/src/chat2.ts +62 -0
  105. package/src/cli.ts +264 -35
  106. package/src/clients/anthropic.ts +14 -7
  107. package/src/clients/gemini.ts +15 -7
  108. package/src/clients/http.ts +17 -7
  109. package/src/clients/index.ts +117 -4
  110. package/src/clients/knowhow.ts +7 -2
  111. package/src/clients/knowhowMcp.ts +118 -0
  112. package/src/clients/openai.ts +32 -8
  113. package/src/clients/types.ts +1 -0
  114. package/src/clients/xai.ts +17 -5
  115. package/src/config.ts +30 -5
  116. package/src/conversion.ts +4 -1
  117. package/src/login.ts +26 -9
  118. package/src/microphone.ts +0 -1
  119. package/src/plugins/downloader/downloader.ts +191 -49
  120. package/src/plugins/downloader/plugin.ts +3 -1
  121. package/src/plugins/plugins.ts +3 -0
  122. package/src/processors/CustomVariables.ts +425 -0
  123. package/src/processors/HarmonyToolProcessor.ts +264 -0
  124. package/src/processors/XmlToolCallProcessor.ts +533 -0
  125. package/src/processors/index.ts +3 -0
  126. package/src/prompts/KnowhowConfigExamples.ts +376 -0
  127. package/src/services/KnowhowClient.ts +49 -3
  128. package/src/services/Mcp.ts +42 -3
  129. package/src/services/McpServer.ts +14 -4
  130. package/src/services/McpWebsocketTransport.ts +21 -7
  131. package/src/services/MessageProcessor.ts +10 -5
  132. package/src/services/index.ts +5 -0
  133. package/src/services/script-execution/ScriptExecutor.ts +34 -1
  134. package/src/services/types.ts +17 -14
  135. package/src/types.ts +17 -0
  136. package/src/utils/index.ts +138 -0
  137. package/tests/XmlToolCallProcessor.test.ts +468 -0
  138. package/tests/manual/ycmd/debug_diagnostics_test.ts +127 -0
  139. package/tests/manual/ycmd/fixtures/debug_diagnostics.ts +26 -0
  140. package/tests/manual/ycmd/fixtures/file_change_test.ts +17 -0
  141. package/tests/manual/ycmd/minimal_advanced_test.ts +108 -0
  142. package/tests/manual/ycmd/simple_diagnostics_test.ts +61 -0
  143. package/tests/manual/ycmd/simple_test.ts +74 -0
  144. package/tests/manual/ycmd/test-typescript-sample.ts +34 -0
  145. package/tests/manual/ycmd/test_advanced_features.ts +407 -0
  146. package/tests/manual/ycmd/test_advanced_with_tools.ts +320 -0
  147. package/tests/manual/ycmd/test_comprehensive_typescript.ts +179 -0
  148. package/tests/manual/ycmd/test_diagnostics_file_changes.ts +249 -0
  149. package/tests/manual/ycmd/test_diagnostics_fix.ts +99 -0
  150. package/tests/manual/ycmd/test_diagnostics_simple.ts +100 -0
  151. package/tests/manual/ycmd/test_diagnostics_timing.ts +120 -0
  152. package/tests/manual/ycmd/test_discover_commands.ts +310 -0
  153. package/tests/manual/ycmd/test_endpoints.ts +115 -0
  154. package/tests/manual/ycmd/test_final_comprehensive.ts +218 -0
  155. package/tests/manual/ycmd/test_final_validation.ts +150 -0
  156. package/tests/manual/ycmd/test_implementation.js +42 -0
  157. package/tests/manual/ycmd/test_individual_ycmd_tool.ts +39 -0
  158. package/tests/manual/ycmd/test_server_manager.ts +52 -0
  159. package/tests/manual/ycmd/test_simple_debug.ts +86 -0
  160. package/tests/manual/ycmd/test_tsserver_workflow.js +83 -0
  161. package/tests/manual/ycmd/test_tsserver_workflow.ts +122 -0
  162. package/tests/manual/ycmd/test_typescript_simple.ts +48 -0
  163. package/tests/manual/ycmd/test_typescript_ycmd.ts +105 -0
  164. package/tests/manual/ycmd/test_workspace_config.ts +90 -0
  165. package/tests/manual/ycmd/test_ycmd_auto_start.ts +137 -0
  166. package/tests/manual/ycmd/test_ycmd_comprehensive.ts +73 -0
  167. package/tests/manual/ycmd/test_ycmd_connection.py +10 -0
  168. package/tests/manual/ycmd/test_ycmd_direct.ts +142 -0
  169. package/tests/manual/ycmd/test_ycmd_experiment.ts +48 -0
  170. package/tests/manual/ycmd/test_ycmd_final.ts +200 -0
  171. package/tests/manual/ycmd/test_ycmd_fixed.py +18 -0
  172. package/tests/manual/ycmd/test_ycmd_integration.ts +112 -0
  173. package/tests/manual/ycmd/test_ycmd_simple.ts +45 -0
  174. package/tests/manual/ycmd/test_ycmd_usage.py +27 -0
  175. package/tests/manual/ycmd/working_simple_test.ts +134 -0
  176. package/ts_build/src/agents/base/base.d.ts +15 -1
  177. package/ts_build/src/agents/base/base.js +121 -20
  178. package/ts_build/src/agents/base/base.js.map +1 -1
  179. package/ts_build/src/agents/base/prompt.d.ts +1 -1
  180. package/ts_build/src/agents/base/prompt.js +28 -0
  181. package/ts_build/src/agents/base/prompt.js.map +1 -1
  182. package/ts_build/src/agents/index.d.ts +2 -0
  183. package/ts_build/src/agents/index.js +2 -0
  184. package/ts_build/src/agents/index.js.map +1 -1
  185. package/ts_build/src/agents/patcher/patcher.js +6 -3
  186. package/ts_build/src/agents/patcher/patcher.js.map +1 -1
  187. package/ts_build/src/agents/setup/setup.d.ts +8 -0
  188. package/ts_build/src/agents/setup/setup.js +59 -0
  189. package/ts_build/src/agents/setup/setup.js.map +1 -0
  190. package/ts_build/src/agents/tools/agentCall.js +5 -2
  191. package/ts_build/src/agents/tools/agentCall.js.map +1 -1
  192. package/ts_build/src/agents/tools/aiClient.d.ts +6 -5
  193. package/ts_build/src/agents/tools/aiClient.js +37 -6
  194. package/ts_build/src/agents/tools/aiClient.js.map +1 -1
  195. package/ts_build/src/agents/tools/execCommand.d.ts +2 -2
  196. package/ts_build/src/agents/tools/execCommand.js +5 -6
  197. package/ts_build/src/agents/tools/execCommand.js.map +1 -1
  198. package/ts_build/src/agents/tools/executeScript/index.d.ts +1 -1
  199. package/ts_build/src/agents/tools/index.d.ts +2 -0
  200. package/ts_build/src/agents/tools/index.js +2 -0
  201. package/ts_build/src/agents/tools/index.js.map +1 -1
  202. package/ts_build/src/agents/tools/list.js +66 -16
  203. package/ts_build/src/agents/tools/list.js.map +1 -1
  204. package/ts_build/src/agents/tools/startAgentTask.d.ts +13 -0
  205. package/ts_build/src/agents/tools/startAgentTask.js +74 -0
  206. package/ts_build/src/agents/tools/startAgentTask.js.map +1 -0
  207. package/ts_build/src/agents/tools/startChatTask.d.ts +13 -0
  208. package/ts_build/src/agents/tools/startChatTask.js +73 -0
  209. package/ts_build/src/agents/tools/startChatTask.js.map +1 -0
  210. package/ts_build/src/agents/tools/textSearch.js +1 -1
  211. package/ts_build/src/agents/tools/textSearch.js.map +1 -1
  212. package/ts_build/src/agents/tools/visionTool.d.ts +1 -1
  213. package/ts_build/src/agents/tools/visionTool.js +23 -3
  214. package/ts_build/src/agents/tools/visionTool.js.map +1 -1
  215. package/ts_build/src/agents/tools/ycmd/client.d.ts +93 -0
  216. package/ts_build/src/agents/tools/ycmd/client.js +355 -0
  217. package/ts_build/src/agents/tools/ycmd/client.js.map +1 -0
  218. package/ts_build/src/agents/tools/ycmd/definitions.d.ts +345 -0
  219. package/ts_build/src/agents/tools/ycmd/definitions.js +298 -0
  220. package/ts_build/src/agents/tools/ycmd/definitions.js.map +1 -0
  221. package/ts_build/src/agents/tools/ycmd/detection.d.ts +11 -0
  222. package/ts_build/src/agents/tools/ycmd/detection.js +175 -0
  223. package/ts_build/src/agents/tools/ycmd/detection.js.map +1 -0
  224. package/ts_build/src/agents/tools/ycmd/index.d.ts +8 -0
  225. package/ts_build/src/agents/tools/ycmd/index.js +20 -0
  226. package/ts_build/src/agents/tools/ycmd/index.js.map +1 -0
  227. package/ts_build/src/agents/tools/ycmd/installer.d.ts +19 -0
  228. package/ts_build/src/agents/tools/ycmd/installer.js +196 -0
  229. package/ts_build/src/agents/tools/ycmd/installer.js.map +1 -0
  230. package/ts_build/src/agents/tools/ycmd/server.d.ts +35 -0
  231. package/ts_build/src/agents/tools/ycmd/server.js +363 -0
  232. package/ts_build/src/agents/tools/ycmd/server.js.map +1 -0
  233. package/ts_build/src/agents/tools/ycmd/serverManager.d.ts +39 -0
  234. package/ts_build/src/agents/tools/ycmd/serverManager.js +210 -0
  235. package/ts_build/src/agents/tools/ycmd/serverManager.js.map +1 -0
  236. package/ts_build/src/agents/tools/ycmd/tools/completion.d.ts +22 -0
  237. package/ts_build/src/agents/tools/ycmd/tools/completion.js +72 -0
  238. package/ts_build/src/agents/tools/ycmd/tools/completion.js.map +1 -0
  239. package/ts_build/src/agents/tools/ycmd/tools/diagnostics.d.ts +42 -0
  240. package/ts_build/src/agents/tools/ycmd/tools/diagnostics.js +88 -0
  241. package/ts_build/src/agents/tools/ycmd/tools/diagnostics.js.map +1 -0
  242. package/ts_build/src/agents/tools/ycmd/tools/getLocations.d.ts +22 -0
  243. package/ts_build/src/agents/tools/ycmd/tools/getLocations.js +142 -0
  244. package/ts_build/src/agents/tools/ycmd/tools/getLocations.js.map +1 -0
  245. package/ts_build/src/agents/tools/ycmd/tools/goto.d.ts +20 -0
  246. package/ts_build/src/agents/tools/ycmd/tools/goto.js +101 -0
  247. package/ts_build/src/agents/tools/ycmd/tools/goto.js.map +1 -0
  248. package/ts_build/src/agents/tools/ycmd/tools/refactor.d.ts +32 -0
  249. package/ts_build/src/agents/tools/ycmd/tools/refactor.js +123 -0
  250. package/ts_build/src/agents/tools/ycmd/tools/refactor.js.map +1 -0
  251. package/ts_build/src/agents/tools/ycmd/tools/signature.d.ts +25 -0
  252. package/ts_build/src/agents/tools/ycmd/tools/signature.js +110 -0
  253. package/ts_build/src/agents/tools/ycmd/tools/signature.js.map +1 -0
  254. package/ts_build/src/agents/tools/ycmd/tools/start.d.ts +17 -0
  255. package/ts_build/src/agents/tools/ycmd/tools/start.js +65 -0
  256. package/ts_build/src/agents/tools/ycmd/tools/start.js.map +1 -0
  257. package/ts_build/src/agents/tools/ycmd/utils/pathUtils.d.ts +4 -0
  258. package/ts_build/src/agents/tools/ycmd/utils/pathUtils.js +67 -0
  259. package/ts_build/src/agents/tools/ycmd/utils/pathUtils.js.map +1 -0
  260. package/ts_build/src/ai.d.ts +1 -0
  261. package/ts_build/src/ai.js +40 -1
  262. package/ts_build/src/ai.js.map +1 -1
  263. package/ts_build/src/chat/ChatCommandHandler.d.ts +36 -0
  264. package/ts_build/src/chat/ChatCommandHandler.js +268 -0
  265. package/ts_build/src/chat/ChatCommandHandler.js.map +1 -0
  266. package/ts_build/src/chat/ChatInputManager.d.ts +22 -0
  267. package/ts_build/src/chat/ChatInputManager.js +85 -0
  268. package/ts_build/src/chat/ChatInputManager.js.map +1 -0
  269. package/ts_build/src/chat/ChatManager.d.ts +49 -0
  270. package/ts_build/src/chat/ChatManager.js +271 -0
  271. package/ts_build/src/chat/ChatManager.js.map +1 -0
  272. package/ts_build/src/chat/ChatSession.d.ts +32 -0
  273. package/ts_build/src/chat/ChatSession.js +3 -0
  274. package/ts_build/src/chat/ChatSession.js.map +1 -0
  275. package/ts_build/src/chat/ChatSessionManager.d.ts +19 -0
  276. package/ts_build/src/chat/ChatSessionManager.js +188 -0
  277. package/ts_build/src/chat/ChatSessionManager.js.map +1 -0
  278. package/ts_build/src/chat/ChatStateManager.d.ts +58 -0
  279. package/ts_build/src/chat/ChatStateManager.js +156 -0
  280. package/ts_build/src/chat/ChatStateManager.js.map +1 -0
  281. package/ts_build/src/chat/CliChatService.d.ts +35 -0
  282. package/ts_build/src/chat/CliChatService.js +201 -0
  283. package/ts_build/src/chat/CliChatService.js.map +1 -0
  284. package/ts_build/src/chat/InterruptibleInput.d.ts +20 -0
  285. package/ts_build/src/chat/InterruptibleInput.js +109 -0
  286. package/ts_build/src/chat/InterruptibleInput.js.map +1 -0
  287. package/ts_build/src/chat/interfaces/ChatModule.d.ts +6 -0
  288. package/ts_build/src/chat/interfaces/ChatModule.js +3 -0
  289. package/ts_build/src/chat/interfaces/ChatModule.js.map +1 -0
  290. package/ts_build/src/chat/modules/AgentModule.d.ts +57 -0
  291. package/ts_build/src/chat/modules/AgentModule.js +709 -0
  292. package/ts_build/src/chat/modules/AgentModule.js.map +1 -0
  293. package/ts_build/src/chat/modules/AskModule.d.ts +10 -0
  294. package/ts_build/src/chat/modules/AskModule.js +63 -0
  295. package/ts_build/src/chat/modules/AskModule.js.map +1 -0
  296. package/ts_build/src/chat/modules/BaseChatModule.d.ts +14 -0
  297. package/ts_build/src/chat/modules/BaseChatModule.js +32 -0
  298. package/ts_build/src/chat/modules/BaseChatModule.js.map +1 -0
  299. package/ts_build/src/chat/modules/InternalChatModule.d.ts +24 -0
  300. package/ts_build/src/chat/modules/InternalChatModule.js +127 -0
  301. package/ts_build/src/chat/modules/InternalChatModule.js.map +1 -0
  302. package/ts_build/src/chat/modules/SearchModule.d.ts +12 -0
  303. package/ts_build/src/chat/modules/SearchModule.js +119 -0
  304. package/ts_build/src/chat/modules/SearchModule.js.map +1 -0
  305. package/ts_build/src/chat/modules/SetupModule.d.ts +15 -0
  306. package/ts_build/src/chat/modules/SetupModule.js +147 -0
  307. package/ts_build/src/chat/modules/SetupModule.js.map +1 -0
  308. package/ts_build/src/chat/modules/SystemModule.d.ts +14 -0
  309. package/ts_build/src/chat/modules/SystemModule.js +90 -0
  310. package/ts_build/src/chat/modules/SystemModule.js.map +1 -0
  311. package/ts_build/src/chat/modules/VoiceModule.d.ts +11 -0
  312. package/ts_build/src/chat/modules/VoiceModule.js +57 -0
  313. package/ts_build/src/chat/modules/VoiceModule.js.map +1 -0
  314. package/ts_build/src/chat/types.d.ts +83 -0
  315. package/ts_build/src/chat/types.js +3 -0
  316. package/ts_build/src/chat/types.js.map +1 -0
  317. package/ts_build/src/chat.js +7 -1
  318. package/ts_build/src/chat.js.map +1 -1
  319. package/ts_build/src/chat2.d.ts +3 -0
  320. package/ts_build/src/chat2.js +47 -0
  321. package/ts_build/src/chat2.js.map +1 -0
  322. package/ts_build/src/cli.js +218 -37
  323. package/ts_build/src/cli.js.map +1 -1
  324. package/ts_build/src/clients/anthropic.d.ts +5 -2
  325. package/ts_build/src/clients/anthropic.js +12 -7
  326. package/ts_build/src/clients/anthropic.js.map +1 -1
  327. package/ts_build/src/clients/gemini.d.ts +6 -3
  328. package/ts_build/src/clients/gemini.js +13 -7
  329. package/ts_build/src/clients/gemini.js.map +1 -1
  330. package/ts_build/src/clients/http.d.ts +1 -0
  331. package/ts_build/src/clients/http.js +12 -5
  332. package/ts_build/src/clients/http.js.map +1 -1
  333. package/ts_build/src/clients/index.d.ts +10 -0
  334. package/ts_build/src/clients/index.js +74 -4
  335. package/ts_build/src/clients/index.js.map +1 -1
  336. package/ts_build/src/clients/knowhow.d.ts +3 -1
  337. package/ts_build/src/clients/knowhow.js +8 -2
  338. package/ts_build/src/clients/knowhow.js.map +1 -1
  339. package/ts_build/src/clients/knowhowMcp.d.ts +20 -0
  340. package/ts_build/src/clients/knowhowMcp.js +86 -0
  341. package/ts_build/src/clients/knowhowMcp.js.map +1 -0
  342. package/ts_build/src/clients/openai.d.ts +5 -2
  343. package/ts_build/src/clients/openai.js +29 -8
  344. package/ts_build/src/clients/openai.js.map +1 -1
  345. package/ts_build/src/clients/types.d.ts +1 -0
  346. package/ts_build/src/clients/xai.d.ts +5 -2
  347. package/ts_build/src/clients/xai.js +15 -5
  348. package/ts_build/src/clients/xai.js.map +1 -1
  349. package/ts_build/src/config.js +24 -3
  350. package/ts_build/src/config.js.map +1 -1
  351. package/ts_build/src/conversion.js +6 -4
  352. package/ts_build/src/conversion.js.map +1 -1
  353. package/ts_build/src/login.d.ts +1 -1
  354. package/ts_build/src/login.js +21 -7
  355. package/ts_build/src/login.js.map +1 -1
  356. package/ts_build/src/microphone.js.map +1 -1
  357. package/ts_build/src/plugins/downloader/downloader.d.ts +7 -5
  358. package/ts_build/src/plugins/downloader/downloader.js +147 -44
  359. package/ts_build/src/plugins/downloader/downloader.js.map +1 -1
  360. package/ts_build/src/plugins/downloader/plugin.js +5 -3
  361. package/ts_build/src/plugins/downloader/plugin.js.map +1 -1
  362. package/ts_build/src/plugins/plugins.js +3 -0
  363. package/ts_build/src/plugins/plugins.js.map +1 -1
  364. package/ts_build/src/processors/CustomVariables.d.ts +32 -0
  365. package/ts_build/src/processors/CustomVariables.js +297 -0
  366. package/ts_build/src/processors/CustomVariables.js.map +1 -0
  367. package/ts_build/src/processors/HarmonyToolProcessor.d.ts +15 -0
  368. package/ts_build/src/processors/HarmonyToolProcessor.js +154 -0
  369. package/ts_build/src/processors/HarmonyToolProcessor.js.map +1 -0
  370. package/ts_build/src/processors/XmlToolCallProcessor.d.ts +14 -0
  371. package/ts_build/src/processors/XmlToolCallProcessor.js +357 -0
  372. package/ts_build/src/processors/XmlToolCallProcessor.js.map +1 -0
  373. package/ts_build/src/processors/index.d.ts +3 -0
  374. package/ts_build/src/processors/index.js +7 -1
  375. package/ts_build/src/processors/index.js.map +1 -1
  376. package/ts_build/src/prompts/KnowhowConfigExamples.d.ts +2 -0
  377. package/ts_build/src/prompts/KnowhowConfigExamples.js +379 -0
  378. package/ts_build/src/prompts/KnowhowConfigExamples.js.map +1 -0
  379. package/ts_build/src/services/KnowhowClient.d.ts +22 -0
  380. package/ts_build/src/services/KnowhowClient.js +14 -2
  381. package/ts_build/src/services/KnowhowClient.js.map +1 -1
  382. package/ts_build/src/services/Mcp.d.ts +1 -0
  383. package/ts_build/src/services/Mcp.js +20 -3
  384. package/ts_build/src/services/Mcp.js.map +1 -1
  385. package/ts_build/src/services/McpServer.d.ts +1 -1
  386. package/ts_build/src/services/McpServer.js +8 -4
  387. package/ts_build/src/services/McpServer.js.map +1 -1
  388. package/ts_build/src/services/McpWebsocketTransport.js +17 -7
  389. package/ts_build/src/services/McpWebsocketTransport.js.map +1 -1
  390. package/ts_build/src/services/MessageProcessor.d.ts +1 -1
  391. package/ts_build/src/services/MessageProcessor.js +4 -4
  392. package/ts_build/src/services/MessageProcessor.js.map +1 -1
  393. package/ts_build/src/services/index.d.ts +2 -0
  394. package/ts_build/src/services/index.js +4 -0
  395. package/ts_build/src/services/index.js.map +1 -1
  396. package/ts_build/src/services/script-execution/ScriptExecutor.d.ts +1 -0
  397. package/ts_build/src/services/script-execution/ScriptExecutor.js +23 -0
  398. package/ts_build/src/services/script-execution/ScriptExecutor.js.map +1 -1
  399. package/ts_build/src/services/types.d.ts +2 -6
  400. package/ts_build/src/services/types.js +4 -4
  401. package/ts_build/src/services/types.js.map +1 -1
  402. package/ts_build/src/types.d.ts +11 -0
  403. package/ts_build/src/types.js +8 -0
  404. package/ts_build/src/types.js.map +1 -1
  405. package/ts_build/src/utils/index.d.ts +2 -0
  406. package/ts_build/src/utils/index.js +102 -1
  407. package/ts_build/src/utils/index.js.map +1 -1
  408. package/ts_build/tests/XmlToolCallProcessor.test.d.ts +1 -0
  409. package/ts_build/tests/XmlToolCallProcessor.test.js +376 -0
  410. package/ts_build/tests/XmlToolCallProcessor.test.js.map +1 -0
  411. package/ts_build/tests/manual/ycmd/debug_diagnostics_test.d.ts +1 -0
  412. package/ts_build/tests/manual/ycmd/debug_diagnostics_test.js +114 -0
  413. package/ts_build/tests/manual/ycmd/debug_diagnostics_test.js.map +1 -0
  414. package/ts_build/tests/manual/ycmd/minimal_advanced_test.d.ts +2 -0
  415. package/ts_build/tests/manual/ycmd/minimal_advanced_test.js +104 -0
  416. package/ts_build/tests/manual/ycmd/minimal_advanced_test.js.map +1 -0
  417. package/ts_build/tests/manual/ycmd/simple_diagnostics_test.d.ts +1 -0
  418. package/ts_build/tests/manual/ycmd/simple_diagnostics_test.js +74 -0
  419. package/ts_build/tests/manual/ycmd/simple_diagnostics_test.js.map +1 -0
  420. package/ts_build/tests/manual/ycmd/simple_test.d.ts +2 -0
  421. package/ts_build/tests/manual/ycmd/simple_test.js +82 -0
  422. package/ts_build/tests/manual/ycmd/simple_test.js.map +1 -0
  423. package/ts_build/tests/manual/ycmd/test-typescript-sample.d.ts +14 -0
  424. package/ts_build/tests/manual/ycmd/test-typescript-sample.js +20 -0
  425. package/ts_build/tests/manual/ycmd/test-typescript-sample.js.map +1 -0
  426. package/ts_build/tests/manual/ycmd/test_advanced_features.d.ts +2 -0
  427. package/ts_build/tests/manual/ycmd/test_advanced_features.js +297 -0
  428. package/ts_build/tests/manual/ycmd/test_advanced_features.js.map +1 -0
  429. package/ts_build/tests/manual/ycmd/test_advanced_with_tools.d.ts +3 -0
  430. package/ts_build/tests/manual/ycmd/test_advanced_with_tools.js +262 -0
  431. package/ts_build/tests/manual/ycmd/test_advanced_with_tools.js.map +1 -0
  432. package/ts_build/tests/manual/ycmd/test_comprehensive_typescript.d.ts +2 -0
  433. package/ts_build/tests/manual/ycmd/test_comprehensive_typescript.js +186 -0
  434. package/ts_build/tests/manual/ycmd/test_comprehensive_typescript.js.map +1 -0
  435. package/ts_build/tests/manual/ycmd/test_diagnostics_file_changes.d.ts +1 -0
  436. package/ts_build/tests/manual/ycmd/test_diagnostics_file_changes.js +174 -0
  437. package/ts_build/tests/manual/ycmd/test_diagnostics_file_changes.js.map +1 -0
  438. package/ts_build/tests/manual/ycmd/test_diagnostics_fix.d.ts +2 -0
  439. package/ts_build/tests/manual/ycmd/test_diagnostics_fix.js +106 -0
  440. package/ts_build/tests/manual/ycmd/test_diagnostics_fix.js.map +1 -0
  441. package/ts_build/tests/manual/ycmd/test_diagnostics_simple.d.ts +1 -0
  442. package/ts_build/tests/manual/ycmd/test_diagnostics_simple.js +104 -0
  443. package/ts_build/tests/manual/ycmd/test_diagnostics_simple.js.map +1 -0
  444. package/ts_build/tests/manual/ycmd/test_diagnostics_timing.d.ts +1 -0
  445. package/ts_build/tests/manual/ycmd/test_diagnostics_timing.js +119 -0
  446. package/ts_build/tests/manual/ycmd/test_diagnostics_timing.js.map +1 -0
  447. package/ts_build/tests/manual/ycmd/test_discover_commands.d.ts +2 -0
  448. package/ts_build/tests/manual/ycmd/test_discover_commands.js +243 -0
  449. package/ts_build/tests/manual/ycmd/test_discover_commands.js.map +1 -0
  450. package/ts_build/tests/manual/ycmd/test_endpoints.d.ts +2 -0
  451. package/ts_build/tests/manual/ycmd/test_endpoints.js +120 -0
  452. package/ts_build/tests/manual/ycmd/test_endpoints.js.map +1 -0
  453. package/ts_build/tests/manual/ycmd/test_final_comprehensive.d.ts +2 -0
  454. package/ts_build/tests/manual/ycmd/test_final_comprehensive.js +221 -0
  455. package/ts_build/tests/manual/ycmd/test_final_comprehensive.js.map +1 -0
  456. package/ts_build/tests/manual/ycmd/test_final_validation.d.ts +2 -0
  457. package/ts_build/tests/manual/ycmd/test_final_validation.js +160 -0
  458. package/ts_build/tests/manual/ycmd/test_final_validation.js.map +1 -0
  459. package/ts_build/tests/manual/ycmd/test_individual_ycmd_tool.d.ts +2 -0
  460. package/ts_build/tests/manual/ycmd/test_individual_ycmd_tool.js +37 -0
  461. package/ts_build/tests/manual/ycmd/test_individual_ycmd_tool.js.map +1 -0
  462. package/ts_build/tests/manual/ycmd/test_server_manager.d.ts +1 -0
  463. package/ts_build/tests/manual/ycmd/test_server_manager.js +38 -0
  464. package/ts_build/tests/manual/ycmd/test_server_manager.js.map +1 -0
  465. package/ts_build/tests/manual/ycmd/test_simple_debug.d.ts +2 -0
  466. package/ts_build/tests/manual/ycmd/test_simple_debug.js +99 -0
  467. package/ts_build/tests/manual/ycmd/test_simple_debug.js.map +1 -0
  468. package/ts_build/tests/manual/ycmd/test_tsserver_workflow.d.ts +1 -0
  469. package/ts_build/tests/manual/ycmd/test_tsserver_workflow.js +128 -0
  470. package/ts_build/tests/manual/ycmd/test_tsserver_workflow.js.map +1 -0
  471. package/ts_build/tests/manual/ycmd/test_typescript_simple.d.ts +1 -0
  472. package/ts_build/tests/manual/ycmd/test_typescript_simple.js +66 -0
  473. package/ts_build/tests/manual/ycmd/test_typescript_simple.js.map +1 -0
  474. package/ts_build/tests/manual/ycmd/test_typescript_ycmd.d.ts +1 -0
  475. package/ts_build/tests/manual/ycmd/test_typescript_ycmd.js +105 -0
  476. package/ts_build/tests/manual/ycmd/test_typescript_ycmd.js.map +1 -0
  477. package/ts_build/tests/manual/ycmd/test_workspace_config.d.ts +1 -0
  478. package/ts_build/tests/manual/ycmd/test_workspace_config.js +89 -0
  479. package/ts_build/tests/manual/ycmd/test_workspace_config.js.map +1 -0
  480. package/ts_build/tests/manual/ycmd/test_ycmd_auto_start.d.ts +2 -0
  481. package/ts_build/tests/manual/ycmd/test_ycmd_auto_start.js +130 -0
  482. package/ts_build/tests/manual/ycmd/test_ycmd_auto_start.js.map +1 -0
  483. package/ts_build/tests/manual/ycmd/test_ycmd_comprehensive.d.ts +1 -0
  484. package/ts_build/tests/manual/ycmd/test_ycmd_comprehensive.js +83 -0
  485. package/ts_build/tests/manual/ycmd/test_ycmd_comprehensive.js.map +1 -0
  486. package/ts_build/tests/manual/ycmd/test_ycmd_direct.d.ts +2 -0
  487. package/ts_build/tests/manual/ycmd/test_ycmd_direct.js +149 -0
  488. package/ts_build/tests/manual/ycmd/test_ycmd_direct.js.map +1 -0
  489. package/ts_build/tests/manual/ycmd/test_ycmd_experiment.d.ts +15 -0
  490. package/ts_build/tests/manual/ycmd/test_ycmd_experiment.js +58 -0
  491. package/ts_build/tests/manual/ycmd/test_ycmd_experiment.js.map +1 -0
  492. package/ts_build/tests/manual/ycmd/test_ycmd_final.d.ts +2 -0
  493. package/ts_build/tests/manual/ycmd/test_ycmd_final.js +195 -0
  494. package/ts_build/tests/manual/ycmd/test_ycmd_final.js.map +1 -0
  495. package/ts_build/tests/manual/ycmd/test_ycmd_integration.d.ts +3 -0
  496. package/ts_build/tests/manual/ycmd/test_ycmd_integration.js +110 -0
  497. package/ts_build/tests/manual/ycmd/test_ycmd_integration.js.map +1 -0
  498. package/ts_build/tests/manual/ycmd/test_ycmd_simple.d.ts +2 -0
  499. package/ts_build/tests/manual/ycmd/test_ycmd_simple.js +36 -0
  500. package/ts_build/tests/manual/ycmd/test_ycmd_simple.js.map +1 -0
  501. package/ts_build/tests/manual/ycmd/working_simple_test.d.ts +2 -0
  502. package/ts_build/tests/manual/ycmd/working_simple_test.js +134 -0
  503. package/ts_build/tests/manual/ycmd/working_simple_test.js.map +1 -0
  504. package/tsconfig.json +3 -1
@@ -0,0 +1,468 @@
1
+ import { XmlToolCallProcessor } from "../src/processors/XmlToolCallProcessor";
2
+ import { Message } from "../src/clients/types";
3
+ import { restoreEscapedNewLines } from "../src/utils";
4
+ import { escapeNewLines } from "../src/utils";
5
+
6
+ describe("XmlToolCallProcessor", () => {
7
+ let processor: XmlToolCallProcessor;
8
+
9
+ beforeEach(() => {
10
+ processor = new XmlToolCallProcessor();
11
+ });
12
+
13
+ describe("JSON-based XML tool calls", () => {
14
+ it("should correctly parse JSON tool calls with string arguments (no double wrapping)", () => {
15
+ const message: Message = {
16
+ role: "assistant",
17
+ content: `I'll help you with that task.
18
+
19
+ <tool_call>
20
+ {"name": "writeFileChunk", "arguments": "{\"filePath\": \"test.js\", \"content\": \"console.log('hello')\", \"isContinuing\": false, \"isDone\": true}"}
21
+ </tool_call>
22
+
23
+ This should create the file.`,
24
+ };
25
+
26
+ const processorFn = processor.createProcessor();
27
+ processorFn([], [message]);
28
+
29
+ expect(message.tool_calls).toBeDefined();
30
+ expect(message.tool_calls!.length).toBe(1);
31
+
32
+ const toolCall = message.tool_calls![0];
33
+ expect(toolCall.function.name).toBe("writeFileChunk");
34
+
35
+ // Parse the arguments to ensure they're not double-wrapped
36
+ const args = JSON.parse(toolCall.function.arguments);
37
+ expect(args.filePath).toBe("test.js");
38
+ expect(args.content).toBe("console.log('hello')");
39
+ expect(args.isContinuing).toBe(false);
40
+ expect(args.isDone).toBe(true);
41
+
42
+ // Ensure arguments is not a nested JSON string
43
+ expect(typeof args).toBe("object");
44
+ expect(typeof args.filePath).toBe("string");
45
+ });
46
+
47
+ it("should handle arguments as an object as well", () => {
48
+ const message: Message = {
49
+ role: "assistant",
50
+ content: `
51
+ Sure thing!
52
+
53
+ <tool_call>
54
+ {"name": "writeFileChunk", "arguments": {"filePath": "accumulate.spec.js", "content": "import { describe, expect, test } from '@jest/globals';\nimport { accumulate } from './accumulate';\n\ndescribe('accumulate()', () => {\n test('accumulation empty', () => {\n const accumulator = (e) => e * e;\n expect(accumulate([], accumulator)).toEqual([]);\n });\n\n test('accumulate squares', () => {\n const accumulator = (number) => number * number;\n const result = accumulate([1, 2, 3], accumulator);\n expect(result).toEqual([1, 4, 9]);\n });\n\n test('accumulate upcases', () => {\n const accumulator = (word) => word.toUpperCase();\n const result = accumulate('hello world'.split(/\s/), accumulator);\n expect(result).toEqual(['HELLO', 'WORLD']);\n });\n\n test('accumulate reversed strings', () => {\n const accumulator = (word) => word.split('').reverse().join('');\n const result = accumulate(\n 'the quick brown fox etc'.split(/\s/),\n accumulator,\n );\n expect(result).toEqual(['eht', 'kciuq', 'nworb', 'xof', 'cte']);\n });\n\n test('accumulate recursively', () => {\n const result = accumulate('a b c'.split(/\s/), (char) =>\n accumulate('1 2 3'.split(/\s/), (digit) => char + digit),\n );\n\n expect(result).toEqual([\n ['a1', 'a2', 'a3'],\n ['b1', 'b2', 'b3'],\n ['c1', 'c2', 'c3'],\n ]);\n });\n});", "isContinuing": false, "isDone": true}}
55
+ </tool_call>`,
56
+ };
57
+ const processorFn = processor.createProcessor();
58
+ processorFn([], [message]);
59
+ expect(message.tool_calls).toBeDefined();
60
+ expect(message.tool_calls!.length).toBe(1);
61
+ const toolCall = message.tool_calls![0];
62
+ expect(toolCall.function.name).toBe("writeFileChunk");
63
+ const args = JSON.parse(toolCall.function.arguments);
64
+ expect(args.filePath).toBe("accumulate.spec.js");
65
+ expect(args.content).toContain(
66
+ `import { describe, expect, test } from '@jest/globals'`
67
+ );
68
+ });
69
+
70
+ it("should handle complex patches", () => {
71
+ const message: Message = {
72
+ role: "assistant",
73
+ content: `
74
+ Great! The tests are running, and the first test "accumulation empty" is passing. The other tests are still skipped, so I need to unskip them.
75
+
76
+ Let me modify the test file to unskip the tests:
77
+
78
+ <tool_call>
79
+ {"name": "patchFile", "arguments": {"filePath": "accumulate.spec.js", "patch": "Index: ./accumulate.spec.js\n===================================================================\n--- ./accumulate.spec.js\n+++ ./accumulate.spec.js\n@@ -11,7 +11,7 @@\n test('accumulation empty', () => {\n const accumulator = (e) => e * e;\n expect(accumulate([], accumulator)).toEqual([]);\n });\n-\n+ \n xtest('accumulate squares', () => {\n const accumulator = (number) => number * number;\n const result = accumulate([1, 2, 3], accumulator);\n expect(result).toEqual([1, 4, 9]);\n });\n-\n+ \n xtest('accumulate upcases', () => {\n const accumulator = (word) => word.toUpperCase();\n const result = accumulate('hello world'.split(/\s/), accumulator);\n expect(result).toEqual(['HELLO', 'WORLD']);\n });\n-\n+ \n xtest('accumulate reversed strings', () => {\n const accumulator = (word) => word.split('').reverse().join('');\n const result = accumulate(\n 'the quick brown fox etc'.split(/\s/),\n accumulator,\n );\n expect(result).toEqual(['eht', 'kciuq', 'nworb', 'xof', 'cte']);\n });\n-\n+ \n xtest('accumulate recursively', () => {\n const result = accumulate('a b c'.split(/\s/), (char) =>\n accumulate('1 2 3'.split(/\s/), (digit) => char + digit),\n );\n\n expect(result).toEqual([\n ['a1', 'a2', 'a3'],\n ['b1', 'b2', 'b3'],\n ['c1', 'c2', 'c3'],\n ]);\n });\n "}}
80
+ </tool_call>
81
+ `,
82
+ };
83
+ const processorFn = processor.createProcessor();
84
+ processorFn([], [message]);
85
+ expect(message.tool_calls).toBeDefined();
86
+ expect(message.tool_calls!.length).toBe(1);
87
+ const toolCall = message.tool_calls![0];
88
+ expect(toolCall.function.name).toBe("patchFile");
89
+ const args = JSON.parse(toolCall.function.arguments);
90
+ expect(args.filePath).toBe("accumulate.spec.js");
91
+ expect(args.patch).toContain(`Index: ./accumulate.spec.js`);
92
+ });
93
+
94
+ it("should handle complex patches 2", () => {
95
+ const message: Message = {
96
+ role: "assistant",
97
+ content: `
98
+ I need to implement the \`accumulate\` function that takes a collection and an operation to apply to each element. Let me implement this from scratch.
99
+
100
+ The function should:
101
+ 1. Take an array (or any iterable) and a function to apply
102
+ 2. Apply the function to each element
103
+ 3. Return a new array with the results
104
+ 4. Not use built-in map functions
105
+
106
+ Here's my implementation:
107
+
108
+ <tool_call>
109
+ {"name": "patchFile", "arguments": {"filePath": "accumulate.js", "patch": "Index: ./accumulate.js\n===================================================================\n--- ./accumulate.js\n+++ ./accumulate.js\n@@ -1,8 +1,10 @@\n //\n // This is only a SKELETON file for the 'Accumulate' exercise. It's been provided as a\n // convenience to get you started writing code faster.\n //\n+\n export const accumulate = (collection, operation) => {\n- throw new Error('Remove this line and implement the function');\n+ const result = [];\n+ for (let i = 0; i < collection.length; i++) {\n+ result.push(operation(collection[i]));\n+ }\n+ return result;\n };\n\n //\n // This is only a SKELETON file for the 'Accumulate' exercise. It's been provided as a\n // convenience to get you started writing code faster.\n //\n"}}
110
+ </tool_call>
111
+ `,
112
+ };
113
+ const processorFn = processor.createProcessor();
114
+ processorFn([], [message]);
115
+ expect(message.tool_calls).toBeDefined();
116
+ expect(message.tool_calls!.length).toBe(1);
117
+ const toolCall = message.tool_calls![0];
118
+ expect(toolCall.function.name).toBe("patchFile");
119
+ const args = JSON.parse(toolCall.function.arguments);
120
+ expect(args.filePath).toBe("accumulate.js");
121
+ expect(args.patch).toContain(`Index: ./accumulate.js`);
122
+ });
123
+
124
+ it("should handle complex patches 3", () => {
125
+ const message: Message = {
126
+ role: "assistant",
127
+ content:
128
+ "Great! The tests are now passing, but the test for \"accumulate squares\" is still skipped. Let me update the test file to unskip it:\n\n<tool_call>\n{\"name\": \"patchFile\", \"arguments\": {\"filePath\": \"accumulate.spec.js\", \"patch\": \"Index: ./accumulate.spec.js\\n===================================================================\\n--- ./accumulate.spec.js\\n+++ ./accumulate.spec.js\\n@@ -1,42 +1,42 @@\\n import { describe, expect, test, xtest } from '@jest/globals';\\n import { accumulate } from './accumulate';\\n\\n describe('accumulate()', () => {\\n test('accumulation empty', () => {\\n const accumulator = (e) => e * e;\\n expect(accumulate([], accumulator)).toEqual([]);\\n });\\n-\\n- xtest('accumulate squares', () => {\\n- const accumulator = (number) => number * number;\\n- const result = accumulate([1, 2, 3], accumulator);\\n- expect(result).toEqual([1, 4, 9]);\\n- });\\n+\\n+ test('accumulate squares', () => {\\n+ const accumulator = (number) => number * number;\\n+ const result = accumulate([1, 2, 3], accumulator);\\n+ expect(result).toEqual([1, 4, 9]);\\n+ });\\n\\n xtest('accumulate upcases', () => {\\n const accumulator = (word) => word.toUpperCase();\\n const result = accumulate('hello world'.split(/\\s/), accumulator);\\n expect(result).toEqual(['HELLO', 'WORLD']);\\n });\\n\\n xtest('accumulate reversed strings', () => {\\n const accumulator = (word) => word.split('').reverse().join('');\\n const result = accumulate(\\n 'the quick brown fox etc'.split(/\\s/),\\n accumulator,\\n );\\n expect(result).toEqual(['eht', 'kciuq', 'nworb', 'xof', 'cte']);\\n });\\n\\n xtest('accumulate recursively', () => {\\n const result = accumulate('a b c'.split(/\\s/), (char) =>\\n accumulate('1 2 3'.split(/\\s/), (digit) => char + digit),\\n );\\n\\n expect(result).toEqual([\\n ['a1', 'a2', 'a3'],\\n ['b1', 'b2', 'b3'],\\n ['c1', 'c2', 'c3'],\\n ]);\\n });\\n });\\n\"}}\n</tool_call>",
129
+ };
130
+ const processorFn = processor.createProcessor();
131
+ processorFn([], [message]);
132
+ expect(message.tool_calls).toBeDefined();
133
+ expect(message.tool_calls!.length).toBe(1);
134
+ const toolCall = message.tool_calls![0];
135
+ expect(toolCall.function.name).toBe("patchFile");
136
+ const args = JSON.parse(toolCall.function.arguments);
137
+ expect(args.filePath).toBe("accumulate.spec.js");
138
+ expect(args.patch).toContain(`Index: ./accumulate.spec.js`);
139
+ });
140
+
141
+ it("should produce arguments compatible with ToolsService.callTool logic", () => {
142
+ const message: Message = {
143
+ role: "assistant",
144
+ content: `
145
+ I need to implement the \`accumulate\` function that takes a collection and an operation to apply to each element. Let me implement this from scratch.
146
+
147
+ The function should:
148
+ 1. Take an array (or any iterable) and a function to apply
149
+ 2. Apply the function to each element
150
+ 3. Return a new array with the results
151
+ 4. Not use built-in map functions
152
+
153
+ Here's my implementation:
154
+
155
+ <tool_call>
156
+ {"name": "patchFile", "arguments": {"filePath": "accumulate.js", "patch": "Index: ./accumulate.js\\n===================================================================\\n--- ./accumulate.js\\n+++ ./accumulate.js\\n@@ -1,8 +1,10 @@\\n //\\n // This is only a SKELETON file for the 'Accumulate' exercise. It's been provided as a\\n // convenience to get you started writing code faster.\\n //\\n+\\n export const accumulate = (collection, operation) => {\\n- throw new Error('Remove this line and implement the function');\\n+ const result = [];\\n+ for (let i = 0; i < collection.length; i++) {\\n+ result.push(operation(collection[i]));\\n+ }\\n+ return result;\\n };\\n\\n //\\n // This is only a SKELETON file for the 'Accumulate' exercise. It's been provided as a\\n // convenience to get you started writing code faster.\\n //\\n"}}
157
+ </tool_call>
158
+ `,
159
+ };
160
+
161
+ const processorFn = processor.createProcessor();
162
+ processorFn([], [message]);
163
+
164
+ expect(message.tool_calls).toBeDefined();
165
+ expect(message.tool_calls!.length).toBe(1);
166
+
167
+ const toolCall = message.tool_calls![0];
168
+ expect(toolCall.function.name).toBe("patchFile");
169
+
170
+ // Now simulate the exact logic from ToolsService.callTool
171
+ const functionName = toolCall.function.name;
172
+ let functionArgs;
173
+ let parseError: Error | null = null;
174
+
175
+ try {
176
+ // This is the exact logic from ToolsService.callTool line 167-170
177
+ functionArgs =
178
+ typeof toolCall.function.arguments === "string"
179
+ ? JSON.parse(restoreEscapedNewLines(toolCall.function.arguments))
180
+ : toolCall.function.arguments;
181
+ } catch (error) {
182
+ parseError = error as Error;
183
+ }
184
+
185
+ // Should not have any parsing errors
186
+ expect(parseError).toBeNull();
187
+ expect(functionArgs).toBeDefined();
188
+ expect(typeof functionArgs).toBe("object");
189
+
190
+ // Should have the correct structure
191
+ expect(functionArgs.filePath).toBe("accumulate.js");
192
+ expect(functionArgs.patch).toBeDefined();
193
+ expect(typeof functionArgs.patch).toBe("string");
194
+ expect(functionArgs.patch).toContain("Index: ./accumulate.js");
195
+
196
+ // Additional validation: ensure arguments is a valid JSON string
197
+ expect(typeof toolCall.function.arguments).toBe("string");
198
+
199
+ // Test that the arguments can be JSON.parsed without errors
200
+ let parsedArgs;
201
+ expect(() => {
202
+ parsedArgs = JSON.parse(toolCall.function.arguments);
203
+ }).not.toThrow();
204
+
205
+ // Verify the parsed structure matches what we expect
206
+ expect(parsedArgs).toEqual(functionArgs);
207
+
208
+ // Ensure no double-wrapping (arguments should not be a stringified JSON string)
209
+ expect(typeof parsedArgs.filePath).toBe("string");
210
+ expect(typeof parsedArgs.patch).toBe("string");
211
+ // The patch should NOT be a JSON string, but actual string content
212
+ expect(() => JSON.parse(parsedArgs.patch)).toThrow(); // Should throw because patch is actual diff content, not JSON
213
+
214
+ console.log("āœ… Tool call arguments format validation passed");
215
+ console.log("Function name:", functionName);
216
+ console.log("Arguments type:", typeof toolCall.function.arguments);
217
+ console.log("Parsed args keys:", Object.keys(functionArgs));
218
+ });
219
+
220
+ it("should correctly parse JSON tool calls with object arguments", () => {
221
+ const message: Message = {
222
+ role: "assistant",
223
+ content: `<tool_call>
224
+ {"name": "readFile", "arguments": {"filePath": "example.txt"}}
225
+ </tool_call>`,
226
+ };
227
+
228
+ const processorFn = processor.createProcessor();
229
+ processorFn([], [message]);
230
+
231
+ expect(message.tool_calls).toBeDefined();
232
+ expect(message.tool_calls!.length).toBe(1);
233
+
234
+ const toolCall = message.tool_calls![0];
235
+ expect(toolCall.function.name).toBe("readFile");
236
+
237
+ const args = JSON.parse(toolCall.function.arguments);
238
+ expect(args.filePath).toBe("example.txt");
239
+ });
240
+ });
241
+
242
+ describe("Attribute-based XML tool calls", () => {
243
+ it("should correctly parse attribute-based tool calls", () => {
244
+ const message: Message = {
245
+ role: "assistant",
246
+ content: `<tool_call name="readFile">{"filePath": "test.txt"}</tool_call>`,
247
+ };
248
+
249
+ const processorFn = processor.createProcessor();
250
+ processorFn([], [message]);
251
+
252
+ expect(message.tool_calls).toBeDefined();
253
+ expect(message.tool_calls!.length).toBe(1);
254
+
255
+ const toolCall = message.tool_calls![0];
256
+ expect(toolCall.function.name).toBe("readFile");
257
+
258
+ const args = JSON.parse(toolCall.function.arguments);
259
+ expect(args.filePath).toBe("test.txt");
260
+ });
261
+
262
+ it("should correctly parse attribute-based tool calls with arguments attribute", () => {
263
+ const message: Message = {
264
+ role: "assistant",
265
+ content: `<tool_call name="execCommand" arguments='{"command": "ls -la"}'/>`,
266
+ };
267
+
268
+ const processorFn = processor.createProcessor();
269
+ processorFn([], [message]);
270
+
271
+ expect(message.tool_calls).toBeDefined();
272
+ expect(message.tool_calls!.length).toBe(1);
273
+
274
+ const toolCall = message.tool_calls![0];
275
+ expect(toolCall.function.name).toBe("execCommand");
276
+
277
+ const args = JSON.parse(toolCall.function.arguments);
278
+ expect(args.command).toBe("ls -la");
279
+ });
280
+ });
281
+
282
+ describe("Nested XML tool calls", () => {
283
+ it("should correctly parse nested XML parameter format", () => {
284
+ const message: Message = {
285
+ role: "assistant",
286
+ content: `<tool_call>
287
+ <invoke name="readFile">
288
+ <parameter name="filePath">example.txt</parameter>
289
+ </invoke>
290
+ </tool_call>`,
291
+ };
292
+
293
+ const processorFn = processor.createProcessor();
294
+ processorFn([], [message]);
295
+
296
+ expect(message.tool_calls).toBeDefined();
297
+ expect(message.tool_calls!.length).toBe(1);
298
+
299
+ const toolCall = message.tool_calls![0];
300
+ expect(toolCall.function.name).toBe("readFile");
301
+
302
+ const args = JSON.parse(toolCall.function.arguments);
303
+ expect(args.filePath).toBe("example.txt");
304
+ });
305
+ });
306
+
307
+ describe("Content cleaning", () => {
308
+ it("should preserve non-XML content in the message", () => {
309
+ const message: Message = {
310
+ role: "assistant",
311
+ content: `I need to read the file first.
312
+
313
+ <tool_call>
314
+ {"name": "readFile", "arguments": "{\"filePath\": \"test.js\"}"}
315
+ </tool_call>
316
+
317
+ This will help me understand the content.`,
318
+ };
319
+
320
+ const processorFn = processor.createProcessor();
321
+ processorFn([], [message]);
322
+
323
+ // Content should still contain the non-XML parts
324
+ expect(message.content).toContain("I need to read the file first.");
325
+ expect(message.content).toContain(
326
+ "This will help me understand the content."
327
+ );
328
+
329
+ // Tool calls should be extracted
330
+ expect(message.tool_calls).toBeDefined();
331
+ expect(message.tool_calls!.length).toBe(1);
332
+ });
333
+ });
334
+
335
+ describe("Multiple tool calls", () => {
336
+ it("should handle multiple tool calls in one message", () => {
337
+ const message: Message = {
338
+ role: "assistant",
339
+ content: `I'll read the file and then write to another one.
340
+
341
+ <tool_call>
342
+ {"name": "readFile", "arguments": "{\"filePath\": \"input.txt\"}"}
343
+ </tool_call>
344
+
345
+ <tool_call>
346
+ {"name": "writeFileChunk", "arguments": "{\"filePath\": \"output.txt\", \"content\": \"processed data\", \"isContinuing\": false, \"isDone\": true}"}
347
+ </tool_call>`,
348
+ };
349
+
350
+ const processorFn = processor.createProcessor();
351
+ processorFn([], [message]);
352
+
353
+ expect(message.tool_calls).toBeDefined();
354
+ expect(message.tool_calls!.length).toBe(2);
355
+
356
+ // First tool call
357
+ const firstCall = message.tool_calls![0];
358
+ expect(firstCall.function.name).toBe("readFile");
359
+ const firstArgs = JSON.parse(firstCall.function.arguments);
360
+ expect(firstArgs.filePath).toBe("input.txt");
361
+
362
+ // Second tool call
363
+ const secondCall = message.tool_calls![1];
364
+ expect(secondCall.function.name).toBe("writeFileChunk");
365
+ const secondArgs = JSON.parse(secondCall.function.arguments);
366
+ expect(secondArgs.filePath).toBe("output.txt");
367
+ expect(secondArgs.content).toBe("processed data");
368
+ expect(secondArgs.isContinuing).toBe(false);
369
+ expect(secondArgs.isDone).toBe(true);
370
+ });
371
+ });
372
+
373
+ describe("Edge cases", () => {
374
+ it("should not process non-assistant messages", () => {
375
+ const message: Message = {
376
+ role: "user",
377
+ content: `<tool_call>
378
+ {"name": "readFile", "arguments": "{\"filePath\": \"test.txt\"}"}
379
+ </tool_call>`,
380
+ };
381
+
382
+ const processorFn = processor.createProcessor();
383
+ processorFn([], [message]);
384
+
385
+ expect(message.tool_calls).toBeUndefined();
386
+ });
387
+
388
+ it("should not process messages that already have tool_calls", () => {
389
+ const message: Message = {
390
+ role: "assistant",
391
+ content: `<tool_call>
392
+ {"name": "readFile", "arguments": "{\"filePath\": \"test.txt\"}"}
393
+ </tool_call>`,
394
+ tool_calls: [
395
+ {
396
+ id: "existing_call",
397
+ type: "function",
398
+ function: {
399
+ name: "existingTool",
400
+ arguments: "{}",
401
+ },
402
+ },
403
+ ],
404
+ };
405
+
406
+ const processorFn = processor.createProcessor();
407
+ processorFn([], [message]);
408
+
409
+ // Should still have only the original tool call
410
+ expect(message.tool_calls!.length).toBe(1);
411
+ expect(message.tool_calls![0].id).toBe("existing_call");
412
+ });
413
+
414
+ it("should handle malformed JSON gracefully", () => {
415
+ const message: Message = {
416
+ role: "assistant",
417
+ content: `<tool_call>
418
+ {"name": "readFile", "arguments": "invalid json here"}
419
+ </tool_call>`,
420
+ };
421
+
422
+ const processorFn = processor.createProcessor();
423
+ processorFn([], [message]);
424
+
425
+ expect(message.tool_calls).toBeDefined();
426
+ expect(message.tool_calls!.length).toBe(1);
427
+
428
+ const toolCall = message.tool_calls![0];
429
+ expect(toolCall.function.name).toBe("readFile");
430
+ // Should fallback to wrapping in input object
431
+ const args = JSON.parse(toolCall.function.arguments);
432
+ expect(args.input).toBe("invalid json here");
433
+ });
434
+ });
435
+
436
+ describe("Incomplete XML tool calls", () => {
437
+ it("should handle incomplete tool calls with missing closing tags", () => {
438
+ const message: Message = {
439
+ role: "assistant",
440
+ content: `I see the issue. Let me make a clean patch with all the changes:
441
+
442
+ <tool_call>
443
+ {"name": "patchFile", "arguments": {"filePath": "bank-account.js", "patch": "//=============================================================================\\n// This is the complete implementation for the Bank Account exercise\\n//=============================================================================\\n\\nexport class BankAccount {\\n constructor() {\\n this._balance = 0;\\n this._isOpen = false;\\n }\\n\\n open() {\\n if (this._isOpen) {\\n throw new ValueError();\\n }\\n this._isOpen = true;\\n this._balance = 0;\\n }\\n\\n close() {\\n if (!this._isOpen) {\\n throw new ValueError();\\n }\\n this._isOpen = false;\\n }\\n\\n deposit(amount) {\\n if (!this._isOpen || amount <= 0) {\\n throw new ValueError();\\n }\\n this._balance += amount;\\n }\\n\\n withdraw(amount) {\\n if (!this._isOpen || amount <= 0 || amount > this._balance) {\\n throw new ValueError();\\n }\\n this._balance -= amount;\\n }\\n\\n get balance() {\\n if (!this._isOpen) {\\n throw new ValueError();\\n }\\n return this._balance;\\n }\\n}\\n\\nexport class ValueError extends Error {\\n constructor() {\\n super('Bank account error');\\n }\\n}"}}`,
444
+ };
445
+
446
+ const processorFn = processor.createProcessor();
447
+ processorFn([], [message]);
448
+
449
+ expect(message.tool_calls).toBeDefined();
450
+ expect(message.tool_calls!.length).toBe(1);
451
+
452
+ const toolCall = message.tool_calls![0];
453
+ expect(toolCall.function.name).toBe("patchFile");
454
+
455
+ // Parse the arguments to ensure they're correctly extracted despite missing closing tag
456
+ const args = JSON.parse(toolCall.function.arguments);
457
+ expect(args.filePath).toBe("bank-account.js");
458
+ expect(args.patch).toBeDefined();
459
+ expect(typeof args.patch).toBe("string");
460
+ expect(args.patch).toContain("export class BankAccount");
461
+ expect(args.patch).toContain("export class ValueError");
462
+
463
+ // Verify the processor correctly handled the incomplete XML (missing </tool_call>)
464
+ expect(toolCall.id).toBeDefined();
465
+ expect(toolCall.type).toBe("function");
466
+ });
467
+ });
468
+ });
@@ -0,0 +1,127 @@
1
+ import { ycmdStart, ycmdDiagnostics } from "../../../src/agents/tools/ycmd";
2
+ import * as fs from "fs";
3
+ import * as path from "path";
4
+ import { execSync } from "child_process";
5
+
6
+ async function testDiagnostics() {
7
+ console.log("šŸ”§ Starting ycmd server...");
8
+
9
+ try {
10
+ // Start ycmd server
11
+ const startResult = await ycmdStart({
12
+ workspaceRoot: process.cwd(),
13
+ logLevel: "debug",
14
+ });
15
+ console.log("āœ… ycmd server started:", startResult);
16
+
17
+ // Wait for server to fully initialize
18
+ console.log("ā³ Waiting for server initialization...");
19
+ await new Promise((resolve) => setTimeout(resolve, 3000));
20
+
21
+ const testFile = path.join(
22
+ process.cwd(),
23
+ "tests/ycmd/fixtures/debug_diagnostics.ts"
24
+ );
25
+
26
+ // Ensure the test file exists
27
+ if (!fs.existsSync(testFile)) {
28
+ console.log("āŒ Test file does not exist:", testFile);
29
+ return;
30
+ }
31
+
32
+ console.log("šŸ“ Test file path:", testFile);
33
+ console.log("šŸ“„ Test file contents:");
34
+ console.log(fs.readFileSync(testFile, "utf8"));
35
+
36
+ // Test diagnostics multiple times with increasing delays
37
+ const delays = [1000, 3000, 5000, 10000];
38
+
39
+ for (const delay of delays) {
40
+ console.log(`\nšŸ” Testing diagnostics after ${delay}ms delay...`);
41
+ await new Promise((resolve) => setTimeout(resolve, delay));
42
+
43
+ try {
44
+ const diagnostics = await ycmdDiagnostics({
45
+ filepath: testFile,
46
+ line: 1,
47
+ column: 1,
48
+ });
49
+
50
+ console.log(
51
+ "šŸ“Š Diagnostics result:",
52
+ JSON.stringify(diagnostics, null, 2)
53
+ );
54
+
55
+ if (
56
+ diagnostics &&
57
+ typeof diagnostics === "object" &&
58
+ "content" in diagnostics
59
+ ) {
60
+ const content = diagnostics.content;
61
+ if (Array.isArray(content) && content.length > 0) {
62
+ console.log(`āœ… Found ${content.length} diagnostic(s)!`);
63
+ content.forEach((diag, index) => {
64
+ console.log(
65
+ ` ${index + 1}. ${
66
+ diag.text || diag.message || JSON.stringify(diag)
67
+ }`
68
+ );
69
+ });
70
+ break; // Found diagnostics, stop testing
71
+ }
72
+ }
73
+ } catch (error) {
74
+ console.log("āŒ Diagnostics error:", error.message);
75
+ }
76
+ }
77
+
78
+ // Try diagnostics on a specific error line
79
+ console.log(
80
+ "\nšŸŽÆ Testing diagnostics on specific error line (line 9 - missing property)..."
81
+ );
82
+ try {
83
+ const specificDiagnostics = await ycmdDiagnostics({
84
+ filepath: testFile,
85
+ line: 9,
86
+ column: 12,
87
+ });
88
+ console.log(
89
+ "šŸ“Š Specific line diagnostics:",
90
+ JSON.stringify(specificDiagnostics, null, 2)
91
+ );
92
+ } catch (error) {
93
+ console.log("āŒ Specific diagnostics error:", error.message);
94
+ }
95
+
96
+ // Check if TypeScript is properly configured
97
+ console.log("\nšŸ”§ Checking TypeScript configuration...");
98
+ const tsconfigPath = path.join(process.cwd(), "tsconfig.json");
99
+ if (fs.existsSync(tsconfigPath)) {
100
+ console.log("āœ… tsconfig.json found");
101
+ const tsconfig = JSON.parse(fs.readFileSync(tsconfigPath, "utf8"));
102
+ console.log(
103
+ "šŸ“‹ Compiler options:",
104
+ JSON.stringify(tsconfig.compilerOptions, null, 2)
105
+ );
106
+ } else {
107
+ console.log("āš ļø No tsconfig.json found");
108
+ }
109
+
110
+ // Try running TypeScript compiler directly to see if it detects errors
111
+ console.log("\nšŸ” Running TypeScript compiler directly...");
112
+ try {
113
+ execSync(`npx tsc --noEmit ${testFile}`, { stdio: "pipe" });
114
+ console.log("āœ… TypeScript compiler found no errors");
115
+ } catch (error) {
116
+ console.log("āŒ TypeScript compiler errors:");
117
+ console.log(
118
+ error.stdout?.toString() || error.stderr?.toString() || error.message
119
+ );
120
+ }
121
+ } catch (error) {
122
+ console.error("āŒ Test failed:", error.message);
123
+ console.error("Stack trace:", error.stack);
124
+ }
125
+ }
126
+
127
+ testDiagnostics().catch(console.error);
@@ -0,0 +1,26 @@
1
+ // TypeScript file with clear errors to test diagnostics
2
+ interface User {
3
+ name: string;
4
+ age: number;
5
+ email?: string;
6
+ }
7
+
8
+ function createUser(name: string, age: number): User {
9
+ // This should trigger a type error - missing 'age' property
10
+ return { name };
11
+ }
12
+
13
+ // This should trigger an error - React is not imported
14
+ const component = React.createElement('div');
15
+
16
+ // This should trigger an error - missing 'age' property
17
+ const user: User = { name: 'Alice' };
18
+
19
+ // This should trigger an error - undefined variable
20
+ console.log(undefinedVariable);
21
+
22
+ // This should trigger an error - calling method on possibly undefined
23
+ const maybeString: string | undefined = undefined;
24
+ maybeString.toUpperCase();
25
+
26
+ export { createUser };
@@ -0,0 +1,17 @@
1
+ interface User {
2
+ name: string;
3
+ age: number;
4
+ }
5
+
6
+ function createUser(name: string, age: number): User {
7
+ // ERROR: Missing 'age' property - should cause TypeScript error
8
+ return { name };
9
+ }
10
+
11
+ // ERROR: Using undefined variable - should cause TypeScript error
12
+ console.log(undefinedVariable);
13
+
14
+ // ERROR: Type mismatch - missing required property - should cause TypeScript error
15
+ const user: User = { name: 'Alice' };
16
+
17
+ export { createUser };