@noorm/marie-cli 0.1.17 → 0.1.25

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 (299) hide show
  1. package/README.md +7 -15
  2. package/SENTINEL.md +4 -7
  3. package/dist/cli-new/components/AgenticSpinner.js +28 -0
  4. package/dist/cli-new/components/AgenticSpinner.js.map +1 -0
  5. package/dist/cli-new/components/App.js +16 -63
  6. package/dist/cli-new/components/App.js.map +1 -1
  7. package/dist/cli-new/components/ApprovalDialog.js +3 -2
  8. package/dist/cli-new/components/ApprovalDialog.js.map +1 -1
  9. package/dist/cli-new/components/Banner.js +16 -5
  10. package/dist/cli-new/components/Banner.js.map +1 -1
  11. package/dist/cli-new/components/ChatArea.js +6 -7
  12. package/dist/cli-new/components/ChatArea.js.map +1 -1
  13. package/dist/cli-new/components/Header.js +14 -8
  14. package/dist/cli-new/components/Header.js.map +1 -1
  15. package/dist/cli-new/components/InputArea.js +98 -31
  16. package/dist/cli-new/components/InputArea.js.map +1 -1
  17. package/dist/cli-new/components/MessageBubble.js +28 -19
  18. package/dist/cli-new/components/MessageBubble.js.map +1 -1
  19. package/dist/cli-new/components/SessionSwitcher.js +6 -9
  20. package/dist/cli-new/components/SessionSwitcher.js.map +1 -1
  21. package/dist/cli-new/components/SetupWizard.js +80 -257
  22. package/dist/cli-new/components/SetupWizard.js.map +1 -1
  23. package/dist/cli-new/components/ToolCallDisplay.js +20 -5
  24. package/dist/cli-new/components/ToolCallDisplay.js.map +1 -1
  25. package/dist/cli-new/components/WizardSteps.js +22 -0
  26. package/dist/cli-new/components/WizardSteps.js.map +1 -0
  27. package/dist/cli-new/constants/SetupConstants.js +42 -0
  28. package/dist/cli-new/constants/SetupConstants.js.map +1 -0
  29. package/dist/cli-new/hooks/useGit.js +19 -62
  30. package/dist/cli-new/hooks/useGit.js.map +1 -1
  31. package/dist/cli-new/hooks/useMarie.js +26 -18
  32. package/dist/cli-new/hooks/useMarie.js.map +1 -1
  33. package/dist/cli-new/hooks/useSessions.js +1 -1
  34. package/dist/cli-new/hooks/useSessions.js.map +1 -1
  35. package/dist/cli-new/hooks/useSetupWizard.js +88 -0
  36. package/dist/cli-new/hooks/useSetupWizard.js.map +1 -0
  37. package/dist/cli-new/hooks/useUpdateCheck.js +4 -3
  38. package/dist/cli-new/hooks/useUpdateCheck.js.map +1 -1
  39. package/dist/cli-new/index.js +2 -4
  40. package/dist/cli-new/index.js.map +1 -1
  41. package/dist/cli-new/services/CommandService.js +104 -0
  42. package/dist/cli-new/services/CommandService.js.map +1 -0
  43. package/dist/cli-new/services/GitService.js +91 -0
  44. package/dist/cli-new/services/GitService.js.map +1 -0
  45. package/dist/cli-new/services/MarieService.js +77 -0
  46. package/dist/cli-new/services/MarieService.js.map +1 -0
  47. package/dist/cli-new/services/auth-server.js +128 -0
  48. package/dist/cli-new/services/auth-server.js.map +1 -0
  49. package/dist/cli-new/styles/theme.js +17 -17
  50. package/dist/cli-new/styles/theme.js.map +1 -1
  51. package/dist/cli-new/utils/version.js +24 -0
  52. package/dist/cli-new/utils/version.js.map +1 -0
  53. package/dist/monolith/adapters/CliMarieAdapter.js +19 -18
  54. package/dist/monolith/adapters/CliMarieAdapter.js.map +1 -1
  55. package/dist/monolith/cli/CliFileSystemPort.js +17 -3
  56. package/dist/monolith/cli/CliFileSystemPort.js.map +1 -1
  57. package/dist/monolith/cli/MarieToolDefinitionsCLI.js +44 -33
  58. package/dist/monolith/cli/MarieToolDefinitionsCLI.js.map +1 -1
  59. package/dist/monolith/cli/index.js +11 -20
  60. package/dist/monolith/cli/index.js.map +1 -1
  61. package/dist/monolith/cli/services/JoyAutomationServiceCLI.js +15 -62
  62. package/dist/monolith/cli/services/JoyAutomationServiceCLI.js.map +1 -1
  63. package/dist/monolith/cli/storage.js +154 -65
  64. package/dist/monolith/cli/storage.js.map +1 -1
  65. package/dist/monolith/domain/joy/RitualService.js +44 -46
  66. package/dist/monolith/domain/joy/RitualService.js.map +1 -1
  67. package/dist/monolith/domain/marie/MarieCortex.js +148 -0
  68. package/dist/monolith/domain/marie/MarieCortex.js.map +1 -0
  69. package/dist/monolith/domain/marie/PersonalityRenderer.js +97 -0
  70. package/dist/monolith/domain/marie/PersonalityRenderer.js.map +1 -0
  71. package/dist/monolith/infrastructure/Configuration.js +68 -0
  72. package/dist/monolith/infrastructure/Configuration.js.map +1 -0
  73. package/dist/monolith/infrastructure/CoreInfrastructure.js +204 -0
  74. package/dist/monolith/infrastructure/CoreInfrastructure.js.map +1 -0
  75. package/dist/monolith/infrastructure/ai/agents/MarieAscendant.js +3 -3
  76. package/dist/monolith/infrastructure/ai/agents/MarieAscendant.js.map +1 -1
  77. package/dist/monolith/infrastructure/ai/context/ContextArchiveService.js +51 -57
  78. package/dist/monolith/infrastructure/ai/context/ContextArchiveService.js.map +1 -1
  79. package/dist/monolith/infrastructure/ai/context/ContextManager.js +142 -98
  80. package/dist/monolith/infrastructure/ai/context/ContextManager.js.map +1 -1
  81. package/dist/monolith/infrastructure/ai/core/MarieEngine.js +104 -556
  82. package/dist/monolith/infrastructure/ai/core/MarieEngine.js.map +1 -1
  83. package/dist/monolith/infrastructure/ai/core/MarieEventDispatcher.js +1 -37
  84. package/dist/monolith/infrastructure/ai/core/MarieEventDispatcher.js.map +1 -1
  85. package/dist/monolith/infrastructure/ai/core/MarieLockManager.js +30 -5
  86. package/dist/monolith/infrastructure/ai/core/MarieLockManager.js.map +1 -1
  87. package/dist/monolith/infrastructure/ai/core/MarieProgressTracker.js +176 -196
  88. package/dist/monolith/infrastructure/ai/core/MarieProgressTracker.js.map +1 -1
  89. package/dist/monolith/infrastructure/ai/core/MariePulseService.js +41 -7
  90. package/dist/monolith/infrastructure/ai/core/MariePulseService.js.map +1 -1
  91. package/dist/monolith/infrastructure/ai/core/MarieSanitizer.js +303 -63
  92. package/dist/monolith/infrastructure/ai/core/MarieSanitizer.js.map +1 -1
  93. package/dist/monolith/infrastructure/ai/core/MarieSemaphore.js +47 -4
  94. package/dist/monolith/infrastructure/ai/core/MarieSemaphore.js.map +1 -1
  95. package/dist/monolith/infrastructure/ai/core/MarieSession.js +95 -15
  96. package/dist/monolith/infrastructure/ai/core/MarieSession.js.map +1 -1
  97. package/dist/monolith/infrastructure/ai/core/MarieStabilityMonitor.js +21 -0
  98. package/dist/monolith/infrastructure/ai/core/MarieStabilityMonitor.js.map +1 -1
  99. package/dist/monolith/infrastructure/ai/core/MarieToolMender.js +12 -0
  100. package/dist/monolith/infrastructure/ai/core/MarieToolMender.js.map +1 -1
  101. package/dist/monolith/infrastructure/ai/core/MarieToolProcessor.js +339 -481
  102. package/dist/monolith/infrastructure/ai/core/MarieToolProcessor.js.map +1 -1
  103. package/dist/monolith/infrastructure/ai/core/MarieVitality.js +238 -0
  104. package/dist/monolith/infrastructure/ai/core/MarieVitality.js.map +1 -0
  105. package/dist/monolith/infrastructure/ai/core/ReasoningBudget.js +23 -12
  106. package/dist/monolith/infrastructure/ai/core/ReasoningBudget.js.map +1 -1
  107. package/dist/monolith/infrastructure/ai/core/SessionLogService.js +9 -2
  108. package/dist/monolith/infrastructure/ai/core/SessionLogService.js.map +1 -1
  109. package/dist/monolith/infrastructure/ai/providers/AIProvider.js +402 -1
  110. package/dist/monolith/infrastructure/ai/providers/AIProvider.js.map +1 -1
  111. package/dist/monolith/infrastructure/ai/providers/DreamBeesProvider.js +114 -0
  112. package/dist/monolith/infrastructure/ai/providers/DreamBeesProvider.js.map +1 -0
  113. package/dist/monolith/infrastructure/ai/providers/OpenRouterProvider.js +426 -370
  114. package/dist/monolith/infrastructure/ai/providers/OpenRouterProvider.js.map +1 -1
  115. package/dist/monolith/infrastructure/ai/providers/OpenRouterStreamParser.js +235 -241
  116. package/dist/monolith/infrastructure/ai/providers/OpenRouterStreamParser.js.map +1 -1
  117. package/dist/monolith/infrastructure/ai/workerAi.js +185 -0
  118. package/dist/monolith/infrastructure/ai/workerAi.js.map +1 -0
  119. package/dist/monolith/infrastructure/config/ConfigService.js +216 -359
  120. package/dist/monolith/infrastructure/config/ConfigService.js.map +1 -1
  121. package/dist/monolith/infrastructure/joy/CognitiveRituals.js +8 -0
  122. package/dist/monolith/infrastructure/joy/CognitiveRituals.js.map +1 -0
  123. package/dist/monolith/infrastructure/joy/JoyTools.js +23 -43
  124. package/dist/monolith/infrastructure/joy/JoyTools.js.map +1 -1
  125. package/dist/monolith/infrastructure/persistence/MarieMindAutonomics.js +4 -0
  126. package/dist/monolith/infrastructure/persistence/MarieMindAutonomics.js.map +1 -0
  127. package/dist/monolith/infrastructure/persistence/MarieMindEngine.js +11 -0
  128. package/dist/monolith/infrastructure/persistence/MarieMindEngine.js.map +1 -0
  129. package/dist/monolith/infrastructure/persistence/NoormmeAutonomics.js +135 -0
  130. package/dist/monolith/infrastructure/persistence/NoormmeAutonomics.js.map +1 -0
  131. package/dist/monolith/infrastructure/persistence/NoormmeEngine.js +523 -0
  132. package/dist/monolith/infrastructure/persistence/NoormmeEngine.js.map +1 -0
  133. package/dist/monolith/infrastructure/persistence/NoormmeSchema.js +179 -0
  134. package/dist/monolith/infrastructure/persistence/NoormmeSchema.js.map +1 -0
  135. package/dist/monolith/infrastructure/persistence/NoormmeSeeder.js +94 -0
  136. package/dist/monolith/infrastructure/persistence/NoormmeSeeder.js.map +1 -0
  137. package/dist/monolith/infrastructure/persistence/NoormmeTools.js +371 -0
  138. package/dist/monolith/infrastructure/persistence/NoormmeTools.js.map +1 -0
  139. package/dist/monolith/infrastructure/services/MarieMemoryStore.js +133 -134
  140. package/dist/monolith/infrastructure/services/MarieMemoryStore.js.map +1 -1
  141. package/dist/monolith/infrastructure/tools/MarieToolDefinitions.js +6 -1578
  142. package/dist/monolith/infrastructure/tools/MarieToolDefinitions.js.map +1 -1
  143. package/dist/monolith/infrastructure/tools/PureStreamParser.js +68 -80
  144. package/dist/monolith/infrastructure/tools/PureStreamParser.js.map +1 -1
  145. package/dist/monolith/infrastructure/tools/SharedToolDefinitions.js +12 -11
  146. package/dist/monolith/infrastructure/tools/SharedToolDefinitions.js.map +1 -1
  147. package/dist/monolith/infrastructure/tools/SovereignTools.js +326 -0
  148. package/dist/monolith/infrastructure/tools/SovereignTools.js.map +1 -0
  149. package/dist/monolith/infrastructure/tools/ToolRegistry.js +45 -26
  150. package/dist/monolith/infrastructure/tools/ToolRegistry.js.map +1 -1
  151. package/dist/monolith/infrastructure/tools/definitions/AnalysisTools.js +232 -0
  152. package/dist/monolith/infrastructure/tools/definitions/AnalysisTools.js.map +1 -0
  153. package/dist/monolith/infrastructure/tools/definitions/AutomationTools.js +274 -0
  154. package/dist/monolith/infrastructure/tools/definitions/AutomationTools.js.map +1 -0
  155. package/dist/monolith/infrastructure/tools/definitions/ContextTools.js +71 -0
  156. package/dist/monolith/infrastructure/tools/definitions/ContextTools.js.map +1 -0
  157. package/dist/monolith/infrastructure/tools/definitions/CoreTools.js +37 -0
  158. package/dist/monolith/infrastructure/tools/definitions/CoreTools.js.map +1 -0
  159. package/dist/monolith/infrastructure/tools/definitions/DiagnosticTools.js +154 -0
  160. package/dist/monolith/infrastructure/tools/definitions/DiagnosticTools.js.map +1 -0
  161. package/dist/monolith/infrastructure/tools/definitions/NavigationTools.js +197 -0
  162. package/dist/monolith/infrastructure/tools/definitions/NavigationTools.js.map +1 -0
  163. package/dist/monolith/infrastructure/tools/definitions/PlanningTools.js +300 -0
  164. package/dist/monolith/infrastructure/tools/definitions/PlanningTools.js.map +1 -0
  165. package/dist/monolith/plumbing/Plumbing.js +238 -0
  166. package/dist/monolith/plumbing/Plumbing.js.map +1 -0
  167. package/dist/monolith/plumbing/PlumbingAnalysis.js +109 -0
  168. package/dist/monolith/plumbing/PlumbingAnalysis.js.map +1 -0
  169. package/dist/monolith/plumbing/PlumbingSystem.js +169 -0
  170. package/dist/monolith/plumbing/PlumbingSystem.js.map +1 -0
  171. package/dist/monolith/plumbing/analysis/ComplexityService.js +30 -34
  172. package/dist/monolith/plumbing/analysis/ComplexityService.js.map +1 -1
  173. package/dist/monolith/plumbing/analysis/DependencyService.js +55 -44
  174. package/dist/monolith/plumbing/analysis/DependencyService.js.map +1 -1
  175. package/dist/monolith/plumbing/analysis/DiscoveryService.js +40 -42
  176. package/dist/monolith/plumbing/analysis/DiscoveryService.js.map +1 -1
  177. package/dist/monolith/plumbing/analysis/JoyMapService.js +52 -56
  178. package/dist/monolith/plumbing/analysis/JoyMapService.js.map +1 -1
  179. package/dist/monolith/plumbing/analysis/LintService.js +118 -118
  180. package/dist/monolith/plumbing/analysis/LintService.js.map +1 -1
  181. package/dist/monolith/plumbing/analysis/MarieSentinelService.js +278 -269
  182. package/dist/monolith/plumbing/analysis/MarieSentinelService.js.map +1 -1
  183. package/dist/monolith/plumbing/analysis/QualityGuardrailService.js +116 -114
  184. package/dist/monolith/plumbing/analysis/QualityGuardrailService.js.map +1 -1
  185. package/dist/monolith/plumbing/analysis/SurgicalMender.js +57 -59
  186. package/dist/monolith/plumbing/analysis/SurgicalMender.js.map +1 -1
  187. package/dist/monolith/plumbing/analysis/TestService.js +89 -89
  188. package/dist/monolith/plumbing/analysis/TestService.js.map +1 -1
  189. package/dist/monolith/plumbing/filesystem/FileService.js +123 -195
  190. package/dist/monolith/plumbing/filesystem/FileService.js.map +1 -1
  191. package/dist/monolith/plumbing/filesystem/PathResolver.js +7 -8
  192. package/dist/monolith/plumbing/filesystem/PathResolver.js.map +1 -1
  193. package/dist/monolith/plumbing/git/GitService.js +4 -4
  194. package/dist/monolith/plumbing/git/GitService.js.map +1 -1
  195. package/dist/monolith/plumbing/lsp/SymbolService.js +5 -34
  196. package/dist/monolith/plumbing/lsp/SymbolService.js.map +1 -1
  197. package/dist/monolith/plumbing/terminal/ProcessRegistry.js +20 -22
  198. package/dist/monolith/plumbing/terminal/ProcessRegistry.js.map +1 -1
  199. package/dist/monolith/plumbing/terminal/TerminalService.js +127 -136
  200. package/dist/monolith/plumbing/terminal/TerminalService.js.map +1 -1
  201. package/dist/monolith/plumbing/utils/EnvironmentUtils.js +3 -23
  202. package/dist/monolith/plumbing/utils/EnvironmentUtils.js.map +1 -1
  203. package/dist/monolith/plumbing/utils/JsonUtils.js +252 -311
  204. package/dist/monolith/plumbing/utils/JsonUtils.js.map +1 -1
  205. package/dist/monolith/plumbing/utils/MutexUtils.js.map +1 -1
  206. package/dist/monolith/plumbing/utils/PlumbingCore.js +549 -0
  207. package/dist/monolith/plumbing/utils/PlumbingCore.js.map +1 -0
  208. package/dist/monolith/plumbing/utils/PrefixTree.js +61 -114
  209. package/dist/monolith/plumbing/utils/PrefixTree.js.map +1 -1
  210. package/dist/monolith/plumbing/utils/StreamTagDetector.js +89 -127
  211. package/dist/monolith/plumbing/utils/StreamTagDetector.js.map +1 -1
  212. package/dist/monolith/plumbing/utils/StringUtils.js +87 -89
  213. package/dist/monolith/plumbing/utils/StringUtils.js.map +1 -1
  214. package/dist/monolith/runtime/MarieRuntime.js +76 -417
  215. package/dist/monolith/runtime/MarieRuntime.js.map +1 -1
  216. package/dist/monolith/runtime/RuntimeAdapterBase.js +1 -1
  217. package/dist/monolith/runtime/RuntimeAdapterBase.js.map +1 -1
  218. package/dist/monolith/runtime/providerFactory.js +1 -7
  219. package/dist/monolith/runtime/providerFactory.js.map +1 -1
  220. package/dist/monolith/services/HealthService.js +29 -32
  221. package/dist/monolith/services/HealthService.js.map +1 -1
  222. package/dist/monolith/services/JoyAutomationService.js +58 -95
  223. package/dist/monolith/services/JoyAutomationService.js.map +1 -1
  224. package/dist/monolith/services/MarieAutomationService.js +59 -0
  225. package/dist/monolith/services/MarieAutomationService.js.map +1 -0
  226. package/dist/monolith/services/MarieGhostService.js +46 -161
  227. package/dist/monolith/services/MarieGhostService.js.map +1 -1
  228. package/dist/monolith/services/MarieServices.js +102 -0
  229. package/dist/monolith/services/MarieServices.js.map +1 -0
  230. package/dist/monolith/services/MarieTypes.js +2 -0
  231. package/dist/monolith/services/MarieTypes.js.map +1 -0
  232. package/dist/monolith/services/UpdateService.js +47 -49
  233. package/dist/monolith/services/UpdateService.js.map +1 -1
  234. package/dist/prompts.js +11 -5
  235. package/dist/prompts.js.map +1 -1
  236. package/dist/test_prefix_tree.js +9 -9
  237. package/dist/test_prefix_tree.js.map +1 -1
  238. package/package.json +18 -88
  239. package/run_test.js +5 -0
  240. package/.marie_visual_verify_1771225696548/progress_bar_check.txt +0 -1
  241. package/dist/extension.cjs +0 -635
  242. package/dist/extension.js +0 -473
  243. package/dist/extension.js.map +0 -1
  244. package/dist/monolith/adapters/VscodeMarieAdapter.js +0 -81
  245. package/dist/monolith/adapters/VscodeMarieAdapter.js.map +0 -1
  246. package/dist/monolith/domain/joy/JoyTools.js +0 -535
  247. package/dist/monolith/domain/joy/JoyTools.js.map +0 -1
  248. package/dist/monolith/infrastructure/ai/agents/MarieYOLO.js +0 -207
  249. package/dist/monolith/infrastructure/ai/agents/MarieYOLO.js.map +0 -1
  250. package/dist/monolith/infrastructure/ai/core/GhostPort.js +0 -2
  251. package/dist/monolith/infrastructure/ai/core/GhostPort.js.map +0 -1
  252. package/dist/monolith/infrastructure/ai/core/MarieYOLOTypes.js +0 -2
  253. package/dist/monolith/infrastructure/ai/core/MarieYOLOTypes.js.map +0 -1
  254. package/dist/monolith/infrastructure/ai/core/VscodeFileSystemPort.js +0 -33
  255. package/dist/monolith/infrastructure/ai/core/VscodeFileSystemPort.js.map +0 -1
  256. package/dist/monolith/infrastructure/ai/providers/AnthropicProvider.js +0 -148
  257. package/dist/monolith/infrastructure/ai/providers/AnthropicProvider.js.map +0 -1
  258. package/dist/monolith/infrastructure/ai/providers/CerebrasProvider.js +0 -208
  259. package/dist/monolith/infrastructure/ai/providers/CerebrasProvider.js.map +0 -1
  260. package/dist/monolith/plumbing/ui/DecorationService.js +0 -54
  261. package/dist/monolith/plumbing/ui/DecorationService.js.map +0 -1
  262. package/dist/monolith/services/JoyLogService.js +0 -48
  263. package/dist/monolith/services/JoyLogService.js.map +0 -1
  264. package/dist/monolith/services/JoyService.js +0 -209
  265. package/dist/monolith/services/JoyService.js.map +0 -1
  266. package/dist/monolith/services/MarieSCMProvider.js +0 -41
  267. package/dist/monolith/services/MarieSCMProvider.js.map +0 -1
  268. package/dist/test_agent_stream_control_plane.js +0 -170
  269. package/dist/test_agent_stream_control_plane.js.map +0 -1
  270. package/dist/test_strategy_integration.js +0 -114
  271. package/dist/test_strategy_integration.js.map +0 -1
  272. package/dist/test_streaming_fragility.js +0 -191
  273. package/dist/test_streaming_fragility.js.map +0 -1
  274. package/dist/webview-ui/App.js +0 -16
  275. package/dist/webview-ui/App.js.map +0 -1
  276. package/dist/webview-ui/Providers.js +0 -6
  277. package/dist/webview-ui/Providers.js.map +0 -1
  278. package/dist/webview-ui/components/ApprovalPanel.js +0 -8
  279. package/dist/webview-ui/components/ApprovalPanel.js.map +0 -1
  280. package/dist/webview-ui/components/ChatPanel.js +0 -19
  281. package/dist/webview-ui/components/ChatPanel.js.map +0 -1
  282. package/dist/webview-ui/components/Composer.js +0 -19
  283. package/dist/webview-ui/components/Composer.js.map +0 -1
  284. package/dist/webview-ui/components/HeaderBar.js +0 -5
  285. package/dist/webview-ui/components/HeaderBar.js.map +0 -1
  286. package/dist/webview-ui/components/SessionList.js +0 -14
  287. package/dist/webview-ui/components/SessionList.js.map +0 -1
  288. package/dist/webview-ui/context/WebviewStateContext.js +0 -146
  289. package/dist/webview-ui/context/WebviewStateContext.js.map +0 -1
  290. package/dist/webview-ui/main.css +0 -1
  291. package/dist/webview-ui/main.js +0 -108
  292. package/dist/webview-ui/main.js.map +0 -1
  293. package/dist/webview-ui/types.js +0 -2
  294. package/dist/webview-ui/types.js.map +0 -1
  295. package/dist/webview-ui/vscode.js +0 -4
  296. package/dist/webview-ui/vscode.js.map +0 -1
  297. package/lint_output.txt +0 -705
  298. package/lint_output_v2.txt +0 -711
  299. package/marie-coder-0.1.16.vsix +0 -0
