@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
|
@@ -17,425 +17,311 @@
|
|
|
17
17
|
* @repository https://github.com/BradA1878/model-exchange-framework
|
|
18
18
|
* @documentation https://mxf-dev.github.io/mxf/
|
|
19
19
|
*/
|
|
20
|
-
|
|
20
|
+
/**
|
|
21
|
+
* TypeScriptTools.ts
|
|
22
|
+
*
|
|
23
|
+
* TypeScript checking, building, formatting, linting and test running. Each tool
|
|
24
|
+
* shells out to the real binary (tsc, prettier, eslint, jest) through
|
|
25
|
+
* executeShellCommand, which validates the command and strips the child's
|
|
26
|
+
* environment.
|
|
27
|
+
*
|
|
28
|
+
* On exit codes: tsc, eslint and jest all exit non-zero to mean "I found
|
|
29
|
+
* problems". That is a successful tool call with a negative finding, not a tool
|
|
30
|
+
* failure — so those tools return `passed: false` with the diagnostics, and
|
|
31
|
+
* `isError` stays false. `isError` is reserved for the tool genuinely not
|
|
32
|
+
* working: the binary is missing, the working directory does not exist, output
|
|
33
|
+
* cannot be parsed.
|
|
34
|
+
*/
|
|
35
|
+
import { TOOL_CATEGORIES } from '../../../constants/ToolNames.js';
|
|
36
|
+
import { defineTool } from '../defineTool.js';
|
|
37
|
+
import { ToolError } from '../ToolError.js';
|
|
21
38
|
import { executeShellCommand } from './InfrastructureTools.js';
|
|
22
|
-
|
|
39
|
+
/** Exit code the shell reports when a command could not be found or spawned. */
|
|
40
|
+
const COMMAND_NOT_FOUND = 127;
|
|
41
|
+
const workingDirectoryProperty = {
|
|
42
|
+
type: 'string',
|
|
43
|
+
description: 'Working directory path (defaults to the server working directory)'
|
|
44
|
+
};
|
|
23
45
|
/**
|
|
24
|
-
*
|
|
46
|
+
* Run one of the node toolchain binaries via npx.
|
|
25
47
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* Full implementation would integrate with shell_execute tool
|
|
48
|
+
* Throws only when the binary could not be run at all. A non-zero exit that the
|
|
49
|
+
* binary uses to report findings is handed back to the caller to interpret.
|
|
29
50
|
*/
|
|
30
|
-
|
|
51
|
+
async function runNpx(args, workingDirectory, context) {
|
|
52
|
+
const result = await executeShellCommand('npx', args, {
|
|
53
|
+
context: {
|
|
54
|
+
agentId: context.agentId,
|
|
55
|
+
channelId: context.channelId,
|
|
56
|
+
requestId: context.requestId
|
|
57
|
+
},
|
|
58
|
+
workingDirectory: workingDirectory || process.cwd(),
|
|
59
|
+
captureOutput: true
|
|
60
|
+
});
|
|
61
|
+
if (result.exitCode === COMMAND_NOT_FOUND) {
|
|
62
|
+
throw ToolError.preconditionFailed(`Could not run "npx ${args[0]}" — the command was not found. ` +
|
|
63
|
+
`${result.stderr?.trim() ?? ''}`.trim(), { command: args[0] });
|
|
64
|
+
}
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
/** Pull `file(line,col): error TSxxxx: message` diagnostics out of tsc output. */
|
|
68
|
+
function parseTscDiagnostics(output) {
|
|
69
|
+
const diagnostics = [];
|
|
70
|
+
// tsc --pretty false emits: path/file.ts(12,5): error TS2304: Cannot find name 'x'.
|
|
71
|
+
const pattern = /^(.+?)\((\d+),(\d+)\):\s+(error|warning)\s+(TS\d+):\s+(.*)$/;
|
|
72
|
+
for (const line of output.split('\n')) {
|
|
73
|
+
const match = line.match(pattern);
|
|
74
|
+
if (!match) {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
diagnostics.push({
|
|
78
|
+
type: match[4],
|
|
79
|
+
file: match[1],
|
|
80
|
+
line: parseInt(match[2], 10),
|
|
81
|
+
column: parseInt(match[3], 10),
|
|
82
|
+
code: match[5],
|
|
83
|
+
message: match[6].trim()
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
return diagnostics;
|
|
87
|
+
}
|
|
88
|
+
export const typescriptCheckTool = defineTool({
|
|
31
89
|
name: 'typescript_check',
|
|
32
|
-
|
|
90
|
+
category: TOOL_CATEGORIES.INFRASTRUCTURE,
|
|
91
|
+
description: 'Type-check TypeScript with `tsc --noEmit` and return the diagnostics. ' +
|
|
92
|
+
'passed is false when there are type errors.',
|
|
33
93
|
inputSchema: {
|
|
34
94
|
type: 'object',
|
|
35
95
|
properties: {
|
|
36
|
-
workingDirectory:
|
|
37
|
-
type: 'string',
|
|
38
|
-
description: 'Working directory path (defaults to current directory)'
|
|
39
|
-
},
|
|
96
|
+
workingDirectory: workingDirectoryProperty,
|
|
40
97
|
files: {
|
|
41
98
|
type: 'array',
|
|
42
99
|
items: { type: 'string' },
|
|
43
|
-
description: 'Specific files to check
|
|
100
|
+
description: 'Specific files to check. Checks the whole project when omitted.'
|
|
44
101
|
}
|
|
45
102
|
}
|
|
46
103
|
},
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
tscArgs.push(...args.files);
|
|
52
|
-
}
|
|
53
|
-
const result = await executeShellCommand('npx', ['tsc', ...tscArgs], {
|
|
54
|
-
workingDirectory: args.workingDirectory || process.cwd(),
|
|
55
|
-
captureOutput: true
|
|
56
|
-
});
|
|
57
|
-
// TypeScript compiler exits with code 1 if there are errors, but this is expected
|
|
58
|
-
const diagnostics = [];
|
|
59
|
-
let totalErrors = 0;
|
|
60
|
-
let totalWarnings = 0;
|
|
61
|
-
let filesChecked = 0;
|
|
62
|
-
if (result.stdout) {
|
|
63
|
-
// Parse TypeScript compiler output
|
|
64
|
-
const lines = result.stdout.split('\n');
|
|
65
|
-
for (const line of lines) {
|
|
66
|
-
if (line.includes('error TS')) {
|
|
67
|
-
totalErrors++;
|
|
68
|
-
diagnostics.push({
|
|
69
|
-
type: 'error',
|
|
70
|
-
message: line.trim(),
|
|
71
|
-
file: line.split('(')[0] || '',
|
|
72
|
-
line: 0,
|
|
73
|
-
column: 0
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
else if (line.includes('warning TS')) {
|
|
77
|
-
totalWarnings++;
|
|
78
|
-
diagnostics.push({
|
|
79
|
-
type: 'warning',
|
|
80
|
-
message: line.trim(),
|
|
81
|
-
file: line.split('(')[0] || '',
|
|
82
|
-
line: 0,
|
|
83
|
-
column: 0
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
const content = {
|
|
89
|
-
type: 'application/json',
|
|
90
|
-
data: {
|
|
91
|
-
success: result.exitCode === 0,
|
|
92
|
-
diagnostics,
|
|
93
|
-
totalErrors,
|
|
94
|
-
totalWarnings,
|
|
95
|
-
filesChecked: args.files ? args.files.length : 0,
|
|
96
|
-
error: result.exitCode !== 0 ? result.stderr : null
|
|
97
|
-
}
|
|
98
|
-
};
|
|
99
|
-
return { content };
|
|
104
|
+
run: async (input, context) => {
|
|
105
|
+
const tscArgs = ['tsc', '--noEmit', '--pretty', 'false'];
|
|
106
|
+
if (input.files && input.files.length > 0) {
|
|
107
|
+
tscArgs.push(...input.files);
|
|
100
108
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}
|
|
113
|
-
};
|
|
114
|
-
return { content };
|
|
109
|
+
const result = await runNpx(tscArgs, input.workingDirectory, context);
|
|
110
|
+
// tsc writes diagnostics to stdout and exits 1 when it finds any. That is
|
|
111
|
+
// the tool working, not the tool failing.
|
|
112
|
+
const diagnostics = parseTscDiagnostics(result.stdout ?? '');
|
|
113
|
+
const totalErrors = diagnostics.filter(d => d.type === 'error').length;
|
|
114
|
+
const totalWarnings = diagnostics.filter(d => d.type === 'warning').length;
|
|
115
|
+
// A non-zero exit with nothing parseable means tsc fell over for some other
|
|
116
|
+
// reason (bad tsconfig, unreadable directory). That is a real failure.
|
|
117
|
+
if (result.exitCode !== 0 && diagnostics.length === 0) {
|
|
118
|
+
throw ToolError.executionFailed(`tsc exited ${result.exitCode} without producing diagnostics: ` +
|
|
119
|
+
`${(result.stderr || result.stdout)?.trim() || 'no output'}`);
|
|
115
120
|
}
|
|
121
|
+
return {
|
|
122
|
+
passed: totalErrors === 0,
|
|
123
|
+
totalErrors,
|
|
124
|
+
totalWarnings,
|
|
125
|
+
diagnostics
|
|
126
|
+
};
|
|
116
127
|
}
|
|
117
|
-
};
|
|
118
|
-
export const typescriptBuildTool = {
|
|
128
|
+
});
|
|
129
|
+
export const typescriptBuildTool = defineTool({
|
|
119
130
|
name: 'typescript_build',
|
|
120
|
-
|
|
131
|
+
category: TOOL_CATEGORIES.INFRASTRUCTURE,
|
|
132
|
+
description: 'Build the TypeScript project with `tsc --build` and emit JavaScript.',
|
|
121
133
|
inputSchema: {
|
|
122
134
|
type: 'object',
|
|
123
135
|
properties: {
|
|
124
|
-
workingDirectory:
|
|
125
|
-
type: 'string',
|
|
126
|
-
description: 'Working directory path (defaults to current directory)'
|
|
127
|
-
},
|
|
136
|
+
workingDirectory: workingDirectoryProperty,
|
|
128
137
|
clean: {
|
|
129
138
|
type: 'boolean',
|
|
130
139
|
default: false,
|
|
131
|
-
description: '
|
|
140
|
+
description: 'Run `tsc --build --clean` first'
|
|
132
141
|
}
|
|
133
142
|
}
|
|
134
143
|
},
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
if (cleanResult.exitCode !== 0) {
|
|
145
|
-
logger.warn('Clean command failed', { error: cleanResult.stderr });
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
const result = await executeShellCommand('npx', ['tsc', '--build'], {
|
|
149
|
-
workingDirectory: args.workingDirectory || process.cwd(),
|
|
150
|
-
captureOutput: true
|
|
151
|
-
});
|
|
152
|
-
const buildTime = Date.now() - startTime;
|
|
153
|
-
const errors = [];
|
|
154
|
-
const warnings = [];
|
|
155
|
-
if (result.stdout) {
|
|
156
|
-
const lines = result.stdout.split('\n');
|
|
157
|
-
for (const line of lines) {
|
|
158
|
-
if (line.includes('error TS')) {
|
|
159
|
-
errors.push(line.trim());
|
|
160
|
-
}
|
|
161
|
-
else if (line.includes('warning TS')) {
|
|
162
|
-
warnings.push(line.trim());
|
|
163
|
-
}
|
|
164
|
-
}
|
|
144
|
+
run: async (input, context) => {
|
|
145
|
+
const startedAt = Date.now();
|
|
146
|
+
if (input.clean) {
|
|
147
|
+
const cleanResult = await runNpx(['tsc', '--build', '--clean'], input.workingDirectory, context);
|
|
148
|
+
// A failed clean leaves stale output behind, which makes the build's
|
|
149
|
+
// result meaningless. Say so rather than building on top of it.
|
|
150
|
+
if (cleanResult.exitCode !== 0) {
|
|
151
|
+
throw ToolError.executionFailed(`tsc --build --clean failed (exit ${cleanResult.exitCode}): ` +
|
|
152
|
+
`${(cleanResult.stderr || cleanResult.stdout)?.trim() || 'no output'}`);
|
|
165
153
|
}
|
|
166
|
-
const content = {
|
|
167
|
-
type: 'application/json',
|
|
168
|
-
data: {
|
|
169
|
-
success: result.exitCode === 0,
|
|
170
|
-
output: result.stdout || '',
|
|
171
|
-
errors,
|
|
172
|
-
warnings,
|
|
173
|
-
buildTime,
|
|
174
|
-
error: result.exitCode !== 0 ? result.stderr : null
|
|
175
|
-
}
|
|
176
|
-
};
|
|
177
|
-
return { content };
|
|
178
|
-
}
|
|
179
|
-
catch (error) {
|
|
180
|
-
logger.error('TypeScript build failed', { error });
|
|
181
|
-
const content = {
|
|
182
|
-
type: 'application/json',
|
|
183
|
-
data: {
|
|
184
|
-
success: false,
|
|
185
|
-
output: '',
|
|
186
|
-
errors: [],
|
|
187
|
-
warnings: [],
|
|
188
|
-
buildTime: 0,
|
|
189
|
-
error: error instanceof Error ? error.message : String(error)
|
|
190
|
-
}
|
|
191
|
-
};
|
|
192
|
-
return { content };
|
|
193
154
|
}
|
|
155
|
+
const result = await runNpx(['tsc', '--build'], input.workingDirectory, context);
|
|
156
|
+
const errors = (result.stdout ?? '')
|
|
157
|
+
.split('\n')
|
|
158
|
+
.filter(line => line.includes('error TS'))
|
|
159
|
+
.map(line => line.trim());
|
|
160
|
+
return {
|
|
161
|
+
passed: result.exitCode === 0,
|
|
162
|
+
buildTimeMs: Date.now() - startedAt,
|
|
163
|
+
errors,
|
|
164
|
+
output: result.stdout ?? ''
|
|
165
|
+
};
|
|
194
166
|
}
|
|
195
|
-
};
|
|
196
|
-
export const typescriptFormatTool = {
|
|
167
|
+
});
|
|
168
|
+
export const typescriptFormatTool = defineTool({
|
|
197
169
|
name: 'typescript_format',
|
|
198
|
-
|
|
170
|
+
category: TOOL_CATEGORIES.INFRASTRUCTURE,
|
|
171
|
+
description: 'Format TypeScript/JavaScript files with prettier. ' +
|
|
172
|
+
'With check: true it reports whether files are formatted without changing them.',
|
|
199
173
|
inputSchema: {
|
|
200
174
|
type: 'object',
|
|
201
175
|
properties: {
|
|
202
176
|
files: {
|
|
203
177
|
type: 'array',
|
|
204
178
|
items: { type: 'string' },
|
|
205
|
-
description: 'Files to format (
|
|
179
|
+
description: 'Files to format (glob patterns allowed). Defaults to all TS/JS sources.'
|
|
206
180
|
},
|
|
207
181
|
check: {
|
|
208
182
|
type: 'boolean',
|
|
209
183
|
default: false,
|
|
210
|
-
description: '
|
|
184
|
+
description: 'Report formatting problems instead of rewriting files'
|
|
211
185
|
},
|
|
212
|
-
workingDirectory:
|
|
213
|
-
type: 'string',
|
|
214
|
-
description: 'Working directory path (defaults to current directory)'
|
|
215
|
-
}
|
|
186
|
+
workingDirectory: workingDirectoryProperty
|
|
216
187
|
}
|
|
217
188
|
},
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
}
|
|
227
|
-
const result = await executeShellCommand('npx', ['prettier', ...prettierArgs], {
|
|
228
|
-
workingDirectory: args.workingDirectory || process.cwd(),
|
|
229
|
-
captureOutput: true
|
|
230
|
-
});
|
|
231
|
-
const formattedFiles = [];
|
|
232
|
-
const unchanged = [];
|
|
233
|
-
if (result.stdout) {
|
|
234
|
-
const lines = result.stdout.split('\n');
|
|
235
|
-
for (const line of lines) {
|
|
236
|
-
if (line.includes('unchanged')) {
|
|
237
|
-
unchanged.push(line.trim());
|
|
238
|
-
}
|
|
239
|
-
else if (line.trim() && !line.startsWith('Checking')) {
|
|
240
|
-
formattedFiles.push(line.trim());
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
const content = {
|
|
245
|
-
type: 'application/json',
|
|
246
|
-
data: {
|
|
247
|
-
success: result.exitCode === 0,
|
|
248
|
-
formattedFiles,
|
|
249
|
-
unchanged,
|
|
250
|
-
error: result.exitCode !== 0 ? result.stderr : null
|
|
251
|
-
}
|
|
252
|
-
};
|
|
253
|
-
return { content };
|
|
189
|
+
run: async (input, context) => {
|
|
190
|
+
const mode = input.check ? 'check' : 'write';
|
|
191
|
+
const prettierArgs = ['prettier', input.check ? '--check' : '--write'];
|
|
192
|
+
if (input.files && input.files.length > 0) {
|
|
193
|
+
prettierArgs.push(...input.files);
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
prettierArgs.push('**/*.{ts,tsx,js,jsx}');
|
|
254
197
|
}
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
formattedFiles: [],
|
|
262
|
-
unchanged: [],
|
|
263
|
-
error: error instanceof Error ? error.message : String(error)
|
|
264
|
-
}
|
|
265
|
-
};
|
|
266
|
-
return { content };
|
|
198
|
+
const result = await runNpx(prettierArgs, input.workingDirectory, context);
|
|
199
|
+
// In check mode prettier exits 1 when files need formatting — a finding,
|
|
200
|
+
// not a failure. In write mode a non-zero exit means it could not write.
|
|
201
|
+
if (mode === 'write' && result.exitCode !== 0) {
|
|
202
|
+
throw ToolError.executionFailed(`prettier --write failed (exit ${result.exitCode}): ` +
|
|
203
|
+
`${(result.stderr || result.stdout)?.trim() || 'no output'}`);
|
|
267
204
|
}
|
|
205
|
+
const files = (result.stdout ?? '')
|
|
206
|
+
.split('\n')
|
|
207
|
+
.map(line => line.trim())
|
|
208
|
+
.filter(line => line.length > 0 && !line.startsWith('Checking'));
|
|
209
|
+
return {
|
|
210
|
+
mode,
|
|
211
|
+
formatted: result.exitCode === 0,
|
|
212
|
+
files,
|
|
213
|
+
output: result.stdout ?? ''
|
|
214
|
+
};
|
|
268
215
|
}
|
|
269
|
-
};
|
|
270
|
-
export const typescriptLintTool = {
|
|
216
|
+
});
|
|
217
|
+
export const typescriptLintTool = defineTool({
|
|
271
218
|
name: 'typescript_lint',
|
|
272
|
-
|
|
219
|
+
category: TOOL_CATEGORIES.INFRASTRUCTURE,
|
|
220
|
+
description: 'Lint TypeScript/JavaScript with ESLint and return the findings. ' +
|
|
221
|
+
'passed is false when there are lint errors.',
|
|
273
222
|
inputSchema: {
|
|
274
223
|
type: 'object',
|
|
275
224
|
properties: {
|
|
276
225
|
files: {
|
|
277
226
|
type: 'array',
|
|
278
227
|
items: { type: 'string' },
|
|
279
|
-
description: 'Files to lint (
|
|
228
|
+
description: 'Files to lint (glob patterns allowed). Defaults to all TS/JS sources.'
|
|
280
229
|
},
|
|
281
230
|
fix: {
|
|
282
231
|
type: 'boolean',
|
|
283
232
|
default: false,
|
|
284
|
-
description: 'Automatically fix problems'
|
|
233
|
+
description: 'Automatically fix the problems ESLint can fix'
|
|
285
234
|
},
|
|
286
|
-
workingDirectory:
|
|
287
|
-
type: 'string',
|
|
288
|
-
description: 'Working directory path (defaults to current directory)'
|
|
289
|
-
}
|
|
235
|
+
workingDirectory: workingDirectoryProperty
|
|
290
236
|
}
|
|
291
237
|
},
|
|
292
|
-
|
|
238
|
+
run: async (input, context) => {
|
|
239
|
+
const eslintArgs = ['eslint', '--format', 'json'];
|
|
240
|
+
if (input.fix) {
|
|
241
|
+
eslintArgs.push('--fix');
|
|
242
|
+
}
|
|
243
|
+
if (input.files && input.files.length > 0) {
|
|
244
|
+
eslintArgs.push(...input.files);
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
eslintArgs.push('**/*.{ts,tsx,js,jsx}');
|
|
248
|
+
}
|
|
249
|
+
const result = await runNpx(eslintArgs, input.workingDirectory, context);
|
|
250
|
+
// ESLint exits 1 when it finds errors, but always prints its JSON report.
|
|
251
|
+
// No parseable report means ESLint itself fell over — that is a failure,
|
|
252
|
+
// and it must not be reported as "no lint problems".
|
|
253
|
+
const raw = (result.stdout ?? '').trim();
|
|
254
|
+
if (raw.length === 0) {
|
|
255
|
+
throw ToolError.executionFailed(`eslint produced no report (exit ${result.exitCode}): ` +
|
|
256
|
+
`${result.stderr?.trim() || 'no error output'}`);
|
|
257
|
+
}
|
|
258
|
+
let results;
|
|
293
259
|
try {
|
|
294
|
-
|
|
295
|
-
if (args.fix) {
|
|
296
|
-
eslintArgs.push('--fix');
|
|
297
|
-
}
|
|
298
|
-
if (args.files && args.files.length > 0) {
|
|
299
|
-
eslintArgs.push(...args.files);
|
|
300
|
-
}
|
|
301
|
-
else {
|
|
302
|
-
eslintArgs.push('**/*.{ts,tsx,js,jsx}');
|
|
303
|
-
}
|
|
304
|
-
const result = await executeShellCommand('npx', ['eslint', ...eslintArgs], {
|
|
305
|
-
workingDirectory: args.workingDirectory || process.cwd(),
|
|
306
|
-
captureOutput: true
|
|
307
|
-
});
|
|
308
|
-
let results = [];
|
|
309
|
-
try {
|
|
310
|
-
if (result.stdout) {
|
|
311
|
-
results = JSON.parse(result.stdout);
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
catch (parseError) {
|
|
315
|
-
logger.warn('Could not parse ESLint output as JSON', { output: result.stdout });
|
|
316
|
-
results = [{
|
|
317
|
-
filePath: 'unknown',
|
|
318
|
-
messages: [{
|
|
319
|
-
message: result.stdout,
|
|
320
|
-
severity: 1,
|
|
321
|
-
line: 0,
|
|
322
|
-
column: 0
|
|
323
|
-
}]
|
|
324
|
-
}];
|
|
325
|
-
}
|
|
326
|
-
const content = {
|
|
327
|
-
type: 'application/json',
|
|
328
|
-
data: {
|
|
329
|
-
success: result.exitCode === 0,
|
|
330
|
-
results,
|
|
331
|
-
error: result.exitCode !== 0 ? result.stderr : null
|
|
332
|
-
}
|
|
333
|
-
};
|
|
334
|
-
return { content };
|
|
260
|
+
results = JSON.parse(raw);
|
|
335
261
|
}
|
|
336
|
-
catch (
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
type: 'application/json',
|
|
340
|
-
data: {
|
|
341
|
-
success: false,
|
|
342
|
-
results: [],
|
|
343
|
-
error: error instanceof Error ? error.message : String(error)
|
|
344
|
-
}
|
|
345
|
-
};
|
|
346
|
-
return { content };
|
|
262
|
+
catch (parseError) {
|
|
263
|
+
throw ToolError.executionFailed(`Could not parse the ESLint JSON report: ` +
|
|
264
|
+
`${parseError instanceof Error ? parseError.message : String(parseError)}`, { details: { outputPreview: raw.slice(0, 200) } });
|
|
347
265
|
}
|
|
266
|
+
const errorCount = results.reduce((sum, file) => sum + (file.errorCount ?? 0), 0);
|
|
267
|
+
const warningCount = results.reduce((sum, file) => sum + (file.warningCount ?? 0), 0);
|
|
268
|
+
return {
|
|
269
|
+
passed: errorCount === 0,
|
|
270
|
+
errorCount,
|
|
271
|
+
warningCount,
|
|
272
|
+
results
|
|
273
|
+
};
|
|
348
274
|
}
|
|
349
|
-
};
|
|
350
|
-
export const typescriptTestTool = {
|
|
275
|
+
});
|
|
276
|
+
export const typescriptTestTool = defineTool({
|
|
351
277
|
name: 'typescript_test',
|
|
352
|
-
|
|
278
|
+
category: TOOL_CATEGORIES.INFRASTRUCTURE,
|
|
279
|
+
description: 'Run Jest tests and return the counts. passed is false when any test fails.',
|
|
353
280
|
inputSchema: {
|
|
354
281
|
type: 'object',
|
|
355
282
|
properties: {
|
|
356
283
|
testFiles: {
|
|
357
284
|
type: 'array',
|
|
358
285
|
items: { type: 'string' },
|
|
359
|
-
description: 'Specific test files to run'
|
|
286
|
+
description: 'Specific test files to run. Runs the whole suite when omitted.'
|
|
360
287
|
},
|
|
361
288
|
coverage: {
|
|
362
289
|
type: 'boolean',
|
|
363
290
|
default: false,
|
|
364
|
-
description: 'Generate
|
|
291
|
+
description: 'Generate a coverage report'
|
|
365
292
|
},
|
|
366
|
-
workingDirectory:
|
|
367
|
-
type: 'string',
|
|
368
|
-
description: 'Working directory path (defaults to current directory)'
|
|
369
|
-
}
|
|
293
|
+
workingDirectory: workingDirectoryProperty
|
|
370
294
|
}
|
|
371
295
|
},
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
jestArgs.push('--coverage');
|
|
377
|
-
}
|
|
378
|
-
if (args.testFiles && args.testFiles.length > 0) {
|
|
379
|
-
jestArgs.push(...args.testFiles);
|
|
380
|
-
}
|
|
381
|
-
const result = await executeShellCommand('npx', ['jest', ...jestArgs], {
|
|
382
|
-
workingDirectory: args.workingDirectory || process.cwd(),
|
|
383
|
-
captureOutput: true
|
|
384
|
-
});
|
|
385
|
-
// Parse Jest output for test results
|
|
386
|
-
let testsRun = 0;
|
|
387
|
-
let testsPassed = 0;
|
|
388
|
-
let testsFailed = 0;
|
|
389
|
-
if (result.stdout) {
|
|
390
|
-
const runMatch = result.stdout.match(/Tests:\s+(\d+)\s+total/);
|
|
391
|
-
const passMatch = result.stdout.match(/Tests:\s+\d+\s+failed,\s+(\d+)\s+passed/);
|
|
392
|
-
const failMatch = result.stdout.match(/Tests:\s+(\d+)\s+failed/);
|
|
393
|
-
if (runMatch)
|
|
394
|
-
testsRun = parseInt(runMatch[1]);
|
|
395
|
-
if (passMatch)
|
|
396
|
-
testsPassed = parseInt(passMatch[1]);
|
|
397
|
-
if (failMatch)
|
|
398
|
-
testsFailed = parseInt(failMatch[1]);
|
|
399
|
-
// Alternative parsing for different Jest output formats
|
|
400
|
-
if (testsRun === 0) {
|
|
401
|
-
const totalMatch = result.stdout.match(/(\d+)\s+tests?\s+passed/);
|
|
402
|
-
if (totalMatch) {
|
|
403
|
-
testsRun = parseInt(totalMatch[1]);
|
|
404
|
-
testsPassed = testsRun;
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
const content = {
|
|
409
|
-
type: 'application/json',
|
|
410
|
-
data: {
|
|
411
|
-
success: result.exitCode === 0,
|
|
412
|
-
output: result.stdout || '',
|
|
413
|
-
testsRun,
|
|
414
|
-
testsPassed,
|
|
415
|
-
testsFailed,
|
|
416
|
-
error: result.exitCode !== 0 ? result.stderr : null
|
|
417
|
-
}
|
|
418
|
-
};
|
|
419
|
-
return { content };
|
|
296
|
+
run: async (input, context) => {
|
|
297
|
+
const jestArgs = ['jest', '--no-watchman', '--passWithNoTests'];
|
|
298
|
+
if (input.coverage) {
|
|
299
|
+
jestArgs.push('--coverage');
|
|
420
300
|
}
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
const content = {
|
|
424
|
-
type: 'application/json',
|
|
425
|
-
data: {
|
|
426
|
-
success: false,
|
|
427
|
-
output: '',
|
|
428
|
-
testsRun: 0,
|
|
429
|
-
testsPassed: 0,
|
|
430
|
-
testsFailed: 0,
|
|
431
|
-
error: error instanceof Error ? error.message : String(error)
|
|
432
|
-
}
|
|
433
|
-
};
|
|
434
|
-
return { content };
|
|
301
|
+
if (input.testFiles && input.testFiles.length > 0) {
|
|
302
|
+
jestArgs.push(...input.testFiles);
|
|
435
303
|
}
|
|
304
|
+
const result = await runNpx(jestArgs, input.workingDirectory, context);
|
|
305
|
+
// Jest writes its summary to stderr, not stdout.
|
|
306
|
+
const output = [result.stdout, result.stderr].filter(Boolean).join('\n');
|
|
307
|
+
// Summary line: "Tests: 1 failed, 2 skipped, 17 passed, 20 total"
|
|
308
|
+
const summary = output.match(/^Tests:\s+(.+)$/m)?.[1] ?? '';
|
|
309
|
+
const readCount = (label) => {
|
|
310
|
+
const match = summary.match(new RegExp(`(\\d+)\\s+${label}`));
|
|
311
|
+
return match ? parseInt(match[1], 10) : 0;
|
|
312
|
+
};
|
|
313
|
+
const testsRun = readCount('total');
|
|
314
|
+
const testsPassed = readCount('passed');
|
|
315
|
+
const testsFailed = readCount('failed');
|
|
316
|
+
return {
|
|
317
|
+
passed: result.exitCode === 0,
|
|
318
|
+
testsRun,
|
|
319
|
+
testsPassed,
|
|
320
|
+
testsFailed,
|
|
321
|
+
output
|
|
322
|
+
};
|
|
436
323
|
}
|
|
437
|
-
};
|
|
438
|
-
// Export all TypeScript tools
|
|
324
|
+
});
|
|
439
325
|
export const typescriptTools = [
|
|
440
326
|
typescriptCheckTool,
|
|
441
327
|
typescriptBuildTool,
|