@mxf-dev/core 1.0.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (298) hide show
  1. package/README.md +18 -0
  2. package/dist/adapters/FrameworkAdapter.js +1 -1
  3. package/dist/adapters/FrameworkAdapter.js.map +1 -1
  4. package/dist/config/ConfigManager.d.ts +9 -8
  5. package/dist/config/ConfigManager.d.ts.map +1 -1
  6. package/dist/config/ConfigManager.js +47 -17
  7. package/dist/config/ConfigManager.js.map +1 -1
  8. package/dist/config/memory-strata.config.d.ts +25 -0
  9. package/dist/config/memory-strata.config.d.ts.map +1 -0
  10. package/dist/config/memory-strata.config.js +107 -0
  11. package/dist/config/memory-strata.config.js.map +1 -0
  12. package/dist/constants/ToolNames.d.ts +1 -29
  13. package/dist/constants/ToolNames.d.ts.map +1 -1
  14. package/dist/constants/ToolNames.js +4 -17
  15. package/dist/constants/ToolNames.js.map +1 -1
  16. package/dist/database/DatabaseAdapterFactory.d.ts +14 -2
  17. package/dist/database/DatabaseAdapterFactory.d.ts.map +1 -1
  18. package/dist/database/DatabaseAdapterFactory.js +21 -6
  19. package/dist/database/DatabaseAdapterFactory.js.map +1 -1
  20. package/dist/database/adapters/mongodb/MongoBaseRepository.d.ts +7 -1
  21. package/dist/database/adapters/mongodb/MongoBaseRepository.d.ts.map +1 -1
  22. package/dist/database/adapters/mongodb/MongoBaseRepository.js +12 -2
  23. package/dist/database/adapters/mongodb/MongoBaseRepository.js.map +1 -1
  24. package/dist/events/ClientEventBus.d.ts +16 -77
  25. package/dist/events/ClientEventBus.d.ts.map +1 -1
  26. package/dist/events/ClientEventBus.js +38 -311
  27. package/dist/events/ClientEventBus.js.map +1 -1
  28. package/dist/events/EventBus.d.ts +1 -1
  29. package/dist/events/EventBus.d.ts.map +1 -1
  30. package/dist/events/EventBus.js +5 -4
  31. package/dist/events/EventBus.js.map +1 -1
  32. package/dist/events/EventBusBase.d.ts +139 -34
  33. package/dist/events/EventBusBase.d.ts.map +1 -1
  34. package/dist/events/EventBusBase.js +366 -88
  35. package/dist/events/EventBusBase.js.map +1 -1
  36. package/dist/events/EventNames.d.ts +10 -1
  37. package/dist/events/EventNames.d.ts.map +1 -1
  38. package/dist/events/EventNames.js +3 -0
  39. package/dist/events/EventNames.js.map +1 -1
  40. package/dist/events/PublicEvents.d.ts +6 -2
  41. package/dist/events/PublicEvents.d.ts.map +1 -1
  42. package/dist/events/PublicEvents.js +7 -4
  43. package/dist/events/PublicEvents.js.map +1 -1
  44. package/dist/events/ServerEventBus.d.ts +23 -112
  45. package/dist/events/ServerEventBus.d.ts.map +1 -1
  46. package/dist/events/ServerEventBus.js +58 -323
  47. package/dist/events/ServerEventBus.js.map +1 -1
  48. package/dist/events/event-definitions/LlmBudgetEvents.d.ts +68 -0
  49. package/dist/events/event-definitions/LlmBudgetEvents.d.ts.map +1 -0
  50. package/dist/events/event-definitions/LlmBudgetEvents.js +35 -0
  51. package/dist/events/event-definitions/LlmBudgetEvents.js.map +1 -0
  52. package/dist/interfaces/IMemoryPersistence.d.ts +41 -0
  53. package/dist/interfaces/IMemoryPersistence.d.ts.map +1 -0
  54. package/dist/interfaces/IMemoryPersistence.js +15 -0
  55. package/dist/interfaces/IMemoryPersistence.js.map +1 -0
  56. package/dist/middleware/MxpMiddleware.d.ts +8 -1
  57. package/dist/middleware/MxpMiddleware.d.ts.map +1 -1
  58. package/dist/middleware/MxpMiddleware.js +42 -20
  59. package/dist/middleware/MxpMiddleware.js.map +1 -1
  60. package/dist/models/channelKey.d.ts +1 -0
  61. package/dist/models/channelKey.d.ts.map +1 -1
  62. package/dist/models/channelKey.js +5 -0
  63. package/dist/models/channelKey.js.map +1 -1
  64. package/dist/models/memoryUtility.d.ts +39 -0
  65. package/dist/models/memoryUtility.d.ts.map +1 -0
  66. package/dist/models/memoryUtility.js +39 -0
  67. package/dist/models/memoryUtility.js.map +1 -0
  68. package/dist/models/user.d.ts.map +1 -1
  69. package/dist/models/user.js +23 -1
  70. package/dist/models/user.js.map +1 -1
  71. package/dist/mxp/BinaryProtocolLayer.d.ts +24 -8
  72. package/dist/mxp/BinaryProtocolLayer.d.ts.map +1 -1
  73. package/dist/mxp/BinaryProtocolLayer.js +90 -103
  74. package/dist/mxp/BinaryProtocolLayer.js.map +1 -1
  75. package/dist/mxp/ContextCompressionEngine.d.ts +57 -10
  76. package/dist/mxp/ContextCompressionEngine.d.ts.map +1 -1
  77. package/dist/mxp/ContextCompressionEngine.js +170 -128
  78. package/dist/mxp/ContextCompressionEngine.js.map +1 -1
  79. package/dist/mxp/MxpTokenOptimizer.d.ts +7 -3
  80. package/dist/mxp/MxpTokenOptimizer.d.ts.map +1 -1
  81. package/dist/mxp/MxpTokenOptimizer.js +8 -5
  82. package/dist/mxp/MxpTokenOptimizer.js.map +1 -1
  83. package/dist/prompts/MxfAgentSystemPrompt.d.ts +1 -1
  84. package/dist/prompts/MxfAgentSystemPrompt.d.ts.map +1 -1
  85. package/dist/prompts/MxfAgentSystemPrompt.js +47 -57
  86. package/dist/prompts/MxfAgentSystemPrompt.js.map +1 -1
  87. package/dist/protocols/mcp/ToolError.d.ts +123 -0
  88. package/dist/protocols/mcp/ToolError.d.ts.map +1 -0
  89. package/dist/protocols/mcp/ToolError.js +108 -0
  90. package/dist/protocols/mcp/ToolError.js.map +1 -0
  91. package/dist/protocols/mcp/defineTool.d.ts +133 -0
  92. package/dist/protocols/mcp/defineTool.d.ts.map +1 -0
  93. package/dist/protocols/mcp/defineTool.js +236 -0
  94. package/dist/protocols/mcp/defineTool.js.map +1 -0
  95. package/dist/protocols/mcp/security/HttpTargetGuard.d.ts +38 -0
  96. package/dist/protocols/mcp/security/HttpTargetGuard.d.ts.map +1 -0
  97. package/dist/protocols/mcp/security/HttpTargetGuard.js +227 -0
  98. package/dist/protocols/mcp/security/HttpTargetGuard.js.map +1 -0
  99. package/dist/protocols/mcp/security/McpSecurityGuard.d.ts +9 -1
  100. package/dist/protocols/mcp/security/McpSecurityGuard.d.ts.map +1 -1
  101. package/dist/protocols/mcp/security/McpSecurityGuard.js +10 -2
  102. package/dist/protocols/mcp/security/McpSecurityGuard.js.map +1 -1
  103. package/dist/protocols/mcp/security/McpToolPolicy.d.ts +81 -0
  104. package/dist/protocols/mcp/security/McpToolPolicy.d.ts.map +1 -0
  105. package/dist/protocols/mcp/security/McpToolPolicy.js +202 -0
  106. package/dist/protocols/mcp/security/McpToolPolicy.js.map +1 -0
  107. package/dist/protocols/mcp/services/ExternalMcpServerManager.d.ts +51 -18
  108. package/dist/protocols/mcp/services/ExternalMcpServerManager.d.ts.map +1 -1
  109. package/dist/protocols/mcp/services/ExternalMcpServerManager.js +256 -283
  110. package/dist/protocols/mcp/services/ExternalMcpServerManager.js.map +1 -1
  111. package/dist/protocols/mcp/services/ExternalServerConfigs.d.ts +39 -6
  112. package/dist/protocols/mcp/services/ExternalServerConfigs.d.ts.map +1 -1
  113. package/dist/protocols/mcp/services/ExternalServerConfigs.js +76 -18
  114. package/dist/protocols/mcp/services/ExternalServerConfigs.js.map +1 -1
  115. package/dist/protocols/mcp/tools/AnalyticsTools.js +1 -1
  116. package/dist/protocols/mcp/tools/AnalyticsTools.js.map +1 -1
  117. package/dist/protocols/mcp/tools/CodeAnalysisTools.d.ts.map +1 -1
  118. package/dist/protocols/mcp/tools/CodeAnalysisTools.js +15 -0
  119. package/dist/protocols/mcp/tools/CodeAnalysisTools.js.map +1 -1
  120. package/dist/protocols/mcp/tools/EffectivenessTools.js +3 -3
  121. package/dist/protocols/mcp/tools/EffectivenessTools.js.map +1 -1
  122. package/dist/protocols/mcp/tools/GitTools.d.ts +9 -369
  123. package/dist/protocols/mcp/tools/GitTools.d.ts.map +1 -1
  124. package/dist/protocols/mcp/tools/GitTools.js +222 -517
  125. package/dist/protocols/mcp/tools/GitTools.js.map +1 -1
  126. package/dist/protocols/mcp/tools/InfrastructureTools.d.ts +56 -24
  127. package/dist/protocols/mcp/tools/InfrastructureTools.d.ts.map +1 -1
  128. package/dist/protocols/mcp/tools/InfrastructureTools.js +117 -26
  129. package/dist/protocols/mcp/tools/InfrastructureTools.js.map +1 -1
  130. package/dist/protocols/mcp/tools/MemorySearchTools.d.ts +0 -3
  131. package/dist/protocols/mcp/tools/MemorySearchTools.d.ts.map +1 -1
  132. package/dist/protocols/mcp/tools/MemorySearchTools.js +58 -1
  133. package/dist/protocols/mcp/tools/MemorySearchTools.js.map +1 -1
  134. package/dist/protocols/mcp/tools/OrparTools.d.ts +8 -0
  135. package/dist/protocols/mcp/tools/OrparTools.d.ts.map +1 -1
  136. package/dist/protocols/mcp/tools/OrparTools.js +66 -0
  137. package/dist/protocols/mcp/tools/OrparTools.js.map +1 -1
  138. package/dist/protocols/mcp/tools/SafetyTools.d.ts +7 -525
  139. package/dist/protocols/mcp/tools/SafetyTools.d.ts.map +1 -1
  140. package/dist/protocols/mcp/tools/SafetyTools.js +349 -514
  141. package/dist/protocols/mcp/tools/SafetyTools.js.map +1 -1
  142. package/dist/protocols/mcp/tools/TaskPlanningTools.d.ts.map +1 -1
  143. package/dist/protocols/mcp/tools/TaskPlanningTools.js +56 -26
  144. package/dist/protocols/mcp/tools/TaskPlanningTools.js.map +1 -1
  145. package/dist/protocols/mcp/tools/TestTools.d.ts +15 -376
  146. package/dist/protocols/mcp/tools/TestTools.d.ts.map +1 -1
  147. package/dist/protocols/mcp/tools/TestTools.js +241 -363
  148. package/dist/protocols/mcp/tools/TestTools.js.map +1 -1
  149. package/dist/protocols/mcp/tools/TypeScriptTools.d.ts +6 -276
  150. package/dist/protocols/mcp/tools/TypeScriptTools.d.ts.map +1 -1
  151. package/dist/protocols/mcp/tools/TypeScriptTools.js +223 -337
  152. package/dist/protocols/mcp/tools/TypeScriptTools.js.map +1 -1
  153. package/dist/protocols/mcp/tools/WebTools.d.ts +15 -728
  154. package/dist/protocols/mcp/tools/WebTools.d.ts.map +1 -1
  155. package/dist/protocols/mcp/tools/WebTools.js +151 -257
  156. package/dist/protocols/mcp/tools/WebTools.js.map +1 -1
  157. package/dist/protocols/mcp/tools/shell/ShellExecuteHandler.d.ts +5 -3
  158. package/dist/protocols/mcp/tools/shell/ShellExecuteHandler.d.ts.map +1 -1
  159. package/dist/protocols/mcp/tools/shell/ShellExecuteHandler.js +31 -6
  160. package/dist/protocols/mcp/tools/shell/ShellExecuteHandler.js.map +1 -1
  161. package/dist/schemas/EventPayloadSchema.d.ts +21 -0
  162. package/dist/schemas/EventPayloadSchema.d.ts.map +1 -1
  163. package/dist/schemas/EventPayloadSchema.js +14 -0
  164. package/dist/schemas/EventPayloadSchema.js.map +1 -1
  165. package/dist/services/BackgroundTaskManager.d.ts.map +1 -1
  166. package/dist/services/BackgroundTaskManager.js +12 -4
  167. package/dist/services/BackgroundTaskManager.js.map +1 -1
  168. package/dist/services/BrowserManager.d.ts +1 -1
  169. package/dist/services/BrowserManager.d.ts.map +1 -1
  170. package/dist/services/BrowserManager.js +26 -3
  171. package/dist/services/BrowserManager.js.map +1 -1
  172. package/dist/services/MemoryCompressor.d.ts +11 -2
  173. package/dist/services/MemoryCompressor.d.ts.map +1 -1
  174. package/dist/services/MemoryCompressor.js +8 -26
  175. package/dist/services/MemoryCompressor.js.map +1 -1
  176. package/dist/services/MemoryService.d.ts +16 -3
  177. package/dist/services/MemoryService.d.ts.map +1 -1
  178. package/dist/services/MemoryService.js +79 -55
  179. package/dist/services/MemoryService.js.map +1 -1
  180. package/dist/services/PredictiveAnalyticsService.d.ts +34 -4
  181. package/dist/services/PredictiveAnalyticsService.d.ts.map +1 -1
  182. package/dist/services/PredictiveAnalyticsService.js +41 -25
  183. package/dist/services/PredictiveAnalyticsService.js.map +1 -1
  184. package/dist/services/QValueManager.d.ts +7 -0
  185. package/dist/services/QValueManager.d.ts.map +1 -1
  186. package/dist/services/QValueManager.js +9 -0
  187. package/dist/services/QValueManager.js.map +1 -1
  188. package/dist/services/RewardSignalProcessor.d.ts +38 -1
  189. package/dist/services/RewardSignalProcessor.d.ts.map +1 -1
  190. package/dist/services/RewardSignalProcessor.js +109 -7
  191. package/dist/services/RewardSignalProcessor.js.map +1 -1
  192. package/dist/services/SharedStateService.d.ts +16 -2
  193. package/dist/services/SharedStateService.d.ts.map +1 -1
  194. package/dist/services/SharedStateService.js +44 -3
  195. package/dist/services/SharedStateService.js.map +1 -1
  196. package/dist/services/TaskEffectivenessService.d.ts +34 -18
  197. package/dist/services/TaskEffectivenessService.d.ts.map +1 -1
  198. package/dist/services/TaskEffectivenessService.js +91 -155
  199. package/dist/services/TaskEffectivenessService.js.map +1 -1
  200. package/dist/services/WebSearchService.d.ts.map +1 -1
  201. package/dist/services/WebSearchService.js.map +1 -1
  202. package/dist/services/dag/TaskDagService.d.ts.map +1 -1
  203. package/dist/services/dag/TaskDagService.js +2 -0
  204. package/dist/services/dag/TaskDagService.js.map +1 -1
  205. package/dist/services/orpar-memory/OrparMemoryCoordinator.d.ts +7 -0
  206. package/dist/services/orpar-memory/OrparMemoryCoordinator.d.ts.map +1 -1
  207. package/dist/services/orpar-memory/OrparMemoryCoordinator.js +71 -10
  208. package/dist/services/orpar-memory/OrparMemoryCoordinator.js.map +1 -1
  209. package/dist/types/MemoryUtilityTypes.d.ts +2 -0
  210. package/dist/types/MemoryUtilityTypes.d.ts.map +1 -1
  211. package/dist/types/MemoryUtilityTypes.js.map +1 -1
  212. package/dist/utils/Logger.d.ts +43 -3
  213. package/dist/utils/Logger.d.ts.map +1 -1
  214. package/dist/utils/Logger.js +78 -36
  215. package/dist/utils/Logger.js.map +1 -1
  216. package/dist/utils/MxpEncryption.d.ts +19 -6
  217. package/dist/utils/MxpEncryption.d.ts.map +1 -1
  218. package/dist/utils/MxpEncryption.js +48 -16
  219. package/dist/utils/MxpEncryption.js.map +1 -1
  220. package/package.json +19 -4
  221. package/src/adapters/FrameworkAdapter.ts +1 -1
  222. package/src/config/ConfigManager.ts +52 -19
  223. package/src/config/memory-strata.config.ts +136 -0
  224. package/src/constants/ToolNames.ts +4 -18
  225. package/src/database/DatabaseAdapterFactory.ts +23 -6
  226. package/src/database/adapters/mongodb/MongoBaseRepository.ts +16 -2
  227. package/src/events/ClientEventBus.ts +68 -403
  228. package/src/events/EventBus.ts +7 -8
  229. package/src/events/EventBusBase.ts +479 -116
  230. package/src/events/EventNames.ts +6 -0
  231. package/src/events/PublicEvents.ts +7 -4
  232. package/src/events/ServerEventBus.ts +78 -473
  233. package/src/events/event-definitions/LlmBudgetEvents.ts +74 -0
  234. package/src/interfaces/IMemoryPersistence.ts +51 -0
  235. package/src/middleware/MxpMiddleware.ts +51 -24
  236. package/src/models/channelKey.ts +18 -4
  237. package/src/models/memoryUtility.ts +64 -0
  238. package/src/models/user.ts +36 -4
  239. package/src/mxp/BinaryProtocolLayer.ts +108 -124
  240. package/src/mxp/ContextCompressionEngine.ts +219 -161
  241. package/src/mxp/MxpTokenOptimizer.ts +10 -10
  242. package/src/prompts/MxfAgentSystemPrompt.ts +45 -55
  243. package/src/protocols/mcp/ToolError.ts +201 -0
  244. package/src/protocols/mcp/defineTool.ts +379 -0
  245. package/src/protocols/mcp/security/HttpTargetGuard.ts +267 -0
  246. package/src/protocols/mcp/security/McpSecurityGuard.ts +10 -3
  247. package/src/protocols/mcp/security/McpToolPolicy.ts +221 -0
  248. package/src/protocols/mcp/services/ExternalMcpServerManager.ts +340 -322
  249. package/src/protocols/mcp/services/ExternalServerConfigs.ts +82 -19
  250. package/src/protocols/mcp/tools/AnalyticsTools.ts +1 -1
  251. package/src/protocols/mcp/tools/CodeAnalysisTools.ts +15 -0
  252. package/src/protocols/mcp/tools/EffectivenessTools.ts +3 -3
  253. package/src/protocols/mcp/tools/GitTools.ts +290 -569
  254. package/src/protocols/mcp/tools/InfrastructureTools.ts +189 -43
  255. package/src/protocols/mcp/tools/MemorySearchTools.ts +77 -1
  256. package/src/protocols/mcp/tools/OrparTools.ts +87 -0
  257. package/src/protocols/mcp/tools/SafetyTools.ts +501 -579
  258. package/src/protocols/mcp/tools/TaskPlanningTools.ts +81 -39
  259. package/src/protocols/mcp/tools/TestTools.ts +339 -419
  260. package/src/protocols/mcp/tools/TypeScriptTools.ts +316 -376
  261. package/src/protocols/mcp/tools/WebTools.ts +209 -307
  262. package/src/protocols/mcp/tools/shell/ShellExecuteHandler.ts +53 -14
  263. package/src/schemas/EventPayloadSchema.ts +37 -0
  264. package/src/services/BackgroundTaskManager.ts +12 -4
  265. package/src/services/BrowserManager.ts +41 -1
  266. package/src/services/MemoryCompressor.ts +20 -32
  267. package/src/services/MemoryService.ts +96 -58
  268. package/src/services/PredictiveAnalyticsService.ts +55 -32
  269. package/src/services/QValueManager.ts +10 -0
  270. package/src/services/RewardSignalProcessor.ts +138 -9
  271. package/src/services/SharedStateService.ts +56 -8
  272. package/src/services/TaskEffectivenessService.ts +114 -187
  273. package/src/services/WebSearchService.ts +2 -1
  274. package/src/services/dag/TaskDagService.ts +2 -0
  275. package/src/services/orpar-memory/OrparMemoryCoordinator.ts +86 -10
  276. package/src/types/MemoryUtilityTypes.ts +2 -0
  277. package/src/utils/Logger.ts +116 -40
  278. package/src/utils/MxpEncryption.ts +69 -34
  279. package/dist/mxp/MxpEventForwardingEnhancer.d.ts +0 -134
  280. package/dist/mxp/MxpEventForwardingEnhancer.d.ts.map +0 -1
  281. package/dist/mxp/MxpEventForwardingEnhancer.js +0 -361
  282. package/dist/mxp/MxpEventForwardingEnhancer.js.map +0 -1
  283. package/dist/protocols/mcp/services/ToolSchemaEnhancements.d.ts +0 -56
  284. package/dist/protocols/mcp/services/ToolSchemaEnhancements.d.ts.map +0 -1
  285. package/dist/protocols/mcp/services/ToolSchemaEnhancements.js +0 -57
  286. package/dist/protocols/mcp/services/ToolSchemaEnhancements.js.map +0 -1
  287. package/dist/protocols/mcp/tools/ControlLoopLifecycle.d.ts +0 -270
  288. package/dist/protocols/mcp/tools/ControlLoopLifecycle.d.ts.map +0 -1
  289. package/dist/protocols/mcp/tools/ControlLoopLifecycle.js +0 -256
  290. package/dist/protocols/mcp/tools/ControlLoopLifecycle.js.map +0 -1
  291. package/dist/protocols/mcp/tools/LspTools.d.ts +0 -495
  292. package/dist/protocols/mcp/tools/LspTools.d.ts.map +0 -1
  293. package/dist/protocols/mcp/tools/LspTools.js +0 -469
  294. package/dist/protocols/mcp/tools/LspTools.js.map +0 -1
  295. package/src/mxp/MxpEventForwardingEnhancer.ts +0 -471
  296. package/src/protocols/mcp/services/ToolSchemaEnhancements.ts +0 -92
  297. package/src/protocols/mcp/tools/ControlLoopLifecycle.ts +0 -302
  298. 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
