@tyvm/knowhow 0.0.1

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 (492) hide show
  1. package/.vscode/launch.json +14 -0
  2. package/CONFIG.md +336 -0
  3. package/README.md +49 -0
  4. package/autodoc/chat.mdx +20 -0
  5. package/autodoc/cli.mdx +11 -0
  6. package/autodoc/plugins/asana.mdx +47 -0
  7. package/autodoc/plugins/downloader/downloader.mdx +38 -0
  8. package/autodoc/plugins/downloader/plugin.mdx +37 -0
  9. package/autodoc/plugins/downloader/types.mdx +42 -0
  10. package/autodoc/plugins/embedding.mdx +41 -0
  11. package/autodoc/plugins/figma.mdx +45 -0
  12. package/autodoc/plugins/github.mdx +40 -0
  13. package/autodoc/plugins/jira.mdx +46 -0
  14. package/autodoc/plugins/language.mdx +37 -0
  15. package/autodoc/plugins/linear.mdx +35 -0
  16. package/autodoc/plugins/notion.mdx +38 -0
  17. package/autodoc/plugins/plugins.mdx +59 -0
  18. package/autodoc/plugins/types.mdx +51 -0
  19. package/autodoc/plugins/vim.mdx +39 -0
  20. package/autodoc/tools/addInternalTools.mdx +1 -0
  21. package/autodoc/tools/agentCall.mdx +1 -0
  22. package/autodoc/tools/asana/definitions.mdx +10 -0
  23. package/autodoc/tools/asana/index.mdx +12 -0
  24. package/autodoc/tools/askHuman.mdx +1 -0
  25. package/autodoc/tools/callPlugin.mdx +1 -0
  26. package/autodoc/tools/embeddingSearch.mdx +1 -0
  27. package/autodoc/tools/execCommand.mdx +1 -0
  28. package/autodoc/tools/fileSearch.mdx +1 -0
  29. package/autodoc/tools/finalAnswer.mdx +1 -0
  30. package/autodoc/tools/github/definitions.mdx +6 -0
  31. package/autodoc/tools/github/index.mdx +8 -0
  32. package/autodoc/tools/index.mdx +14 -0
  33. package/autodoc/tools/lintFile.mdx +7 -0
  34. package/autodoc/tools/list.mdx +16 -0
  35. package/autodoc/tools/modifyFile.mdx +7 -0
  36. package/autodoc/tools/patch.mdx +9 -0
  37. package/autodoc/tools/readBlocks.mdx +1 -0
  38. package/autodoc/tools/readFile.mdx +1 -0
  39. package/autodoc/tools/scanFile.mdx +1 -0
  40. package/autodoc/tools/textSearch.mdx +6 -0
  41. package/autodoc/tools/types/fileblock.mdx +1 -0
  42. package/autodoc/tools/visionTool.mdx +1 -0
  43. package/autodoc/tools/writeFile.mdx +1 -0
  44. package/jest.config.js +18 -0
  45. package/package.json +89 -0
  46. package/src/agents/base/base.ts +619 -0
  47. package/src/agents/base/prompt.ts +26 -0
  48. package/src/agents/configurable/ConfigAgent.ts +23 -0
  49. package/src/agents/developer/developer.ts +69 -0
  50. package/src/agents/index.ts +8 -0
  51. package/src/agents/interface.ts +11 -0
  52. package/src/agents/patcher/codebase.md +27 -0
  53. package/src/agents/patcher/patcher.ts +110 -0
  54. package/src/agents/researcher/researcher.ts +109 -0
  55. package/src/agents/tools/addInternalTools.ts +21 -0
  56. package/src/agents/tools/agentCall.ts +18 -0
  57. package/src/agents/tools/aiClient.ts +36 -0
  58. package/src/agents/tools/asana/definitions.ts +199 -0
  59. package/src/agents/tools/asana/index.ts +108 -0
  60. package/src/agents/tools/askHuman.ts +8 -0
  61. package/src/agents/tools/callPlugin.ts +4 -0
  62. package/src/agents/tools/embeddingSearch.ts +5 -0
  63. package/src/agents/tools/execCommand.ts +26 -0
  64. package/src/agents/tools/fileSearch.ts +33 -0
  65. package/src/agents/tools/finalAnswer.ts +4 -0
  66. package/src/agents/tools/github/definitions.ts +89 -0
  67. package/src/agents/tools/github/index.ts +67 -0
  68. package/src/agents/tools/googleSearch.ts +242 -0
  69. package/src/agents/tools/index.ts +24 -0
  70. package/src/agents/tools/language/definitions.ts +97 -0
  71. package/src/agents/tools/language/index.ts +19 -0
  72. package/src/agents/tools/lintFile.ts +17 -0
  73. package/src/agents/tools/list.ts +514 -0
  74. package/src/agents/tools/loadWebpage.ts +129 -0
  75. package/src/agents/tools/modifyFile.ts +53 -0
  76. package/src/agents/tools/patch.ts +672 -0
  77. package/src/agents/tools/readBlocks.ts +41 -0
  78. package/src/agents/tools/readFile.ts +39 -0
  79. package/src/agents/tools/scanFile.ts +16 -0
  80. package/src/agents/tools/textSearch.ts +21 -0
  81. package/src/agents/tools/types/fileblock.ts +5 -0
  82. package/src/agents/tools/visionTool.ts +5 -0
  83. package/src/agents/tools/writeFile.ts +46 -0
  84. package/src/agents/vim/vim.ts +153 -0
  85. package/src/ai.ts +167 -0
  86. package/src/chat.ts +412 -0
  87. package/src/cli.ts +85 -0
  88. package/src/clients/anthropic.ts +399 -0
  89. package/src/clients/gemini.ts +486 -0
  90. package/src/clients/http.ts +107 -0
  91. package/src/clients/index.ts +183 -0
  92. package/src/clients/knowhow.ts +33 -0
  93. package/src/clients/openai.ts +253 -0
  94. package/src/clients/types.ts +91 -0
  95. package/src/clients/xai.ts +132 -0
  96. package/src/config.ts +211 -0
  97. package/src/conversion.ts +140 -0
  98. package/src/dataset/diffs/README.md +12 -0
  99. package/src/dataset/diffs/debug-errors.ts +29 -0
  100. package/src/dataset/diffs/debug.ts +64 -0
  101. package/src/dataset/diffs/generate.ts +71 -0
  102. package/src/dataset/diffs/jsonl.ts +54 -0
  103. package/src/dataset/diffs/test.ts +193 -0
  104. package/src/embeddings.ts +411 -0
  105. package/src/hashes.ts +67 -0
  106. package/src/index.ts +376 -0
  107. package/src/login.ts +78 -0
  108. package/src/microphone.ts +136 -0
  109. package/src/modules/index.ts +37 -0
  110. package/src/modules/types.ts +48 -0
  111. package/src/plugins/asana.ts +134 -0
  112. package/src/plugins/downloader/downloader.ts +204 -0
  113. package/src/plugins/downloader/plugin.ts +85 -0
  114. package/src/plugins/downloader/types.ts +85 -0
  115. package/src/plugins/embedding.ts +42 -0
  116. package/src/plugins/figma.ts +137 -0
  117. package/src/plugins/github.ts +153 -0
  118. package/src/plugins/jira.ts +104 -0
  119. package/src/plugins/language.ts +100 -0
  120. package/src/plugins/linear.ts +219 -0
  121. package/src/plugins/notion.ts +170 -0
  122. package/src/plugins/plugins.ts +56 -0
  123. package/src/plugins/types.ts +5 -0
  124. package/src/plugins/url.ts +63 -0
  125. package/src/plugins/vim.ts +73 -0
  126. package/src/prompts/BasicCodeDocumenter.ts +1 -0
  127. package/src/prompts/BasicProjectDocumenter.ts +1 -0
  128. package/src/prompts/EmbeddingSeachHelper.ts +1 -0
  129. package/src/prompts/index.ts +9 -0
  130. package/src/server/index.ts +14 -0
  131. package/src/services/AgentService.ts +98 -0
  132. package/src/services/EmbeddingService.ts +410 -0
  133. package/src/services/EventService.ts +20 -0
  134. package/src/services/GitHub.ts +60 -0
  135. package/src/services/KnowhowClient.ts +113 -0
  136. package/src/services/Mcp.ts +270 -0
  137. package/src/services/McpServer.ts +119 -0
  138. package/src/services/McpWebsocketTransport.ts +64 -0
  139. package/src/services/S3.ts +126 -0
  140. package/src/services/Tools.ts +65 -0
  141. package/src/services/flags.ts +52 -0
  142. package/src/services/index.ts +8 -0
  143. package/src/types.ts +225 -0
  144. package/src/utils/index.ts +108 -0
  145. package/src/worker.ts +80 -0
  146. package/tests/integration/figma.test.ts +70 -0
  147. package/tests/integration/fileblocks/readwrite.test.ts +95 -0
  148. package/tests/integration/patching/input.txt +145 -0
  149. package/tests/integration/patching/output.txt +145 -0
  150. package/tests/integration/patching/patch.txt +15 -0
  151. package/tests/integration/patching/unseen.txt +80 -0
  152. package/tests/integration/patching.test.ts +136 -0
  153. package/tests/languagePlugin.test.ts +74 -0
  154. package/tests/patching/corrupted.test.ts +78 -0
  155. package/tests/patching/imports.patch.txt +11 -0
  156. package/tests/patching/imports.test.ts +43 -0
  157. package/tests/patching/imports.txt +11 -0
  158. package/tests/patching/interface.patch.txt +15 -0
  159. package/tests/patching/interface.txt +7 -0
  160. package/tests/test.spec.ts +132 -0
  161. package/ts_build/src/agents/base/base.d.ts +88 -0
  162. package/ts_build/src/agents/base/base.js +464 -0
  163. package/ts_build/src/agents/base/base.js.map +1 -0
  164. package/ts_build/src/agents/base/prompt.d.ts +1 -0
  165. package/ts_build/src/agents/base/prompt.js +30 -0
  166. package/ts_build/src/agents/base/prompt.js.map +1 -0
  167. package/ts_build/src/agents/configurable/ConfigAgent.d.ts +10 -0
  168. package/ts_build/src/agents/configurable/ConfigAgent.js +25 -0
  169. package/ts_build/src/agents/configurable/ConfigAgent.js.map +1 -0
  170. package/ts_build/src/agents/configurable/OpenAIAgent.d.ts +0 -0
  171. package/ts_build/src/agents/configurable/OpenAIAgent.js +1 -0
  172. package/ts_build/src/agents/configurable/OpenAIAgent.js.map +1 -0
  173. package/ts_build/src/agents/developer/developer.d.ts +9 -0
  174. package/ts_build/src/agents/developer/developer.js +69 -0
  175. package/ts_build/src/agents/developer/developer.js.map +1 -0
  176. package/ts_build/src/agents/index.d.ts +7 -0
  177. package/ts_build/src/agents/index.js +38 -0
  178. package/ts_build/src/agents/index.js.map +1 -0
  179. package/ts_build/src/agents/interface.d.ts +10 -0
  180. package/ts_build/src/agents/interface.js +3 -0
  181. package/ts_build/src/agents/interface.js.map +1 -0
  182. package/ts_build/src/agents/patcher/patcher.d.ts +9 -0
  183. package/ts_build/src/agents/patcher/patcher.js +106 -0
  184. package/ts_build/src/agents/patcher/patcher.js.map +1 -0
  185. package/ts_build/src/agents/researcher/researcher.d.ts +9 -0
  186. package/ts_build/src/agents/researcher/researcher.js +107 -0
  187. package/ts_build/src/agents/researcher/researcher.js.map +1 -0
  188. package/ts_build/src/agents/tools/addInternalTools.d.ts +5 -0
  189. package/ts_build/src/agents/tools/addInternalTools.js +18 -0
  190. package/ts_build/src/agents/tools/addInternalTools.js.map +1 -0
  191. package/ts_build/src/agents/tools/agentCall.d.ts +1 -0
  192. package/ts_build/src/agents/tools/agentCall.js +21 -0
  193. package/ts_build/src/agents/tools/agentCall.js.map +1 -0
  194. package/ts_build/src/agents/tools/aiClient.d.ts +6 -0
  195. package/ts_build/src/agents/tools/aiClient.js +25 -0
  196. package/ts_build/src/agents/tools/aiClient.js.map +1 -0
  197. package/ts_build/src/agents/tools/asana/definitions.d.ts +202 -0
  198. package/ts_build/src/agents/tools/asana/definitions.js +197 -0
  199. package/ts_build/src/agents/tools/asana/definitions.js.map +1 -0
  200. package/ts_build/src/agents/tools/asana/index.d.ts +8 -0
  201. package/ts_build/src/agents/tools/asana/index.js +98 -0
  202. package/ts_build/src/agents/tools/asana/index.js.map +1 -0
  203. package/ts_build/src/agents/tools/askHuman.d.ts +1 -0
  204. package/ts_build/src/agents/tools/askHuman.js +15 -0
  205. package/ts_build/src/agents/tools/askHuman.js.map +1 -0
  206. package/ts_build/src/agents/tools/callPlugin.d.ts +1 -0
  207. package/ts_build/src/agents/tools/callPlugin.js +9 -0
  208. package/ts_build/src/agents/tools/callPlugin.js.map +1 -0
  209. package/ts_build/src/agents/tools/client.d.ts +5 -0
  210. package/ts_build/src/agents/tools/client.js +21 -0
  211. package/ts_build/src/agents/tools/client.js.map +1 -0
  212. package/ts_build/src/agents/tools/embeddingSearch.d.ts +1 -0
  213. package/ts_build/src/agents/tools/embeddingSearch.js +9 -0
  214. package/ts_build/src/agents/tools/embeddingSearch.js.map +1 -0
  215. package/ts_build/src/agents/tools/execCommand.d.ts +1 -0
  216. package/ts_build/src/agents/tools/execCommand.js +25 -0
  217. package/ts_build/src/agents/tools/execCommand.js.map +1 -0
  218. package/ts_build/src/agents/tools/fileSearch.d.ts +1 -0
  219. package/ts_build/src/agents/tools/fileSearch.js +31 -0
  220. package/ts_build/src/agents/tools/fileSearch.js.map +1 -0
  221. package/ts_build/src/agents/tools/finalAnswer.d.ts +1 -0
  222. package/ts_build/src/agents/tools/finalAnswer.js +8 -0
  223. package/ts_build/src/agents/tools/finalAnswer.js.map +1 -0
  224. package/ts_build/src/agents/tools/github/definitions.d.ts +47 -0
  225. package/ts_build/src/agents/tools/github/definitions.js +86 -0
  226. package/ts_build/src/agents/tools/github/definitions.js.map +1 -0
  227. package/ts_build/src/agents/tools/github/index.d.ts +789 -0
  228. package/ts_build/src/agents/tools/github/index.js +56 -0
  229. package/ts_build/src/agents/tools/github/index.js.map +1 -0
  230. package/ts_build/src/agents/tools/googleSearch.d.ts +93 -0
  231. package/ts_build/src/agents/tools/googleSearch.js +117 -0
  232. package/ts_build/src/agents/tools/googleSearch.js.map +1 -0
  233. package/ts_build/src/agents/tools/googleSearchTypes.d.ts +74 -0
  234. package/ts_build/src/agents/tools/googleSearchTypes.js +3 -0
  235. package/ts_build/src/agents/tools/googleSearchTypes.js.map +1 -0
  236. package/ts_build/src/agents/tools/index.d.ts +24 -0
  237. package/ts_build/src/agents/tools/index.js +41 -0
  238. package/ts_build/src/agents/tools/index.js.map +1 -0
  239. package/ts_build/src/agents/tools/language/definitions.d.ts +89 -0
  240. package/ts_build/src/agents/tools/language/definitions.js +95 -0
  241. package/ts_build/src/agents/tools/language/definitions.js.map +1 -0
  242. package/ts_build/src/agents/tools/language/index.d.ts +4 -0
  243. package/ts_build/src/agents/tools/language/index.js +22 -0
  244. package/ts_build/src/agents/tools/language/index.js.map +1 -0
  245. package/ts_build/src/agents/tools/lintFile.d.ts +1 -0
  246. package/ts_build/src/agents/tools/lintFile.js +22 -0
  247. package/ts_build/src/agents/tools/lintFile.js.map +1 -0
  248. package/ts_build/src/agents/tools/list.d.ts +2 -0
  249. package/ts_build/src/agents/tools/list.js +505 -0
  250. package/ts_build/src/agents/tools/list.js.map +1 -0
  251. package/ts_build/src/agents/tools/loadWebpage.d.ts +8 -0
  252. package/ts_build/src/agents/tools/loadWebpage.js +97 -0
  253. package/ts_build/src/agents/tools/loadWebpage.js.map +1 -0
  254. package/ts_build/src/agents/tools/modifyFile.d.ts +2 -0
  255. package/ts_build/src/agents/tools/modifyFile.js +74 -0
  256. package/ts_build/src/agents/tools/modifyFile.js.map +1 -0
  257. package/ts_build/src/agents/tools/patch.d.ts +21 -0
  258. package/ts_build/src/agents/tools/patch.js +443 -0
  259. package/ts_build/src/agents/tools/patch.js.map +1 -0
  260. package/ts_build/src/agents/tools/readBlocks.d.ts +2 -0
  261. package/ts_build/src/agents/tools/readBlocks.js +59 -0
  262. package/ts_build/src/agents/tools/readBlocks.js.map +1 -0
  263. package/ts_build/src/agents/tools/readFile.d.ts +1 -0
  264. package/ts_build/src/agents/tools/readFile.js +46 -0
  265. package/ts_build/src/agents/tools/readFile.js.map +1 -0
  266. package/ts_build/src/agents/tools/scanFile.d.ts +1 -0
  267. package/ts_build/src/agents/tools/scanFile.js +36 -0
  268. package/ts_build/src/agents/tools/scanFile.js.map +1 -0
  269. package/ts_build/src/agents/tools/textSearch.d.ts +1 -0
  270. package/ts_build/src/agents/tools/textSearch.js +22 -0
  271. package/ts_build/src/agents/tools/textSearch.js.map +1 -0
  272. package/ts_build/src/agents/tools/types/fileblock.d.ts +5 -0
  273. package/ts_build/src/agents/tools/types/fileblock.js +3 -0
  274. package/ts_build/src/agents/tools/types/fileblock.js.map +1 -0
  275. package/ts_build/src/agents/tools/visionTool.d.ts +1 -0
  276. package/ts_build/src/agents/tools/visionTool.js +9 -0
  277. package/ts_build/src/agents/tools/visionTool.js.map +1 -0
  278. package/ts_build/src/agents/tools/writeFile.d.ts +2 -0
  279. package/ts_build/src/agents/tools/writeFile.js +61 -0
  280. package/ts_build/src/agents/tools/writeFile.js.map +1 -0
  281. package/ts_build/src/agents/vim/vim.d.ts +14 -0
  282. package/ts_build/src/agents/vim/vim.js +171 -0
  283. package/ts_build/src/agents/vim/vim.js.map +1 -0
  284. package/ts_build/src/ai.d.ts +10 -0
  285. package/ts_build/src/ai.js +102 -0
  286. package/ts_build/src/ai.js.map +1 -0
  287. package/ts_build/src/chat.d.ts +13 -0
  288. package/ts_build/src/chat.js +319 -0
  289. package/ts_build/src/chat.js.map +1 -0
  290. package/ts_build/src/cli.d.ts +2 -0
  291. package/ts_build/src/cli.js +98 -0
  292. package/ts_build/src/cli.js.map +1 -0
  293. package/ts_build/src/clients/anthropic.d.ts +31 -0
  294. package/ts_build/src/clients/anthropic.js +344 -0
  295. package/ts_build/src/clients/anthropic.js.map +1 -0
  296. package/ts_build/src/clients/gemini.d.ts +20 -0
  297. package/ts_build/src/clients/gemini.js +347 -0
  298. package/ts_build/src/clients/gemini.js.map +1 -0
  299. package/ts_build/src/clients/http.d.ts +12 -0
  300. package/ts_build/src/clients/http.js +91 -0
  301. package/ts_build/src/clients/http.js.map +1 -0
  302. package/ts_build/src/clients/index.d.ts +47 -0
  303. package/ts_build/src/clients/index.js +143 -0
  304. package/ts_build/src/clients/index.js.map +1 -0
  305. package/ts_build/src/clients/knowhow.d.ts +10 -0
  306. package/ts_build/src/clients/knowhow.js +24 -0
  307. package/ts_build/src/clients/knowhow.js.map +1 -0
  308. package/ts_build/src/clients/openai.d.ts +20 -0
  309. package/ts_build/src/clients/openai.js +221 -0
  310. package/ts_build/src/clients/openai.js.map +1 -0
  311. package/ts_build/src/clients/types.d.ts +89 -0
  312. package/ts_build/src/clients/types.js +3 -0
  313. package/ts_build/src/clients/types.js.map +1 -0
  314. package/ts_build/src/clients/xai.d.ts +22 -0
  315. package/ts_build/src/clients/xai.js +108 -0
  316. package/ts_build/src/clients/xai.js.map +1 -0
  317. package/ts_build/src/config.d.ts +9 -0
  318. package/ts_build/src/config.js +216 -0
  319. package/ts_build/src/config.js.map +1 -0
  320. package/ts_build/src/conversion.d.ts +7 -0
  321. package/ts_build/src/conversion.js +114 -0
  322. package/ts_build/src/conversion.js.map +1 -0
  323. package/ts_build/src/dataset/diffs/debug-errors.d.ts +1 -0
  324. package/ts_build/src/dataset/diffs/debug-errors.js +28 -0
  325. package/ts_build/src/dataset/diffs/debug-errors.js.map +1 -0
  326. package/ts_build/src/dataset/diffs/debug.d.ts +1 -0
  327. package/ts_build/src/dataset/diffs/debug.js +50 -0
  328. package/ts_build/src/dataset/diffs/debug.js.map +1 -0
  329. package/ts_build/src/dataset/diffs/generate.d.ts +1 -0
  330. package/ts_build/src/dataset/diffs/generate.js +70 -0
  331. package/ts_build/src/dataset/diffs/generate.js.map +1 -0
  332. package/ts_build/src/dataset/diffs/jsonl.d.ts +1 -0
  333. package/ts_build/src/dataset/diffs/jsonl.js +47 -0
  334. package/ts_build/src/dataset/diffs/jsonl.js.map +1 -0
  335. package/ts_build/src/dataset/diffs/test.d.ts +1 -0
  336. package/ts_build/src/dataset/diffs/test.js +114 -0
  337. package/ts_build/src/dataset/diffs/test.js.map +1 -0
  338. package/ts_build/src/embeddings.d.ts +19 -0
  339. package/ts_build/src/embeddings.js +322 -0
  340. package/ts_build/src/embeddings.js.map +1 -0
  341. package/ts_build/src/hashes.d.ts +6 -0
  342. package/ts_build/src/hashes.js +78 -0
  343. package/ts_build/src/hashes.js.map +1 -0
  344. package/ts_build/src/index.d.ts +14 -0
  345. package/ts_build/src/index.js +258 -0
  346. package/ts_build/src/index.js.map +1 -0
  347. package/ts_build/src/login.d.ts +2 -0
  348. package/ts_build/src/login.js +63 -0
  349. package/ts_build/src/login.js.map +1 -0
  350. package/ts_build/src/microphone.d.ts +9 -0
  351. package/ts_build/src/microphone.js +131 -0
  352. package/ts_build/src/microphone.js.map +1 -0
  353. package/ts_build/src/modules/index.d.ts +3 -0
  354. package/ts_build/src/modules/index.js +34 -0
  355. package/ts_build/src/modules/index.js.map +1 -0
  356. package/ts_build/src/modules/types.d.ts +37 -0
  357. package/ts_build/src/modules/types.js +3 -0
  358. package/ts_build/src/modules/types.js.map +1 -0
  359. package/ts_build/src/plugins/asana.d.ts +16 -0
  360. package/ts_build/src/plugins/asana.js +114 -0
  361. package/ts_build/src/plugins/asana.js.map +1 -0
  362. package/ts_build/src/plugins/downloader/downloader.d.ts +12 -0
  363. package/ts_build/src/plugins/downloader/downloader.js +174 -0
  364. package/ts_build/src/plugins/downloader/downloader.js.map +1 -0
  365. package/ts_build/src/plugins/downloader/index.d.ts +3 -0
  366. package/ts_build/src/plugins/downloader/index.js +41 -0
  367. package/ts_build/src/plugins/downloader/index.js.map +1 -0
  368. package/ts_build/src/plugins/downloader/plugin.d.ts +8 -0
  369. package/ts_build/src/plugins/downloader/plugin.js +83 -0
  370. package/ts_build/src/plugins/downloader/plugin.js.map +1 -0
  371. package/ts_build/src/plugins/downloader/types.d.ts +82 -0
  372. package/ts_build/src/plugins/downloader/types.js +79 -0
  373. package/ts_build/src/plugins/downloader/types.js.map +1 -0
  374. package/ts_build/src/plugins/embedding.d.ts +5 -0
  375. package/ts_build/src/plugins/embedding.js +28 -0
  376. package/ts_build/src/plugins/embedding.js.map +1 -0
  377. package/ts_build/src/plugins/figma.d.ts +20 -0
  378. package/ts_build/src/plugins/figma.js +94 -0
  379. package/ts_build/src/plugins/figma.js.map +1 -0
  380. package/ts_build/src/plugins/github.d.ts +1223 -0
  381. package/ts_build/src/plugins/github.js +115 -0
  382. package/ts_build/src/plugins/github.js.map +1 -0
  383. package/ts_build/src/plugins/jira.d.ts +15 -0
  384. package/ts_build/src/plugins/jira.js +94 -0
  385. package/ts_build/src/plugins/jira.js.map +1 -0
  386. package/ts_build/src/plugins/language.d.ts +8 -0
  387. package/ts_build/src/plugins/language.js +69 -0
  388. package/ts_build/src/plugins/language.js.map +1 -0
  389. package/ts_build/src/plugins/linear.d.ts +23 -0
  390. package/ts_build/src/plugins/linear.js +184 -0
  391. package/ts_build/src/plugins/linear.js.map +1 -0
  392. package/ts_build/src/plugins/notion.d.ts +32 -0
  393. package/ts_build/src/plugins/notion.js +131 -0
  394. package/ts_build/src/plugins/notion.js.map +1 -0
  395. package/ts_build/src/plugins/plugins.d.ts +11 -0
  396. package/ts_build/src/plugins/plugins.js +51 -0
  397. package/ts_build/src/plugins/plugins.js.map +1 -0
  398. package/ts_build/src/plugins/types.d.ts +5 -0
  399. package/ts_build/src/plugins/types.js +3 -0
  400. package/ts_build/src/plugins/types.js.map +1 -0
  401. package/ts_build/src/plugins/url.d.ts +8 -0
  402. package/ts_build/src/plugins/url.js +50 -0
  403. package/ts_build/src/plugins/url.js.map +1 -0
  404. package/ts_build/src/plugins/vim.d.ts +11 -0
  405. package/ts_build/src/plugins/vim.js +63 -0
  406. package/ts_build/src/plugins/vim.js.map +1 -0
  407. package/ts_build/src/prompts/BasicCodeDocumenter.d.ts +2 -0
  408. package/ts_build/src/prompts/BasicCodeDocumenter.js +4 -0
  409. package/ts_build/src/prompts/BasicCodeDocumenter.js.map +1 -0
  410. package/ts_build/src/prompts/BasicProjectDocumenter.d.ts +2 -0
  411. package/ts_build/src/prompts/BasicProjectDocumenter.js +4 -0
  412. package/ts_build/src/prompts/BasicProjectDocumenter.js.map +1 -0
  413. package/ts_build/src/prompts/EmbeddingSeachHelper.d.ts +2 -0
  414. package/ts_build/src/prompts/EmbeddingSeachHelper.js +4 -0
  415. package/ts_build/src/prompts/EmbeddingSeachHelper.js.map +1 -0
  416. package/ts_build/src/prompts/index.d.ts +13 -0
  417. package/ts_build/src/prompts/index.js +15 -0
  418. package/ts_build/src/prompts/index.js.map +1 -0
  419. package/ts_build/src/server/index.d.ts +1 -0
  420. package/ts_build/src/server/index.js +17 -0
  421. package/ts_build/src/server/index.js.map +1 -0
  422. package/ts_build/src/services/AgentService.d.ts +14 -0
  423. package/ts_build/src/services/AgentService.js +87 -0
  424. package/ts_build/src/services/AgentService.js.map +1 -0
  425. package/ts_build/src/services/EmbeddingService.d.ts +39 -0
  426. package/ts_build/src/services/EmbeddingService.js +307 -0
  427. package/ts_build/src/services/EmbeddingService.js.map +1 -0
  428. package/ts_build/src/services/EventService.d.ts +9 -0
  429. package/ts_build/src/services/EventService.js +20 -0
  430. package/ts_build/src/services/EventService.js.map +1 -0
  431. package/ts_build/src/services/GitHub.d.ts +11 -0
  432. package/ts_build/src/services/GitHub.js +52 -0
  433. package/ts_build/src/services/GitHub.js.map +1 -0
  434. package/ts_build/src/services/KnowhowClient.d.ts +18 -0
  435. package/ts_build/src/services/KnowhowClient.js +85 -0
  436. package/ts_build/src/services/KnowhowClient.js.map +1 -0
  437. package/ts_build/src/services/Mcp.d.ts +377 -0
  438. package/ts_build/src/services/Mcp.js +221 -0
  439. package/ts_build/src/services/Mcp.js.map +1 -0
  440. package/ts_build/src/services/McpServer.d.ts +19 -0
  441. package/ts_build/src/services/McpServer.js +104 -0
  442. package/ts_build/src/services/McpServer.js.map +1 -0
  443. package/ts_build/src/services/McpWebsocketTransport.d.ts +13 -0
  444. package/ts_build/src/services/McpWebsocketTransport.js +59 -0
  445. package/ts_build/src/services/McpWebsocketTransport.js.map +1 -0
  446. package/ts_build/src/services/S3.d.ts +9 -0
  447. package/ts_build/src/services/S3.js +116 -0
  448. package/ts_build/src/services/S3.js.map +1 -0
  449. package/ts_build/src/services/Tools.d.ts +19 -0
  450. package/ts_build/src/services/Tools.js +51 -0
  451. package/ts_build/src/services/Tools.js.map +1 -0
  452. package/ts_build/src/services/flags.d.ts +13 -0
  453. package/ts_build/src/services/flags.js +48 -0
  454. package/ts_build/src/services/flags.js.map +1 -0
  455. package/ts_build/src/services/index.d.ts +8 -0
  456. package/ts_build/src/services/index.js +38 -0
  457. package/ts_build/src/services/index.js.map +1 -0
  458. package/ts_build/src/terminal.d.ts +1 -0
  459. package/ts_build/src/terminal.js +35 -0
  460. package/ts_build/src/terminal.js.map +1 -0
  461. package/ts_build/src/types.d.ts +181 -0
  462. package/ts_build/src/types.js +94 -0
  463. package/ts_build/src/types.js.map +1 -0
  464. package/ts_build/src/utils/index.d.ts +24 -0
  465. package/ts_build/src/utils/index.js +116 -0
  466. package/ts_build/src/utils/index.js.map +1 -0
  467. package/ts_build/src/worker.d.ts +1 -0
  468. package/ts_build/src/worker.js +68 -0
  469. package/ts_build/src/worker.js.map +1 -0
  470. package/ts_build/tests/integration/figma.test.d.ts +1 -0
  471. package/ts_build/tests/integration/figma.test.js +47 -0
  472. package/ts_build/tests/integration/figma.test.js.map +1 -0
  473. package/ts_build/tests/integration/fileblocks/readwrite.test.d.ts +1 -0
  474. package/ts_build/tests/integration/fileblocks/readwrite.test.js +95 -0
  475. package/ts_build/tests/integration/fileblocks/readwrite.test.js.map +1 -0
  476. package/ts_build/tests/integration/patching.test.d.ts +1 -0
  477. package/ts_build/tests/integration/patching.test.js +117 -0
  478. package/ts_build/tests/integration/patching.test.js.map +1 -0
  479. package/ts_build/tests/languagePlugin.test.d.ts +1 -0
  480. package/ts_build/tests/languagePlugin.test.js +78 -0
  481. package/ts_build/tests/languagePlugin.test.js.map +1 -0
  482. package/ts_build/tests/patching/corrupted.test.d.ts +1 -0
  483. package/ts_build/tests/patching/corrupted.test.js +53 -0
  484. package/ts_build/tests/patching/corrupted.test.js.map +1 -0
  485. package/ts_build/tests/patching/imports.test.d.ts +1 -0
  486. package/ts_build/tests/patching/imports.test.js +61 -0
  487. package/ts_build/tests/patching/imports.test.js.map +1 -0
  488. package/ts_build/tests/test.spec.d.ts +1 -0
  489. package/ts_build/tests/test.spec.js +101 -0
  490. package/ts_build/tests/test.spec.js.map +1 -0
  491. package/tsconfig.json +31 -0
  492. package/tslint.json +11 -0
