@tyvm/knowhow 0.0.46 → 0.0.48
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/benchmarks/results/27b0a06/2025-09-27/xai/xai-grok-code-fast-1.json +2909 -0
- package/benchmarks/results/4057aed/2025-08-14/anthropic/anthropic-claude-sonnet-4-20250514.json +1671 -0
- package/jest.config.js +2 -2
- package/package.json +8 -3
- package/src/agents/base/base.ts +30 -24
- package/src/agents/patcher/patcher.ts +26 -5
- package/src/agents/tools/agentCall.ts +4 -2
- package/src/agents/tools/aiClient.ts +3 -11
- package/src/agents/tools/ast/astAppendNode.ts +90 -0
- package/src/agents/tools/ast/astDeleteNode.ts +88 -0
- package/src/agents/tools/ast/astEditNode.ts +95 -0
- package/src/agents/tools/ast/astGetPathForLine.ts +73 -0
- package/src/agents/tools/ast/astListPaths.ts +66 -0
- package/src/agents/tools/ast/index.ts +7 -0
- package/src/agents/tools/callPlugin.ts +8 -2
- package/src/agents/tools/embeddingSearch.ts +2 -1
- package/src/agents/tools/execCommand.ts +239 -94
- package/src/agents/tools/fileSearch.ts +15 -17
- package/src/agents/tools/index.ts +1 -0
- package/src/agents/tools/language/definitions.ts +10 -2
- package/src/agents/tools/language/index.ts +3 -2
- package/src/agents/tools/lintFile.ts +4 -2
- package/src/agents/tools/list.ts +203 -62
- package/src/agents/tools/patch.ts +48 -14
- package/src/agents/tools/readBlocks.ts +34 -0
- package/src/agents/tools/readFile.ts +23 -0
- package/src/agents/tools/stringReplace.ts +33 -9
- package/src/agents/tools/writeFile.ts +55 -0
- package/src/agents/tools/ycmd/server.ts +14 -4
- package/src/chat/CliChatService.ts +6 -1
- package/src/chat/modules/AgentModule.ts +107 -64
- package/src/chat/modules/AskModule.ts +0 -1
- package/src/chat/modules/SetupModule.ts +4 -4
- package/src/chat/modules/SystemModule.ts +28 -5
- package/src/chat/types.ts +2 -0
- package/src/chat-old.ts +2 -2
- package/src/clients/anthropic.ts +22 -1
- package/src/clients/openai.ts +1 -1
- package/src/clients/types.ts +1 -1
- package/src/clients/xai.ts +15 -5
- package/src/config.ts +17 -5
- package/src/dataset/diffs/generate.ts +2 -2
- package/src/dataset/diffs/jsonl.ts +0 -1
- package/src/embeddings.ts +6 -4
- package/src/index.ts +11 -5
- package/src/plugins/GitPlugin.ts +530 -0
- package/src/plugins/LinterPlugin.ts +89 -0
- package/src/plugins/PluginBase.ts +4 -2
- package/src/plugins/asana.ts +4 -2
- package/src/plugins/downloader/plugin.ts +5 -2
- package/src/plugins/embedding.ts +24 -4
- package/src/plugins/figma.ts +7 -3
- package/src/plugins/github.ts +4 -2
- package/src/plugins/jira.ts +4 -2
- package/src/plugins/language.ts +134 -27
- package/src/plugins/linear.ts +4 -2
- package/src/plugins/notion.ts +4 -2
- package/src/plugins/plugins.ts +27 -16
- package/src/plugins/tree-sitter/editor.ts +369 -0
- package/src/plugins/tree-sitter/lang-packs/index.ts +23 -0
- package/src/plugins/tree-sitter/lang-packs/java.ts +59 -0
- package/src/plugins/tree-sitter/lang-packs/javascript.ts +57 -0
- package/src/plugins/tree-sitter/lang-packs/python.ts +45 -0
- package/src/plugins/tree-sitter/lang-packs/types.ts +79 -0
- package/src/plugins/tree-sitter/lang-packs/typescript.ts +49 -0
- package/src/plugins/tree-sitter/parser.ts +444 -0
- package/src/plugins/tree-sitter/simple-paths.ts +467 -0
- package/src/plugins/types.ts +11 -0
- package/src/plugins/url.ts +5 -3
- package/src/plugins/vim.ts +8 -5
- package/src/processors/CustomVariables.ts +19 -7
- package/src/processors/TokenCompressor.ts +13 -13
- package/src/processors/ToolResponseCache.ts +15 -6
- package/src/services/EmbeddingService.ts +18 -9
- package/src/services/EventService.ts +80 -0
- package/src/services/Mcp.ts +5 -0
- package/src/services/S3.ts +4 -3
- package/src/services/Tools.ts +125 -53
- package/src/services/index.ts +16 -11
- package/src/services/types.ts +3 -3
- package/src/types.ts +7 -2
- package/src/worker.ts +14 -1
- package/test-comprehensive.ts +31 -0
- package/tests/clients/AIClient.test.ts +490 -0
- package/tests/manual/agent-events/run-test.ts +203 -0
- package/tests/{integration → manual/file-edits}/figma.test.ts +1 -1
- package/tests/{integration → manual/file-edits}/fileblocks/readwrite.test.ts +7 -3
- package/tests/{integration → manual/file-edits}/patching.test.ts +11 -8
- package/tests/plugins/language/languagePlugin-content-triggers.test.ts +332 -0
- package/tests/plugins/language/languagePlugin-integration.test.ts +456 -0
- package/tests/plugins/language/languagePlugin.test.ts +363 -0
- package/tests/processors/Base64ImageDetector.test.ts +403 -0
- package/tests/processors/CustomVariables.test.ts +430 -0
- package/tests/processors/HarmonyToolProcessor.test.ts +490 -0
- package/tests/processors/TokenCompressor.test.ts +391 -0
- package/tests/processors/ToolResponseCache.test.ts +688 -0
- package/tests/services/Tools.test.ts +1339 -0
- package/tests/test.spec.ts +162 -117
- package/tests/tree-sitter/editor.test.ts +113 -0
- package/tests/tree-sitter/invalid.test.ts +299 -0
- package/tests/tree-sitter/paths/common-edits.test.ts +564 -0
- package/tests/tree-sitter/paths/debug-exact-position.test.ts +44 -0
- package/tests/tree-sitter/paths/debug-line-indexing.test.ts +49 -0
- package/tests/tree-sitter/paths/debug-paths.test.ts +90 -0
- package/tests/tree-sitter/paths/paths.test.ts +170 -0
- package/tests/tree-sitter/paths/simple-paths.test.ts +367 -0
- package/tests/tree-sitter/sample-after.ts +48 -0
- package/tests/tree-sitter/sample-before.ts +25 -0
- package/tests/tree-sitter/test-files/completely-broken.ts +7 -0
- package/tests/tree-sitter/test-files/duplicate-braces.ts +39 -0
- package/tests/tree-sitter/test-files/invalid-nesting.ts +39 -0
- package/tests/tree-sitter/test-files/malformed-signature.ts +39 -0
- package/tests/tree-sitter/test-files/mismatched-parens.ts +39 -0
- package/tests/tree-sitter/test-files/missing-semicolon.ts +39 -0
- package/tests/tree-sitter/test-files/partially-broken.ts +20 -0
- package/tests/tree-sitter/test-files/specific-errors.ts +14 -0
- package/tests/tree-sitter/test-files/unclosed-string.ts +39 -0
- package/tests/tree-sitter/tree-sitter.test.ts +251 -0
- package/ts_build/package.json +8 -3
- package/ts_build/src/agents/base/base.d.ts +2 -2
- package/ts_build/src/agents/base/base.js +24 -20
- package/ts_build/src/agents/base/base.js.map +1 -1
- package/ts_build/src/agents/patcher/patcher.js +26 -5
- package/ts_build/src/agents/patcher/patcher.js.map +1 -1
- package/ts_build/src/agents/tools/agentCall.js +2 -1
- package/ts_build/src/agents/tools/agentCall.js.map +1 -1
- package/ts_build/src/agents/tools/aiClient.d.ts +7 -8
- package/ts_build/src/agents/tools/aiClient.js.map +1 -1
- package/ts_build/src/agents/tools/ast/astAppendNode.d.ts +1 -0
- package/ts_build/src/agents/tools/ast/astAppendNode.js +96 -0
- package/ts_build/src/agents/tools/ast/astAppendNode.js.map +1 -0
- package/ts_build/src/agents/tools/ast/astDeleteNode.d.ts +1 -0
- package/ts_build/src/agents/tools/ast/astDeleteNode.js +94 -0
- package/ts_build/src/agents/tools/ast/astDeleteNode.js.map +1 -0
- package/ts_build/src/agents/tools/ast/astEditNode.d.ts +1 -0
- package/ts_build/src/agents/tools/ast/astEditNode.js +96 -0
- package/ts_build/src/agents/tools/ast/astEditNode.js.map +1 -0
- package/ts_build/src/agents/tools/ast/astGetPathForLine.d.ts +1 -0
- package/ts_build/src/agents/tools/ast/astGetPathForLine.js +78 -0
- package/ts_build/src/agents/tools/ast/astGetPathForLine.js.map +1 -0
- package/ts_build/src/agents/tools/ast/astListPaths.d.ts +1 -0
- package/ts_build/src/agents/tools/ast/astListPaths.js +78 -0
- package/ts_build/src/agents/tools/ast/astListPaths.js.map +1 -0
- package/ts_build/src/agents/tools/ast/index.d.ts +5 -0
- package/ts_build/src/agents/tools/ast/index.js +14 -0
- package/ts_build/src/agents/tools/ast/index.js.map +1 -0
- package/ts_build/src/agents/tools/astAppendNode.d.ts +1 -0
- package/ts_build/src/agents/tools/astAppendNode.js +98 -0
- package/ts_build/src/agents/tools/astAppendNode.js.map +1 -0
- package/ts_build/src/agents/tools/astDeleteNode.d.ts +1 -0
- package/ts_build/src/agents/tools/astDeleteNode.js +95 -0
- package/ts_build/src/agents/tools/astDeleteNode.js.map +1 -0
- package/ts_build/src/agents/tools/astEditNode.d.ts +1 -0
- package/ts_build/src/agents/tools/astEditNode.js +98 -0
- package/ts_build/src/agents/tools/astEditNode.js.map +1 -0
- package/ts_build/src/agents/tools/astGetPathForLine.d.ts +1 -0
- package/ts_build/src/agents/tools/astGetPathForLine.js +89 -0
- package/ts_build/src/agents/tools/astGetPathForLine.js.map +1 -0
- package/ts_build/src/agents/tools/astListPaths.d.ts +1 -0
- package/ts_build/src/agents/tools/astListPaths.js +82 -0
- package/ts_build/src/agents/tools/astListPaths.js.map +1 -0
- package/ts_build/src/agents/tools/callPlugin.js +4 -2
- package/ts_build/src/agents/tools/callPlugin.js.map +1 -1
- package/ts_build/src/agents/tools/embeddingSearch.js +3 -2
- package/ts_build/src/agents/tools/embeddingSearch.js.map +1 -1
- package/ts_build/src/agents/tools/execCommand.d.ts +2 -2
- package/ts_build/src/agents/tools/execCommand.js +201 -67
- package/ts_build/src/agents/tools/execCommand.js.map +1 -1
- package/ts_build/src/agents/tools/fileSearch.d.ts +1 -1
- package/ts_build/src/agents/tools/fileSearch.js +11 -15
- package/ts_build/src/agents/tools/fileSearch.js.map +1 -1
- package/ts_build/src/agents/tools/github/index.d.ts +1 -1
- package/ts_build/src/agents/tools/index.d.ts +1 -0
- package/ts_build/src/agents/tools/index.js +1 -0
- package/ts_build/src/agents/tools/index.js.map +1 -1
- package/ts_build/src/agents/tools/language/definitions.js +11 -2
- package/ts_build/src/agents/tools/language/definitions.js.map +1 -1
- package/ts_build/src/agents/tools/language/index.js +4 -3
- package/ts_build/src/agents/tools/language/index.js.map +1 -1
- package/ts_build/src/agents/tools/lintFile.js +4 -2
- package/ts_build/src/agents/tools/lintFile.js.map +1 -1
- package/ts_build/src/agents/tools/list.js +185 -49
- package/ts_build/src/agents/tools/list.js.map +1 -1
- package/ts_build/src/agents/tools/patch.js +33 -10
- package/ts_build/src/agents/tools/patch.js.map +1 -1
- package/ts_build/src/agents/tools/readBlocks.js +23 -0
- package/ts_build/src/agents/tools/readBlocks.js.map +1 -1
- package/ts_build/src/agents/tools/readFile.js +14 -0
- package/ts_build/src/agents/tools/readFile.js.map +1 -1
- package/ts_build/src/agents/tools/stringReplace.js +19 -2
- package/ts_build/src/agents/tools/stringReplace.js.map +1 -1
- package/ts_build/src/agents/tools/writeFile.js +40 -0
- package/ts_build/src/agents/tools/writeFile.js.map +1 -1
- package/ts_build/src/agents/tools/ycmd/server.js +5 -0
- package/ts_build/src/agents/tools/ycmd/server.js.map +1 -1
- package/ts_build/src/chat/CliChatService.d.ts +1 -0
- package/ts_build/src/chat/CliChatService.js +6 -2
- package/ts_build/src/chat/CliChatService.js.map +1 -1
- package/ts_build/src/chat/modules/AgentModule.d.ts +5 -1
- package/ts_build/src/chat/modules/AgentModule.js +53 -31
- package/ts_build/src/chat/modules/AgentModule.js.map +1 -1
- package/ts_build/src/chat/modules/AskModule.js.map +1 -1
- package/ts_build/src/chat/modules/SetupModule.js +4 -3
- package/ts_build/src/chat/modules/SetupModule.js.map +1 -1
- package/ts_build/src/chat/modules/SystemModule.js +19 -4
- package/ts_build/src/chat/modules/SystemModule.js.map +1 -1
- package/ts_build/src/chat/modules/index.d.ts +5 -0
- package/ts_build/src/chat/modules/index.js +14 -0
- package/ts_build/src/chat/modules/index.js.map +1 -0
- package/ts_build/src/chat/types.d.ts +2 -0
- package/ts_build/src/chat-old.js +3 -3
- package/ts_build/src/chat-old.js.map +1 -1
- package/ts_build/src/clients/anthropic.d.ts +1 -0
- package/ts_build/src/clients/anthropic.js +22 -1
- package/ts_build/src/clients/anthropic.js.map +1 -1
- package/ts_build/src/clients/openai.js +1 -1
- package/ts_build/src/clients/openai.js.map +1 -1
- package/ts_build/src/clients/types.d.ts +1 -1
- package/ts_build/src/clients/xai.d.ts +7 -0
- package/ts_build/src/clients/xai.js +13 -4
- package/ts_build/src/clients/xai.js.map +1 -1
- package/ts_build/src/config.js +14 -3
- package/ts_build/src/config.js.map +1 -1
- package/ts_build/src/dataset/diffs/generate.js +2 -2
- package/ts_build/src/dataset/diffs/generate.js.map +1 -1
- package/ts_build/src/dataset/diffs/jsonl.js.map +1 -1
- package/ts_build/src/embeddings.js +7 -9
- package/ts_build/src/embeddings.js.map +1 -1
- package/ts_build/src/index.js +10 -10
- package/ts_build/src/index.js.map +1 -1
- package/ts_build/src/plugins/GitPlugin.d.ts +39 -0
- package/ts_build/src/plugins/GitPlugin.js +439 -0
- package/ts_build/src/plugins/GitPlugin.js.map +1 -0
- package/ts_build/src/plugins/LinterPlugin.d.ts +15 -0
- package/ts_build/src/plugins/LinterPlugin.js +65 -0
- package/ts_build/src/plugins/LinterPlugin.js.map +1 -0
- package/ts_build/src/plugins/PluginBase.d.ts +4 -3
- package/ts_build/src/plugins/PluginBase.js +3 -3
- package/ts_build/src/plugins/PluginBase.js.map +1 -1
- package/ts_build/src/plugins/asana.d.ts +3 -1
- package/ts_build/src/plugins/asana.js +3 -2
- package/ts_build/src/plugins/asana.js.map +1 -1
- package/ts_build/src/plugins/downloader/plugin.d.ts +3 -1
- package/ts_build/src/plugins/downloader/plugin.js +3 -2
- package/ts_build/src/plugins/downloader/plugin.js.map +1 -1
- package/ts_build/src/plugins/embedding.d.ts +5 -1
- package/ts_build/src/plugins/embedding.js +15 -3
- package/ts_build/src/plugins/embedding.js.map +1 -1
- package/ts_build/src/plugins/figma.d.ts +3 -1
- package/ts_build/src/plugins/figma.js +28 -4
- package/ts_build/src/plugins/figma.js.map +1 -1
- package/ts_build/src/plugins/github.d.ts +3 -1
- package/ts_build/src/plugins/github.js +3 -2
- package/ts_build/src/plugins/github.js.map +1 -1
- package/ts_build/src/plugins/jira.d.ts +3 -1
- package/ts_build/src/plugins/jira.js +3 -2
- package/ts_build/src/plugins/jira.js.map +1 -1
- package/ts_build/src/plugins/language.d.ts +7 -4
- package/ts_build/src/plugins/language.js +85 -20
- package/ts_build/src/plugins/language.js.map +1 -1
- package/ts_build/src/plugins/linear.d.ts +3 -1
- package/ts_build/src/plugins/linear.js +3 -2
- package/ts_build/src/plugins/linear.js.map +1 -1
- package/ts_build/src/plugins/notion.d.ts +3 -1
- package/ts_build/src/plugins/notion.js +3 -2
- package/ts_build/src/plugins/notion.js.map +1 -1
- package/ts_build/src/plugins/plugins.d.ts +4 -3
- package/ts_build/src/plugins/plugins.js +24 -14
- package/ts_build/src/plugins/plugins.js.map +1 -1
- package/ts_build/src/plugins/tree-sitter/editor.d.ts +34 -0
- package/ts_build/src/plugins/tree-sitter/editor.js +218 -0
- package/ts_build/src/plugins/tree-sitter/editor.js.map +1 -0
- package/ts_build/src/plugins/tree-sitter/human-readable-paths-new.d.ts +29 -0
- package/ts_build/src/plugins/tree-sitter/human-readable-paths-new.js +538 -0
- package/ts_build/src/plugins/tree-sitter/human-readable-paths-new.js.map +1 -0
- package/ts_build/src/plugins/tree-sitter/human-readable-paths.d.ts +22 -0
- package/ts_build/src/plugins/tree-sitter/human-readable-paths.js +332 -0
- package/ts_build/src/plugins/tree-sitter/human-readable-paths.js.map +1 -0
- package/ts_build/src/plugins/tree-sitter/lang-packs/index.d.ts +8 -0
- package/ts_build/src/plugins/tree-sitter/lang-packs/index.js +26 -0
- package/ts_build/src/plugins/tree-sitter/lang-packs/index.js.map +1 -0
- package/ts_build/src/plugins/tree-sitter/lang-packs/java.d.ts +2 -0
- package/ts_build/src/plugins/tree-sitter/lang-packs/java.js +61 -0
- package/ts_build/src/plugins/tree-sitter/lang-packs/java.js.map +1 -0
- package/ts_build/src/plugins/tree-sitter/lang-packs/javascript.d.ts +2 -0
- package/ts_build/src/plugins/tree-sitter/lang-packs/javascript.js +59 -0
- package/ts_build/src/plugins/tree-sitter/lang-packs/javascript.js.map +1 -0
- package/ts_build/src/plugins/tree-sitter/lang-packs/python.d.ts +2 -0
- package/ts_build/src/plugins/tree-sitter/lang-packs/python.js +47 -0
- package/ts_build/src/plugins/tree-sitter/lang-packs/python.js.map +1 -0
- package/ts_build/src/plugins/tree-sitter/lang-packs/types.d.ts +43 -0
- package/ts_build/src/plugins/tree-sitter/lang-packs/types.js +3 -0
- package/ts_build/src/plugins/tree-sitter/lang-packs/types.js.map +1 -0
- package/ts_build/src/plugins/tree-sitter/lang-packs/typescript.d.ts +2 -0
- package/ts_build/src/plugins/tree-sitter/lang-packs/typescript.js +50 -0
- package/ts_build/src/plugins/tree-sitter/lang-packs/typescript.js.map +1 -0
- package/ts_build/src/plugins/tree-sitter/parser.d.ts +75 -0
- package/ts_build/src/plugins/tree-sitter/parser.js +306 -0
- package/ts_build/src/plugins/tree-sitter/parser.js.map +1 -0
- package/ts_build/src/plugins/tree-sitter/simple-paths.d.ts +22 -0
- package/ts_build/src/plugins/tree-sitter/simple-paths.js +332 -0
- package/ts_build/src/plugins/tree-sitter/simple-paths.js.map +1 -0
- package/ts_build/src/plugins/types.d.ts +10 -0
- package/ts_build/src/plugins/url.d.ts +3 -2
- package/ts_build/src/plugins/url.js +3 -2
- package/ts_build/src/plugins/url.js.map +1 -1
- package/ts_build/src/plugins/vim.d.ts +4 -2
- package/ts_build/src/plugins/vim.js +6 -8
- package/ts_build/src/plugins/vim.js.map +1 -1
- package/ts_build/src/processors/CustomVariables.js +12 -3
- package/ts_build/src/processors/CustomVariables.js.map +1 -1
- package/ts_build/src/processors/TokenCompressor.js +8 -11
- package/ts_build/src/processors/TokenCompressor.js.map +1 -1
- package/ts_build/src/processors/ToolResponseCache.d.ts +2 -2
- package/ts_build/src/processors/ToolResponseCache.js +12 -2
- package/ts_build/src/processors/ToolResponseCache.js.map +1 -1
- package/ts_build/src/services/EmbeddingService.d.ts +10 -1
- package/ts_build/src/services/EmbeddingService.js +12 -12
- package/ts_build/src/services/EmbeddingService.js.map +1 -1
- package/ts_build/src/services/EventService.d.ts +7 -0
- package/ts_build/src/services/EventService.js +49 -0
- package/ts_build/src/services/EventService.js.map +1 -1
- package/ts_build/src/services/Mcp.js +8 -0
- package/ts_build/src/services/Mcp.js.map +1 -1
- package/ts_build/src/services/S3.js +4 -3
- package/ts_build/src/services/S3.js.map +1 -1
- package/ts_build/src/services/Tools.d.ts +1 -0
- package/ts_build/src/services/Tools.js +97 -35
- package/ts_build/src/services/Tools.js.map +1 -1
- package/ts_build/src/services/index.d.ts +4 -5
- package/ts_build/src/services/index.js +14 -9
- package/ts_build/src/services/index.js.map +1 -1
- package/ts_build/src/services/types.js +3 -3
- package/ts_build/src/services/types.js.map +1 -1
- package/ts_build/src/types.d.ts +7 -1
- package/ts_build/src/types.js +4 -0
- package/ts_build/src/types.js.map +1 -1
- package/ts_build/src/worker.js +12 -1
- package/ts_build/src/worker.js.map +1 -1
- package/ts_build/tests/clients/AIClient.test.d.ts +1 -0
- package/ts_build/tests/clients/AIClient.test.js +377 -0
- package/ts_build/tests/clients/AIClient.test.js.map +1 -0
- package/ts_build/tests/languagePlugin.test.js +217 -11
- package/ts_build/tests/languagePlugin.test.js.map +1 -1
- package/ts_build/tests/manual/agent-events/event-handler-reliability.test.d.ts +1 -0
- package/ts_build/tests/manual/agent-events/event-handler-reliability.test.js +315 -0
- package/ts_build/tests/manual/agent-events/event-handler-reliability.test.js.map +1 -0
- package/ts_build/tests/manual/agent-events/run-test.d.ts +2 -0
- package/ts_build/tests/manual/agent-events/run-test.js +148 -0
- package/ts_build/tests/manual/agent-events/run-test.js.map +1 -0
- package/ts_build/tests/manual/file-edits/figma.test.d.ts +1 -0
- package/ts_build/tests/manual/file-edits/figma.test.js +47 -0
- package/ts_build/tests/manual/file-edits/figma.test.js.map +1 -0
- package/ts_build/tests/manual/file-edits/fileblocks/readwrite.test.d.ts +1 -0
- package/ts_build/tests/manual/file-edits/fileblocks/readwrite.test.js +100 -0
- package/ts_build/tests/manual/file-edits/fileblocks/readwrite.test.js.map +1 -0
- package/ts_build/tests/manual/file-edits/patching.test.d.ts +1 -0
- package/ts_build/tests/manual/file-edits/patching.test.js +119 -0
- package/ts_build/tests/manual/file-edits/patching.test.js.map +1 -0
- package/ts_build/tests/plugins/language/languagePlugin-content-triggers.test.d.ts +1 -0
- package/ts_build/tests/plugins/language/languagePlugin-content-triggers.test.js +277 -0
- package/ts_build/tests/plugins/language/languagePlugin-content-triggers.test.js.map +1 -0
- package/ts_build/tests/plugins/language/languagePlugin-integration.test.d.ts +1 -0
- package/ts_build/tests/plugins/language/languagePlugin-integration.test.js +331 -0
- package/ts_build/tests/plugins/language/languagePlugin-integration.test.js.map +1 -0
- package/ts_build/tests/plugins/language/languagePlugin.test.d.ts +1 -0
- package/ts_build/tests/plugins/language/languagePlugin.test.js +286 -0
- package/ts_build/tests/plugins/language/languagePlugin.test.js.map +1 -0
- package/ts_build/tests/processors/Base64ImageDetector.test.d.ts +1 -0
- package/ts_build/tests/processors/Base64ImageDetector.test.js +351 -0
- package/ts_build/tests/processors/Base64ImageDetector.test.js.map +1 -0
- package/ts_build/tests/processors/CustomVariables.test.d.ts +1 -0
- package/ts_build/tests/processors/CustomVariables.test.js +351 -0
- package/ts_build/tests/processors/CustomVariables.test.js.map +1 -0
- package/ts_build/tests/processors/HarmonyToolProcessor.test.d.ts +1 -0
- package/ts_build/tests/processors/HarmonyToolProcessor.test.js +382 -0
- package/ts_build/tests/processors/HarmonyToolProcessor.test.js.map +1 -0
- package/ts_build/tests/processors/TokenCompressor.test.d.ts +1 -0
- package/ts_build/tests/processors/TokenCompressor.test.js +300 -0
- package/ts_build/tests/processors/TokenCompressor.test.js.map +1 -0
- package/ts_build/tests/processors/ToolResponseCache.test.d.ts +1 -0
- package/ts_build/tests/processors/ToolResponseCache.test.js +539 -0
- package/ts_build/tests/processors/ToolResponseCache.test.js.map +1 -0
- package/ts_build/tests/services/Plugins/plugin-event-integration.test.d.ts +1 -0
- package/ts_build/tests/services/Plugins/plugin-event-integration.test.js +232 -0
- package/ts_build/tests/services/Plugins/plugin-event-integration.test.js.map +1 -0
- package/ts_build/tests/services/Tools.test.d.ts +1 -0
- package/ts_build/tests/services/Tools.test.js +1059 -0
- package/ts_build/tests/services/Tools.test.js.map +1 -0
- package/ts_build/tests/test.spec.js +110 -68
- package/ts_build/tests/test.spec.js.map +1 -1
- package/ts_build/tests/tree-sitter/editor.test.d.ts +1 -0
- package/ts_build/tests/tree-sitter/editor.test.js +85 -0
- package/ts_build/tests/tree-sitter/editor.test.js.map +1 -0
- package/ts_build/tests/tree-sitter/invalid.test.d.ts +1 -0
- package/ts_build/tests/tree-sitter/invalid.test.js +198 -0
- package/ts_build/tests/tree-sitter/invalid.test.js.map +1 -0
- package/ts_build/tests/tree-sitter/paths/common-edits.test.d.ts +1 -0
- package/ts_build/tests/tree-sitter/paths/common-edits.test.js +347 -0
- package/ts_build/tests/tree-sitter/paths/common-edits.test.js.map +1 -0
- package/ts_build/tests/tree-sitter/paths/debug-exact-position.test.d.ts +1 -0
- package/ts_build/tests/tree-sitter/paths/debug-exact-position.test.js +35 -0
- package/ts_build/tests/tree-sitter/paths/debug-exact-position.test.js.map +1 -0
- package/ts_build/tests/tree-sitter/paths/debug-line-indexing.test.d.ts +1 -0
- package/ts_build/tests/tree-sitter/paths/debug-line-indexing.test.js +38 -0
- package/ts_build/tests/tree-sitter/paths/debug-line-indexing.test.js.map +1 -0
- package/ts_build/tests/tree-sitter/paths/debug-paths.test.d.ts +1 -0
- package/ts_build/tests/tree-sitter/paths/debug-paths.test.js +74 -0
- package/ts_build/tests/tree-sitter/paths/debug-paths.test.js.map +1 -0
- package/ts_build/tests/tree-sitter/paths/human-readable-paths.test.d.ts +1 -0
- package/ts_build/tests/tree-sitter/paths/human-readable-paths.test.js +302 -0
- package/ts_build/tests/tree-sitter/paths/human-readable-paths.test.js.map +1 -0
- package/ts_build/tests/tree-sitter/paths/paths.test.d.ts +1 -0
- package/ts_build/tests/tree-sitter/paths/paths.test.js +116 -0
- package/ts_build/tests/tree-sitter/paths/paths.test.js.map +1 -0
- package/ts_build/tests/tree-sitter/paths/simple-paths.test.d.ts +1 -0
- package/ts_build/tests/tree-sitter/paths/simple-paths.test.js +302 -0
- package/ts_build/tests/tree-sitter/paths/simple-paths.test.js.map +1 -0
- package/ts_build/tests/tree-sitter/sample-after.d.ts +11 -0
- package/ts_build/tests/tree-sitter/sample-after.js +44 -0
- package/ts_build/tests/tree-sitter/sample-after.js.map +1 -0
- package/ts_build/tests/tree-sitter/sample-before.d.ts +9 -0
- package/ts_build/tests/tree-sitter/sample-before.js +28 -0
- package/ts_build/tests/tree-sitter/sample-before.js.map +1 -0
- package/ts_build/tests/tree-sitter/test-files/completely-broken.d.ts +2 -0
- package/ts_build/tests/tree-sitter/test-files/completely-broken.js +17 -0
- package/ts_build/tests/tree-sitter/test-files/completely-broken.js.map +1 -0
- package/ts_build/tests/tree-sitter/test-files/duplicate-braces.d.ts +8 -0
- package/ts_build/tests/tree-sitter/test-files/duplicate-braces.js +38 -0
- package/ts_build/tests/tree-sitter/test-files/duplicate-braces.js.map +1 -0
- package/ts_build/tests/tree-sitter/test-files/invalid-nesting.d.ts +8 -0
- package/ts_build/tests/tree-sitter/test-files/invalid-nesting.js +38 -0
- package/ts_build/tests/tree-sitter/test-files/invalid-nesting.js.map +1 -0
- package/ts_build/tests/tree-sitter/test-files/malformed-signature.d.ts +8 -0
- package/ts_build/tests/tree-sitter/test-files/malformed-signature.js +38 -0
- package/ts_build/tests/tree-sitter/test-files/malformed-signature.js.map +1 -0
- package/ts_build/tests/tree-sitter/test-files/mismatched-parens.d.ts +10 -0
- package/ts_build/tests/tree-sitter/test-files/mismatched-parens.js +38 -0
- package/ts_build/tests/tree-sitter/test-files/mismatched-parens.js.map +1 -0
- package/ts_build/tests/tree-sitter/test-files/missing-semicolon.d.ts +8 -0
- package/ts_build/tests/tree-sitter/test-files/missing-semicolon.js +38 -0
- package/ts_build/tests/tree-sitter/test-files/missing-semicolon.js.map +1 -0
- package/ts_build/tests/tree-sitter/test-files/partially-broken.d.ts +6 -0
- package/ts_build/tests/tree-sitter/test-files/partially-broken.js +20 -0
- package/ts_build/tests/tree-sitter/test-files/partially-broken.js.map +1 -0
- package/ts_build/tests/tree-sitter/test-files/specific-errors.d.ts +7 -0
- package/ts_build/tests/tree-sitter/test-files/specific-errors.js +14 -0
- package/ts_build/tests/tree-sitter/test-files/specific-errors.js.map +1 -0
- package/ts_build/tests/tree-sitter/test-files/unclosed-string.d.ts +8 -0
- package/ts_build/tests/tree-sitter/test-files/unclosed-string.js +38 -0
- package/ts_build/tests/tree-sitter/test-files/unclosed-string.js.map +1 -0
- package/ts_build/tests/tree-sitter/tree-sitter.test.d.ts +1 -0
- package/ts_build/tests/tree-sitter/tree-sitter.test.js +185 -0
- package/ts_build/tests/tree-sitter/tree-sitter.test.js.map +1 -0
- package/tsconfig.json +2 -1
- package/tests/languagePlugin.test.ts +0 -74
- /package/src/chat/modules/{index.js → index.ts} +0 -0
- /package/tests/{integration → manual/file-edits}/patching/input.txt +0 -0
- /package/tests/{integration → manual/file-edits}/patching/output.txt +0 -0
- /package/tests/{integration → manual/file-edits}/patching/patch.txt +0 -0
- /package/tests/{integration → manual/file-edits}/patching/unseen.txt +0 -0
|
@@ -0,0 +1,530 @@
|
|
|
1
|
+
import { PluginBase, PluginMeta } from "./PluginBase";
|
|
2
|
+
import { PluginContext } from "./types";
|
|
3
|
+
import { MinimalEmbedding } from "../types";
|
|
4
|
+
import { EventService } from "../services/EventService";
|
|
5
|
+
import { execSync } from "child_process";
|
|
6
|
+
import * as fs from "fs";
|
|
7
|
+
import * as path from "path";
|
|
8
|
+
|
|
9
|
+
export class GitPlugin extends PluginBase {
|
|
10
|
+
readonly meta: PluginMeta = {
|
|
11
|
+
key: "git",
|
|
12
|
+
name: "Git Plugin",
|
|
13
|
+
description: "Git tracking for agent modifications using .knowhow/.git",
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
private knowhowGitPath: string;
|
|
17
|
+
private knowhowDir: string;
|
|
18
|
+
private projectRoot: string;
|
|
19
|
+
private projectHasGit: boolean = false;
|
|
20
|
+
private eventService: EventService;
|
|
21
|
+
private currentTask: string | null = null;
|
|
22
|
+
|
|
23
|
+
constructor(context: PluginContext = {}) {
|
|
24
|
+
super(context);
|
|
25
|
+
this.projectRoot = process.cwd();
|
|
26
|
+
this.knowhowDir = path.join(this.projectRoot, ".knowhow");
|
|
27
|
+
this.knowhowGitPath = path.join(this.knowhowDir, ".git");
|
|
28
|
+
this.eventService = context.Events || new EventService();
|
|
29
|
+
this.setupEventListeners();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async call(input: string): Promise<string> {
|
|
33
|
+
// Get current project git status
|
|
34
|
+
const projectGitStatus = this.getProjectGitStatus();
|
|
35
|
+
|
|
36
|
+
return `Git Plugin:
|
|
37
|
+
|
|
38
|
+
- Current branch: ${this.getCurrentBranch()}
|
|
39
|
+
- Agent edit history is tracked separately in .knowhow/.git
|
|
40
|
+
- Use git commands with git --git-dir="${
|
|
41
|
+
this.knowhowGitPath
|
|
42
|
+
}" to view/revert your changes
|
|
43
|
+
|
|
44
|
+
PROJECT REPOSITORY STATUS:
|
|
45
|
+
${projectGitStatus}
|
|
46
|
+
|
|
47
|
+
via git status
|
|
48
|
+
|
|
49
|
+
Note: The files shown above are files that have changed in the user's git repo. It is likely these files are relevant to the user's request as they've got changes recently.
|
|
50
|
+
Your modifications are automatically tracked separately and won't affect the user's git history.`;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
private getProjectGitStatus(): string {
|
|
54
|
+
try {
|
|
55
|
+
// Get project git status
|
|
56
|
+
const status = execSync("git status --porcelain", {
|
|
57
|
+
cwd: this.projectRoot,
|
|
58
|
+
stdio: "pipe",
|
|
59
|
+
})
|
|
60
|
+
.toString()
|
|
61
|
+
.trim();
|
|
62
|
+
|
|
63
|
+
return status
|
|
64
|
+
? `Modified files:\n${status}`
|
|
65
|
+
: "- No modified files (working tree clean)";
|
|
66
|
+
} catch (error) {
|
|
67
|
+
return `- Error reading project git status: ${
|
|
68
|
+
error instanceof Error ? error.message : "Unknown error"
|
|
69
|
+
}`;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async embed(input: string): Promise<MinimalEmbedding[]> {
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
private async initializeKnowhowRepo(): Promise<void> {
|
|
78
|
+
try {
|
|
79
|
+
// Create .knowhow directory if it doesn't exist
|
|
80
|
+
if (!fs.existsSync(this.knowhowDir)) {
|
|
81
|
+
fs.mkdirSync(this.knowhowDir, { recursive: true });
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Initialize git repo in .knowhow if not already initialized
|
|
85
|
+
if (!fs.existsSync(this.knowhowGitPath)) {
|
|
86
|
+
execSync("git init", { cwd: this.knowhowDir, stdio: "pipe" });
|
|
87
|
+
|
|
88
|
+
// Create initial .gitignore file in the .knowhow directory (not tracked by the repo)
|
|
89
|
+
const gitignorePath = path.join(this.knowhowDir, ".gitignore");
|
|
90
|
+
fs.writeFileSync(
|
|
91
|
+
gitignorePath,
|
|
92
|
+
"# Knowhow agent tracking repository\n"
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
const hasChanges = await this.hasChanges();
|
|
96
|
+
if (hasChanges) {
|
|
97
|
+
this.commit("Initial commit for agent tracking, with changes");
|
|
98
|
+
} else {
|
|
99
|
+
this.gitCommand(
|
|
100
|
+
'commit --allow-empty -m "Initial commit for agent tracking, no changes"'
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
await this.setBranch("main");
|
|
106
|
+
} catch (error) {
|
|
107
|
+
console.error("Failed to initialize .knowhow git repository:", error);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private gitCommand(
|
|
112
|
+
command: string,
|
|
113
|
+
options: { stdio?: any } = { stdio: "pipe" }
|
|
114
|
+
): string {
|
|
115
|
+
try {
|
|
116
|
+
const fullCommand = `git --git-dir="${this.knowhowGitPath}" --work-tree="${this.projectRoot}" ${command}`;
|
|
117
|
+
return execSync(fullCommand, {
|
|
118
|
+
cwd: this.projectRoot,
|
|
119
|
+
...options,
|
|
120
|
+
}).toString();
|
|
121
|
+
} catch (error: any) {
|
|
122
|
+
// Re-throw with more context
|
|
123
|
+
const errorMessage = error.stderr
|
|
124
|
+
? error.stderr.toString()
|
|
125
|
+
: error.message;
|
|
126
|
+
const newError = new Error(
|
|
127
|
+
`Git command failed: ${command}\nError: ${errorMessage}`
|
|
128
|
+
);
|
|
129
|
+
newError.stack = error.stack;
|
|
130
|
+
throw newError;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
private safeGitCommand(
|
|
135
|
+
command: string,
|
|
136
|
+
options: { stdio?: any } = { stdio: "pipe" }
|
|
137
|
+
): string | null {
|
|
138
|
+
try {
|
|
139
|
+
return this.gitCommand(command, options);
|
|
140
|
+
} catch (error) {
|
|
141
|
+
console.warn(`Safe git command failed: ${command}`, error);
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
private setupEventListeners(): void {
|
|
147
|
+
// Listen for file:post-edit events to auto-commit
|
|
148
|
+
this.eventService.on("file:post-edit", async (data: any) => {
|
|
149
|
+
if (this.isEnabled()) {
|
|
150
|
+
await this.autoCommit(data);
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// Listen for agent newTask events to create new branches
|
|
155
|
+
this.eventService.on("agent:newTask", async (data: any) => {
|
|
156
|
+
if (this.isEnabled()) {
|
|
157
|
+
await this.ensureCleanState(data);
|
|
158
|
+
await this.handleNewTask(data);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
// Listen for task completion events to squash merge
|
|
163
|
+
this.eventService.on("agent:taskComplete", async (data: any) => {
|
|
164
|
+
if (this.isEnabled()) {
|
|
165
|
+
await this.handleTaskComplete(data);
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Gets the current branch name from the git repository
|
|
172
|
+
*/
|
|
173
|
+
private getCurrentBranch(): string {
|
|
174
|
+
try {
|
|
175
|
+
return this.gitCommand("branch --show-current").trim() || "main";
|
|
176
|
+
} catch {
|
|
177
|
+
return "main";
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
private getRepoHash(): string | null {
|
|
182
|
+
let actualRepoHash: string | null = null;
|
|
183
|
+
try {
|
|
184
|
+
actualRepoHash = execSync("git rev-parse --short HEAD", {
|
|
185
|
+
cwd: this.projectRoot,
|
|
186
|
+
stdio: "pipe",
|
|
187
|
+
})
|
|
188
|
+
.toString()
|
|
189
|
+
.trim();
|
|
190
|
+
} catch {
|
|
191
|
+
// No actual git repo or no commits
|
|
192
|
+
actualRepoHash = null;
|
|
193
|
+
}
|
|
194
|
+
return actualRepoHash;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Ensures the .knowhow/.git repository is in a clean state before starting new tasks.
|
|
199
|
+
* This method commits any uncommitted changes and preserves work from any current branch.
|
|
200
|
+
*/
|
|
201
|
+
private async ensureCleanState(taskData?: any): Promise<void> {
|
|
202
|
+
try {
|
|
203
|
+
// Initialize the repo if it doesn't exist
|
|
204
|
+
if (!fs.existsSync(this.knowhowGitPath)) {
|
|
205
|
+
await this.initializeKnowhowRepo();
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Get the current HEAD commit hash from the actual repo (if it exists)
|
|
210
|
+
const actualRepoHash = this.getRepoHash();
|
|
211
|
+
console.log(`GitPlugin: Current branch is ${this.getCurrentBranch()}`);
|
|
212
|
+
|
|
213
|
+
// First, handle any uncommitted changes on the current branch
|
|
214
|
+
const hasChanges = await this.hasChanges();
|
|
215
|
+
if (hasChanges) {
|
|
216
|
+
try {
|
|
217
|
+
const message = actualRepoHash
|
|
218
|
+
? `sync ${actualRepoHash}`
|
|
219
|
+
: `sync ${new Date().toISOString()}`;
|
|
220
|
+
await this.commitAll(message);
|
|
221
|
+
} catch (error) {
|
|
222
|
+
console.error("Failed to commit uncommitted changes:", error);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// If we're not on main, we need to merge the current branch into main to preserve work
|
|
227
|
+
const branchToMerge = this.getCurrentBranch();
|
|
228
|
+
if (this.getCurrentBranch() !== "main") {
|
|
229
|
+
await this.setBranch("main");
|
|
230
|
+
await this.squashMerge(branchToMerge);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
await this.setBranch("main");
|
|
234
|
+
} catch (error) {
|
|
235
|
+
console.error("Failed to ensure clean state:", error);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
async hasChanges() {
|
|
240
|
+
// Check if there are uncommitted changes in the .knowhow repo
|
|
241
|
+
let hasChanges = false;
|
|
242
|
+
try {
|
|
243
|
+
this.gitCommand("diff-index --quiet HEAD --");
|
|
244
|
+
} catch {
|
|
245
|
+
hasChanges = true;
|
|
246
|
+
}
|
|
247
|
+
return hasChanges;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
async setBranch(branchName: string): Promise<void> {
|
|
251
|
+
if (!this.isEnabled()) return;
|
|
252
|
+
|
|
253
|
+
try {
|
|
254
|
+
// Check if branch exists
|
|
255
|
+
try {
|
|
256
|
+
this.gitCommand(`rev-parse --verify ${branchName}`);
|
|
257
|
+
// Branch exists, switch to it
|
|
258
|
+
this.gitCommand(`checkout ${branchName}`);
|
|
259
|
+
} catch {
|
|
260
|
+
// Branch doesn't exist, create and switch to it
|
|
261
|
+
this.gitCommand(`checkout -b ${branchName}`);
|
|
262
|
+
}
|
|
263
|
+
} catch (error) {
|
|
264
|
+
console.error(`GitPlugin: Failed to set branch ${branchName}:`);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
async createBranch(branchName: string): Promise<void> {
|
|
269
|
+
if (!this.isEnabled()) return;
|
|
270
|
+
|
|
271
|
+
try {
|
|
272
|
+
this.gitCommand(`checkout -b ${branchName}`);
|
|
273
|
+
} catch (error) {
|
|
274
|
+
console.error(`GitPlugin: Failed to create branch ${branchName}:`);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
async commit(message: string, files?: string[]): Promise<void> {
|
|
279
|
+
if (!this.isEnabled()) return;
|
|
280
|
+
|
|
281
|
+
const hasChanges = await this.hasChanges();
|
|
282
|
+
|
|
283
|
+
if (!hasChanges) {
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// Add files (or all if none specified)
|
|
288
|
+
if (files && files.length > 0) {
|
|
289
|
+
for (const file of files) {
|
|
290
|
+
try {
|
|
291
|
+
this.gitCommand(`add "${file}"`);
|
|
292
|
+
} catch (error) {
|
|
293
|
+
console.warn(`Failed to add file ${file}:`, error);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
} else {
|
|
297
|
+
this.gitCommand("add -A");
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// Ensure we have a valid HEAD before committing
|
|
301
|
+
this.ensureValidHead();
|
|
302
|
+
|
|
303
|
+
// Commit the changes
|
|
304
|
+
this.gitCommand(`commit -m "${message}"`);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
async commitAll(message: string): Promise<void> {
|
|
308
|
+
if (!this.isEnabled()) return;
|
|
309
|
+
|
|
310
|
+
try {
|
|
311
|
+
this.gitCommand("add -A");
|
|
312
|
+
await this.commitWithEvents(message);
|
|
313
|
+
} catch (error) {
|
|
314
|
+
console.error("Failed to commit all changes:", error);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
async commitWithEvents(message: string, files?: string[]): Promise<void> {
|
|
319
|
+
try {
|
|
320
|
+
const preCommitResults = await this.eventService.emitBlocking(
|
|
321
|
+
"git:pre-commit",
|
|
322
|
+
{
|
|
323
|
+
branch: this.getCurrentBranch(),
|
|
324
|
+
message,
|
|
325
|
+
files,
|
|
326
|
+
}
|
|
327
|
+
);
|
|
328
|
+
|
|
329
|
+
let enhancedMessage = message;
|
|
330
|
+
|
|
331
|
+
// Append pre-commit event results to message
|
|
332
|
+
if (preCommitResults && preCommitResults.length > 0) {
|
|
333
|
+
const resultMessages = preCommitResults
|
|
334
|
+
.filter((result) => result && typeof result === "string")
|
|
335
|
+
.join("\n");
|
|
336
|
+
|
|
337
|
+
if (resultMessages) {
|
|
338
|
+
enhancedMessage += "\n\n" + resultMessages;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
await this.commit(enhancedMessage, files);
|
|
343
|
+
|
|
344
|
+
// Emit post-commit event
|
|
345
|
+
this.eventService.emit("git:post-commit", {
|
|
346
|
+
branch: this.getCurrentBranch(),
|
|
347
|
+
message: enhancedMessage,
|
|
348
|
+
files,
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
this.eventService.emit(
|
|
352
|
+
"agent:msg",
|
|
353
|
+
`GitPlugin::Commit: ${enhancedMessage} on branch: ${this.getCurrentBranch()}
|
|
354
|
+
You can access your change history via git --git-dir ${
|
|
355
|
+
this.knowhowGitPath
|
|
356
|
+
} log or other commands
|
|
357
|
+
This can be used to revert changes, or compare against previous states during a task.
|
|
358
|
+
`
|
|
359
|
+
);
|
|
360
|
+
} catch (error) {
|
|
361
|
+
console.error("Failed to commit with events:", error);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
private ensureValidHead(): void {
|
|
366
|
+
try {
|
|
367
|
+
// Check if HEAD exists
|
|
368
|
+
this.gitCommand("rev-parse HEAD");
|
|
369
|
+
} catch {
|
|
370
|
+
// No HEAD exists, need to create initial commit
|
|
371
|
+
try {
|
|
372
|
+
this.gitCommand('commit --allow-empty -m "Initial empty commit"');
|
|
373
|
+
} catch (error) {
|
|
374
|
+
console.warn("Could not create initial commit:", error);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
private async autoCommit(data: any): Promise<void> {
|
|
380
|
+
if (!this.isEnabled()) return;
|
|
381
|
+
|
|
382
|
+
try {
|
|
383
|
+
const { filePath, operation } = data;
|
|
384
|
+
if (!filePath) return;
|
|
385
|
+
|
|
386
|
+
// Create commit message based on operation
|
|
387
|
+
let message = `Auto-commit: ${operation || "modified"} ${filePath}`;
|
|
388
|
+
|
|
389
|
+
// Add current task context if available
|
|
390
|
+
if (this.currentTask) {
|
|
391
|
+
message = `[${this.currentTask}] ${message}`;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
await this.commitAll(message);
|
|
395
|
+
} catch (error) {
|
|
396
|
+
console.error("Auto-commit failed:", error);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
private async handleNewTask(data: {
|
|
401
|
+
taskId: string;
|
|
402
|
+
description: string;
|
|
403
|
+
}): Promise<void> {
|
|
404
|
+
if (!this.isEnabled()) return;
|
|
405
|
+
|
|
406
|
+
try {
|
|
407
|
+
const { taskId, description } = data;
|
|
408
|
+
if (!taskId) return;
|
|
409
|
+
|
|
410
|
+
// Create task-specific branch name
|
|
411
|
+
const branchName = `task/${taskId}`;
|
|
412
|
+
|
|
413
|
+
// Add to task stack
|
|
414
|
+
this.currentTask = taskId;
|
|
415
|
+
|
|
416
|
+
// Create new branch from current branch
|
|
417
|
+
await this.createBranch(branchName);
|
|
418
|
+
|
|
419
|
+
// Create initial commit for the task
|
|
420
|
+
const hasChanges = await this.hasChanges();
|
|
421
|
+
if (hasChanges) {
|
|
422
|
+
await this.commitWithEvents(
|
|
423
|
+
`[${taskId}] Start new task: ${description || taskId}`
|
|
424
|
+
);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
console.log(`Created new task branch: ${branchName}`);
|
|
428
|
+
} catch (error) {
|
|
429
|
+
console.error("Failed to handle new task:", error);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
private async handleTaskComplete(data: any): Promise<void> {
|
|
434
|
+
if (!this.isEnabled()) return;
|
|
435
|
+
|
|
436
|
+
try {
|
|
437
|
+
if (!this.currentTask) {
|
|
438
|
+
console.warn("No tasks in progress to complete");
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// Get current task
|
|
443
|
+
const completedTaskId = this.currentTask;
|
|
444
|
+
const completedBranch = this.getCurrentBranch();
|
|
445
|
+
|
|
446
|
+
// commit all changes before merge
|
|
447
|
+
await this.commitAll("Final commit before merging task");
|
|
448
|
+
|
|
449
|
+
// Switch to main branch
|
|
450
|
+
await this.setBranch("main");
|
|
451
|
+
|
|
452
|
+
const squashMessage = `[${completedTaskId}] Complete task: ${
|
|
453
|
+
data.answer ? data.answer.substring(0, 100) + "..." : completedTaskId
|
|
454
|
+
}`;
|
|
455
|
+
await this.squashMerge(completedBranch, squashMessage);
|
|
456
|
+
|
|
457
|
+
// Clear current task
|
|
458
|
+
this.currentTask = null;
|
|
459
|
+
} catch (error) {
|
|
460
|
+
console.error("Failed to handle task completion:", error);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
async getGitStatus(): Promise<string> {
|
|
465
|
+
if (!this.isEnabled()) return "Git plugin not enabled";
|
|
466
|
+
|
|
467
|
+
try {
|
|
468
|
+
return this.gitCommand("status --porcelain");
|
|
469
|
+
} catch (error) {
|
|
470
|
+
return `Error getting git status: ${error}`;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
async getGitLog(count: number = 10): Promise<string> {
|
|
475
|
+
if (!this.isEnabled()) return "Git plugin not enabled";
|
|
476
|
+
|
|
477
|
+
try {
|
|
478
|
+
return this.gitCommand(`log --oneline -${count}`);
|
|
479
|
+
} catch (error) {
|
|
480
|
+
return `Error getting git log: ${error}`;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
async getBranches(): Promise<string[]> {
|
|
485
|
+
if (!this.isEnabled()) return [];
|
|
486
|
+
|
|
487
|
+
try {
|
|
488
|
+
const output = this.gitCommand("branch");
|
|
489
|
+
return output
|
|
490
|
+
.split("\n")
|
|
491
|
+
.map((line) => line.replace(/^\*?\s*/, "").trim())
|
|
492
|
+
.filter((line) => line.length > 0);
|
|
493
|
+
} catch (error) {
|
|
494
|
+
console.error("Error getting branches:", error);
|
|
495
|
+
return [];
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
// Manual git operations for advanced users
|
|
500
|
+
async manualCommit(message: string, files?: string[]): Promise<void> {
|
|
501
|
+
await this.commitWithEvents(message, files);
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
async manualBranch(branchName: string): Promise<void> {
|
|
505
|
+
await this.createBranch(branchName);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
async squashMerge(
|
|
509
|
+
branchName: string,
|
|
510
|
+
message: string = "",
|
|
511
|
+
squash: boolean = true
|
|
512
|
+
): Promise<void> {
|
|
513
|
+
if (!this.isEnabled()) return;
|
|
514
|
+
|
|
515
|
+
try {
|
|
516
|
+
const mergeCommand = squash
|
|
517
|
+
? `merge --squash ${branchName}`
|
|
518
|
+
: `merge ${branchName}`;
|
|
519
|
+
this.gitCommand(mergeCommand);
|
|
520
|
+
|
|
521
|
+
if (squash) {
|
|
522
|
+
// Need to create commit after squash merge
|
|
523
|
+
message = message || `Squash merge ${branchName}`;
|
|
524
|
+
this.commitAll(message);
|
|
525
|
+
}
|
|
526
|
+
} catch (error) {
|
|
527
|
+
console.error(`Failed to merge ${branchName}:`, error);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { getConfig } from "../config";
|
|
2
|
+
import { execCommand } from "../agents/tools";
|
|
3
|
+
import { PluginBase, PluginMeta } from "./PluginBase";
|
|
4
|
+
|
|
5
|
+
export class LinterPlugin extends PluginBase {
|
|
6
|
+
static readonly meta: PluginMeta = {
|
|
7
|
+
key: "linter",
|
|
8
|
+
name: "Linter Plugin",
|
|
9
|
+
requires: [],
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
meta = LinterPlugin.meta;
|
|
13
|
+
|
|
14
|
+
constructor(context) {
|
|
15
|
+
super(context);
|
|
16
|
+
|
|
17
|
+
// Subscribe to file:post-edit events
|
|
18
|
+
this.context.Events.onBlocking(
|
|
19
|
+
"file:post-edit",
|
|
20
|
+
this.handleFilePostEdit.bind(this)
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
this.context.Events.onBlocking(
|
|
24
|
+
"git:pre-commit",
|
|
25
|
+
this.handleFilesPreCommit.bind(this)
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async embed() {
|
|
30
|
+
return [];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async call(userPrompt: string): Promise<string> {
|
|
34
|
+
return "";
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async handleFilesPreCommit(payload: { files: string[] }): Promise<string> {
|
|
38
|
+
const { files = [] } = payload;
|
|
39
|
+
let lintResult = "";
|
|
40
|
+
for (const filePath of files) {
|
|
41
|
+
const result = await this.lintFile(filePath);
|
|
42
|
+
if (result) {
|
|
43
|
+
lintResult += `Results for ${filePath}:\n${result}\n\n`;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return lintResult || "[Build Stable] No linting issues found";
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Handle file:post-edit events by linting the file
|
|
51
|
+
* @param payload The event payload containing filePath
|
|
52
|
+
* @returns The linting results as a string
|
|
53
|
+
*/
|
|
54
|
+
async handleFilePostEdit(payload: { filePath: string }): Promise<string> {
|
|
55
|
+
const { filePath } = payload;
|
|
56
|
+
const lintResult = await this.lintFile(filePath);
|
|
57
|
+
return lintResult || "No linting issues found";
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Lint a file and return the results
|
|
62
|
+
* @param filePath The path to the file to lint
|
|
63
|
+
* @returns The linting results as a string
|
|
64
|
+
*/
|
|
65
|
+
async lintFile(filePath: string): Promise<string> {
|
|
66
|
+
const config = await getConfig();
|
|
67
|
+
const extension = filePath.split(".").pop();
|
|
68
|
+
|
|
69
|
+
if (config.lintCommands && config.lintCommands[extension]) {
|
|
70
|
+
let lintCommand = config.lintCommands[extension];
|
|
71
|
+
if (lintCommand.includes("$1")) {
|
|
72
|
+
lintCommand = lintCommand.replace("$1", filePath);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
try {
|
|
76
|
+
const lintResult = await execCommand(`${lintCommand}`, -1);
|
|
77
|
+
if (lintResult) {
|
|
78
|
+
console.log("Lint Result:", lintResult);
|
|
79
|
+
}
|
|
80
|
+
return lintResult;
|
|
81
|
+
} catch (error) {
|
|
82
|
+
console.error("Linting failed:", error);
|
|
83
|
+
return `Linting failed: ${error}`;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return "";
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { MinimalEmbedding } from "../types";
|
|
2
|
-
import { Plugin, PluginMeta } from "./types";
|
|
2
|
+
import { Plugin, PluginContext, PluginMeta } from "./types";
|
|
3
3
|
|
|
4
4
|
export abstract class PluginBase implements Plugin {
|
|
5
5
|
/** Manual on/off toggle (default ON) */
|
|
6
6
|
private active = true;
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
abstract readonly meta: PluginMeta;
|
|
9
|
+
|
|
10
|
+
constructor(protected context: PluginContext = {}) {}
|
|
9
11
|
|
|
10
12
|
/* ------------------------------------------------------------------ */
|
|
11
13
|
/** Public helpers called by PluginService -------------------------- */
|
package/src/plugins/asana.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { PluginBase, PluginMeta } from "./PluginBase";
|
|
2
2
|
import { Embeddable, MinimalEmbedding } from "../types";
|
|
3
|
+
import { PluginContext } from "./types";
|
|
3
4
|
|
|
4
5
|
export class AsanaPlugin extends PluginBase {
|
|
5
6
|
static readonly meta: PluginMeta = {
|
|
@@ -8,10 +9,11 @@ export class AsanaPlugin extends PluginBase {
|
|
|
8
9
|
requires: ["ASANA_TOKEN"]
|
|
9
10
|
};
|
|
10
11
|
|
|
12
|
+
meta = AsanaPlugin.meta;
|
|
11
13
|
private asanaClient = require("asana").ApiClient.instance;
|
|
12
14
|
|
|
13
|
-
constructor() {
|
|
14
|
-
super(
|
|
15
|
+
constructor(context: PluginContext) {
|
|
16
|
+
super(context);
|
|
15
17
|
|
|
16
18
|
if (!this.isEnabled()) return;
|
|
17
19
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import { PluginBase, PluginMeta } from "../PluginBase";
|
|
3
3
|
import { MinimalEmbedding } from "../../types";
|
|
4
|
+
import { PluginContext } from "../types";
|
|
4
5
|
import { convertToText, processVideo } from "../../conversion";
|
|
5
6
|
import { services } from "../../services";
|
|
6
7
|
|
|
@@ -11,8 +12,10 @@ export class DownloaderPlugin extends PluginBase {
|
|
|
11
12
|
requires: [],
|
|
12
13
|
};
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
meta = DownloaderPlugin.meta;
|
|
16
|
+
|
|
17
|
+
constructor(context: PluginContext) {
|
|
18
|
+
super(context);
|
|
16
19
|
}
|
|
17
20
|
|
|
18
21
|
skipExt = ["jpg", "jpeg", "png", "gif"];
|