@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.
- package/.vscode/launch.json +14 -0
- package/CONFIG.md +336 -0
- package/README.md +49 -0
- package/autodoc/chat.mdx +20 -0
- package/autodoc/cli.mdx +11 -0
- package/autodoc/plugins/asana.mdx +47 -0
- package/autodoc/plugins/downloader/downloader.mdx +38 -0
- package/autodoc/plugins/downloader/plugin.mdx +37 -0
- package/autodoc/plugins/downloader/types.mdx +42 -0
- package/autodoc/plugins/embedding.mdx +41 -0
- package/autodoc/plugins/figma.mdx +45 -0
- package/autodoc/plugins/github.mdx +40 -0
- package/autodoc/plugins/jira.mdx +46 -0
- package/autodoc/plugins/language.mdx +37 -0
- package/autodoc/plugins/linear.mdx +35 -0
- package/autodoc/plugins/notion.mdx +38 -0
- package/autodoc/plugins/plugins.mdx +59 -0
- package/autodoc/plugins/types.mdx +51 -0
- package/autodoc/plugins/vim.mdx +39 -0
- package/autodoc/tools/addInternalTools.mdx +1 -0
- package/autodoc/tools/agentCall.mdx +1 -0
- package/autodoc/tools/asana/definitions.mdx +10 -0
- package/autodoc/tools/asana/index.mdx +12 -0
- package/autodoc/tools/askHuman.mdx +1 -0
- package/autodoc/tools/callPlugin.mdx +1 -0
- package/autodoc/tools/embeddingSearch.mdx +1 -0
- package/autodoc/tools/execCommand.mdx +1 -0
- package/autodoc/tools/fileSearch.mdx +1 -0
- package/autodoc/tools/finalAnswer.mdx +1 -0
- package/autodoc/tools/github/definitions.mdx +6 -0
- package/autodoc/tools/github/index.mdx +8 -0
- package/autodoc/tools/index.mdx +14 -0
- package/autodoc/tools/lintFile.mdx +7 -0
- package/autodoc/tools/list.mdx +16 -0
- package/autodoc/tools/modifyFile.mdx +7 -0
- package/autodoc/tools/patch.mdx +9 -0
- package/autodoc/tools/readBlocks.mdx +1 -0
- package/autodoc/tools/readFile.mdx +1 -0
- package/autodoc/tools/scanFile.mdx +1 -0
- package/autodoc/tools/textSearch.mdx +6 -0
- package/autodoc/tools/types/fileblock.mdx +1 -0
- package/autodoc/tools/visionTool.mdx +1 -0
- package/autodoc/tools/writeFile.mdx +1 -0
- package/jest.config.js +18 -0
- package/package.json +89 -0
- package/src/agents/base/base.ts +619 -0
- package/src/agents/base/prompt.ts +26 -0
- package/src/agents/configurable/ConfigAgent.ts +23 -0
- package/src/agents/developer/developer.ts +69 -0
- package/src/agents/index.ts +8 -0
- package/src/agents/interface.ts +11 -0
- package/src/agents/patcher/codebase.md +27 -0
- package/src/agents/patcher/patcher.ts +110 -0
- package/src/agents/researcher/researcher.ts +109 -0
- package/src/agents/tools/addInternalTools.ts +21 -0
- package/src/agents/tools/agentCall.ts +18 -0
- package/src/agents/tools/aiClient.ts +36 -0
- package/src/agents/tools/asana/definitions.ts +199 -0
- package/src/agents/tools/asana/index.ts +108 -0
- package/src/agents/tools/askHuman.ts +8 -0
- package/src/agents/tools/callPlugin.ts +4 -0
- package/src/agents/tools/embeddingSearch.ts +5 -0
- package/src/agents/tools/execCommand.ts +26 -0
- package/src/agents/tools/fileSearch.ts +33 -0
- package/src/agents/tools/finalAnswer.ts +4 -0
- package/src/agents/tools/github/definitions.ts +89 -0
- package/src/agents/tools/github/index.ts +67 -0
- package/src/agents/tools/googleSearch.ts +242 -0
- package/src/agents/tools/index.ts +24 -0
- package/src/agents/tools/language/definitions.ts +97 -0
- package/src/agents/tools/language/index.ts +19 -0
- package/src/agents/tools/lintFile.ts +17 -0
- package/src/agents/tools/list.ts +514 -0
- package/src/agents/tools/loadWebpage.ts +129 -0
- package/src/agents/tools/modifyFile.ts +53 -0
- package/src/agents/tools/patch.ts +672 -0
- package/src/agents/tools/readBlocks.ts +41 -0
- package/src/agents/tools/readFile.ts +39 -0
- package/src/agents/tools/scanFile.ts +16 -0
- package/src/agents/tools/textSearch.ts +21 -0
- package/src/agents/tools/types/fileblock.ts +5 -0
- package/src/agents/tools/visionTool.ts +5 -0
- package/src/agents/tools/writeFile.ts +46 -0
- package/src/agents/vim/vim.ts +153 -0
- package/src/ai.ts +167 -0
- package/src/chat.ts +412 -0
- package/src/cli.ts +85 -0
- package/src/clients/anthropic.ts +399 -0
- package/src/clients/gemini.ts +486 -0
- package/src/clients/http.ts +107 -0
- package/src/clients/index.ts +183 -0
- package/src/clients/knowhow.ts +33 -0
- package/src/clients/openai.ts +253 -0
- package/src/clients/types.ts +91 -0
- package/src/clients/xai.ts +132 -0
- package/src/config.ts +211 -0
- package/src/conversion.ts +140 -0
- package/src/dataset/diffs/README.md +12 -0
- package/src/dataset/diffs/debug-errors.ts +29 -0
- package/src/dataset/diffs/debug.ts +64 -0
- package/src/dataset/diffs/generate.ts +71 -0
- package/src/dataset/diffs/jsonl.ts +54 -0
- package/src/dataset/diffs/test.ts +193 -0
- package/src/embeddings.ts +411 -0
- package/src/hashes.ts +67 -0
- package/src/index.ts +376 -0
- package/src/login.ts +78 -0
- package/src/microphone.ts +136 -0
- package/src/modules/index.ts +37 -0
- package/src/modules/types.ts +48 -0
- package/src/plugins/asana.ts +134 -0
- package/src/plugins/downloader/downloader.ts +204 -0
- package/src/plugins/downloader/plugin.ts +85 -0
- package/src/plugins/downloader/types.ts +85 -0
- package/src/plugins/embedding.ts +42 -0
- package/src/plugins/figma.ts +137 -0
- package/src/plugins/github.ts +153 -0
- package/src/plugins/jira.ts +104 -0
- package/src/plugins/language.ts +100 -0
- package/src/plugins/linear.ts +219 -0
- package/src/plugins/notion.ts +170 -0
- package/src/plugins/plugins.ts +56 -0
- package/src/plugins/types.ts +5 -0
- package/src/plugins/url.ts +63 -0
- package/src/plugins/vim.ts +73 -0
- package/src/prompts/BasicCodeDocumenter.ts +1 -0
- package/src/prompts/BasicProjectDocumenter.ts +1 -0
- package/src/prompts/EmbeddingSeachHelper.ts +1 -0
- package/src/prompts/index.ts +9 -0
- package/src/server/index.ts +14 -0
- package/src/services/AgentService.ts +98 -0
- package/src/services/EmbeddingService.ts +410 -0
- package/src/services/EventService.ts +20 -0
- package/src/services/GitHub.ts +60 -0
- package/src/services/KnowhowClient.ts +113 -0
- package/src/services/Mcp.ts +270 -0
- package/src/services/McpServer.ts +119 -0
- package/src/services/McpWebsocketTransport.ts +64 -0
- package/src/services/S3.ts +126 -0
- package/src/services/Tools.ts +65 -0
- package/src/services/flags.ts +52 -0
- package/src/services/index.ts +8 -0
- package/src/types.ts +225 -0
- package/src/utils/index.ts +108 -0
- package/src/worker.ts +80 -0
- package/tests/integration/figma.test.ts +70 -0
- package/tests/integration/fileblocks/readwrite.test.ts +95 -0
- package/tests/integration/patching/input.txt +145 -0
- package/tests/integration/patching/output.txt +145 -0
- package/tests/integration/patching/patch.txt +15 -0
- package/tests/integration/patching/unseen.txt +80 -0
- package/tests/integration/patching.test.ts +136 -0
- package/tests/languagePlugin.test.ts +74 -0
- package/tests/patching/corrupted.test.ts +78 -0
- package/tests/patching/imports.patch.txt +11 -0
- package/tests/patching/imports.test.ts +43 -0
- package/tests/patching/imports.txt +11 -0
- package/tests/patching/interface.patch.txt +15 -0
- package/tests/patching/interface.txt +7 -0
- package/tests/test.spec.ts +132 -0
- package/ts_build/src/agents/base/base.d.ts +88 -0
- package/ts_build/src/agents/base/base.js +464 -0
- package/ts_build/src/agents/base/base.js.map +1 -0
- package/ts_build/src/agents/base/prompt.d.ts +1 -0
- package/ts_build/src/agents/base/prompt.js +30 -0
- package/ts_build/src/agents/base/prompt.js.map +1 -0
- package/ts_build/src/agents/configurable/ConfigAgent.d.ts +10 -0
- package/ts_build/src/agents/configurable/ConfigAgent.js +25 -0
- package/ts_build/src/agents/configurable/ConfigAgent.js.map +1 -0
- package/ts_build/src/agents/configurable/OpenAIAgent.d.ts +0 -0
- package/ts_build/src/agents/configurable/OpenAIAgent.js +1 -0
- package/ts_build/src/agents/configurable/OpenAIAgent.js.map +1 -0
- package/ts_build/src/agents/developer/developer.d.ts +9 -0
- package/ts_build/src/agents/developer/developer.js +69 -0
- package/ts_build/src/agents/developer/developer.js.map +1 -0
- package/ts_build/src/agents/index.d.ts +7 -0
- package/ts_build/src/agents/index.js +38 -0
- package/ts_build/src/agents/index.js.map +1 -0
- package/ts_build/src/agents/interface.d.ts +10 -0
- package/ts_build/src/agents/interface.js +3 -0
- package/ts_build/src/agents/interface.js.map +1 -0
- package/ts_build/src/agents/patcher/patcher.d.ts +9 -0
- package/ts_build/src/agents/patcher/patcher.js +106 -0
- package/ts_build/src/agents/patcher/patcher.js.map +1 -0
- package/ts_build/src/agents/researcher/researcher.d.ts +9 -0
- package/ts_build/src/agents/researcher/researcher.js +107 -0
- package/ts_build/src/agents/researcher/researcher.js.map +1 -0
- package/ts_build/src/agents/tools/addInternalTools.d.ts +5 -0
- package/ts_build/src/agents/tools/addInternalTools.js +18 -0
- package/ts_build/src/agents/tools/addInternalTools.js.map +1 -0
- package/ts_build/src/agents/tools/agentCall.d.ts +1 -0
- package/ts_build/src/agents/tools/agentCall.js +21 -0
- package/ts_build/src/agents/tools/agentCall.js.map +1 -0
- package/ts_build/src/agents/tools/aiClient.d.ts +6 -0
- package/ts_build/src/agents/tools/aiClient.js +25 -0
- package/ts_build/src/agents/tools/aiClient.js.map +1 -0
- package/ts_build/src/agents/tools/asana/definitions.d.ts +202 -0
- package/ts_build/src/agents/tools/asana/definitions.js +197 -0
- package/ts_build/src/agents/tools/asana/definitions.js.map +1 -0
- package/ts_build/src/agents/tools/asana/index.d.ts +8 -0
- package/ts_build/src/agents/tools/asana/index.js +98 -0
- package/ts_build/src/agents/tools/asana/index.js.map +1 -0
- package/ts_build/src/agents/tools/askHuman.d.ts +1 -0
- package/ts_build/src/agents/tools/askHuman.js +15 -0
- package/ts_build/src/agents/tools/askHuman.js.map +1 -0
- package/ts_build/src/agents/tools/callPlugin.d.ts +1 -0
- package/ts_build/src/agents/tools/callPlugin.js +9 -0
- package/ts_build/src/agents/tools/callPlugin.js.map +1 -0
- package/ts_build/src/agents/tools/client.d.ts +5 -0
- package/ts_build/src/agents/tools/client.js +21 -0
- package/ts_build/src/agents/tools/client.js.map +1 -0
- package/ts_build/src/agents/tools/embeddingSearch.d.ts +1 -0
- package/ts_build/src/agents/tools/embeddingSearch.js +9 -0
- package/ts_build/src/agents/tools/embeddingSearch.js.map +1 -0
- package/ts_build/src/agents/tools/execCommand.d.ts +1 -0
- package/ts_build/src/agents/tools/execCommand.js +25 -0
- package/ts_build/src/agents/tools/execCommand.js.map +1 -0
- package/ts_build/src/agents/tools/fileSearch.d.ts +1 -0
- package/ts_build/src/agents/tools/fileSearch.js +31 -0
- package/ts_build/src/agents/tools/fileSearch.js.map +1 -0
- package/ts_build/src/agents/tools/finalAnswer.d.ts +1 -0
- package/ts_build/src/agents/tools/finalAnswer.js +8 -0
- package/ts_build/src/agents/tools/finalAnswer.js.map +1 -0
- package/ts_build/src/agents/tools/github/definitions.d.ts +47 -0
- package/ts_build/src/agents/tools/github/definitions.js +86 -0
- package/ts_build/src/agents/tools/github/definitions.js.map +1 -0
- package/ts_build/src/agents/tools/github/index.d.ts +789 -0
- package/ts_build/src/agents/tools/github/index.js +56 -0
- package/ts_build/src/agents/tools/github/index.js.map +1 -0
- package/ts_build/src/agents/tools/googleSearch.d.ts +93 -0
- package/ts_build/src/agents/tools/googleSearch.js +117 -0
- package/ts_build/src/agents/tools/googleSearch.js.map +1 -0
- package/ts_build/src/agents/tools/googleSearchTypes.d.ts +74 -0
- package/ts_build/src/agents/tools/googleSearchTypes.js +3 -0
- package/ts_build/src/agents/tools/googleSearchTypes.js.map +1 -0
- package/ts_build/src/agents/tools/index.d.ts +24 -0
- package/ts_build/src/agents/tools/index.js +41 -0
- package/ts_build/src/agents/tools/index.js.map +1 -0
- package/ts_build/src/agents/tools/language/definitions.d.ts +89 -0
- package/ts_build/src/agents/tools/language/definitions.js +95 -0
- package/ts_build/src/agents/tools/language/definitions.js.map +1 -0
- package/ts_build/src/agents/tools/language/index.d.ts +4 -0
- package/ts_build/src/agents/tools/language/index.js +22 -0
- package/ts_build/src/agents/tools/language/index.js.map +1 -0
- package/ts_build/src/agents/tools/lintFile.d.ts +1 -0
- package/ts_build/src/agents/tools/lintFile.js +22 -0
- package/ts_build/src/agents/tools/lintFile.js.map +1 -0
- package/ts_build/src/agents/tools/list.d.ts +2 -0
- package/ts_build/src/agents/tools/list.js +505 -0
- package/ts_build/src/agents/tools/list.js.map +1 -0
- package/ts_build/src/agents/tools/loadWebpage.d.ts +8 -0
- package/ts_build/src/agents/tools/loadWebpage.js +97 -0
- package/ts_build/src/agents/tools/loadWebpage.js.map +1 -0
- package/ts_build/src/agents/tools/modifyFile.d.ts +2 -0
- package/ts_build/src/agents/tools/modifyFile.js +74 -0
- package/ts_build/src/agents/tools/modifyFile.js.map +1 -0
- package/ts_build/src/agents/tools/patch.d.ts +21 -0
- package/ts_build/src/agents/tools/patch.js +443 -0
- package/ts_build/src/agents/tools/patch.js.map +1 -0
- package/ts_build/src/agents/tools/readBlocks.d.ts +2 -0
- package/ts_build/src/agents/tools/readBlocks.js +59 -0
- package/ts_build/src/agents/tools/readBlocks.js.map +1 -0
- package/ts_build/src/agents/tools/readFile.d.ts +1 -0
- package/ts_build/src/agents/tools/readFile.js +46 -0
- package/ts_build/src/agents/tools/readFile.js.map +1 -0
- package/ts_build/src/agents/tools/scanFile.d.ts +1 -0
- package/ts_build/src/agents/tools/scanFile.js +36 -0
- package/ts_build/src/agents/tools/scanFile.js.map +1 -0
- package/ts_build/src/agents/tools/textSearch.d.ts +1 -0
- package/ts_build/src/agents/tools/textSearch.js +22 -0
- package/ts_build/src/agents/tools/textSearch.js.map +1 -0
- package/ts_build/src/agents/tools/types/fileblock.d.ts +5 -0
- package/ts_build/src/agents/tools/types/fileblock.js +3 -0
- package/ts_build/src/agents/tools/types/fileblock.js.map +1 -0
- package/ts_build/src/agents/tools/visionTool.d.ts +1 -0
- package/ts_build/src/agents/tools/visionTool.js +9 -0
- package/ts_build/src/agents/tools/visionTool.js.map +1 -0
- package/ts_build/src/agents/tools/writeFile.d.ts +2 -0
- package/ts_build/src/agents/tools/writeFile.js +61 -0
- package/ts_build/src/agents/tools/writeFile.js.map +1 -0
- package/ts_build/src/agents/vim/vim.d.ts +14 -0
- package/ts_build/src/agents/vim/vim.js +171 -0
- package/ts_build/src/agents/vim/vim.js.map +1 -0
- package/ts_build/src/ai.d.ts +10 -0
- package/ts_build/src/ai.js +102 -0
- package/ts_build/src/ai.js.map +1 -0
- package/ts_build/src/chat.d.ts +13 -0
- package/ts_build/src/chat.js +319 -0
- package/ts_build/src/chat.js.map +1 -0
- package/ts_build/src/cli.d.ts +2 -0
- package/ts_build/src/cli.js +98 -0
- package/ts_build/src/cli.js.map +1 -0
- package/ts_build/src/clients/anthropic.d.ts +31 -0
- package/ts_build/src/clients/anthropic.js +344 -0
- package/ts_build/src/clients/anthropic.js.map +1 -0
- package/ts_build/src/clients/gemini.d.ts +20 -0
- package/ts_build/src/clients/gemini.js +347 -0
- package/ts_build/src/clients/gemini.js.map +1 -0
- package/ts_build/src/clients/http.d.ts +12 -0
- package/ts_build/src/clients/http.js +91 -0
- package/ts_build/src/clients/http.js.map +1 -0
- package/ts_build/src/clients/index.d.ts +47 -0
- package/ts_build/src/clients/index.js +143 -0
- package/ts_build/src/clients/index.js.map +1 -0
- package/ts_build/src/clients/knowhow.d.ts +10 -0
- package/ts_build/src/clients/knowhow.js +24 -0
- package/ts_build/src/clients/knowhow.js.map +1 -0
- package/ts_build/src/clients/openai.d.ts +20 -0
- package/ts_build/src/clients/openai.js +221 -0
- package/ts_build/src/clients/openai.js.map +1 -0
- package/ts_build/src/clients/types.d.ts +89 -0
- package/ts_build/src/clients/types.js +3 -0
- package/ts_build/src/clients/types.js.map +1 -0
- package/ts_build/src/clients/xai.d.ts +22 -0
- package/ts_build/src/clients/xai.js +108 -0
- package/ts_build/src/clients/xai.js.map +1 -0
- package/ts_build/src/config.d.ts +9 -0
- package/ts_build/src/config.js +216 -0
- package/ts_build/src/config.js.map +1 -0
- package/ts_build/src/conversion.d.ts +7 -0
- package/ts_build/src/conversion.js +114 -0
- package/ts_build/src/conversion.js.map +1 -0
- package/ts_build/src/dataset/diffs/debug-errors.d.ts +1 -0
- package/ts_build/src/dataset/diffs/debug-errors.js +28 -0
- package/ts_build/src/dataset/diffs/debug-errors.js.map +1 -0
- package/ts_build/src/dataset/diffs/debug.d.ts +1 -0
- package/ts_build/src/dataset/diffs/debug.js +50 -0
- package/ts_build/src/dataset/diffs/debug.js.map +1 -0
- package/ts_build/src/dataset/diffs/generate.d.ts +1 -0
- package/ts_build/src/dataset/diffs/generate.js +70 -0
- package/ts_build/src/dataset/diffs/generate.js.map +1 -0
- package/ts_build/src/dataset/diffs/jsonl.d.ts +1 -0
- package/ts_build/src/dataset/diffs/jsonl.js +47 -0
- package/ts_build/src/dataset/diffs/jsonl.js.map +1 -0
- package/ts_build/src/dataset/diffs/test.d.ts +1 -0
- package/ts_build/src/dataset/diffs/test.js +114 -0
- package/ts_build/src/dataset/diffs/test.js.map +1 -0
- package/ts_build/src/embeddings.d.ts +19 -0
- package/ts_build/src/embeddings.js +322 -0
- package/ts_build/src/embeddings.js.map +1 -0
- package/ts_build/src/hashes.d.ts +6 -0
- package/ts_build/src/hashes.js +78 -0
- package/ts_build/src/hashes.js.map +1 -0
- package/ts_build/src/index.d.ts +14 -0
- package/ts_build/src/index.js +258 -0
- package/ts_build/src/index.js.map +1 -0
- package/ts_build/src/login.d.ts +2 -0
- package/ts_build/src/login.js +63 -0
- package/ts_build/src/login.js.map +1 -0
- package/ts_build/src/microphone.d.ts +9 -0
- package/ts_build/src/microphone.js +131 -0
- package/ts_build/src/microphone.js.map +1 -0
- package/ts_build/src/modules/index.d.ts +3 -0
- package/ts_build/src/modules/index.js +34 -0
- package/ts_build/src/modules/index.js.map +1 -0
- package/ts_build/src/modules/types.d.ts +37 -0
- package/ts_build/src/modules/types.js +3 -0
- package/ts_build/src/modules/types.js.map +1 -0
- package/ts_build/src/plugins/asana.d.ts +16 -0
- package/ts_build/src/plugins/asana.js +114 -0
- package/ts_build/src/plugins/asana.js.map +1 -0
- package/ts_build/src/plugins/downloader/downloader.d.ts +12 -0
- package/ts_build/src/plugins/downloader/downloader.js +174 -0
- package/ts_build/src/plugins/downloader/downloader.js.map +1 -0
- package/ts_build/src/plugins/downloader/index.d.ts +3 -0
- package/ts_build/src/plugins/downloader/index.js +41 -0
- package/ts_build/src/plugins/downloader/index.js.map +1 -0
- package/ts_build/src/plugins/downloader/plugin.d.ts +8 -0
- package/ts_build/src/plugins/downloader/plugin.js +83 -0
- package/ts_build/src/plugins/downloader/plugin.js.map +1 -0
- package/ts_build/src/plugins/downloader/types.d.ts +82 -0
- package/ts_build/src/plugins/downloader/types.js +79 -0
- package/ts_build/src/plugins/downloader/types.js.map +1 -0
- package/ts_build/src/plugins/embedding.d.ts +5 -0
- package/ts_build/src/plugins/embedding.js +28 -0
- package/ts_build/src/plugins/embedding.js.map +1 -0
- package/ts_build/src/plugins/figma.d.ts +20 -0
- package/ts_build/src/plugins/figma.js +94 -0
- package/ts_build/src/plugins/figma.js.map +1 -0
- package/ts_build/src/plugins/github.d.ts +1223 -0
- package/ts_build/src/plugins/github.js +115 -0
- package/ts_build/src/plugins/github.js.map +1 -0
- package/ts_build/src/plugins/jira.d.ts +15 -0
- package/ts_build/src/plugins/jira.js +94 -0
- package/ts_build/src/plugins/jira.js.map +1 -0
- package/ts_build/src/plugins/language.d.ts +8 -0
- package/ts_build/src/plugins/language.js +69 -0
- package/ts_build/src/plugins/language.js.map +1 -0
- package/ts_build/src/plugins/linear.d.ts +23 -0
- package/ts_build/src/plugins/linear.js +184 -0
- package/ts_build/src/plugins/linear.js.map +1 -0
- package/ts_build/src/plugins/notion.d.ts +32 -0
- package/ts_build/src/plugins/notion.js +131 -0
- package/ts_build/src/plugins/notion.js.map +1 -0
- package/ts_build/src/plugins/plugins.d.ts +11 -0
- package/ts_build/src/plugins/plugins.js +51 -0
- package/ts_build/src/plugins/plugins.js.map +1 -0
- package/ts_build/src/plugins/types.d.ts +5 -0
- package/ts_build/src/plugins/types.js +3 -0
- package/ts_build/src/plugins/types.js.map +1 -0
- package/ts_build/src/plugins/url.d.ts +8 -0
- package/ts_build/src/plugins/url.js +50 -0
- package/ts_build/src/plugins/url.js.map +1 -0
- package/ts_build/src/plugins/vim.d.ts +11 -0
- package/ts_build/src/plugins/vim.js +63 -0
- package/ts_build/src/plugins/vim.js.map +1 -0
- package/ts_build/src/prompts/BasicCodeDocumenter.d.ts +2 -0
- package/ts_build/src/prompts/BasicCodeDocumenter.js +4 -0
- package/ts_build/src/prompts/BasicCodeDocumenter.js.map +1 -0
- package/ts_build/src/prompts/BasicProjectDocumenter.d.ts +2 -0
- package/ts_build/src/prompts/BasicProjectDocumenter.js +4 -0
- package/ts_build/src/prompts/BasicProjectDocumenter.js.map +1 -0
- package/ts_build/src/prompts/EmbeddingSeachHelper.d.ts +2 -0
- package/ts_build/src/prompts/EmbeddingSeachHelper.js +4 -0
- package/ts_build/src/prompts/EmbeddingSeachHelper.js.map +1 -0
- package/ts_build/src/prompts/index.d.ts +13 -0
- package/ts_build/src/prompts/index.js +15 -0
- package/ts_build/src/prompts/index.js.map +1 -0
- package/ts_build/src/server/index.d.ts +1 -0
- package/ts_build/src/server/index.js +17 -0
- package/ts_build/src/server/index.js.map +1 -0
- package/ts_build/src/services/AgentService.d.ts +14 -0
- package/ts_build/src/services/AgentService.js +87 -0
- package/ts_build/src/services/AgentService.js.map +1 -0
- package/ts_build/src/services/EmbeddingService.d.ts +39 -0
- package/ts_build/src/services/EmbeddingService.js +307 -0
- package/ts_build/src/services/EmbeddingService.js.map +1 -0
- package/ts_build/src/services/EventService.d.ts +9 -0
- package/ts_build/src/services/EventService.js +20 -0
- package/ts_build/src/services/EventService.js.map +1 -0
- package/ts_build/src/services/GitHub.d.ts +11 -0
- package/ts_build/src/services/GitHub.js +52 -0
- package/ts_build/src/services/GitHub.js.map +1 -0
- package/ts_build/src/services/KnowhowClient.d.ts +18 -0
- package/ts_build/src/services/KnowhowClient.js +85 -0
- package/ts_build/src/services/KnowhowClient.js.map +1 -0
- package/ts_build/src/services/Mcp.d.ts +377 -0
- package/ts_build/src/services/Mcp.js +221 -0
- package/ts_build/src/services/Mcp.js.map +1 -0
- package/ts_build/src/services/McpServer.d.ts +19 -0
- package/ts_build/src/services/McpServer.js +104 -0
- package/ts_build/src/services/McpServer.js.map +1 -0
- package/ts_build/src/services/McpWebsocketTransport.d.ts +13 -0
- package/ts_build/src/services/McpWebsocketTransport.js +59 -0
- package/ts_build/src/services/McpWebsocketTransport.js.map +1 -0
- package/ts_build/src/services/S3.d.ts +9 -0
- package/ts_build/src/services/S3.js +116 -0
- package/ts_build/src/services/S3.js.map +1 -0
- package/ts_build/src/services/Tools.d.ts +19 -0
- package/ts_build/src/services/Tools.js +51 -0
- package/ts_build/src/services/Tools.js.map +1 -0
- package/ts_build/src/services/flags.d.ts +13 -0
- package/ts_build/src/services/flags.js +48 -0
- package/ts_build/src/services/flags.js.map +1 -0
- package/ts_build/src/services/index.d.ts +8 -0
- package/ts_build/src/services/index.js +38 -0
- package/ts_build/src/services/index.js.map +1 -0
- package/ts_build/src/terminal.d.ts +1 -0
- package/ts_build/src/terminal.js +35 -0
- package/ts_build/src/terminal.js.map +1 -0
- package/ts_build/src/types.d.ts +181 -0
- package/ts_build/src/types.js +94 -0
- package/ts_build/src/types.js.map +1 -0
- package/ts_build/src/utils/index.d.ts +24 -0
- package/ts_build/src/utils/index.js +116 -0
- package/ts_build/src/utils/index.js.map +1 -0
- package/ts_build/src/worker.d.ts +1 -0
- package/ts_build/src/worker.js +68 -0
- package/ts_build/src/worker.js.map +1 -0
- package/ts_build/tests/integration/figma.test.d.ts +1 -0
- package/ts_build/tests/integration/figma.test.js +47 -0
- package/ts_build/tests/integration/figma.test.js.map +1 -0
- package/ts_build/tests/integration/fileblocks/readwrite.test.d.ts +1 -0
- package/ts_build/tests/integration/fileblocks/readwrite.test.js +95 -0
- package/ts_build/tests/integration/fileblocks/readwrite.test.js.map +1 -0
- package/ts_build/tests/integration/patching.test.d.ts +1 -0
- package/ts_build/tests/integration/patching.test.js +117 -0
- package/ts_build/tests/integration/patching.test.js.map +1 -0
- package/ts_build/tests/languagePlugin.test.d.ts +1 -0
- package/ts_build/tests/languagePlugin.test.js +78 -0
- package/ts_build/tests/languagePlugin.test.js.map +1 -0
- package/ts_build/tests/patching/corrupted.test.d.ts +1 -0
- package/ts_build/tests/patching/corrupted.test.js +53 -0
- package/ts_build/tests/patching/corrupted.test.js.map +1 -0
- package/ts_build/tests/patching/imports.test.d.ts +1 -0
- package/ts_build/tests/patching/imports.test.js +61 -0
- package/ts_build/tests/patching/imports.test.js.map +1 -0
- package/ts_build/tests/test.spec.d.ts +1 -0
- package/ts_build/tests/test.spec.js +101 -0
- package/ts_build/tests/test.spec.js.map +1 -0
- package/tsconfig.json +31 -0
- 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
|
+
}
|