@mxf-dev/core 1.0.1 → 2.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/README.md +18 -0
- package/dist/adapters/FrameworkAdapter.js +1 -1
- package/dist/adapters/FrameworkAdapter.js.map +1 -1
- package/dist/config/ConfigManager.d.ts +9 -8
- package/dist/config/ConfigManager.d.ts.map +1 -1
- package/dist/config/ConfigManager.js +47 -17
- package/dist/config/ConfigManager.js.map +1 -1
- package/dist/config/memory-strata.config.d.ts +25 -0
- package/dist/config/memory-strata.config.d.ts.map +1 -0
- package/dist/config/memory-strata.config.js +107 -0
- package/dist/config/memory-strata.config.js.map +1 -0
- package/dist/constants/ToolNames.d.ts +1 -29
- package/dist/constants/ToolNames.d.ts.map +1 -1
- package/dist/constants/ToolNames.js +4 -17
- package/dist/constants/ToolNames.js.map +1 -1
- package/dist/database/DatabaseAdapterFactory.d.ts +14 -2
- package/dist/database/DatabaseAdapterFactory.d.ts.map +1 -1
- package/dist/database/DatabaseAdapterFactory.js +21 -6
- package/dist/database/DatabaseAdapterFactory.js.map +1 -1
- package/dist/database/adapters/mongodb/MongoBaseRepository.d.ts +7 -1
- package/dist/database/adapters/mongodb/MongoBaseRepository.d.ts.map +1 -1
- package/dist/database/adapters/mongodb/MongoBaseRepository.js +12 -2
- package/dist/database/adapters/mongodb/MongoBaseRepository.js.map +1 -1
- package/dist/events/ClientEventBus.d.ts +16 -77
- package/dist/events/ClientEventBus.d.ts.map +1 -1
- package/dist/events/ClientEventBus.js +38 -311
- package/dist/events/ClientEventBus.js.map +1 -1
- package/dist/events/EventBus.d.ts +1 -1
- package/dist/events/EventBus.d.ts.map +1 -1
- package/dist/events/EventBus.js +5 -4
- package/dist/events/EventBus.js.map +1 -1
- package/dist/events/EventBusBase.d.ts +139 -34
- package/dist/events/EventBusBase.d.ts.map +1 -1
- package/dist/events/EventBusBase.js +366 -88
- package/dist/events/EventBusBase.js.map +1 -1
- package/dist/events/EventNames.d.ts +10 -1
- package/dist/events/EventNames.d.ts.map +1 -1
- package/dist/events/EventNames.js +3 -0
- package/dist/events/EventNames.js.map +1 -1
- package/dist/events/PublicEvents.d.ts +6 -2
- package/dist/events/PublicEvents.d.ts.map +1 -1
- package/dist/events/PublicEvents.js +7 -4
- package/dist/events/PublicEvents.js.map +1 -1
- package/dist/events/ServerEventBus.d.ts +23 -112
- package/dist/events/ServerEventBus.d.ts.map +1 -1
- package/dist/events/ServerEventBus.js +58 -323
- package/dist/events/ServerEventBus.js.map +1 -1
- package/dist/events/event-definitions/LlmBudgetEvents.d.ts +68 -0
- package/dist/events/event-definitions/LlmBudgetEvents.d.ts.map +1 -0
- package/dist/events/event-definitions/LlmBudgetEvents.js +35 -0
- package/dist/events/event-definitions/LlmBudgetEvents.js.map +1 -0
- package/dist/interfaces/IMemoryPersistence.d.ts +41 -0
- package/dist/interfaces/IMemoryPersistence.d.ts.map +1 -0
- package/dist/interfaces/IMemoryPersistence.js +15 -0
- package/dist/interfaces/IMemoryPersistence.js.map +1 -0
- package/dist/middleware/MxpMiddleware.d.ts +8 -1
- package/dist/middleware/MxpMiddleware.d.ts.map +1 -1
- package/dist/middleware/MxpMiddleware.js +42 -20
- package/dist/middleware/MxpMiddleware.js.map +1 -1
- package/dist/models/channelKey.d.ts +1 -0
- package/dist/models/channelKey.d.ts.map +1 -1
- package/dist/models/channelKey.js +5 -0
- package/dist/models/channelKey.js.map +1 -1
- package/dist/models/memoryUtility.d.ts +39 -0
- package/dist/models/memoryUtility.d.ts.map +1 -0
- package/dist/models/memoryUtility.js +39 -0
- package/dist/models/memoryUtility.js.map +1 -0
- package/dist/models/user.d.ts.map +1 -1
- package/dist/models/user.js +23 -1
- package/dist/models/user.js.map +1 -1
- package/dist/mxp/BinaryProtocolLayer.d.ts +24 -8
- package/dist/mxp/BinaryProtocolLayer.d.ts.map +1 -1
- package/dist/mxp/BinaryProtocolLayer.js +90 -103
- package/dist/mxp/BinaryProtocolLayer.js.map +1 -1
- package/dist/mxp/ContextCompressionEngine.d.ts +57 -10
- package/dist/mxp/ContextCompressionEngine.d.ts.map +1 -1
- package/dist/mxp/ContextCompressionEngine.js +170 -128
- package/dist/mxp/ContextCompressionEngine.js.map +1 -1
- package/dist/mxp/MxpTokenOptimizer.d.ts +7 -3
- package/dist/mxp/MxpTokenOptimizer.d.ts.map +1 -1
- package/dist/mxp/MxpTokenOptimizer.js +8 -5
- package/dist/mxp/MxpTokenOptimizer.js.map +1 -1
- package/dist/prompts/MxfAgentSystemPrompt.d.ts +1 -1
- package/dist/prompts/MxfAgentSystemPrompt.d.ts.map +1 -1
- package/dist/prompts/MxfAgentSystemPrompt.js +47 -57
- package/dist/prompts/MxfAgentSystemPrompt.js.map +1 -1
- package/dist/protocols/mcp/ToolError.d.ts +123 -0
- package/dist/protocols/mcp/ToolError.d.ts.map +1 -0
- package/dist/protocols/mcp/ToolError.js +108 -0
- package/dist/protocols/mcp/ToolError.js.map +1 -0
- package/dist/protocols/mcp/defineTool.d.ts +133 -0
- package/dist/protocols/mcp/defineTool.d.ts.map +1 -0
- package/dist/protocols/mcp/defineTool.js +236 -0
- package/dist/protocols/mcp/defineTool.js.map +1 -0
- package/dist/protocols/mcp/security/HttpTargetGuard.d.ts +38 -0
- package/dist/protocols/mcp/security/HttpTargetGuard.d.ts.map +1 -0
- package/dist/protocols/mcp/security/HttpTargetGuard.js +227 -0
- package/dist/protocols/mcp/security/HttpTargetGuard.js.map +1 -0
- package/dist/protocols/mcp/security/McpSecurityGuard.d.ts +9 -1
- package/dist/protocols/mcp/security/McpSecurityGuard.d.ts.map +1 -1
- package/dist/protocols/mcp/security/McpSecurityGuard.js +10 -2
- package/dist/protocols/mcp/security/McpSecurityGuard.js.map +1 -1
- package/dist/protocols/mcp/security/McpToolPolicy.d.ts +81 -0
- package/dist/protocols/mcp/security/McpToolPolicy.d.ts.map +1 -0
- package/dist/protocols/mcp/security/McpToolPolicy.js +202 -0
- package/dist/protocols/mcp/security/McpToolPolicy.js.map +1 -0
- package/dist/protocols/mcp/services/ExternalMcpServerManager.d.ts +51 -18
- package/dist/protocols/mcp/services/ExternalMcpServerManager.d.ts.map +1 -1
- package/dist/protocols/mcp/services/ExternalMcpServerManager.js +256 -283
- package/dist/protocols/mcp/services/ExternalMcpServerManager.js.map +1 -1
- package/dist/protocols/mcp/services/ExternalServerConfigs.d.ts +39 -6
- package/dist/protocols/mcp/services/ExternalServerConfigs.d.ts.map +1 -1
- package/dist/protocols/mcp/services/ExternalServerConfigs.js +76 -18
- package/dist/protocols/mcp/services/ExternalServerConfigs.js.map +1 -1
- package/dist/protocols/mcp/tools/AnalyticsTools.js +1 -1
- package/dist/protocols/mcp/tools/AnalyticsTools.js.map +1 -1
- package/dist/protocols/mcp/tools/CodeAnalysisTools.d.ts.map +1 -1
- package/dist/protocols/mcp/tools/CodeAnalysisTools.js +15 -0
- package/dist/protocols/mcp/tools/CodeAnalysisTools.js.map +1 -1
- package/dist/protocols/mcp/tools/EffectivenessTools.js +3 -3
- package/dist/protocols/mcp/tools/EffectivenessTools.js.map +1 -1
- package/dist/protocols/mcp/tools/GitTools.d.ts +9 -369
- package/dist/protocols/mcp/tools/GitTools.d.ts.map +1 -1
- package/dist/protocols/mcp/tools/GitTools.js +222 -517
- package/dist/protocols/mcp/tools/GitTools.js.map +1 -1
- package/dist/protocols/mcp/tools/InfrastructureTools.d.ts +56 -24
- package/dist/protocols/mcp/tools/InfrastructureTools.d.ts.map +1 -1
- package/dist/protocols/mcp/tools/InfrastructureTools.js +117 -26
- package/dist/protocols/mcp/tools/InfrastructureTools.js.map +1 -1
- package/dist/protocols/mcp/tools/MemorySearchTools.d.ts +0 -3
- package/dist/protocols/mcp/tools/MemorySearchTools.d.ts.map +1 -1
- package/dist/protocols/mcp/tools/MemorySearchTools.js +58 -1
- package/dist/protocols/mcp/tools/MemorySearchTools.js.map +1 -1
- package/dist/protocols/mcp/tools/OrparTools.d.ts +8 -0
- package/dist/protocols/mcp/tools/OrparTools.d.ts.map +1 -1
- package/dist/protocols/mcp/tools/OrparTools.js +66 -0
- package/dist/protocols/mcp/tools/OrparTools.js.map +1 -1
- package/dist/protocols/mcp/tools/SafetyTools.d.ts +7 -525
- package/dist/protocols/mcp/tools/SafetyTools.d.ts.map +1 -1
- package/dist/protocols/mcp/tools/SafetyTools.js +349 -514
- package/dist/protocols/mcp/tools/SafetyTools.js.map +1 -1
- package/dist/protocols/mcp/tools/TaskPlanningTools.d.ts.map +1 -1
- package/dist/protocols/mcp/tools/TaskPlanningTools.js +56 -26
- package/dist/protocols/mcp/tools/TaskPlanningTools.js.map +1 -1
- package/dist/protocols/mcp/tools/TestTools.d.ts +15 -376
- package/dist/protocols/mcp/tools/TestTools.d.ts.map +1 -1
- package/dist/protocols/mcp/tools/TestTools.js +241 -363
- package/dist/protocols/mcp/tools/TestTools.js.map +1 -1
- package/dist/protocols/mcp/tools/TypeScriptTools.d.ts +6 -276
- package/dist/protocols/mcp/tools/TypeScriptTools.d.ts.map +1 -1
- package/dist/protocols/mcp/tools/TypeScriptTools.js +223 -337
- package/dist/protocols/mcp/tools/TypeScriptTools.js.map +1 -1
- package/dist/protocols/mcp/tools/WebTools.d.ts +15 -728
- package/dist/protocols/mcp/tools/WebTools.d.ts.map +1 -1
- package/dist/protocols/mcp/tools/WebTools.js +151 -257
- package/dist/protocols/mcp/tools/WebTools.js.map +1 -1
- package/dist/protocols/mcp/tools/shell/ShellExecuteHandler.d.ts +5 -3
- package/dist/protocols/mcp/tools/shell/ShellExecuteHandler.d.ts.map +1 -1
- package/dist/protocols/mcp/tools/shell/ShellExecuteHandler.js +31 -6
- package/dist/protocols/mcp/tools/shell/ShellExecuteHandler.js.map +1 -1
- package/dist/schemas/EventPayloadSchema.d.ts +21 -0
- package/dist/schemas/EventPayloadSchema.d.ts.map +1 -1
- package/dist/schemas/EventPayloadSchema.js +14 -0
- package/dist/schemas/EventPayloadSchema.js.map +1 -1
- package/dist/services/BackgroundTaskManager.d.ts.map +1 -1
- package/dist/services/BackgroundTaskManager.js +12 -4
- package/dist/services/BackgroundTaskManager.js.map +1 -1
- package/dist/services/BrowserManager.d.ts +1 -1
- package/dist/services/BrowserManager.d.ts.map +1 -1
- package/dist/services/BrowserManager.js +26 -3
- package/dist/services/BrowserManager.js.map +1 -1
- package/dist/services/MemoryCompressor.d.ts +11 -2
- package/dist/services/MemoryCompressor.d.ts.map +1 -1
- package/dist/services/MemoryCompressor.js +8 -26
- package/dist/services/MemoryCompressor.js.map +1 -1
- package/dist/services/MemoryService.d.ts +16 -3
- package/dist/services/MemoryService.d.ts.map +1 -1
- package/dist/services/MemoryService.js +79 -55
- package/dist/services/MemoryService.js.map +1 -1
- package/dist/services/MxfMLService.d.ts +5 -0
- package/dist/services/MxfMLService.d.ts.map +1 -1
- package/dist/services/MxfMLService.js +32 -6
- package/dist/services/MxfMLService.js.map +1 -1
- package/dist/services/PredictiveAnalyticsService.d.ts +45 -9
- package/dist/services/PredictiveAnalyticsService.d.ts.map +1 -1
- package/dist/services/PredictiveAnalyticsService.js +82 -44
- package/dist/services/PredictiveAnalyticsService.js.map +1 -1
- package/dist/services/QValueManager.d.ts +7 -0
- package/dist/services/QValueManager.d.ts.map +1 -1
- package/dist/services/QValueManager.js +9 -0
- package/dist/services/QValueManager.js.map +1 -1
- package/dist/services/RewardSignalProcessor.d.ts +38 -1
- package/dist/services/RewardSignalProcessor.d.ts.map +1 -1
- package/dist/services/RewardSignalProcessor.js +109 -7
- package/dist/services/RewardSignalProcessor.js.map +1 -1
- package/dist/services/SharedStateService.d.ts +16 -2
- package/dist/services/SharedStateService.d.ts.map +1 -1
- package/dist/services/SharedStateService.js +44 -3
- package/dist/services/SharedStateService.js.map +1 -1
- package/dist/services/TaskEffectivenessService.d.ts +34 -18
- package/dist/services/TaskEffectivenessService.d.ts.map +1 -1
- package/dist/services/TaskEffectivenessService.js +91 -155
- package/dist/services/TaskEffectivenessService.js.map +1 -1
- package/dist/services/WebSearchService.d.ts.map +1 -1
- package/dist/services/WebSearchService.js.map +1 -1
- package/dist/services/dag/TaskDagService.d.ts.map +1 -1
- package/dist/services/dag/TaskDagService.js +2 -0
- package/dist/services/dag/TaskDagService.js.map +1 -1
- package/dist/services/orpar-memory/OrparMemoryCoordinator.d.ts +7 -0
- package/dist/services/orpar-memory/OrparMemoryCoordinator.d.ts.map +1 -1
- package/dist/services/orpar-memory/OrparMemoryCoordinator.js +71 -10
- package/dist/services/orpar-memory/OrparMemoryCoordinator.js.map +1 -1
- package/dist/types/MemoryUtilityTypes.d.ts +2 -0
- package/dist/types/MemoryUtilityTypes.d.ts.map +1 -1
- package/dist/types/MemoryUtilityTypes.js.map +1 -1
- package/dist/utils/Logger.d.ts +43 -3
- package/dist/utils/Logger.d.ts.map +1 -1
- package/dist/utils/Logger.js +78 -36
- package/dist/utils/Logger.js.map +1 -1
- package/dist/utils/MxpEncryption.d.ts +19 -6
- package/dist/utils/MxpEncryption.d.ts.map +1 -1
- package/dist/utils/MxpEncryption.js +48 -16
- package/dist/utils/MxpEncryption.js.map +1 -1
- package/package.json +19 -4
- package/src/adapters/FrameworkAdapter.ts +1 -1
- package/src/config/ConfigManager.ts +52 -19
- package/src/config/memory-strata.config.ts +136 -0
- package/src/constants/ToolNames.ts +4 -18
- package/src/database/DatabaseAdapterFactory.ts +23 -6
- package/src/database/adapters/mongodb/MongoBaseRepository.ts +16 -2
- package/src/events/ClientEventBus.ts +68 -403
- package/src/events/EventBus.ts +7 -8
- package/src/events/EventBusBase.ts +479 -116
- package/src/events/EventNames.ts +6 -0
- package/src/events/PublicEvents.ts +7 -4
- package/src/events/ServerEventBus.ts +78 -473
- package/src/events/event-definitions/LlmBudgetEvents.ts +74 -0
- package/src/interfaces/IMemoryPersistence.ts +51 -0
- package/src/middleware/MxpMiddleware.ts +51 -24
- package/src/models/channelKey.ts +18 -4
- package/src/models/memoryUtility.ts +64 -0
- package/src/models/user.ts +36 -4
- package/src/mxp/BinaryProtocolLayer.ts +108 -124
- package/src/mxp/ContextCompressionEngine.ts +219 -161
- package/src/mxp/MxpTokenOptimizer.ts +10 -10
- package/src/prompts/MxfAgentSystemPrompt.ts +45 -55
- package/src/protocols/mcp/ToolError.ts +201 -0
- package/src/protocols/mcp/defineTool.ts +379 -0
- package/src/protocols/mcp/security/HttpTargetGuard.ts +267 -0
- package/src/protocols/mcp/security/McpSecurityGuard.ts +10 -3
- package/src/protocols/mcp/security/McpToolPolicy.ts +221 -0
- package/src/protocols/mcp/services/ExternalMcpServerManager.ts +340 -322
- package/src/protocols/mcp/services/ExternalServerConfigs.ts +82 -19
- package/src/protocols/mcp/tools/AnalyticsTools.ts +1 -1
- package/src/protocols/mcp/tools/CodeAnalysisTools.ts +15 -0
- package/src/protocols/mcp/tools/EffectivenessTools.ts +3 -3
- package/src/protocols/mcp/tools/GitTools.ts +290 -569
- package/src/protocols/mcp/tools/InfrastructureTools.ts +189 -43
- package/src/protocols/mcp/tools/MemorySearchTools.ts +77 -1
- package/src/protocols/mcp/tools/OrparTools.ts +87 -0
- package/src/protocols/mcp/tools/SafetyTools.ts +501 -579
- package/src/protocols/mcp/tools/TaskPlanningTools.ts +81 -39
- package/src/protocols/mcp/tools/TestTools.ts +339 -419
- package/src/protocols/mcp/tools/TypeScriptTools.ts +316 -376
- package/src/protocols/mcp/tools/WebTools.ts +209 -307
- package/src/protocols/mcp/tools/shell/ShellExecuteHandler.ts +53 -14
- package/src/schemas/EventPayloadSchema.ts +37 -0
- package/src/services/BackgroundTaskManager.ts +12 -4
- package/src/services/BrowserManager.ts +41 -1
- package/src/services/MemoryCompressor.ts +20 -32
- package/src/services/MemoryService.ts +96 -58
- package/src/services/MxfMLService.ts +41 -7
- package/src/services/PredictiveAnalyticsService.ts +101 -51
- package/src/services/QValueManager.ts +10 -0
- package/src/services/RewardSignalProcessor.ts +138 -9
- package/src/services/SharedStateService.ts +56 -8
- package/src/services/TaskEffectivenessService.ts +114 -187
- package/src/services/WebSearchService.ts +2 -1
- package/src/services/dag/TaskDagService.ts +2 -0
- package/src/services/orpar-memory/OrparMemoryCoordinator.ts +86 -10
- package/src/types/MemoryUtilityTypes.ts +2 -0
- package/src/utils/Logger.ts +116 -40
- package/src/utils/MxpEncryption.ts +69 -34
- package/dist/mxp/MxpEventForwardingEnhancer.d.ts +0 -134
- package/dist/mxp/MxpEventForwardingEnhancer.d.ts.map +0 -1
- package/dist/mxp/MxpEventForwardingEnhancer.js +0 -361
- package/dist/mxp/MxpEventForwardingEnhancer.js.map +0 -1
- package/dist/protocols/mcp/services/ToolSchemaEnhancements.d.ts +0 -56
- package/dist/protocols/mcp/services/ToolSchemaEnhancements.d.ts.map +0 -1
- package/dist/protocols/mcp/services/ToolSchemaEnhancements.js +0 -57
- package/dist/protocols/mcp/services/ToolSchemaEnhancements.js.map +0 -1
- package/dist/protocols/mcp/tools/ControlLoopLifecycle.d.ts +0 -270
- package/dist/protocols/mcp/tools/ControlLoopLifecycle.d.ts.map +0 -1
- package/dist/protocols/mcp/tools/ControlLoopLifecycle.js +0 -256
- package/dist/protocols/mcp/tools/ControlLoopLifecycle.js.map +0 -1
- package/dist/protocols/mcp/tools/LspTools.d.ts +0 -495
- package/dist/protocols/mcp/tools/LspTools.d.ts.map +0 -1
- package/dist/protocols/mcp/tools/LspTools.js +0 -469
- package/dist/protocols/mcp/tools/LspTools.js.map +0 -1
- package/src/mxp/MxpEventForwardingEnhancer.ts +0 -471
- package/src/protocols/mcp/services/ToolSchemaEnhancements.ts +0 -92
- package/src/protocols/mcp/tools/ControlLoopLifecycle.ts +0 -302
- package/src/protocols/mcp/tools/LspTools.ts +0 -476
|
@@ -18,432 +18,289 @@
|
|
|
18
18
|
* @documentation https://mxf-dev.github.io/mxf/
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
/**
|
|
22
|
+
* GitTools.ts
|
|
23
|
+
*
|
|
24
|
+
* Git operations, run by shelling out to the `git` binary through
|
|
25
|
+
* executeShellCommand — which validates the command against the security guard
|
|
26
|
+
* and hands the child a stripped environment.
|
|
27
|
+
*
|
|
28
|
+
* Each tool is declared with defineTool: a git command that fails throws a
|
|
29
|
+
* ToolError and comes back as one envelope with `isError: true`, rather than a
|
|
30
|
+
* `{ success: false, error: '...' }` object that reads like a successful result.
|
|
31
|
+
*/
|
|
24
32
|
|
|
25
|
-
|
|
33
|
+
import { TOOL_CATEGORIES } from '../../../constants/ToolNames.js';
|
|
34
|
+
import { defineTool, ToolRunContext } from '../defineTool.js';
|
|
35
|
+
import { ToolError } from '../ToolError.js';
|
|
36
|
+
import { executeShellCommand, ShellCommandResult } from './InfrastructureTools.js';
|
|
37
|
+
|
|
38
|
+
/** Working-directory property shared by every git tool's schema. */
|
|
39
|
+
const workingDirectoryProperty = {
|
|
40
|
+
type: 'string',
|
|
41
|
+
description: 'Working directory path (defaults to the server working directory)'
|
|
42
|
+
};
|
|
26
43
|
|
|
27
44
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* Full implementation would integrate with shell_execute tool
|
|
45
|
+
* Run a git subcommand, throwing a ToolError when git reports failure.
|
|
46
|
+
*
|
|
47
|
+
* Non-zero exit is genuine failure for every subcommand used here — none of them
|
|
48
|
+
* use exit codes to signal a non-error condition the way `git diff --quiet` does.
|
|
33
49
|
*/
|
|
50
|
+
async function runGit(
|
|
51
|
+
args: string[],
|
|
52
|
+
workingDirectory: string | undefined,
|
|
53
|
+
context: ToolRunContext
|
|
54
|
+
): Promise<ShellCommandResult> {
|
|
55
|
+
const result = await executeShellCommand('git', args, {
|
|
56
|
+
context: {
|
|
57
|
+
agentId: context.agentId,
|
|
58
|
+
channelId: context.channelId,
|
|
59
|
+
requestId: context.requestId
|
|
60
|
+
},
|
|
61
|
+
workingDirectory: workingDirectory || process.cwd(),
|
|
62
|
+
captureOutput: true
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
if (result.exitCode !== 0) {
|
|
66
|
+
throw ToolError.executionFailed(
|
|
67
|
+
`git ${args.join(' ')} failed (exit ${result.exitCode}): ` +
|
|
68
|
+
`${result.stderr?.trim() || 'no error output'}`,
|
|
69
|
+
{ details: { exitCode: result.exitCode, args } }
|
|
70
|
+
);
|
|
71
|
+
}
|
|
34
72
|
|
|
35
|
-
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export const gitStatusTool = defineTool<
|
|
77
|
+
{ workingDirectory?: string },
|
|
78
|
+
{
|
|
79
|
+
status: string;
|
|
80
|
+
branch: string;
|
|
81
|
+
files: { staged: string[]; modified: string[]; untracked: string[]; deleted: string[] };
|
|
82
|
+
}
|
|
83
|
+
>({
|
|
36
84
|
name: 'git_status',
|
|
37
|
-
|
|
85
|
+
category: TOOL_CATEGORIES.VERSION_CONTROL,
|
|
86
|
+
description: 'Report the current branch plus staged, modified, untracked and deleted files.',
|
|
38
87
|
inputSchema: {
|
|
39
88
|
type: 'object',
|
|
40
89
|
properties: {
|
|
41
|
-
workingDirectory:
|
|
42
|
-
type: 'string',
|
|
43
|
-
description: 'Working directory path (defaults to current directory)'
|
|
44
|
-
}
|
|
90
|
+
workingDirectory: workingDirectoryProperty
|
|
45
91
|
}
|
|
46
92
|
},
|
|
47
|
-
|
|
48
|
-
workingDirectory
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
return { content };
|
|
93
|
+
run: async (input, context) => {
|
|
94
|
+
const result = await runGit(['status', '--porcelain', '--branch'], input.workingDirectory, context);
|
|
95
|
+
|
|
96
|
+
const lines = result.stdout?.split('\n').filter(line => line.trim()) ?? [];
|
|
97
|
+
const files = {
|
|
98
|
+
staged: [] as string[],
|
|
99
|
+
modified: [] as string[],
|
|
100
|
+
untracked: [] as string[],
|
|
101
|
+
deleted: [] as string[]
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
let branch = 'unknown';
|
|
105
|
+
|
|
106
|
+
for (const line of lines) {
|
|
107
|
+
if (line.startsWith('## ')) {
|
|
108
|
+
const branchMatch = line.match(/^## (.+?)(?:\.\.\.|\s|$)/);
|
|
109
|
+
if (branchMatch) {
|
|
110
|
+
branch = branchMatch[1];
|
|
111
|
+
}
|
|
112
|
+
continue;
|
|
70
113
|
}
|
|
71
114
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
const files = {
|
|
75
|
-
staged: [] as string[],
|
|
76
|
-
modified: [] as string[],
|
|
77
|
-
untracked: [] as string[],
|
|
78
|
-
deleted: [] as string[]
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
let branch = 'unknown';
|
|
82
|
-
|
|
83
|
-
for (const line of lines) {
|
|
84
|
-
if (line.startsWith('## ')) {
|
|
85
|
-
// Branch information
|
|
86
|
-
const branchMatch = line.match(/^## (.+?)(?:\.\.\.|\s|$)/);
|
|
87
|
-
if (branchMatch) {
|
|
88
|
-
branch = branchMatch[1];
|
|
89
|
-
}
|
|
90
|
-
} else if (line.length >= 2) {
|
|
91
|
-
// File status
|
|
92
|
-
const statusCode = line.substring(0, 2);
|
|
93
|
-
const fileName = line.substring(3);
|
|
94
|
-
|
|
95
|
-
// Index status (first character)
|
|
96
|
-
if (statusCode[0] === 'A' || statusCode[0] === 'M' || statusCode[0] === 'D') {
|
|
97
|
-
files.staged.push(fileName);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Working tree status (second character)
|
|
101
|
-
if (statusCode[1] === 'M') {
|
|
102
|
-
files.modified.push(fileName);
|
|
103
|
-
} else if (statusCode[1] === 'D') {
|
|
104
|
-
files.deleted.push(fileName);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// Untracked files
|
|
108
|
-
if (statusCode === '??') {
|
|
109
|
-
files.untracked.push(fileName);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
115
|
+
if (line.length < 2) {
|
|
116
|
+
continue;
|
|
112
117
|
}
|
|
113
118
|
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
status: '',
|
|
132
|
-
files: { staged: [], modified: [], untracked: [], deleted: [] },
|
|
133
|
-
branch: 'unknown',
|
|
134
|
-
error: error instanceof Error ? error.message : String(error)
|
|
135
|
-
}
|
|
136
|
-
};
|
|
137
|
-
return { content };
|
|
119
|
+
const statusCode = line.substring(0, 2);
|
|
120
|
+
const fileName = line.substring(3);
|
|
121
|
+
|
|
122
|
+
// Porcelain format: first char is the index state, second is the
|
|
123
|
+
// working-tree state. '??' in both positions means untracked.
|
|
124
|
+
if (statusCode === '??') {
|
|
125
|
+
files.untracked.push(fileName);
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
if (statusCode[0] === 'A' || statusCode[0] === 'M' || statusCode[0] === 'D') {
|
|
129
|
+
files.staged.push(fileName);
|
|
130
|
+
}
|
|
131
|
+
if (statusCode[1] === 'M') {
|
|
132
|
+
files.modified.push(fileName);
|
|
133
|
+
} else if (statusCode[1] === 'D') {
|
|
134
|
+
files.deleted.push(fileName);
|
|
135
|
+
}
|
|
138
136
|
}
|
|
137
|
+
|
|
138
|
+
return {
|
|
139
|
+
status: result.stdout ?? '',
|
|
140
|
+
branch,
|
|
141
|
+
files
|
|
142
|
+
};
|
|
139
143
|
}
|
|
140
|
-
};
|
|
144
|
+
});
|
|
141
145
|
|
|
142
|
-
export const gitAddTool =
|
|
146
|
+
export const gitAddTool = defineTool<
|
|
147
|
+
{ files: string[]; workingDirectory?: string },
|
|
148
|
+
{ stagedCount: number; files: string[] }
|
|
149
|
+
>({
|
|
143
150
|
name: 'git_add',
|
|
144
|
-
|
|
151
|
+
category: TOOL_CATEGORIES.VERSION_CONTROL,
|
|
152
|
+
description: 'Stage files for commit. Pass "." to stage everything.',
|
|
145
153
|
inputSchema: {
|
|
146
154
|
type: 'object',
|
|
147
155
|
properties: {
|
|
148
156
|
files: {
|
|
149
157
|
type: 'array',
|
|
150
158
|
items: { type: 'string' },
|
|
159
|
+
minItems: 1,
|
|
151
160
|
description: 'Files to stage (use "." for all files)'
|
|
152
161
|
},
|
|
153
|
-
workingDirectory:
|
|
154
|
-
type: 'string',
|
|
155
|
-
description: 'Working directory path (defaults to current directory)'
|
|
156
|
-
}
|
|
162
|
+
workingDirectory: workingDirectoryProperty
|
|
157
163
|
},
|
|
158
164
|
required: ['files']
|
|
159
165
|
},
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
workingDirectory?: string;
|
|
163
|
-
}, context: McpToolHandlerContext): Promise<McpToolHandlerResult> => {
|
|
164
|
-
|
|
165
|
-
try {
|
|
166
|
-
const result = await executeShellCommand('git', ['add', ...args.files], {
|
|
167
|
-
workingDirectory: args.workingDirectory || process.cwd(),
|
|
168
|
-
captureOutput: true
|
|
169
|
-
});
|
|
166
|
+
run: async (input, context) => {
|
|
167
|
+
await runGit(['add', ...input.files], input.workingDirectory, context);
|
|
170
168
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
success: false,
|
|
176
|
-
message: result.stderr || 'Git add failed',
|
|
177
|
-
error: result.stderr || 'Git add command failed'
|
|
178
|
-
}
|
|
179
|
-
};
|
|
180
|
-
return { content };
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
const content: McpToolResultContent = {
|
|
184
|
-
type: 'application/json',
|
|
185
|
-
data: {
|
|
186
|
-
success: true,
|
|
187
|
-
message: `Successfully staged ${args.files.length} file(s)`,
|
|
188
|
-
error: null
|
|
189
|
-
}
|
|
190
|
-
};
|
|
191
|
-
return { content };
|
|
192
|
-
} catch (error) {
|
|
193
|
-
logger.error('Git add failed', { error });
|
|
194
|
-
const content: McpToolResultContent = {
|
|
195
|
-
type: 'application/json',
|
|
196
|
-
data: {
|
|
197
|
-
success: false,
|
|
198
|
-
message: '',
|
|
199
|
-
error: error instanceof Error ? error.message : String(error)
|
|
200
|
-
}
|
|
201
|
-
};
|
|
202
|
-
return { content };
|
|
203
|
-
}
|
|
169
|
+
return {
|
|
170
|
+
stagedCount: input.files.length,
|
|
171
|
+
files: input.files
|
|
172
|
+
};
|
|
204
173
|
}
|
|
205
|
-
};
|
|
174
|
+
});
|
|
206
175
|
|
|
207
|
-
export const gitCommitTool =
|
|
176
|
+
export const gitCommitTool = defineTool<
|
|
177
|
+
{ message: string; workingDirectory?: string },
|
|
178
|
+
{ message: string; commitHash: string }
|
|
179
|
+
>({
|
|
208
180
|
name: 'git_commit',
|
|
209
|
-
|
|
181
|
+
category: TOOL_CATEGORIES.VERSION_CONTROL,
|
|
182
|
+
description: 'Create a commit from the staged changes.',
|
|
210
183
|
inputSchema: {
|
|
211
184
|
type: 'object',
|
|
212
185
|
properties: {
|
|
213
186
|
message: {
|
|
214
187
|
type: 'string',
|
|
188
|
+
minLength: 1,
|
|
215
189
|
description: 'Commit message'
|
|
216
190
|
},
|
|
217
|
-
workingDirectory:
|
|
218
|
-
type: 'string',
|
|
219
|
-
description: 'Working directory path (defaults to current directory)'
|
|
220
|
-
}
|
|
191
|
+
workingDirectory: workingDirectoryProperty
|
|
221
192
|
},
|
|
222
193
|
required: ['message']
|
|
223
194
|
},
|
|
224
|
-
|
|
225
|
-
message
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
if (result.exitCode !== 0) {
|
|
236
|
-
const content: McpToolResultContent = {
|
|
237
|
-
type: 'application/json',
|
|
238
|
-
data: {
|
|
239
|
-
success: false,
|
|
240
|
-
message: args.message,
|
|
241
|
-
error: result.stderr || 'Git commit failed'
|
|
242
|
-
}
|
|
243
|
-
};
|
|
244
|
-
return { content };
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
const content: McpToolResultContent = {
|
|
248
|
-
type: 'application/json',
|
|
249
|
-
data: {
|
|
250
|
-
success: true,
|
|
251
|
-
message: args.message,
|
|
252
|
-
commitHash: result.stdout?.match(/\[(.+?)\]/)?.[1] || 'unknown',
|
|
253
|
-
error: null
|
|
254
|
-
}
|
|
255
|
-
};
|
|
256
|
-
return { content };
|
|
257
|
-
} catch (error) {
|
|
258
|
-
logger.error('Git commit failed', { error });
|
|
259
|
-
const content: McpToolResultContent = {
|
|
260
|
-
type: 'application/json',
|
|
261
|
-
data: {
|
|
262
|
-
success: false,
|
|
263
|
-
message: args.message,
|
|
264
|
-
error: error instanceof Error ? error.message : String(error)
|
|
265
|
-
}
|
|
266
|
-
};
|
|
267
|
-
return { content };
|
|
195
|
+
run: async (input, context) => {
|
|
196
|
+
const result = await runGit(['commit', '-m', input.message], input.workingDirectory, context);
|
|
197
|
+
|
|
198
|
+
// git prints `[branch abc1234] subject` on success.
|
|
199
|
+
const commitHash = result.stdout?.match(/\[[^\]]*\s([0-9a-f]{7,40})\]/)?.[1];
|
|
200
|
+
if (!commitHash) {
|
|
201
|
+
throw ToolError.executionFailed(
|
|
202
|
+
`git commit succeeded but its output did not contain a commit hash: ${result.stdout?.trim()}`
|
|
203
|
+
);
|
|
268
204
|
}
|
|
205
|
+
|
|
206
|
+
return {
|
|
207
|
+
message: input.message,
|
|
208
|
+
commitHash
|
|
209
|
+
};
|
|
269
210
|
}
|
|
270
|
-
};
|
|
211
|
+
});
|
|
271
212
|
|
|
272
|
-
export const gitDiffTool =
|
|
213
|
+
export const gitDiffTool = defineTool<
|
|
214
|
+
{ staged?: boolean; workingDirectory?: string },
|
|
215
|
+
{ diff: string; filesChanged: number; insertions: number; deletions: number }
|
|
216
|
+
>({
|
|
273
217
|
name: 'git_diff',
|
|
274
|
-
|
|
218
|
+
category: TOOL_CATEGORIES.VERSION_CONTROL,
|
|
219
|
+
description: 'Show the working-tree diff, or the staged diff when staged is true.',
|
|
275
220
|
inputSchema: {
|
|
276
221
|
type: 'object',
|
|
277
222
|
properties: {
|
|
278
223
|
staged: {
|
|
279
224
|
type: 'boolean',
|
|
280
225
|
default: false,
|
|
281
|
-
description: 'Show staged changes (--cached)'
|
|
226
|
+
description: 'Show staged changes (--cached) instead of working-tree changes'
|
|
282
227
|
},
|
|
283
|
-
workingDirectory:
|
|
284
|
-
type: 'string',
|
|
285
|
-
description: 'Working directory path (defaults to current directory)'
|
|
286
|
-
}
|
|
228
|
+
workingDirectory: workingDirectoryProperty
|
|
287
229
|
}
|
|
288
230
|
},
|
|
289
|
-
|
|
290
|
-
staged
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
if (result.exitCode !== 0) {
|
|
307
|
-
const content: McpToolResultContent = {
|
|
308
|
-
type: 'application/json',
|
|
309
|
-
data: {
|
|
310
|
-
success: false,
|
|
311
|
-
diff: '',
|
|
312
|
-
filesChanged: 0,
|
|
313
|
-
insertions: 0,
|
|
314
|
-
deletions: 0,
|
|
315
|
-
error: result.stderr || 'Git diff failed'
|
|
316
|
-
}
|
|
317
|
-
};
|
|
318
|
-
return { content };
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
// Get the actual diff content
|
|
322
|
-
const diffResult = await executeShellCommand('git', args.staged ? ['diff', '--cached'] : ['diff'], {
|
|
323
|
-
workingDirectory: args.workingDirectory || process.cwd(),
|
|
324
|
-
captureOutput: true
|
|
325
|
-
});
|
|
326
|
-
|
|
327
|
-
// Parse stats from output
|
|
328
|
-
const statsMatch = result.stdout?.match(/(\d+) files? changed(?:, (\d+) insertions?\(\+\))?(?:, (\d+) deletions?\(\-\))?/);
|
|
329
|
-
|
|
330
|
-
const content: McpToolResultContent = {
|
|
331
|
-
type: 'application/json',
|
|
332
|
-
data: {
|
|
333
|
-
success: true,
|
|
334
|
-
diff: diffResult.stdout || '',
|
|
335
|
-
filesChanged: statsMatch ? parseInt(statsMatch[1]) : 0,
|
|
336
|
-
insertions: statsMatch ? parseInt(statsMatch[2] || '0') : 0,
|
|
337
|
-
deletions: statsMatch ? parseInt(statsMatch[3] || '0') : 0,
|
|
338
|
-
error: null
|
|
339
|
-
}
|
|
340
|
-
};
|
|
341
|
-
return { content };
|
|
342
|
-
} catch (error) {
|
|
343
|
-
logger.error('Git diff failed', { error });
|
|
344
|
-
const content: McpToolResultContent = {
|
|
345
|
-
type: 'application/json',
|
|
346
|
-
data: {
|
|
347
|
-
success: false,
|
|
348
|
-
diff: '',
|
|
349
|
-
filesChanged: 0,
|
|
350
|
-
insertions: 0,
|
|
351
|
-
deletions: 0,
|
|
352
|
-
error: error instanceof Error ? error.message : String(error)
|
|
353
|
-
}
|
|
354
|
-
};
|
|
355
|
-
return { content };
|
|
356
|
-
}
|
|
231
|
+
run: async (input, context) => {
|
|
232
|
+
const baseArgs = input.staged ? ['diff', '--cached'] : ['diff'];
|
|
233
|
+
|
|
234
|
+
const statResult = await runGit([...baseArgs, '--stat'], input.workingDirectory, context);
|
|
235
|
+
const diffResult = await runGit(baseArgs, input.workingDirectory, context);
|
|
236
|
+
|
|
237
|
+
const statsMatch = statResult.stdout?.match(
|
|
238
|
+
/(\d+) files? changed(?:, (\d+) insertions?\(\+\))?(?:, (\d+) deletions?\(-\))?/
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
return {
|
|
242
|
+
diff: diffResult.stdout ?? '',
|
|
243
|
+
filesChanged: statsMatch ? parseInt(statsMatch[1], 10) : 0,
|
|
244
|
+
insertions: statsMatch ? parseInt(statsMatch[2] ?? '0', 10) : 0,
|
|
245
|
+
deletions: statsMatch ? parseInt(statsMatch[3] ?? '0', 10) : 0
|
|
246
|
+
};
|
|
357
247
|
}
|
|
358
|
-
};
|
|
248
|
+
});
|
|
359
249
|
|
|
360
|
-
export const gitLogTool =
|
|
250
|
+
export const gitLogTool = defineTool<
|
|
251
|
+
{ maxCount?: number; workingDirectory?: string },
|
|
252
|
+
{ commits: Array<{ hash: string; subject: string; author: string; date: string; refs: string }> }
|
|
253
|
+
>({
|
|
361
254
|
name: 'git_log',
|
|
362
|
-
|
|
255
|
+
category: TOOL_CATEGORIES.VERSION_CONTROL,
|
|
256
|
+
description: 'List recent commits with hash, subject, author and date.',
|
|
363
257
|
inputSchema: {
|
|
364
258
|
type: 'object',
|
|
365
259
|
properties: {
|
|
366
260
|
maxCount: {
|
|
367
261
|
type: 'number',
|
|
368
262
|
default: 10,
|
|
263
|
+
minimum: 1,
|
|
264
|
+
maximum: 500,
|
|
369
265
|
description: 'Maximum number of commits to show'
|
|
370
266
|
},
|
|
371
|
-
workingDirectory:
|
|
372
|
-
type: 'string',
|
|
373
|
-
description: 'Working directory path (defaults to current directory)'
|
|
374
|
-
}
|
|
267
|
+
workingDirectory: workingDirectoryProperty
|
|
375
268
|
}
|
|
376
269
|
},
|
|
377
|
-
|
|
378
|
-
maxCount
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
data: {
|
|
398
|
-
success: false,
|
|
399
|
-
commits: [],
|
|
400
|
-
error: result.stderr || 'Git log failed'
|
|
401
|
-
}
|
|
270
|
+
run: async (input, context) => {
|
|
271
|
+
const maxCount = input.maxCount ?? 10;
|
|
272
|
+
|
|
273
|
+
const result = await runGit(
|
|
274
|
+
['log', '--format=%H|%s|%an|%ad|%d', '--date=iso', `-n${maxCount}`],
|
|
275
|
+
input.workingDirectory,
|
|
276
|
+
context
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
const commits = (result.stdout ?? '')
|
|
280
|
+
.split('\n')
|
|
281
|
+
.filter(line => line.trim())
|
|
282
|
+
.map(line => {
|
|
283
|
+
const [hash, subject, author, date, refs] = line.split('|');
|
|
284
|
+
return {
|
|
285
|
+
hash,
|
|
286
|
+
subject,
|
|
287
|
+
author,
|
|
288
|
+
date,
|
|
289
|
+
refs: refs ? refs.trim() : ''
|
|
402
290
|
};
|
|
403
|
-
|
|
404
|
-
}
|
|
291
|
+
});
|
|
405
292
|
|
|
406
|
-
|
|
407
|
-
const commits = result.stdout?.split('\n')
|
|
408
|
-
.filter(line => line.trim())
|
|
409
|
-
.map(line => {
|
|
410
|
-
const [hash, subject, author, date, refs] = line.split('|');
|
|
411
|
-
return {
|
|
412
|
-
hash,
|
|
413
|
-
subject,
|
|
414
|
-
author,
|
|
415
|
-
date,
|
|
416
|
-
refs: refs ? refs.trim() : ''
|
|
417
|
-
};
|
|
418
|
-
}) || [];
|
|
419
|
-
|
|
420
|
-
const content: McpToolResultContent = {
|
|
421
|
-
type: 'application/json',
|
|
422
|
-
data: {
|
|
423
|
-
success: true,
|
|
424
|
-
commits,
|
|
425
|
-
error: null
|
|
426
|
-
}
|
|
427
|
-
};
|
|
428
|
-
return { content };
|
|
429
|
-
} catch (error) {
|
|
430
|
-
logger.error('Git log failed', { error });
|
|
431
|
-
const content: McpToolResultContent = {
|
|
432
|
-
type: 'application/json',
|
|
433
|
-
data: {
|
|
434
|
-
success: false,
|
|
435
|
-
commits: [],
|
|
436
|
-
error: error instanceof Error ? error.message : String(error)
|
|
437
|
-
}
|
|
438
|
-
};
|
|
439
|
-
return { content };
|
|
440
|
-
}
|
|
293
|
+
return { commits };
|
|
441
294
|
}
|
|
442
|
-
};
|
|
295
|
+
});
|
|
443
296
|
|
|
444
|
-
export const gitBranchTool =
|
|
297
|
+
export const gitBranchTool = defineTool<
|
|
298
|
+
{ action?: 'list' | 'create' | 'delete' | 'switch'; branchName?: string; workingDirectory?: string },
|
|
299
|
+
{ action: string; currentBranch: string; branches: string[] }
|
|
300
|
+
>({
|
|
445
301
|
name: 'git_branch',
|
|
446
|
-
|
|
302
|
+
category: TOOL_CATEGORIES.VERSION_CONTROL,
|
|
303
|
+
description: 'List branches, or create, delete, or switch to a branch.',
|
|
447
304
|
inputSchema: {
|
|
448
305
|
type: 'object',
|
|
449
306
|
properties: {
|
|
@@ -455,122 +312,67 @@ export const gitBranchTool = {
|
|
|
455
312
|
},
|
|
456
313
|
branchName: {
|
|
457
314
|
type: 'string',
|
|
458
|
-
description: 'Branch name (required for create, delete
|
|
315
|
+
description: 'Branch name (required for create, delete and switch)'
|
|
459
316
|
},
|
|
460
|
-
workingDirectory:
|
|
461
|
-
type: 'string',
|
|
462
|
-
description: 'Working directory path (defaults to current directory)'
|
|
463
|
-
}
|
|
317
|
+
workingDirectory: workingDirectoryProperty
|
|
464
318
|
}
|
|
465
319
|
},
|
|
466
|
-
|
|
467
|
-
action
|
|
468
|
-
branchName?: string;
|
|
469
|
-
workingDirectory?: string;
|
|
470
|
-
}, context: McpToolHandlerContext): Promise<McpToolHandlerResult> => {
|
|
471
|
-
|
|
472
|
-
try {
|
|
473
|
-
let result;
|
|
474
|
-
|
|
475
|
-
switch (args.action) {
|
|
476
|
-
case 'create':
|
|
477
|
-
if (!args.branchName) {
|
|
478
|
-
throw new Error('Branch name required for create action');
|
|
479
|
-
}
|
|
480
|
-
result = await executeShellCommand('git', ['branch', args.branchName], {
|
|
481
|
-
workingDirectory: args.workingDirectory || process.cwd(),
|
|
482
|
-
captureOutput: true
|
|
483
|
-
});
|
|
484
|
-
break;
|
|
485
|
-
|
|
486
|
-
case 'delete':
|
|
487
|
-
if (!args.branchName) {
|
|
488
|
-
throw new Error('Branch name required for delete action');
|
|
489
|
-
}
|
|
490
|
-
result = await executeShellCommand('git', ['branch', '-d', args.branchName], {
|
|
491
|
-
workingDirectory: args.workingDirectory || process.cwd(),
|
|
492
|
-
captureOutput: true
|
|
493
|
-
});
|
|
494
|
-
break;
|
|
495
|
-
|
|
496
|
-
case 'switch':
|
|
497
|
-
if (!args.branchName) {
|
|
498
|
-
throw new Error('Branch name required for switch action');
|
|
499
|
-
}
|
|
500
|
-
result = await executeShellCommand('git', ['switch', args.branchName], {
|
|
501
|
-
workingDirectory: args.workingDirectory || process.cwd(),
|
|
502
|
-
captureOutput: true
|
|
503
|
-
});
|
|
504
|
-
break;
|
|
505
|
-
|
|
506
|
-
case 'list':
|
|
507
|
-
default:
|
|
508
|
-
result = await executeShellCommand('git', ['branch', '-a'], {
|
|
509
|
-
workingDirectory: args.workingDirectory || process.cwd(),
|
|
510
|
-
captureOutput: true
|
|
511
|
-
});
|
|
512
|
-
break;
|
|
513
|
-
}
|
|
320
|
+
run: async (input, context) => {
|
|
321
|
+
const action = input.action ?? 'list';
|
|
514
322
|
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
currentBranch: '',
|
|
521
|
-
branches: [],
|
|
522
|
-
error: result.stderr || 'Git branch command failed'
|
|
523
|
-
}
|
|
524
|
-
};
|
|
525
|
-
return { content };
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
// Get current branch
|
|
529
|
-
const currentBranchResult = await executeShellCommand('git', ['branch', '--show-current'], {
|
|
530
|
-
workingDirectory: args.workingDirectory || process.cwd(),
|
|
531
|
-
captureOutput: true
|
|
532
|
-
});
|
|
323
|
+
// create/delete/switch are meaningless without a name — reject before
|
|
324
|
+
// shelling out, so the model gets a precise correction.
|
|
325
|
+
if (action !== 'list' && !input.branchName) {
|
|
326
|
+
throw ToolError.invalidInput(`branchName is required for the "${action}" action.`);
|
|
327
|
+
}
|
|
533
328
|
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
329
|
+
let listOutput = '';
|
|
330
|
+
|
|
331
|
+
switch (action) {
|
|
332
|
+
case 'create':
|
|
333
|
+
await runGit(['branch', input.branchName!], input.workingDirectory, context);
|
|
334
|
+
break;
|
|
335
|
+
case 'delete':
|
|
336
|
+
await runGit(['branch', '-d', input.branchName!], input.workingDirectory, context);
|
|
337
|
+
break;
|
|
338
|
+
case 'switch':
|
|
339
|
+
await runGit(['switch', input.branchName!], input.workingDirectory, context);
|
|
340
|
+
break;
|
|
341
|
+
case 'list':
|
|
342
|
+
default: {
|
|
343
|
+
const result = await runGit(['branch', '-a'], input.workingDirectory, context);
|
|
344
|
+
listOutput = result.stdout ?? '';
|
|
345
|
+
break;
|
|
543
346
|
}
|
|
544
|
-
|
|
545
|
-
const content: McpToolResultContent = {
|
|
546
|
-
type: 'application/json',
|
|
547
|
-
data: {
|
|
548
|
-
success: true,
|
|
549
|
-
currentBranch,
|
|
550
|
-
branches,
|
|
551
|
-
error: null
|
|
552
|
-
}
|
|
553
|
-
};
|
|
554
|
-
return { content };
|
|
555
|
-
} catch (error) {
|
|
556
|
-
logger.error('Git branch failed', { error });
|
|
557
|
-
const content: McpToolResultContent = {
|
|
558
|
-
type: 'application/json',
|
|
559
|
-
data: {
|
|
560
|
-
success: false,
|
|
561
|
-
currentBranch: '',
|
|
562
|
-
branches: [],
|
|
563
|
-
error: error instanceof Error ? error.message : String(error)
|
|
564
|
-
}
|
|
565
|
-
};
|
|
566
|
-
return { content };
|
|
567
347
|
}
|
|
348
|
+
|
|
349
|
+
const currentBranchResult = await runGit(
|
|
350
|
+
['branch', '--show-current'],
|
|
351
|
+
input.workingDirectory,
|
|
352
|
+
context
|
|
353
|
+
);
|
|
354
|
+
|
|
355
|
+
const branches = listOutput
|
|
356
|
+
.split('\n')
|
|
357
|
+
.filter(line => line.trim())
|
|
358
|
+
.map(line => line.replace(/^[\s*]+/, '').trim())
|
|
359
|
+
.filter(branch => branch.length > 0);
|
|
360
|
+
|
|
361
|
+
return {
|
|
362
|
+
action,
|
|
363
|
+
currentBranch: currentBranchResult.stdout?.trim() ?? '',
|
|
364
|
+
branches
|
|
365
|
+
};
|
|
568
366
|
}
|
|
569
|
-
};
|
|
367
|
+
});
|
|
570
368
|
|
|
571
|
-
export const gitPushTool =
|
|
369
|
+
export const gitPushTool = defineTool<
|
|
370
|
+
{ remote?: string; branch?: string; workingDirectory?: string },
|
|
371
|
+
{ remote: string; branch?: string; output: string }
|
|
372
|
+
>({
|
|
572
373
|
name: 'git_push',
|
|
573
|
-
|
|
374
|
+
category: TOOL_CATEGORIES.VERSION_CONTROL,
|
|
375
|
+
description: 'Push commits to a remote repository.',
|
|
574
376
|
inputSchema: {
|
|
575
377
|
type: 'object',
|
|
576
378
|
properties: {
|
|
@@ -581,73 +383,36 @@ export const gitPushTool = {
|
|
|
581
383
|
},
|
|
582
384
|
branch: {
|
|
583
385
|
type: 'string',
|
|
584
|
-
description: 'Branch to push (defaults to current branch)'
|
|
386
|
+
description: 'Branch to push (defaults to the current branch)'
|
|
585
387
|
},
|
|
586
|
-
workingDirectory:
|
|
587
|
-
type: 'string',
|
|
588
|
-
description: 'Working directory path (defaults to current directory)'
|
|
589
|
-
}
|
|
388
|
+
workingDirectory: workingDirectoryProperty
|
|
590
389
|
}
|
|
591
390
|
},
|
|
592
|
-
|
|
593
|
-
remote
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
try {
|
|
599
|
-
const gitArgs = ['push'];
|
|
600
|
-
if (args.remote) {
|
|
601
|
-
gitArgs.push(args.remote);
|
|
602
|
-
}
|
|
603
|
-
if (args.branch) {
|
|
604
|
-
gitArgs.push(args.branch);
|
|
605
|
-
}
|
|
606
|
-
|
|
607
|
-
const result = await executeShellCommand('git', gitArgs, {
|
|
608
|
-
workingDirectory: args.workingDirectory || process.cwd(),
|
|
609
|
-
captureOutput: true
|
|
610
|
-
});
|
|
391
|
+
run: async (input, context) => {
|
|
392
|
+
const remote = input.remote ?? 'origin';
|
|
393
|
+
const args = ['push', remote];
|
|
394
|
+
if (input.branch) {
|
|
395
|
+
args.push(input.branch);
|
|
396
|
+
}
|
|
611
397
|
|
|
612
|
-
|
|
613
|
-
const content: McpToolResultContent = {
|
|
614
|
-
type: 'application/json',
|
|
615
|
-
data: {
|
|
616
|
-
success: false,
|
|
617
|
-
message: result.stderr || 'Git push failed',
|
|
618
|
-
error: result.stderr || 'Git push command failed'
|
|
619
|
-
}
|
|
620
|
-
};
|
|
621
|
-
return { content };
|
|
622
|
-
}
|
|
398
|
+
const result = await runGit(args, input.workingDirectory, context);
|
|
623
399
|
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
}
|
|
631
|
-
};
|
|
632
|
-
return { content };
|
|
633
|
-
} catch (error) {
|
|
634
|
-
logger.error('Git push failed', { error });
|
|
635
|
-
const content: McpToolResultContent = {
|
|
636
|
-
type: 'application/json',
|
|
637
|
-
data: {
|
|
638
|
-
success: false,
|
|
639
|
-
message: '',
|
|
640
|
-
error: error instanceof Error ? error.message : String(error)
|
|
641
|
-
}
|
|
642
|
-
};
|
|
643
|
-
return { content };
|
|
644
|
-
}
|
|
400
|
+
// git push reports progress on stderr even when it succeeds, so include both.
|
|
401
|
+
return {
|
|
402
|
+
remote,
|
|
403
|
+
branch: input.branch,
|
|
404
|
+
output: [result.stdout, result.stderr].filter(Boolean).join('\n').trim()
|
|
405
|
+
};
|
|
645
406
|
}
|
|
646
|
-
};
|
|
407
|
+
});
|
|
647
408
|
|
|
648
|
-
export const gitPullTool =
|
|
409
|
+
export const gitPullTool = defineTool<
|
|
410
|
+
{ remote?: string; workingDirectory?: string },
|
|
411
|
+
{ remote: string; output: string }
|
|
412
|
+
>({
|
|
649
413
|
name: 'git_pull',
|
|
650
|
-
|
|
414
|
+
category: TOOL_CATEGORIES.VERSION_CONTROL,
|
|
415
|
+
description: 'Pull changes from a remote repository.',
|
|
651
416
|
inputSchema: {
|
|
652
417
|
type: 'object',
|
|
653
418
|
properties: {
|
|
@@ -656,65 +421,21 @@ export const gitPullTool = {
|
|
|
656
421
|
default: 'origin',
|
|
657
422
|
description: 'Remote name'
|
|
658
423
|
},
|
|
659
|
-
workingDirectory:
|
|
660
|
-
type: 'string',
|
|
661
|
-
description: 'Working directory path (defaults to current directory)'
|
|
662
|
-
}
|
|
424
|
+
workingDirectory: workingDirectoryProperty
|
|
663
425
|
}
|
|
664
426
|
},
|
|
665
|
-
|
|
666
|
-
remote
|
|
667
|
-
workingDirectory?: string;
|
|
668
|
-
}, context: McpToolHandlerContext): Promise<McpToolHandlerResult> => {
|
|
669
|
-
|
|
670
|
-
try {
|
|
671
|
-
const gitArgs = ['pull'];
|
|
672
|
-
if (args.remote) {
|
|
673
|
-
gitArgs.push(args.remote);
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
const result = await executeShellCommand('git', gitArgs, {
|
|
677
|
-
workingDirectory: args.workingDirectory || process.cwd(),
|
|
678
|
-
captureOutput: true
|
|
679
|
-
});
|
|
427
|
+
run: async (input, context) => {
|
|
428
|
+
const remote = input.remote ?? 'origin';
|
|
680
429
|
|
|
681
|
-
|
|
682
|
-
const content: McpToolResultContent = {
|
|
683
|
-
type: 'application/json',
|
|
684
|
-
data: {
|
|
685
|
-
success: false,
|
|
686
|
-
message: result.stderr || 'Git pull failed',
|
|
687
|
-
error: result.stderr || 'Git pull command failed'
|
|
688
|
-
}
|
|
689
|
-
};
|
|
690
|
-
return { content };
|
|
691
|
-
}
|
|
430
|
+
const result = await runGit(['pull', remote], input.workingDirectory, context);
|
|
692
431
|
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
message: result.stdout || 'Pull completed successfully',
|
|
698
|
-
error: null
|
|
699
|
-
}
|
|
700
|
-
};
|
|
701
|
-
return { content };
|
|
702
|
-
} catch (error) {
|
|
703
|
-
logger.error('Git pull failed', { error });
|
|
704
|
-
const content: McpToolResultContent = {
|
|
705
|
-
type: 'application/json',
|
|
706
|
-
data: {
|
|
707
|
-
success: false,
|
|
708
|
-
message: '',
|
|
709
|
-
error: error instanceof Error ? error.message : String(error)
|
|
710
|
-
}
|
|
711
|
-
};
|
|
712
|
-
return { content };
|
|
713
|
-
}
|
|
432
|
+
return {
|
|
433
|
+
remote,
|
|
434
|
+
output: [result.stdout, result.stderr].filter(Boolean).join('\n').trim()
|
|
435
|
+
};
|
|
714
436
|
}
|
|
715
|
-
};
|
|
437
|
+
});
|
|
716
438
|
|
|
717
|
-
// Export all git tools
|
|
718
439
|
export const gitTools = [
|
|
719
440
|
gitStatusTool,
|
|
720
441
|
gitAddTool,
|