@@ -1,355 +1,320 @@
1
+ import { getTool, getRegisteredTools } from "../../tools/ToolRegistry.js";
1
2
  import * as path from "path";
2
- import { nodeRequire } from "../../../plumbing/utils/EnvironmentUtils.js";
3
+ import { getWorkspaceRoot, nodeRequire, } from "../../../plumbing/utils/EnvironmentUtils.js";
4
+ import { getInstance, } from "../../persistence/NoormmeEngine.js";
5
+ import { getCapabilities, isMfaRequired } from "../../config/ConfigService.js";
3
6
  const require = nodeRequire;
4
- // Lazy-load vscode to avoid CLI errors
5
- let vscodeModule = null;
6
- let hasAttemptedVscodeLoad = false;
7
- function getVscode() {
8
- if (!hasAttemptedVscodeLoad) {
9
- hasAttemptedVscodeLoad = true;
10
- try {
11
- vscodeModule = require("vscode");
12
- }
13
- catch {
14
- vscodeModule = null;
15
- }
16
- }
17
- return vscodeModule;
18
- }
19
- import { getStringArg } from "../../tools/ToolUtils.js";
20
7
  import { getErrorMessage } from "../../../plumbing/utils/ErrorUtils.js";
21
8
  import { withRetry, RetryConfig } from "../../../plumbing/utils/RetryUtils.js";