- import { Logger } from '../../../utils/Logger.js';
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
- const logger = new Logger('info', 'TypeScriptTools', 'server');
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
- * TypeScript Language Server Tools for MXF
46
+ * Run one of the node toolchain binaries via npx.
25
47
  *
26
- * Provides TypeScript analysis, diagnostics, and code intelligence
27
- * These tools are placeholders that demonstrate the interface
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
- export const typescriptCheckTool = {
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
- description: 'Type-check TypeScript files and report diagnostics',
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 (optional, checks all if not provided)'
100
+ description: 'Specific files to check. Checks the whole project when omitted.'
44
101
  }
45
102
  }
46
103
  },
47
- handler: async (args, context) => {
48
- try {
49
- const tscArgs = ['--noEmit', '--pretty', 'false'];
50
- if (args.files && args.files.length > 0) {
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
- catch (error) {
102
- logger.error('TypeScript check failed', { error });
103
- const content = {
104
- type: 'application/json',
105
- data: {
106
- success: false,
107
- diagnostics: [],
108
- totalErrors: 0,
109
- totalWarnings: 0,
110
- filesChecked: 0,
111
- error: error instanceof Error ? error.message : String(error)
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
- description: 'Build TypeScript project and emit JavaScript files',
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: 'Clean output directory before build'
140
+ description: 'Run `tsc --build --clean` first'
132
141
  }
133
142
  }
134
143
  },
135
- handler: async (args, context) => {
136
- try {
137
- const startTime = Date.now();
138
- // Clean output directory if requested
139
- if (args.clean) {
140
- const cleanResult = await executeShellCommand('npx', ['tsc', '--build', '--clean'], {
141
- workingDirectory: args.workingDirectory || process.cwd(),
142
- captureOutput: true
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
- description: 'Format TypeScript files using prettier or similar formatter',
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 (supports glob patterns)'
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: 'Check if files are formatted without modifying them'
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
- handler: async (args, context) => {
219
- try {
220
- const prettierArgs = args.check ? ['--check'] : ['--write'];
221
- if (args.files && args.files.length > 0) {
222
- prettierArgs.push(...args.files);
223
- }
224
- else {
225
- prettierArgs.push('**/*.{ts,tsx,js,jsx}');
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
- catch (error) {
256
- logger.error('TypeScript format failed', { error });
257
- const content = {
258
- type: 'application/json',
259
- data: {
260
- success: false,
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
- description: 'Lint TypeScript files using ESLint',
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 (supports glob patterns)'
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
- handler: async (args, context) => {
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
- const eslintArgs = ['--format', 'json'];
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 (error) {
337
- logger.error('TypeScript lint failed', { error });
338
- const content = {
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
- description: 'Run TypeScript tests using Jest or other test runners',
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 test coverage report'
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
- handler: async (args, context) => {
373
- try {
374
- const jestArgs = ['--no-watchman', '--passWithNoTests'];
375
- if (args.coverage) {
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
- catch (error) {
422
- logger.error('TypeScript test failed', { error });
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,