@@ -0,0 +1,672 @@
1
+ import * as fs from "fs";
2
+ import * as util from "util";
3
+ // Assuming 'diff' library provides applyPatch and createTwoFilesPatch (or similar for basic patch creation if needed later)
4
+ import { applyPatch, createTwoFilesPatch } from "diff";
5
+ import {
6
+ writeFile,
7
+ readFile,
8
+ fileExists,
9
+ mkdir,
10
+ splitByNewLines,
11
+ } from "../../utils"; // Assuming these utils exist
12
+ import { lintFile } from "./lintFile"; // Assuming this exists
13
+
14
+ // --- Utility Functions (Keep or Simplify) ---
15
+
16
+ /**
17
+ * Finds all 1-based line numbers where a line (trimmed) matches the search text.
18
+ */
19
+ function findAllLineNumbers(fullText: string, searchText: string): number[] {
20
+ const lines = splitByNewLines(fullText);
21
+ const search =
22
+ searchText.startsWith("+") || searchText.startsWith("-")
23
+ ? searchText.slice(1).trim()
24
+ : searchText.trim();
25
+
26
+ if (!search) return []; // Don't match empty lines everywhere
27
+
28
+ const lineNumbers: number[] = [];
29
+ lines.forEach((line, index) => {
30
+ if (line.trim() === search) {
31
+ lineNumbers.push(index + 1);
32
+ }
33
+ });
34
+ return lineNumbers;
35
+ }
36
+
37
+ /**
38
+ * Finds the number in a list closest to the goal number.
39
+ */
40
+ function findClosestNumber(
41
+ numbers: number[],
42
+ goal: number
43
+ ): number | undefined {
44
+ if (!numbers || numbers.length === 0) {
45
+ return undefined; // Return undefined if no numbers to choose from
46
+ }
47
+ return numbers.reduce((prev, curr) => {
48
+ return Math.abs(curr - goal) < Math.abs(prev - goal) ? curr : prev;
49
+ });
50
+ }
51
+
52
+ /**
53
+ * Finds the starting index (0-based) of a sequence (needle) within a larger array (haystack),
54
+ * using a while loop.
55
+ * * @param haystack The array to search within.
56
+ * @param needle The sequence of strings to find.
57
+ * @returns The 0-based starting index of the first occurrence of the needle, or -1 if not found.
58
+ */
59
+ function findSequenceIndex(haystack: string[], needle: string[]): number {
60
+ // Basic edge cases
61
+ if (!needle || needle.length === 0) {
62
+ // console.warn("findSequenceIndex: Needle is empty."); // Or return 0 depending on desired behavior for empty needle
63
+ return -1; // Cannot find an empty sequence according to original logic
64
+ }
65
+ if (!haystack || needle.length > haystack.length) {
66
+ return -1; // Needle cannot exist if it's longer than haystack
67
+ }
68
+
69
+ let haystackIndex = 0; // Current position to start searching for needle[0] in haystack
70
+
71
+ // Continue searching as long as there's enough space left in the haystack
72
+ // for the needle to potentially fit.
73
+ while (haystackIndex <= haystack.length - needle.length) {
74
+ // Find the *next* occurrence of the *first* element of the needle
75
+ // starting from the current haystackIndex.
76
+ const potentialStartIndex = haystack.indexOf(needle[0], haystackIndex);
77
+
78
+ // If the first element of the needle is not found anymore, the sequence cannot be found.
79
+ if (potentialStartIndex === -1) {
80
+ return -1;
81
+ }
82
+
83
+ // Optimization: If the found index doesn't leave enough room for the rest of the needle, stop.
84
+ if (potentialStartIndex > haystack.length - needle.length) {
85
+ return -1;
86
+ }
87
+
88
+ // Found the first element, now check if the rest of the sequence matches.
89
+ let sequenceMatches = true;
90
+ for (let needleIndex = 1; needleIndex < needle.length; needleIndex++) {
91
+ // If any element in the sequence doesn't match, break the inner loop.
92
+ if (haystack[potentialStartIndex + needleIndex] !== needle[needleIndex]) {
93
+ sequenceMatches = false;
94
+ break;
95
+ }
96
+ }
97
+
98
+ // If the inner loop completed without breaking, the sequence matches.
99
+ if (sequenceMatches) {
100
+ return potentialStartIndex; // Return the index where the sequence starts.
101
+ }
102
+
103
+ // If the sequence didn't match starting at potentialStartIndex,
104
+ // continue searching for needle[0] *after* the current potentialStartIndex.
105
+ haystackIndex = potentialStartIndex + 1;
106
+ }
107
+
108
+ // If the while loop finishes without returning, the sequence was not found.
109
+ return -1;
110
+ } // --- Hunk Parsing and Formatting (Keep as is) ---
111
+
112
+ export interface Hunk {
113
+ header: string;
114
+ originalStartLine: number; // Parsed from -s,l
115
+ originalLineCount: number; // Parsed from -s,l
116
+ newStartLine: number; // Parsed from +s,l
117
+ newLineCount: number; // Parsed from +s,l
118
+ lines: string[]; // All lines in the hunk body (context, -, +)
119
+ // Derived properties for convenience
120
+ additions: string[];
121
+ subtractions: string[];
122
+ contextLines: string[];
123
+ }
124
+
125
+ export function parseHunks(patch: string): Hunk[] {
126
+ const patchLines = splitByNewLines(patch);
127
+ const hunks: Hunk[] = [];
128
+ let currentHunkLines: string[] = [];
129
+ let currentHeader = "";
130
+ let originalStart = 0,
131
+ originalCount = 0,
132
+ newStart = 0,
133
+ newCount = 0;
134
+
135
+ for (const line of patchLines) {
136
+ if (line.startsWith("@@")) {
137
+ // Finalize previous hunk
138
+ if (currentHeader) {
139
+ const additions = currentHunkLines.filter((l) => l.startsWith("+"));
140
+ const subtractions = currentHunkLines.filter((l) => l.startsWith("-"));
141
+ const contextLines = currentHunkLines.filter((l) => l.startsWith(" "));
142
+ hunks.push({
143
+ header: currentHeader,
144
+ originalStartLine: originalStart,
145
+ originalLineCount: originalCount,
146
+ newStartLine: newStart,
147
+ newLineCount: newCount,
148
+ lines: currentHunkLines,
149
+ additions,
150
+ subtractions,
151
+ contextLines,
152
+ });
153
+ }
154
+ // Start new hunk
155
+ currentHeader = line;
156
+ currentHunkLines = [];
157
+ const match = line.match(/@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/);
158
+ if (match) {
159
+ originalStart = parseInt(match[1], 10);
160
+ originalCount = parseInt(match[2] || "1", 10); // Default length is 1 if omitted
161
+ newStart = parseInt(match[3], 10);
162
+ newCount = parseInt(match[4] || "1", 10); // Default length is 1 if omitted
163
+ } else {
164
+ // Malformed header, use defaults or throw error? Using defaults for robustness.
165
+ originalStart = 0;
166
+ originalCount = 0;
167
+ newStart = 0;
168
+ newCount = 0;
169
+ console.warn("Could not parse hunk header:", line);
170
+ }
171
+ } else if (
172
+ currentHeader &&
173
+ (line.startsWith(" ") ||
174
+ line.startsWith("+") ||
175
+ line.startsWith("-") ||
176
+ line === "\")
177
+ ) {
178
+ currentHunkLines.push(line);
179
+ }
180
+ // Ignore lines before first header or lines not part of hunk content (like index, ---, +++)
181
+ }
182
+
183
+ // Finalize the last hunk
184
+ if (currentHeader) {
185
+ const additions = currentHunkLines.filter((l) => l.startsWith("+"));
186
+ const subtractions = currentHunkLines.filter((l) => l.startsWith("-"));
187
+ const contextLines = currentHunkLines.filter((l) => l.startsWith(" "));
188
+ hunks.push({
189
+ header: currentHeader,
190
+ originalStartLine: originalStart,
191
+ originalLineCount: originalCount,
192
+ newStartLine: newStart,
193
+ newLineCount: newCount,
194
+ lines: currentHunkLines,
195
+ additions,
196
+ subtractions,
197
+ contextLines,
198
+ });
199
+ }
200
+
201
+ return hunks;
202
+ }
203
+
204
+ export function hunksToPatch(hunks: Hunk[]): string {
205
+ const noNewLineMessage = "\";
206
+ return hunks
207
+ .map((hunk) => {
208
+ // Check if the last line might be the no-newline indicator and handle it
209
+ let lines = [...hunk.lines];
210
+ let endsWithNoNewline = false;
211
+ if (lines[lines.length - 1]?.trim() === noNewLineMessage.trim()) {
212
+ endsWithNoNewline = true;
213
+ lines = lines.slice(0, -1); // Temporarily remove for join
214
+ }
215
+
216
+ let hunkContent = lines.join("\n");
217
+ if (endsWithNoNewline) {
218
+ hunkContent += "\n" + noNewLineMessage;
219
+ }
220
+
221
+ return [hunk.header, hunkContent].join("\n");
222
+ })
223
+ .join("\n");
224
+ }
225
+
226
+ /**
227
+ * Checks if a hunk results in no effective change.
228
+ */
229
+ export function hunkIsEmpty(hunk: Hunk): boolean {
230
+ const noLines = hunk.lines.length === 0;
231
+ const noChanges =
232
+ hunk.additions.length === 0 && hunk.subtractions.length === 0;
233
+
234
+ // Check if additions and subtractions exactly cancel each other out
235
+ const additionsText = hunk.additions.map((l) => l.slice(1)).join("\n");
236
+ const subtractionsText = hunk.subtractions.map((l) => l.slice(1)).join("\n");
237
+ const noEffectiveChange = additionsText === subtractionsText;
238
+
239
+ return noLines || noChanges || noEffectiveChange;
240
+ }
241
+
242
+ // --- Core Patch Fixing Logic (Rewrite) ---
243
+
244
+ const CONTEXT_LINES = 3; // Standard number of context lines
245
+
246
+ /**
247
+ * Attempts to fix a single hunk by anchoring it to the original content
248
+ * and regenerating context and header.
249
+ */
250
+ function fixSingleHunk(hunk: Hunk, originalContent: string): Hunk | null {
251
+ const originalLines = splitByNewLines(originalContent);
252
+
253
+ const deletionLinesContent = hunk.subtractions.map((l) => l.slice(1));
254
+ const additionLinesContent = hunk.additions.map((l) => l.slice(1));
255
+
256
+ let actualOriginalStartLine = -1; // 1-based line number of the first deletion/change
257
+
258
+ // 1. Try to anchor using the exact sequence of deleted lines
259
+ if (deletionLinesContent.length > 0) {
260
+ const deletionStartIndex = findSequenceIndex(
261
+ originalLines,
262
+ deletionLinesContent
263
+ );
264
+ if (deletionStartIndex !== -1) {
265
+ actualOriginalStartLine = deletionStartIndex + 1; // Convert 0-based index to 1-based line number
266
+ console.log(
267
+ `Anchor found via deletion sequence at line ${actualOriginalStartLine}`
268
+ );
269
+ }
270
+ }
271
+
272
+ // 2. If deletions didn't anchor, try anchoring using context *before* the first change
273
+ // (This is more complex and heuristic, let's focus on deletion anchor first for simplicity)
274
+ // ... (Could add logic here using findAllLineNumbers/findClosestNumber for context lines near hunk.originalStartLine if needed as fallback) ...
275
+
276
+ // 3. If only additions, try anchoring using context *before* the first addition.
277
+ if (
278
+ actualOriginalStartLine === -1 &&
279
+ deletionLinesContent.length === 0 &&
280
+ additionLinesContent.length > 0
281
+ ) {
282
+ // Find the context line just before the first addition in the *original* patch hunk
283
+ let precedingContextLine = "";
284
+ for (const line of hunk.lines) {
285
+ if (line.startsWith("+")) break; // Stop when we hit the first addition
286
+ if (line.startsWith(" ")) {
287
+ precedingContextLine = line.slice(1); // Keep track of the last context line seen
288
+ }
289
+ }
290
+
291
+ if (precedingContextLine) {
292
+ const potentialLines = findAllLineNumbers(
293
+ originalContent,
294
+ precedingContextLine
295
+ );
296
+ const closestLine = findClosestNumber(
297
+ potentialLines,
298
+ hunk.originalStartLine
299
+ ); // Use original header as hint
300
+ if (closestLine !== undefined) {
301
+ // The change happens *after* this context line
302
+ actualOriginalStartLine = closestLine + 1;
303
+ console.log(
304
+ `Anchor found via preceding context '${precedingContextLine}' targeting line ${actualOriginalStartLine}`
305
+ );
306
+ }
307
+ }
308
+ }
309
+
310
+ // If we couldn't find a reliable anchor, we can't fix this hunk.
311
+ if (actualOriginalStartLine === -1) {
312
+ console.warn("Could not determine anchor point for hunk:", hunk.header);
313
+ // Try a last resort: Assume the original header's start line was roughly correct
314
+ // Find *any* non-added line from the hunk in the original source near the expected start.
315
+ let fallbackAnchorFound = false;
316
+ for (let i = 0; i < hunk.lines.length; i++) {
317
+ const line = hunk.lines[i];
318
+ if (line.startsWith("+")) continue; // Skip additions
319
+
320
+ const lineContent = line.slice(1);
321
+ const potentialLines = findAllLineNumbers(originalContent, lineContent);
322
+ if (potentialLines.length > 0) {
323
+ const closestLine = findClosestNumber(
324
+ potentialLines,
325
+ hunk.originalStartLine + i
326
+ ); // Estimate position
327
+ if (closestLine !== undefined) {
328
+ // Calculate the *start* based on this line's position in the hunk
329
+ let offset = 0;
330
+ for (let j = 0; j < i; j++) {
331
+ if (!hunk.lines[j].startsWith("+")) {
332
+ // Count original lines before this one
333
+ offset++;
334
+ }
335
+ }
336
+ actualOriginalStartLine = closestLine - offset;
337
+ console.log(
338
+ `Fallback anchor found via line '${lineContent}' near ${hunk.originalStartLine}, estimated start: ${actualOriginalStartLine}`
339
+ );
340
+ fallbackAnchorFound = true;
341
+ break;
342
+ }
343
+ }
344
+ }
345
+ if (!fallbackAnchorFound) {
346
+ console.error("Failed to find any anchor for hunk:", hunk.header);
347
+ return null;
348
+ }
349
+ }
350
+
351
+ // Ensure start line is at least 1
352
+ actualOriginalStartLine = Math.max(1, actualOriginalStartLine);
353
+
354
+ // 4. Reconstruct the hunk with correct context
355
+ const contextBeforeStartLine = Math.max(
356
+ 0,
357
+ actualOriginalStartLine - CONTEXT_LINES - 1
358
+ ); // 0-based index
359
+ const contextBeforeEndLine = Math.max(0, actualOriginalStartLine - 1); // 0-based index
360
+ const contextBefore = originalLines
361
+ .slice(contextBeforeStartLine, contextBeforeEndLine)
362
+ .map((l) => ` ${l}`);
363
+
364
+ // End line of original content affected by deletions (1-based)
365
+ const originalContentEndLine =
366
+ actualOriginalStartLine + deletionLinesContent.length;
367
+ const contextAfterStartLine = originalContentEndLine - 1; // 0-based index
368
+ const contextAfterEndLine = Math.min(
369
+ originalLines.length,
370
+ contextAfterStartLine + CONTEXT_LINES
371
+ ); // 0-based index
372
+ const contextAfter = originalLines
373
+ .slice(contextAfterStartLine, contextAfterEndLine)
374
+ .map((l) => ` ${l}`);
375
+
376
+ const newHunkLines = [
377
+ ...contextBefore,
378
+ ...hunk.subtractions, // Use the original subtraction lines from the input hunk
379
+ ...hunk.additions, // Use the original addition lines from the input hunk
380
+ ...contextAfter,
381
+ ];
382
+
383
+ // 5. Recalculate the header
384
+ const newOriginalStart =
385
+ contextBefore.length > 0
386
+ ? actualOriginalStartLine - contextBefore.length
387
+ : actualOriginalStartLine;
388
+ const newOriginalCount =
389
+ contextBefore.length + hunk.subtractions.length + contextAfter.length;
390
+
391
+ // The new start line depends on how many lines were added/removed *before* this hunk.
392
+ // For an isolated hunk fix, we often just base it on the original start.
393
+ // A more robust diff tool might recalculate this based on cumulative changes.
394
+ // Let's keep it simple and relative to the original start for now.
395
+ const newNewStart = newOriginalStart; // Simplification: Assume start line number matches original unless offset by prior hunks (which we don't know here)
396
+ const newNewCount =
397
+ contextBefore.length + hunk.additions.length + contextAfter.length;
398
+
399
+ // Handle edge case where count is 0 (e.g., adding to an empty file) - header format needs >= 1
400
+ const finalOriginalStart = Math.max(1, newOriginalStart);
401
+ const finalOriginalCount = Math.max(1, newOriginalCount); // Should be at least 1 if start is specified, unless file was empty
402
+ const finalNewStart = Math.max(1, newNewStart);
403
+ const finalNewCount = Math.max(1, newNewCount); // Should be at least 1 if start is specified
404
+
405
+ // Adjust count for empty file scenario
406
+ const displayOriginalCount =
407
+ originalLines.length === 0 && newOriginalCount === 0
408
+ ? 0
409
+ : finalOriginalCount;
410
+ const displayNewCount =
411
+ originalLines.length === 0 && newNewCount === 0 ? 0 : finalNewCount; // Handle adding to empty file
412
+
413
+ const newHeader = `@@ -${finalOriginalStart},${displayOriginalCount} +${finalNewStart},${displayNewCount} @@`;
414
+
415
+ const fixedHunk: Hunk = {
416
+ header: newHeader,
417
+ originalStartLine: finalOriginalStart,
418
+ originalLineCount: displayOriginalCount,
419
+ newStartLine: finalNewStart,
420
+ newLineCount: displayNewCount,
421
+ lines: newHunkLines,
422
+ additions: hunk.additions, // Keep original intended changes
423
+ subtractions: hunk.subtractions, // Keep original intended changes
424
+ contextLines: [...contextBefore, ...contextAfter], // Store the newly generated context
425
+ };
426
+
427
+ // 6. Filter out empty hunks
428
+ if (hunkIsEmpty(fixedHunk)) {
429
+ console.log("Hunk became empty after fixing:", fixedHunk.header);
430
+ return null;
431
+ }
432
+
433
+ return fixedHunk;
434
+ }
435
+
436
+ /**
437
+ * Takes a potentially corrupted patch and attempts to fix its hunks
438
+ * by aligning them with the original content.
439
+ */
440
+ export function fixPatch(originalContent: string, patch: string): string {
441
+ const originalHunks = parseHunks(patch);
442
+ const fixedHunks: Hunk[] = [];
443
+
444
+ console.log(`Attempting to fix ${originalHunks.length} hunks...`);
445
+
446
+ for (const hunk of originalHunks) {
447
+ console.log(`\nProcessing Hunk: ${hunk.header}`);
448
+ try {
449
+ const fixed = fixSingleHunk(hunk, originalContent);
450
+ if (fixed) {
451
+ console.log(`Successfully fixed. New header: ${fixed.header}`);
452
+ fixedHunks.push(fixed);
453
+ } else {
454
+ console.warn(`Could not fix hunk, discarding: ${hunk.header}`);
455
+ }
456
+ } catch (error) {
457
+ console.error(`Error fixing hunk ${hunk.header}:`, error);
458
+ // Optionally decide whether to keep the original hunk or discard
459
+ }
460
+ }
461
+
462
+ // Check if the result ends with a newline like the original content
463
+ const needsNoNewlineSuffix =
464
+ !originalContent.endsWith("\n") && fixedHunks.length > 0;
465
+ let finalPatch = hunksToPatch(fixedHunks);
466
+
467
+ // The hunkToPatch function might handle the \ No newline ... line based on content,
468
+ // but we might need to ensure it's added if the *intended* final state doesn't have a newline.
469
+ // This is tricky. Let's rely on applyPatch to handle it correctly if the content matches.
470
+ // Re-apply the check: Does the *last* fixed hunk *imply* no newline?
471
+ if (fixedHunks.length > 0) {
472
+ const lastHunk = fixedHunks[fixedHunks.length - 1];
473
+ const lastLine = lastHunk.lines[lastHunk.lines.length - 1];
474
+ // If the original patch had the indicator, try to preserve it if relevant
475
+ if (
476
+ patch.includes("\") &&
477
+ !lastLine?.endsWith("\n") &&
478
+ !finalPatch.endsWith("\")
479
+ ) {
480
+ // This logic is imperfect. Let's assume for now hunkToPatch handles it ok.
481
+ }
482
+ }
483
+
484
+ // Add trailing newline if the original patch had one and the fixed one doesn't
485
+ if (
486
+ patch.endsWith("\n") &&
487
+ !finalPatch.endsWith("\n") &&
488
+ finalPatch.length > 0
489
+ ) {
490
+ finalPatch += "\n";
491
+ }
492
+
493
+ return finalPatch;
494
+ }
495
+
496
+ // --- Existing Application/Utility Code (Keep as is, ensure imports/exports are correct) ---
497
+
498
+ export async function savePatchError(
499
+ originalPatch: string,
500
+ fixedPatch: string | null, // Can be null if fixing failed
501
+ fileContent: string,
502
+ errorMsg: string // Add error message for context
503
+ ) {
504
+ const dirName = ".knowhow/tools/patchFile"; // Use path.join ideally
505
+ const fileName = "errors.json";
506
+ const filePath = `${dirName}/${fileName}`; // Use path.join ideally
507
+ try {
508
+ if (!(await fileExists(filePath))) {
509
+ await mkdir(dirName, { recursive: true });
510
+ await writeFile(filePath, "[]");
511
+ }
512
+ let errors = [];
513
+ try {
514
+ errors = JSON.parse(await readFile(filePath, "utf8"));
515
+ if (!Array.isArray(errors)) errors = []; // Ensure it's an array
516
+ } catch (readError) {
517
+ console.error(
518
+ "Error reading patch error log, starting fresh.",
519
+ readError
520
+ );
521
+ errors = [];
522
+ }
523
+ errors.push({
524
+ timestamp: new Date().toISOString(),
525
+ error: errorMsg,
526
+ originalPatch,
527
+ fixedPatch, // May be null or the attempted fix
528
+ fileContent,
529
+ });
530
+ // Limit log size maybe?
531
+ // errors = errors.slice(-50);
532
+ await writeFile(filePath, JSON.stringify(errors, null, 2));
533
+ } catch (logError) {
534
+ console.error("Failed to save patch error information:", logError);
535
+ }
536
+ }
537
+
538
+ // Tool to apply a patch file to a file
539
+ export async function patchFile(
540
+ filePath: string,
541
+ patch: string
542
+ ): Promise<string> {
543
+ let originalContent = "";
544
+ try {
545
+ if (!fs.existsSync(filePath)) {
546
+ // If file doesn't exist, the patch should ideally be creating it.
547
+ // The patch should start with --- /dev/null
548
+ console.log(
549
+ `File ${filePath} does not exist. Attempting to apply patch as creation.`
550
+ );
551
+ originalContent = "";
552
+ // Ensure fs operations use async/await if utils are async
553
+ // fs.writeFileSync(filePath, ""); // Don't create it yet, let applyPatch handle it from /dev/null
554
+ } else {
555
+ originalContent = await readFile(filePath, "utf8"); // Use async read
556
+ }
557
+
558
+ let updatedContent = applyPatch(originalContent, patch);
559
+ let appliedPatch = patch; // Keep track of which patch succeeded
560
+
561
+ // If the patch doesn't apply, try to fix it
562
+ if (updatedContent === false) {
563
+ // diff library often returns false on failure
564
+ console.warn("Initial patch apply failed. Attempting to fix patch...");
565
+ let fixedPatch: string | null = null; // Initialize as null
566
+ try {
567
+ fixedPatch = fixPatch(originalContent, patch);
568
+ console.log("--- Attempted Fixed Patch ---");
569
+ console.log(fixedPatch || "<Fixing resulted in empty patch>");
570
+ console.log("---------------------------");
571
+ } catch (fixError: any) {
572
+ console.error("Error during fixPatch execution:", fixError);
573
+ await savePatchError(
574
+ patch,
575
+ null,
576
+ originalContent,
577
+ `fixPatch function errored: ${fixError.message}`
578
+ );
579
+ return `An error occured while trying to fix the patch: ${fixError.message}`;
580
+ }
581
+
582
+ if (!fixedPatch || fixedPatch.trim() === "") {
583
+ // If fixing resulted in an empty patch, it means no valid changes could be salvaged.
584
+ console.error(
585
+ "Patch could not be fixed or resulted in an empty patch."
586
+ );
587
+ await savePatchError(
588
+ patch,
589
+ fixedPatch,
590
+ originalContent,
591
+ "Patch fix resulted in empty or null patch."
592
+ );
593
+ // It might be valid that the patch had no real changes, but applyPatch failed anyway?
594
+ // Let's return an error indicating failure.
595
+ return `Patch failed to apply and could not be fixed or resulted in no changes.`;
596
+ }
597
+
598
+ updatedContent = applyPatch(originalContent, fixedPatch);
599
+ appliedPatch = fixedPatch; // Use the fixed patch now
600
+
601
+ // Sometimes patches need a trailing newline
602
+ if (updatedContent === false && !fixedPatch.endsWith("\n")) {
603
+ console.log(
604
+ "Applying fixed patch failed, trying with added newline..."
605
+ );
606
+ fixedPatch += "\n";
607
+ updatedContent = applyPatch(originalContent, fixedPatch);
608
+ appliedPatch = fixedPatch;
609
+ }
610
+
611
+ if (updatedContent === false) {
612
+ console.error("Applying the *fixed* patch also failed.");
613
+ await savePatchError(
614
+ patch,
615
+ fixedPatch,
616
+ originalContent,
617
+ "Fixed patch also failed to apply."
618
+ );
619
+ // Try to provide more specific feedback from applyPatch if possible (library might not offer it)
620
+ return "Patch failed to apply even after attempting to fix it.";
621
+ } else {
622
+ console.log("Successfully applied the *fixed* patch.");
623
+ }
624
+ } else {
625
+ console.log("Successfully applied the original patch.");
626
+ }
627
+
628
+ // Write the updated content
629
+ await writeFile(filePath, updatedContent as string); // Type assertion needed as applyPatch might return boolean
630
+
631
+ // Optional: Lint the result
632
+ let lintResult = "";
633
+ try {
634
+ lintResult = await lintFile(filePath);
635
+ } catch (lintError: any) {
636
+ console.warn("Linting failed after patching:", lintError);
637
+ lintResult = `Linting after patch failed: ${lintError.message}`;
638
+ }
639
+
640
+ return `Patch applied successfully.${
641
+ filePath ? ` Use readFile on ${filePath} to verify changes.` : ""
642
+ }
643
+ ${lintResult ? "\nLinting Result:\n" + lintResult : ""}`.trim();
644
+ } catch (e: any) {
645
+ console.error(`Error in patchFile function for ${filePath}:`, e);
646
+ // Save error only if it's not a controlled failure path that already saved
647
+ if (!String(e.message).includes("Patch failed to apply")) {
648
+ // Avoid double logging known failures
649
+ await savePatchError(
650
+ patch,
651
+ null,
652
+ originalContent,
653
+ `Unexpected error in patchFile: ${e.message}`
654
+ );
655
+ }
656
+ return `An error occured while applying the patch: ${e.message}`;
657
+ }
658
+ }
659
+
660
+ export function categorizeHunks(originalContent: string, patch: string) {
661
+ const hunks = parseHunks(patch);
662
+
663
+ const validHunks = hunks.filter((hunk) =>
664
+ applyPatch(originalContent, hunksToPatch([hunk]))
665
+ );
666
+
667
+ const invalidHunks = hunks.filter(
668
+ (hunk) => !applyPatch(originalContent, hunksToPatch([hunk]))
669
+ );
670
+
671
+ return { validHunks, invalidHunks };
672
+ }