22
- import { rollbackAll, } from "../../../plumbing/filesystem/FileService.js";
9
+ import { rollbackAll } from "../../../plumbing/filesystem/FileService.js";
10
+ import { similarity } from "../../../plumbing/utils/StringUtils.js";
11
+ import { repairJsonDetailed, } from "../../../plumbing/utils/JsonUtils.js";
12
+ import { safeStringify, safeSpread } from "./MarieSanitizer.js";
13
+ const PROACTIVE_REPAIRS = {
14
+ write_file: "write_to_file",
15
+ edit_file: "replace_file_content",
16
+ replace_in_file: "replace_file_content",
17
+ read_files: "read_file",
18
+ list_files: "list_dir",
19
+ search_files: "grep_search",
20
+ execute_command: "run_command",
21
+ get_folder_tree: "get_folder_structure",
22
+ multi_replace: "multi_replace_file_content",
23
+ delete_file: "discard_file",
24
+ discard_file: "delete_file",
25
+ };
23
26
  /**
24
27
  * Handles the validation and execution of AI tool calls.
28
+ * Principle 2: Compressed Common Path.
25
29
  */
26
30
  export class MarieToolProcessor {
27
- toolRegistry;
28
31
  tracker;
29
32
  approvalRequester;
30
33
  state;
31
34
  fs;
35
+ vitality;
32
36
  static RETRY_CONFIG = new RetryConfig();
33
37
  failureCircuitBreaker = new Map();
34
- constructor(toolRegistry, tracker, approvalRequester, state, fs) {
35
- this.toolRegistry = toolRegistry;
38
+ constructor(tracker, approvalRequester, state, fs, vitality) {
36
39
  this.tracker = tracker;
37
40
  this.approvalRequester = approvalRequester;
38
41
  this.state = state;
39
42
  this.fs = fs;
43
+ this.vitality = vitality;
40
44
  }
41
45
  async process(toolCall, signal) {
42
- const { name, start_line, end_line, repaired } = toolCall;
43
- const input = toolCall.input;
44
- const inputStr = JSON.stringify(input);
45
- if (repaired) {
46
- this.tracker.recordHeuristicFix(toolCall.name);
46
+ const { name, input, repaired, id } = toolCall;
47
+ const inputStr = safeStringify(input);
48
+ if (repaired)
49
+ this.tracker.recordHeuristicFix(name);
50
+ try {
51
+ // 1. Pre-Execute: Circuit Breaker & Validation
52
+ const preError = await this.preExecute(name, input, inputStr);
53
+ if (preError)
54
+ return preError;
55
+ const tool = getTool(name);
56
+ if (!tool)
57
+ return `Error: Tool "${name}" not found.`;
58
+ // 2. Prepare: Logging & Backups
59
+ const toolStartTime = Date.now();
60
+ await this.prepareExecution(name, input, id, tool.isDestructive, signal);
61
+ // 3. Execute
62
+ const result = await withRetry(() => tool.execute(input, (update) => this.handleToolUpdate(update, name), signal), MarieToolProcessor.RETRY_CONFIG, `Tool: ${name}`, signal);
63
+ // 4. Post-Execute: Truncation, Metrics, Sentinels
64
+ return await this.postExecute(name, input, result, toolStartTime, id, tool.isDestructive, signal);
65
+ }
66
+ catch (error) {
67
+ const repairedResult = await this.performFuzzyRepair(toolCall, error, signal);
68
+ if (repairedResult)
69
+ return repairedResult;
70
+ return await this.handleError(name, inputStr, error, id, signal);
47
71
  }
48
- // SUB-ATOMIC INTEGRITY: Tool Circuit Breaker
49
- const failureState = this.failureCircuitBreaker.get(name);
50
- if (failureState &&
51
- failureState.lastInput === inputStr &&
52
- failureState.count >= 3) {
53
- this.recordError(name, `CIRCUIT BREAKER: ${name} has failed 3 times with the same input. Possible death spiral.`, true);
54
- return `HALT: Protocol Violation. Circuit breaker tripped for ${name} after repeated failures. Diversify your approach immediately.`;
72
+ }
73
+ async performFuzzyRepair(toolCall, error, signal) {
74
+ const errorMsg = getErrorMessage(error);
75
+ if (!errorMsg.includes("not found") &&
76
+ !errorMsg.includes("ENOENT") &&
77
+ !errorMsg.includes("registry"))
78
+ return null;
79
+ // 1. Proactive Mapping
80
+ if (PROACTIVE_REPAIRS[toolCall.name]) {
81
+ const mapped = PROACTIVE_REPAIRS[toolCall.name];
82
+ if (getTool(mapped)) {
83
+ this.tracker.emitEvent({
84
+ type: "reasoning",
85
+ runId: this.tracker.getRun().runId,
86
+ text: `🩹 REPAIR: ${toolCall.name} -> ${mapped}`,
87
+ elapsedMs: this.tracker.elapsedMs(),
88
+ });
89
+ toolCall.name = mapped;
90
+ toolCall.repaired = true;
91
+ return this.process(toolCall, signal);
92
+ }
55
93
  }
56
- const tool = this.toolRegistry.getTool(toolCall.name);
57
- if (!tool) {
58
- this.recordError(toolCall.name, "Tool not found");
59
- return `Tool ${toolCall.name} not found`;
94
+ // 2. Fuzzy Tool Name
95
+ const tools = getRegisteredTools();
96
+ let bestMatch = { name: "", sim: 0 };
97
+ for (const t of tools) {
98
+ const sim = similarity(toolCall.name, t.name);
99
+ if (sim > bestMatch.sim)
100
+ bestMatch = { name: t.name, sim };
60
101
  }
102
+ if (bestMatch.sim > 0.8 && bestMatch.name !== toolCall.name) {
103
+ this.tracker.emitEvent({
104
+ type: "reasoning",
105
+ runId: this.tracker.getRun().runId,
106
+ text: `🩹 FUZZY REPAIR: ${toolCall.name} -> ${bestMatch.name}`,
107
+ elapsedMs: this.tracker.elapsedMs(),
108
+ });
109
+ toolCall.name = bestMatch.name;
110
+ toolCall.repaired = true;
111
+ return this.process(toolCall, signal);
112
+ }
113
+ return null;
114
+ }
115
+ repairJsonString(json) {
116
+ const { repaired } = repairJsonDetailed(json);
61
117
  try {
62
- const validationError = this.validate(toolCall.name, input);
63
- if (validationError) {
64
- this.recordError(toolCall.name, validationError);
65
- return `Error: ${validationError}`;
66
- }
67
- // Autonomy: destructive tools execute immediately without approval gates.
68
- const toolStartTime = Date.now();
69
- console.log(`[Marie] Tool ${toolCall.name} starting. ID: ${toolCall.id}`);
70
- const sanitizedInput = { ...input };
71
- // Hygiene: Truncate massive fields to prevent log bloat
72
- if (typeof sanitizedInput.content === "string" &&
73
- sanitizedInput.content.length > 500) {
74
- sanitizedInput.content =
75
- sanitizedInput.content.substring(0, 500) + "...[TRUNCATED]";
76
- }
77
- if (typeof sanitizedInput.replacementContent === "string" &&
78
- sanitizedInput.replacementContent.length > 500) {
79
- sanitizedInput.replacementContent =
80
- sanitizedInput.replacementContent.substring(0, 500) +
81
- "...[TRUNCATED]";
82
- }
118
+ JSON.parse(repaired);
119
+ return repaired;
120
+ }
121
+ catch {
122
+ return json;
123
+ }
124
+ }
125
+ async preExecute(name, input, inputStr) {
126
+ // Persistent Circuit Breaker
127
+ try {
128
+ const db = await getInstance();
129
+ const failures = await db.execute("SELECT COUNT(*) as count FROM agent_actions WHERE tool_name = ? AND input_summary = ? AND status = 'failure' AND created_at > datetime('now', '-1 hour')", [name, inputStr.slice(0, 500)]);
130
+ if (failures[0]?.count >= 3)
131
+ return `HALT: Persistent circuit breaker tripped for ${name}. Pivot your strategy.`;
132
+ }
133
+ catch (e) {
134
+ const state = this.failureCircuitBreaker.get(name);
135
+ if (state && state.lastInput === inputStr && state.count >= 3)
136
+ return `HALT: In-memory circuit breaker tripped for ${name}.`;
137
+ }
138
+ // Validation
139
+ const validationError = this.validate(name, input);
140
+ if (validationError) {
141
+ this.recordError(name, validationError);
142
+ return `Error: ${validationError}`;
143
+ }
144
+ // Sovereign Affirmation (MFA)
145
+ if (this.requiresSovereignAffirmation(name, input)) {
146
+ if (!(await this.requestApproval(name, input)))
147
+ return `Sovereign Denial: Operation "${name}" rejected by governor. 🛡️`;
83
148
  this.tracker.emitEvent({
84
- type: "tool",
149
+ type: "reasoning",
85
150
  runId: this.tracker.getRun().runId,
86
- id: toolCall.id,
87
- phase: "start",
88
- name: toolCall.name,
89
- input: sanitizedInput,
151
+ text: `🔐 **C-MFA AFFIRMED**: Sovereign clearance granted.`,
90
152
  elapsedMs: this.tracker.elapsedMs(),
91
153
  });
92
- const run = this.tracker.getRun();
93
- run.activeToolName = toolCall.name;
94
- run.lastToolName = toolCall.name;
95
- this.tracker.emitProgressUpdate();
96
- this.tracker.recordToolUsage(toolCall.name);
97
- // TRANSACTIONAL INTEGRITY: Backup files before destructive operations
98
- const impactedFiles = [];
99
- const execFile = toolCall.input?.path ||
100
- toolCall.input?.targetFile ||
101
- toolCall.input?.file ||
102
- toolCall.input?.filePath;
103
- // UI FEEDBACK: Set active file path for editor visualization
104
- if (execFile && typeof execFile === "string") {
105
- run.activeFilePath = execFile;
106
- this.tracker.emitEvent({
107
- type: "stage",
108
- runId: run.runId,
109
- stage: "editing",
110
- label: `Editing ${path.basename(execFile)}...`,
111
- elapsedMs: this.tracker.elapsedMs(),
112
- });
113
- this.tracker.emitProgressUpdate();
114
- }
115
- if (tool.isDestructive) {
116
- if (execFile && typeof execFile === "string") {
117
- impactedFiles.push(execFile);
118
- if (this.fs) {
119
- await this.fs.backupFile(execFile, signal);
120
- }
121
- }
122
- // Custom handling for multi-file tools
123
- if (name === "execute_semantic_move" && input.dest) {
124
- impactedFiles.push(input.dest);
125
- if (this.fs) {
126
- await this.fs.backupFile(input.dest, signal);
127
- }
128
- }
129
- }
130
- let result = await withRetry(() => tool.execute(input, (update) => {
131
- if (update.bytesWritten !== undefined && update.path) {
132
- this.tracker.emitEvent({
133
- type: "file_stream_delta",
134
- runId: this.tracker.getRun().runId,
135
- path: update.path,
136
- bytesWritten: update.bytesWritten,
137
- totalBytes: update.totalBytes,
138
- elapsedMs: this.tracker.elapsedMs(),
139
- });
140
- }
141
- else {
142
- this.applyUpdate(update, toolCall.name);
143
- }
144
- }, signal), MarieToolProcessor.RETRY_CONFIG, `Tool: ${toolCall.name}`, signal);
145
- // PROACTIVE TRUNCATION: Source-level safety cap (512KB)
146
- if (typeof result === "string" && result.length > 512 * 1024) {
147
- console.warn(`[MarieStability] Tool ${toolCall.name} output exceeded 512KB. Truncating at source.`);
148
- result =
149
- result.substring(0, 512 * 1024) +
150
- "\n\n🚨 STABILITY ALERT: Output truncated at 512KB to prevent Extension Host lag.";
151
- }
152
- else if (result && typeof result === "object") {
153
- const json = JSON.stringify(result);
154
- if (json.length > 512 * 1024) {
155
- console.warn(`[MarieStability] Tool ${toolCall.name} JSON output exceeded 512KB. Truncating at source.`);
156
- result =
157
- json.substring(0, 512 * 1024) +
158
- "\n\n🚨 STABILITY ALERT: JSON output truncated at 512KB.";
159
- }
160
- }
161
- // TRANSACTIONAL SUCCESS: Clear backups for this tool/turn
162
- if (this.fs) {
163
- this.fs.clearBackups();
164
- }
165
- // CIRCUIT BREAKER FLUSH: Tool succeeded
166
- this.failureCircuitBreaker.delete(name);
167
- const toolDurationMs = Date.now() - toolStartTime;
168
- console.log(`[Marie] Tool ${toolCall.name} completed in ${toolDurationMs}ms.`);
154
+ }
155
+ return null;
156
+ }
157
+ async prepareExecution(name, input, id, isDestructive, signal) {
158
+ this.tracker.recordLog(`[Marie] Tool ${name} starting. ID: ${id}`);
159
+ // UI Feedback: Active Path
160
+ const execFile = input?.path || input?.targetFile || input?.file || input?.filePath;
161
+ if (execFile && typeof execFile === "string") {
162
+ this.tracker.getRun().activeFilePath = execFile;
169
163
  this.tracker.emitEvent({
170
- type: "tool",
164
+ type: "stage",
171
165
  runId: this.tracker.getRun().runId,
172
- id: toolCall.id,
173
- phase: "complete",
174
- name: toolCall.name,
175
- message: typeof result === "string" ? result.substring(0, 100) : "Completed",
166
+ stage: "editing",
167
+ label: `Editing ${path.basename(execFile)}...`,
176
168
  elapsedMs: this.tracker.elapsedMs(),
177
169
  });
178
- run.activeToolName = undefined;
179
- run.activeFilePath = undefined; // Clear active file
180
- run.lastToolName = toolCall.name;
181
170
  this.tracker.emitProgressUpdate();
182
- if (result && typeof result === "object") {
183
- this.applyUpdate(result, toolCall.name);
184
- }
185
- // Phase 11: Code Impact Analysis
186
- this.recordCodeStats(toolCall.name, input);
187
- // Ascension Mastery: Record execution
188
- this.state.techniqueExecutions.push({
189
- name: toolCall.name,
190
- durationMs: toolDurationMs,
191
- success: true,
192
- timestamp: Date.now(),
193
- filePath: typeof execFile === "string" ? execFile : undefined,
194
- });
195
- this.state.toolHistory.push(toolCall.name);
196
- if (this.state.toolHistory.length > 20)
197
- this.state.toolHistory.shift();
198
- this.state.victoryStreak++;
199
- // Phase 7: Track sentimental metrics
200
- const runMetrics = this.tracker.getRun();
201
- if (!runMetrics.metrics)
202
- runMetrics.metrics = { cherishedFiles: [], releasedDebtCount: 0 };
203
- if (toolCall.name === "cherish_file" &&
204
- input &&
205
- typeof input === "object") {
206
- try {
207
- const p = getStringArg(input, "path");
208
- if (p && !runMetrics.metrics.cherishedFiles.includes(p)) {
209
- runMetrics.metrics.cherishedFiles.push(p);
210
- this.tracker.emitProgressUpdate(`File cherished: ${p.split("/").pop()}`);
211
- }
212
- }
213
- catch (e) {
214
- console.warn("Failed to extract path for cherish_file metric", e);
215
- }
216
- }
217
- else if (toolCall.name === "discard_file") {
218
- runMetrics.metrics.releasedDebtCount++;
219
- this.tracker.emitProgressUpdate("Technical debt released 🍂");
220
- }
221
- let finalResult = typeof result === "string" ? result : JSON.stringify(result);
222
- // ZENITH AUTONOMY: Autonomous Dependency Sentinel
223
- if (tool.isDestructive && execFile && typeof execFile === "string") {
224
- const [zoningAlert, buildAlert] = await Promise.all([
225
- this.runZoningSentinel(execFile, typeof result === "string" ? result : undefined, signal),
226
- this.runBuildSentinel(execFile, signal),
227
- ]);
228
- if (zoningAlert) {
229
- finalResult += `\n\n🛡️ **ZENITH: Zoning Sentinel Alert**\n${zoningAlert}`;
230
- }
231
- if (buildAlert) {
232
- finalResult += `\n\n🧱 **SINGULARITY: Build Sentinel Alert**\n${buildAlert}`;
233
- }
234
- }
235
- return finalResult;
171
+ if (isDestructive && this.fs)
172
+ await this.fs.backupFile(execFile, signal);
236
173
  }
237
- catch (error) {
238
- const rawMsg = getErrorMessage(error);
239
- const isTerminal = this.isTerminalError(name, rawMsg);
240
- const run = this.tracker.getRun();
241
- run.activeToolName = undefined;
242
- run.lastToolName = name;
243
- this.tracker.emitProgressUpdate();
244
- // TRANSACTIONAL RECOVERY: Restore state on failure
245
- let rollbackErrorMsg = "";
246
- try {
247
- console.log(`[Marie] Initiating systemic rollback for tool failure: ${name}`);
248
- if (this.fs) {
249
- await this.fs.rollbackAll(signal);
250
- }
251
- else {
252
- await rollbackAll(signal);
253
- }
254
- }
255
- catch (restoreError) {
256
- console.error(`[Marie] Transactional recovery failed: ${restoreError}`);
257
- rollbackErrorMsg = `\n\n🚨 CRITICAL: Systemic rollback failed. File system may be in an inconsistent state. Manual verification required. Error: ${restoreError}`;
258
- }
259
- // CIRCUIT BREAKER RECORD: Increment failure count for same tool/input
260
- const state = this.failureCircuitBreaker.get(name) || {
261
- count: 0,
262
- lastInput: inputStr,
263
- };
264
- if (state.lastInput === inputStr) {
265
- state.count++;
266
- }
267
- else {
268
- state.count = 1;
269
- state.lastInput = inputStr;
270
- }
271
- this.failureCircuitBreaker.set(name, state);
272
- this.recordError(name, rawMsg, isTerminal, toolCall.id);
273
- console.error(`[Marie] Tool ${name} failed: ${rawMsg}`);
274
- // Ascension Mastery: Record failure
275
- const failFile = toolCall.input?.path ||
276
- toolCall.input?.targetFile ||
277
- toolCall.input?.file ||
278
- toolCall.input?.filePath;
279
- this.state.techniqueExecutions.push({
280
- name: name,
281
- durationMs: 0,
282
- success: false,
283
- timestamp: Date.now(),
284
- filePath: typeof failFile === "string" ? failFile : undefined,
174
+ // Start Event
175
+ this.tracker.emitEvent({
176
+ type: "tool",
177
+ runId: this.tracker.getRun().runId,
178
+ id,
179
+ phase: "start",
180
+ name,
181
+ input: this.sanitizeForLogging(input),
182
+ elapsedMs: this.tracker.elapsedMs(),
183
+ });
184
+ this.tracker.recordToolUsage(name);
185
+ }
186
+ handleToolUpdate(update, name) {
187
+ if (update.bytesWritten !== undefined && update.path) {
188
+ this.tracker.emitEvent({
189
+ type: "file_stream_delta",
190
+ runId: this.tracker.getRun().runId,
191
+ path: update.path,
192
+ bytesWritten: update.bytesWritten,
193
+ totalBytes: update.totalBytes,
194
+ elapsedMs: this.tracker.elapsedMs(),
285
195
  });
286
- this.state.totalErrorCount++;
287
- this.state.victoryStreak = 0;
288
- if (typeof failFile === "string") {
289
- this.state.errorHotspots[failFile] =
290
- (this.state.errorHotspots[failFile] || 0) + 1;
291
- }
292
- if (isTerminal || state.count >= 3) {
293
- const circuitBreakerSuffix = state.count >= 3 ? " [CIRCUIT BREAKER TRIPPED]" : "";
294
- return `HALT: Critical protocol or parsing failure in ${name}: ${rawMsg}${circuitBreakerSuffix}${rollbackErrorMsg}`;
295
- }
296
- // Constructive Feedback Layer
297
- const msgParts = [`Error executing ${name}: ${rawMsg}${rollbackErrorMsg}`];
298
- // Ascension-Aware Error Hotspot Hint
299
- if (failFile && typeof failFile === "string") {
300
- const hotspotCount = this.state.errorHotspots[failFile] || 0;
301
- if (hotspotCount >= 2) {
302
- msgParts.push(`\n\n🔥 CURSE HOTSPOT: This file (${failFile}) has failed ${hotspotCount} times. Technique adjustment required.`);
303
- }
304
- }
305
- if (this.state.spiritPressure < 30) {
306
- msgParts.push(`\n⚠️ Low spirit pressure (${this.state.spiritPressure}/100). Simplify your next action.`);
307
- }
308
- if (this.state.mood === "CAUTIOUS") {
309
- msgParts.push(`\n🛡️ Ascension Mood: CAUTIOUS. Observe before acting. Verify the pattern.`);
310
- }
311
- if (rawMsg.includes("ENOENT") || rawMsg.includes("no such file")) {
312
- msgParts.push(`\n\n💡 Reflection Hint: The file or directory does not exist. Use 'list_dir' to verify the path or 'grep_search' to locate it.`);
313
- }
314
- else if (rawMsg.includes("target content not found")) {
315
- msgParts.push(`\n\n💡 Reflection Hint: The content you tried to replace wasn't found. Use 'read_file' (without line numbers) to verify the current file content before retrying.`);
316
- }
317
- else if (rawMsg.includes("Input is required")) {
318
- msgParts.push(`\n\n💡 Reflection Hint: You missed a required argument. Check the tool schema.`);
319
- }
320
- else {
321
- msgParts.push(`\n\n💡 Reflection Hint: Please analyze why this failed and propose a diverse alternative strategy.`);
322
- }
323
- if (state.count > 1) {
324
- msgParts.push(`\n\n⚠️ REPEATED FAILURE: This exact tool call has failed ${state.count} times. If it fails again, the circuit breaker will trip and you will be forced to change strategy.`);
325
- }
326
- return msgParts.join("");
327
196
  }
197
+ else {
198
+ this.applyUpdate(update, name);
199
+ }
200
+ }
201
+ async postExecute(name, input, result, startTime, id, isDestructive, signal) {
202
+ let finalResult = typeof result === "string" ? result : safeStringify(result);
203
+ if (finalResult.length > 512 * 1024) {
204
+ finalResult =
205
+ finalResult.substring(0, 512 * 1024) +
206
+ "\n\n🚨 STABILITY ALERT: Output truncated at 512KB.";
207
+ }
208
+ if (this.fs)
209
+ this.fs.clearBackups();
210
+ this.failureCircuitBreaker.delete(name);
211
+ const duration = Date.now() - startTime;
212
+ this.tracker.emitEvent({
213
+ type: "tool",
214
+ runId: this.tracker.getRun().runId,
215
+ id,
216
+ phase: "complete",
217
+ name,
218
+ message: finalResult.substring(0, 100),
219
+ elapsedMs: this.tracker.elapsedMs(),
220
+ });
221
+ const run = this.tracker.getRun();
222
+ run.activeToolName = undefined;
223
+ run.activeFilePath = undefined;
224
+ this.tracker.emitProgressUpdate();
225
+ // Stats & History
226
+ this.recordCodeStats(name, input);
227
+ this.state.techniqueExecutions.push({
228
+ name,
229
+ durationMs: duration,
230
+ success: true,
231
+ timestamp: Date.now(),
232
+ filePath: input?.path || input?.targetFile,
233
+ });
234
+ this.state.toolHistory.push(name);
235
+ if (this.state.toolHistory.length > 20)
236
+ this.state.toolHistory.shift();
237
+ this.state.victoryStreak++;
238
+ // Sentinels
239
+ const execFile = input?.path || input?.targetFile || input?.file || input?.filePath;
240
+ if (isDestructive && execFile && typeof execFile === "string") {
241
+ const [zoning, build] = await Promise.all([
242
+ this.runZoningSentinel(execFile, finalResult, signal),
243
+ this.runBuildSentinel(execFile, signal),
244
+ ]);
245
+ if (zoning)
246
+ finalResult += `\n\n🛡️ **ZENITH ALERT**\n${zoning}`;
247
+ if (build)
248
+ finalResult += `\n\n🧱 **SINGULARITY ALERT**\n${build}`;
249
+ }
250
+ return finalResult;
328
251
  }
252
+ async handleError(name, inputStr, error, id, signal) {
253
+ const rawMsg = getErrorMessage(error);
254
+ const isTerminal = this.isTerminalError(name, rawMsg);
255
+ // Rollback
256
+ try {
257
+ if (this.fs)
258
+ await this.fs.rollbackAll(signal);
259
+ else
260
+ await rollbackAll(signal);
261
+ }
262
+ catch (e) {
263
+ console.error("Rollback failed", e);
264
+ }
265
+ // Circuit Breaker Increment
266
+ const state = this.failureCircuitBreaker.get(name) || {
267
+ count: 0,
268
+ lastInput: inputStr,
269
+ };
270
+ state.count = state.lastInput === inputStr ? state.count + 1 : 1;
271
+ state.lastInput = inputStr;
272
+ this.failureCircuitBreaker.set(name, state);
273
+ this.recordError(name, rawMsg, isTerminal, id);
274
+ this.state.totalErrorCount++;
275
+ this.state.victoryStreak = 0;
276
+ if (isTerminal || state.count >= 3)
277
+ return `HALT: Critical failure in ${name}: ${rawMsg}`;
278
+ return `Error executing ${name}: ${rawMsg}. Refine your strategy.`;
279
+ }
280
+ sanitizeForLogging(input) {
281
+ const sanitized = safeSpread(input);
282
+ if (typeof sanitized.content === "string" && sanitized.content.length > 500)
283
+ sanitized.content =
284
+ sanitized.content.substring(0, 500) + "...[TRUNCATED]";
285
+ if (typeof sanitized.replacementContent === "string" &&
286
+ sanitized.replacementContent.length > 500)
287
+ sanitized.replacementContent =
288
+ sanitized.replacementContent.substring(0, 500) + "...[TRUNCATED]";
289
+ return sanitized;
290
+ }
291
+ // --- Methods below are mostly unchanged logic, just kept for completeness ---
329
292
  isTerminalError(toolName, message) {
330
- // Critical ritual failures are terminal
331
293
  if (toolName === "checkpoint_pass" && message.includes("failed"))
332
294
  return true;
333
- // Repeated parsing failures (marked by provider) are terminal
334
295
  if (message.includes("Failed to parse tool arguments"))
335
296
  return true;
336
297
  return false;
337
298
  }
338
299
  validate(name, input) {
300
+ const requirements = this.constructor.TOOL_CAPABILITIES[name] || [
301
+ "READ",
302
+ ];
303
+ const allowed = getCapabilities();
304
+ const missing = requirements.filter((cap) => !allowed.includes(cap));
305
+ if (missing.length > 0)
306
+ return `Capability Breach: Tool "${name}" requires missing capabilities: [${missing.join(", ")}]. 🛑`;
339
307
  if (!input || typeof input !== "object")
340
308
  return "Input must be a valid object";
341
- const tool = this.toolRegistry.getTool(name);
309
+ const tool = getTool(name);
342
310
  if (!tool)
343
- return `Tool "${name}" not found in registry`;
344
- // Check required fields from schema
311
+ return `Tool "${name}" not found.`;
345
312
  const schema = tool.input_schema;
346
313
  if (schema.required && Array.isArray(schema.required)) {
347
- const missing = schema.required.filter((field) => !(field in input));
348
- if (missing.length > 0) {
349
- return `Missing required fields: ${missing.join(", ")}`;
350
- }
314
+ const missingFields = schema.required.filter((field) => !(field in input));
315
+ if (missingFields.length > 0)
316
+ return `Missing required fields: ${missingFields.join(", ")}`;
351
317
  }
352
- // Security: Workspace Boundary Enforcement
353
318
  const pathFields = [
354
319
  "path",
355
320
  "targetFile",
@@ -360,223 +325,116 @@ export class MarieToolProcessor {
360
325
  ];
361
326
  for (const field of pathFields) {
362
327
  if (input[field] && typeof input[field] === "string") {
363
- const pathError = this.validatePath(input[field]);
364
- if (pathError)
365
- return pathError;
328
+ const error = this.validatePath(input[field]);
329
+ if (error)
330
+ return error;
366
331
  }
367
332
  }
368
333
  return null;
369
334
  }
370
335
  validatePath(p) {
371
- const vscode = getVscode();
372
- const workspaceFolders = vscode?.workspace.workspaceFolders;
373
- if (!workspaceFolders || workspaceFolders.length === 0)
374
- return null; // No workspace, no boundary to enforce
375
- const workspaceRoot = workspaceFolders[0].uri.fsPath;
376
- // Basic check for drive-letter-relative or absolute paths that bypass the root
377
- const normalized = p.startsWith("~") ? p : p.includes(":") ? p : p; // PathResolver handles ~ expansion
378
- // We'll trust resolvePath but check the result against workspace root if possible
379
- // Since ToolProcessor doesn't have easy access to resolvePath without importing,
380
- // we'll do a simple string check for now, matching FileService's logic.
381
- // If the path starts with / or \ but NOT workspaceRoot, it's a breach.
382
- if (p.startsWith("/") || (p.length > 1 && p[1] === ":")) {
383
- if (!p.startsWith(workspaceRoot)) {
384
- return `Security Error: Path ${p} is outside the workspace boundary (${workspaceRoot}). Access denied. 🛑`;
385
- }
336
+ const root = getWorkspaceRoot();
337
+ if (!root)
338
+ return null;
339
+ if ((p.startsWith("/") || (p.length > 1 && p[1] === ":")) &&
340
+ !p.startsWith(root)) {
341
+ return `Security Error: Path ${p} is outside workspace boundary.`;
386
342
  }
387
343
  return null;
388
344
  }
389
- async requestApproval(name, input) {
390
- const run = this.tracker.getRun();
391
- // Try to construct a diff for preview
392
- let diff;
393
- if (name === "replace_in_file" &&
394
- input.targetContent &&
395
- input.replacementContent) {
396
- diff = { old: input.targetContent, new: input.replacementContent };
397
- }
398
- else if (name === "write_file" && input.content) {
399
- diff = { old: "", new: input.content };
345
+ requiresSovereignAffirmation(name, input) {
346
+ if (!isMfaRequired())
347
+ return false;
348
+ if (name === "run_command") {
349
+ const cmd = (input.CommandLine || input.command || "").toLowerCase();
350
+ return ["sudo ", "rm ", "kill ", "chmod "].some((kw) => cmd.includes(kw));
400
351
  }
401
- // Use the callback to request approval via the frontend
402
- const approved = await this.approvalRequester(name, input, diff);
403
- return approved;
352
+ return ["delete_file", "prune_sovereign_memory"].includes(name);
353
+ }
354
+ async requestApproval(name, input) {
355
+ return await this.approvalRequester(name, input);
404
356
  }
405
357
  applyUpdate(update, toolName) {
406
358
  const run = this.tracker.getRun();
407
- if (update.context)
408
- run.currentContext = update.context;
409
- if (update.activeObjectiveId)
410
- run.activeObjectiveId = update.activeObjectiveId;
411
- if (update.lifecycleStage)
412
- run.lifecycleStage = update.lifecycleStage;
413
- if (update.totalPasses !== undefined)
414
- run.totalPasses = update.totalPasses;
415
- if (update.currentPass !== undefined)
416
- run.currentPass =
417
- update.currentPass === null ? undefined : update.currentPass;
418
- if (update.passFocus !== undefined)
419
- run.passFocus = update.passFocus;
420
- if (update.passHistory) {
421
- run.passHistory = [...(run.passHistory || []), ...update.passHistory];
422
- }
423
- if (update.metrics) {
424
- run.metrics = {
425
- cherishedFiles: Array.from(new Set([
426
- ...(run.metrics?.cherishedFiles || []),
427
- ...(update.metrics.cherishedFiles || []),
428
- ])),
429
- releasedDebtCount: (run.metrics?.releasedDebtCount || 0) +
430
- (update.metrics.releasedDebtCount || 0),
431
- };
432
- }
433
- // Auto-increment currentPass on checkpoint_pass or if specifically requested
434
- if (toolName === "checkpoint_pass" && run.currentPass !== undefined) {
359
+ Object.assign(run, safeSpread(update));
360
+ if (toolName === "checkpoint_pass" && run.currentPass !== undefined)
435
361
  run.currentPass++;
436
- }
437
- if (run.currentPass !== undefined &&
438
- run.totalPasses !== undefined &&
439
- run.passFocus) {
440
- this.tracker.emitPassTransition(run.currentPass, run.totalPasses, run.passFocus);
441
- }
442
- else {
443
- this.tracker.emitProgressUpdate();
444
- }
445
- // Handle Roadmap Augmentation
446
- if (toolName === "augment_roadmap" && update.totalPasses !== undefined) {
447
- run.totalPasses = (run.totalPasses || 0) + update.totalPasses;
448
- this.tracker.emitProgressUpdate(`Roadmap calibrated: ${run.totalPasses} total passes.`);
449
- }
450
- }
451
- countLines(str) {
452
- if (!str)
453
- return 0;
454
- let count = 1; // Start at 1 for single line
455
- let pos = -1;
456
- while ((pos = str.indexOf("\n", pos + 1)) !== -1) {
457
- count++;
458
- }
459
- return count;
362
+ this.tracker.emitProgressUpdate();
460
363
  }
461
364
  recordCodeStats(toolName, input) {
462
- try {
463
- if (toolName === "write_to_file") {
464
- // Counts as strict addition
465
- const lines = this.countLines(input.content);
466
- const path = input.targetFile || input.file || input.path || input.filePath; // Handle varying schemas
467
- if (path)
468
- this.tracker.recordFileChange(path, lines, 0);
469
- }
470
- else if (toolName === "replace_file_content") {
471
- const added = this.countLines(input.replacementContent);
472
- const removed = this.countLines(input.targetContent);
473
- const path = input.targetFile || input.file || input.path || input.filePath;
474
- if (path)
475
- this.tracker.recordFileChange(path, added, removed);
476
- }
477
- else if (toolName === "multi_replace_file_content" &&
478
- Array.isArray(input.replacementChunks)) {
479
- let added = 0;
480
- let removed = 0;
481
- for (const chunk of input.replacementChunks) {
482
- added += this.countLines(chunk.replacementContent);
483
- removed += this.countLines(chunk.targetContent);
484
- }
485
- const path = input.targetFile || input.file || input.path || input.filePath;
486
- if (path)
487
- this.tracker.recordFileChange(path, added, removed);
488
- }
489
- }
490
- catch (e) {
491
- console.warn("Failed to record code stats", e);
492
- }
365
+ const path = input.targetFile || input.file || input.path;
366
+ if (!path)
367
+ return;
368
+ const roundedInput = safeSpread(input);
369
+ const added = roundedInput.content
370
+ ? roundedInput.content.split("\n").length
371
+ : roundedInput.replacementContent
372
+ ? roundedInput.replacementContent.split("\n").length
373
+ : 0;
374
+ const removed = roundedInput.targetContent
375
+ ? roundedInput.targetContent.split("\n").length
376
+ : 0;
377
+ if (added || removed)
378
+ this.tracker.recordFileChange(path, added, removed);
493
379
  }
494
- recordError(name, message, isTerminal = false, toolCallId) {
380
+ recordError(name, message, terminal = false, id) {
495
381
  this.tracker.emitEvent({
496
382
  type: "tool",
497
383
  runId: this.tracker.getRun().runId,
498
- id: toolCallId,
384
+ id,
499
385
  phase: "error",
500
386
  name,
501
- message: (isTerminal ? "[TERMINAL] " : "") + message,
387
+ message: (terminal ? "[TERMINAL] " : "") + message,
502
388
  elapsedMs: this.tracker.elapsedMs(),
503
389
  });
504
390
  }
505
- async runZoningSentinel(filePath, toolResult, signal) {
391
+ async runZoningSentinel(filePath, result, signal) {
506
392
  try {
507
- if (signal?.aborted)
508
- return null;
509
393
  const { detectMigrationNeeds } = await import("../../../plumbing/analysis/CodeHealthService.js");
510
394
  const { readFile } = await import("../../../plumbing/filesystem/FileService.js");
511
395
  const content = await readFile(filePath, undefined, undefined, signal);
512
396
  const { shouldMigrate, targetZone, reason } = detectMigrationNeeds(filePath, content);
513
- if (shouldMigrate) {
514
- this.tracker.emitEvent({
515
- type: "reasoning",
516
- runId: this.tracker.getRun().runId,
517
- text: `🛡️ ZENITH: Zoning Sentinel detected a leak in \`${filePath.split("/").pop()}\`.`,
518
- elapsedMs: this.tracker.elapsedMs(),
519
- });
520
- return `⚠️ **Dependency Leak**: ${reason}\nSuggested Zone: \`${targetZone}\`. Consider moving this file or refactoring its dependencies.`;
521
- }
522
- // Also check for cross-zone import leaks (Heuristic)
523
- if (filePath.includes("/domain/") &&
524
- (content.includes("/infrastructure/") || content.includes("/adapters/"))) {
525
- return `⚠️ **Architectural Heresy**: Domain layer should not depend on Infrastructure. Found infrastructure imports in \`${path.basename(filePath)}\`.`;
526
- }
527
- return null;
397
+ return shouldMigrate
398
+ ? `Dependency Leak: ${reason}. Target: ${targetZone}`
399
+ : null;
528
400
  }
529
- catch (e) {
530
- console.warn("[Zenith] Zoning Sentinel failed", e);
401
+ catch {
531
402
  return null;
532
403
  }
533
404
  }
534
405
  async runBuildSentinel(filePath, signal) {
535
- const vscode = getVscode();
536
- const workingDir = vscode?.workspace.workspaceFolders?.[0].uri.fsPath || process.cwd();
537
406
  try {
538
- if (signal?.aborted)
539
- return null;
540
- const { QualityGuardrailService } = await import("../../../plumbing/analysis/QualityGuardrailService.js");
541
- this.tracker.emitProgressUpdate("Initiating Sub-Atomic Integrity Audit... 🛡️");
542
- const result = await QualityGuardrailService.evaluate(workingDir, filePath);
543
- if (result.surgicalMends > 0) {
544
- this.tracker.emitEvent({
545
- type: "reasoning",
546
- runId: this.tracker.getRun().runId,
547
- text: `✨ SURGICAL MEND: Marie autonomously repaired ${result.surgicalMends} sub-atomic issue(s) in \`${path.basename(filePath)}\`.`,
548
- elapsedMs: this.tracker.elapsedMs(),
549
- });
550
- }
551
- if (!result.passed) {
552
- this.tracker.emitEvent({
553
- type: "reasoning",
554
- runId: this.tracker.getRun().runId,
555
- text: `🧱 SUB-ATOMIC REJECTION: Project integrity at risk (Score: ${result.score}/100).`,
556
- elapsedMs: this.tracker.elapsedMs(),
557
- });
558
- let summary = `🚨 **SUB-ATOMIC INTEGRITY REJECTION** 🚨\n\nMarie has audited your change and found it architecturally or stylistically toxic.\n\n`;
559
- summary += `**Quality Score**: ${result.score}/100\n`;
560
- summary += result.violations.map((v) => `- ❌ ${v}`).join("\n");
561
- summary += `\n\n**Action Required**: You must resolve these precision regressions. Use 'resolve_lint_errors' for location-specific data. Type sovereignty is absolute. 🚩`;
562
- return summary;
563
- }
564
- if (result.score < 100) {
565
- this.tracker.emitProgressUpdate(`Sub-Atomic Audit Passed (Score: ${result.score}/100) ✨`);
566
- }
407
+ const { evaluateQualityGuardrail } = await import("../../../plumbing/analysis/QualityGuardrailService.js");
408
+ const res = await evaluateQualityGuardrail(getWorkspaceRoot() || "", filePath);
409
+ return res.passed ? null : `Quality rejection (Score: ${res.score}/100)`;
567
410
  }
568
- catch (e) {
569
- console.warn("[Singularity] Sub-Atomic Guardrails failed", e);
570
- // Fallback to basic VS Code diagnostics if service fails
571
- if (vscode) {
572
- const diagnostics = vscode.languages.getDiagnostics(vscode.Uri.file(filePath));
573
- const errors = diagnostics.filter((d) => d.severity === vscode.DiagnosticSeverity.Error);
574
- if (errors.length > 0) {
575
- return `🚨 **Build Regressions Detected**: ${errors.length} error(s) found. Fix these immediately.`;
576
- }
577
- }
411
+ catch {
412
+ return null;
578
413
  }
579
- return null;
580
414
  }
415
+ static TOOL_CAPABILITIES = {
416
+ read_file: ["READ"],
417
+ view_file: ["READ"],
418
+ list_dir: ["READ"],
419
+ grep_search: ["READ"],
420
+ find_by_name: ["READ"],
421
+ get_file_diagnostics: ["READ"],
422
+ write_to_file: ["WRITE"],
423
+ replace_file_content: ["WRITE"],
424
+ multi_replace_file_content: ["WRITE"],
425
+ delete_file: ["WRITE"],
426
+ rename_file: ["WRITE"],
427
+ move_file: ["WRITE"],
428
+ run_command: ["SHELL"],
429
+ search_web: ["NETWORK"],
430
+ read_url_content: ["NETWORK"],
431
+ read_browser_page: ["NETWORK"],
432
+ open_browser_url: ["NETWORK"],
433
+ evolve_mind_structure: ["WRITE", "SHELL"],
434
+ prune_sovereign_memory: ["WRITE"],
435
+ complete_task_ritual: ["READ", "WRITE"],
436
+ execute_semantic_move: ["READ", "WRITE"],
437
+ self_heal: ["READ", "WRITE", "SHELL"],
438
+ };
581
439
  }
582
440
  //# sourceMappingURL=MarieToolProcessor.js.map