rea-agents 1.7.0 → 2.1.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 (333) hide show
  1. package/README.md +112 -59
  2. package/bridge/ghidra/ReaGhidraBridge.java +96 -11
  3. package/dist/application/ArtifactExtraction.js +1 -1
  4. package/dist/application/ArtifactInventory/classify.js +42 -0
  5. package/dist/application/ArtifactInventory/hash.js +43 -0
  6. package/dist/application/ArtifactInventory/reader.js +41 -0
  7. package/dist/application/ArtifactInventory/scanCanonical.js +155 -0
  8. package/dist/application/ArtifactInventory/scanReader.js +124 -0
  9. package/dist/application/ArtifactInventory/types.js +10 -0
  10. package/dist/application/ArtifactInventory.js +9 -351
  11. package/dist/application/AuthorizedArtifactInventory.js +2 -2
  12. package/dist/application/BinarySession.js +47 -270
  13. package/dist/application/BinarySessionExecution.js +28 -0
  14. package/dist/application/BinarySessionOpen.js +39 -0
  15. package/dist/application/BinarySessionRecords.js +149 -0
  16. package/dist/application/BinarySessionStatus.js +75 -0
  17. package/dist/application/CapabilityInventory.js +42 -2
  18. package/dist/application/ClientRegistrationStatus.js +1 -1
  19. package/dist/application/CrossVersionInventory.js +8 -2
  20. package/dist/application/CrossVersionInvestigation.js +11 -29
  21. package/dist/application/CrossVersionInvestigationCollections.js +23 -0
  22. package/dist/application/DirectAnalysis.js +47 -44
  23. package/dist/application/Doctor.js +165 -197
  24. package/dist/application/DoctorDiagnostics.js +180 -0
  25. package/dist/application/ElectronBoundaryAnalysis.js +112 -0
  26. package/dist/application/ElectronBoundaryGraph.js +9 -0
  27. package/dist/application/ElectronBoundaryGraphContext.js +62 -0
  28. package/dist/application/ElectronBoundaryGraphIpc.js +242 -0
  29. package/dist/application/ElectronBoundaryGraphNative.js +86 -0
  30. package/dist/application/ElectronBoundaryGraphWindows.js +223 -0
  31. package/dist/application/EnhancedToolPagination.js +22 -0
  32. package/dist/application/EnhancedToolTypes.js +4 -0
  33. package/dist/application/EnhancedTools.js +58 -50
  34. package/dist/application/InstrumentedJavaScriptReplayHost.js +36 -0
  35. package/dist/application/InvestigationProviders.js +30 -0
  36. package/dist/application/InvestigationWorkspaceStore.js +24 -10
  37. package/dist/application/JavaScriptApplicationEvidence.js +26 -0
  38. package/dist/application/JavaScriptApplicationEvidenceGraph.js +89 -0
  39. package/dist/application/JavaScriptApplicationService.js +74 -0
  40. package/dist/application/JavaScriptApplicationWorkflowEvidence.js +29 -0
  41. package/dist/application/JavaScriptApplicationWorkflowService.js +90 -0
  42. package/dist/application/JavaScriptArtifactAnalysis.js +52 -7
  43. package/dist/application/JavaScriptArtifactFiles.js +6 -2
  44. package/dist/application/JavaScriptArtifactGraphBuilder.js +82 -17
  45. package/dist/application/JavaScriptArtifactGraphBundlers.js +225 -0
  46. package/dist/application/JavaScriptArtifactGraphContext.js +37 -36
  47. package/dist/application/JavaScriptArtifactGraphDocuments.js +27 -4
  48. package/dist/application/JavaScriptArtifactGraphEvidence.js +24 -14
  49. package/dist/application/JavaScriptArtifactGraphFindings.js +54 -8
  50. package/dist/application/JavaScriptArtifactGraphStructure.js +29 -101
  51. package/dist/application/JavaScriptArtifactPathResolution.js +269 -0
  52. package/dist/application/JavaScriptArtifactReconstruction.js +4 -1
  53. package/dist/application/JavaScriptArtifactReconstructionInput.js +2 -83
  54. package/dist/application/JavaScriptJsonModules.js +39 -0
  55. package/dist/application/JavaScriptModuleRelationships.js +262 -0
  56. package/dist/application/JavaScriptReplayPermission.js +16 -0
  57. package/dist/application/JavaScriptReplayPlanning.js +201 -0
  58. package/dist/application/JavaScriptReplayService.js +292 -0
  59. package/dist/application/JavaScriptRuntimeReconciliationEvidence.js +25 -0
  60. package/dist/application/JavaScriptRuntimeReconciliationService.js +27 -0
  61. package/dist/application/LinuxHopper.js +10 -0
  62. package/dist/application/MacHopper.js +22 -11
  63. package/dist/application/ManagedApplicationGraphService.js +55 -0
  64. package/dist/application/ManagedMemberComparisonService.js +122 -0
  65. package/dist/application/ManagedNativeVerificationService.js +39 -0
  66. package/dist/application/ManagedReconstructionService.js +58 -0
  67. package/dist/application/ManagedRuntimeCorrelationService.js +103 -0
  68. package/dist/application/NodeRuntimeCharacterizationService.js +196 -0
  69. package/dist/application/PermissionAuthority.js +106 -63
  70. package/dist/application/ProcessCaptureCapability.js +1 -1
  71. package/dist/application/ProcessCapturePermission.js +13 -0
  72. package/dist/application/ProcessCli.js +2 -12
  73. package/dist/application/ProcessHarness.js +1 -1
  74. package/dist/application/ProcessSampling.js +15 -11
  75. package/dist/application/ProjectPermissionStore.js +49 -9
  76. package/dist/application/RealHopperAssertions.js +76 -0
  77. package/dist/application/ReconstructionCoverageService.js +69 -0
  78. package/dist/application/ReconstructionCoverageWorkspaceStore.js +31 -0
  79. package/dist/application/RuntimeExecutableDiagnostics.js +172 -0
  80. package/dist/application/Setup.js +147 -259
  81. package/dist/application/SetupClientConfiguration.js +220 -0
  82. package/dist/application/SetupClients.js +24 -2
  83. package/dist/application/SetupPlan.js +123 -12
  84. package/dist/application/SetupSkill.js +26 -12
  85. package/dist/application/SupportedClients.js +1 -0
  86. package/dist/application/Uninstall.js +6 -3
  87. package/dist/application/WindowsCapabilities.js +86 -0
  88. package/dist/application/runtime.js +2 -0
  89. package/dist/artifacts/AsarArtifactReader.js +11 -0
  90. package/dist/browser/BrowserProcessStartup.js +88 -0
  91. package/dist/browser/CdpCaptureDocuments.js +12 -8
  92. package/dist/browser/CdpCaptureEventBodyShapes.js +75 -0
  93. package/dist/browser/CdpCaptureEventHandlers.js +336 -0
  94. package/dist/browser/CdpCaptureEventHelpers.js +71 -0
  95. package/dist/browser/CdpCaptureEventState.js +1 -0
  96. package/dist/browser/CdpCaptureEventTypes.js +1 -0
  97. package/dist/browser/CdpCaptureEvents.js +46 -464
  98. package/dist/browser/CdpElectronInspection.js +106 -162
  99. package/dist/browser/CdpElectronProvider.js +5 -1
  100. package/dist/browser/CdpElectronScriptEvents.js +69 -0
  101. package/dist/browser/CdpElectronScripts.js +94 -0
  102. package/dist/browser/CdpElectronWorkers.js +56 -0
  103. package/dist/browser/CdpObservationSession.js +51 -8
  104. package/dist/browser/CdpPageCapture.js +12 -129
  105. package/dist/browser/CdpPageCaptureScripts.js +97 -0
  106. package/dist/browser/CdpPageCaptureWorkers.js +46 -0
  107. package/dist/browser/CdpWebMcpDiscovery.js +38 -14
  108. package/dist/browser/PngVisualDiff.js +9 -2
  109. package/dist/catalogIdentity.js +8 -1
  110. package/dist/cli/artifactCommands.js +82 -0
  111. package/dist/cli/coreAnalysisCommands.js +232 -0
  112. package/dist/cli/managedCommands.js +397 -0
  113. package/dist/cli/managedProjectGraphCommand.js +24 -0
  114. package/dist/cli/options.js +9 -0
  115. package/dist/cli/setupCommands.js +108 -0
  116. package/dist/cli/types.js +1 -0
  117. package/dist/cli/utilityCommands.js +122 -0
  118. package/dist/cli.js +13 -383
  119. package/dist/cliApplicationCommands.js +176 -0
  120. package/dist/cliBrowserAdvancedCommands.js +73 -16
  121. package/dist/cliBrowserCommands.js +39 -115
  122. package/dist/cliCommandNames.js +17 -0
  123. package/dist/cliElectronCommands.js +100 -27
  124. package/dist/cliEvidenceCommands.js +13 -2
  125. package/dist/cliInvestigationCommands.js +53 -10
  126. package/dist/cliJsonInput.js +54 -0
  127. package/dist/cliObservationOptions.js +137 -0
  128. package/dist/cliPolicyCommands.js +80 -46
  129. package/dist/cliSetup.js +289 -0
  130. package/dist/config/environment.js +107 -0
  131. package/dist/config/parseConfig.js +228 -0
  132. package/dist/config/parsers.js +68 -0
  133. package/dist/config/permissions.js +30 -0
  134. package/dist/config/types.js +1 -0
  135. package/dist/config.js +1 -292
  136. package/dist/contracts/applicationToolContracts.js +225 -0
  137. package/dist/contracts/artifactToolContracts.js +5 -9
  138. package/dist/contracts/browserToolContracts.js +14 -62
  139. package/dist/contracts/electronToolContracts.js +45 -19
  140. package/dist/contracts/errorSchemas.js +1 -0
  141. package/dist/contracts/investigationExamples.js +0 -6
  142. package/dist/contracts/javascriptApplicationWorkflowExamples.js +46 -0
  143. package/dist/contracts/javascriptRuntimeReconciliationExample.js +208 -0
  144. package/dist/contracts/managedToolContracts.js +153 -0
  145. package/dist/contracts/managedWorkflowExamples.js +346 -0
  146. package/dist/contracts/managedWorkflowToolContracts.js +203 -0
  147. package/dist/contracts/nativeToolContracts.js +2 -6
  148. package/dist/contracts/promptContracts.js +18 -2
  149. package/dist/contracts/providerSelection.js +2 -0
  150. package/dist/contracts/toolContractExamples.js +10 -25
  151. package/dist/contracts/toolContracts.js +49 -47
  152. package/dist/contracts/toolEffects.js +174 -0
  153. package/dist/contracts/toolOutputSchemaGroups.js +232 -0
  154. package/dist/contracts/toolOutputSchemaPrimitives.js +327 -0
  155. package/dist/contracts/toolOutputSchemas.js +2 -535
  156. package/dist/doctorRuntime.js +42 -1
  157. package/dist/domain/analysisErrorPresentation.js +234 -0
  158. package/dist/domain/analysisErrorProjection.js +284 -0
  159. package/dist/domain/artifactComparison.js +37 -19
  160. package/dist/domain/binaryTarget.js +87 -37
  161. package/dist/domain/browserObservation.js +1 -282
  162. package/dist/domain/browserObservationSchemas.js +286 -0
  163. package/dist/domain/bundleComparison.js +4 -4
  164. package/dist/domain/electronObservation.js +13 -0
  165. package/dist/domain/electronStaticAnalysis.js +9 -0
  166. package/dist/domain/electronStaticAnalysisBrowser.js +206 -0
  167. package/dist/domain/electronStaticAnalysisIpc.js +171 -0
  168. package/dist/domain/electronStaticAnalysisNative.js +164 -0
  169. package/dist/domain/electronStaticAnalysisTypes.js +1 -0
  170. package/dist/domain/electronStaticAnalysisValues.js +103 -0
  171. package/dist/domain/errors.js +32 -448
  172. package/dist/domain/functionComparison.js +4 -165
  173. package/dist/domain/functionComparisonDimensions.js +164 -0
  174. package/dist/domain/functionComparisonSchemas.js +3 -8
  175. package/dist/domain/inputIssueProjection.js +52 -0
  176. package/dist/domain/javascriptApplicationAnalysis.js +155 -0
  177. package/dist/domain/javascriptApplicationChangeGraph.js +231 -0
  178. package/dist/domain/javascriptApplicationEvidenceSchemas.js +18 -0
  179. package/dist/domain/javascriptApplicationGraph.js +2 -1
  180. package/dist/domain/javascriptApplicationGraphSchemas.js +7 -0
  181. package/dist/domain/javascriptApplicationVersionComparison.js +116 -0
  182. package/dist/domain/javascriptApplicationVersionComparisonSchemas.js +139 -0
  183. package/dist/domain/javascriptApplicationVersionItems.js +233 -0
  184. package/dist/domain/javascriptApplicationVersionKeys.js +170 -0
  185. package/dist/domain/javascriptExportInstrumentation.js +97 -0
  186. package/dist/domain/javascriptFeatureSeed.js +140 -0
  187. package/dist/domain/javascriptFeatureTrace.js +232 -0
  188. package/dist/domain/javascriptFeatureTraceSchemas.js +136 -0
  189. package/dist/domain/javascriptFeatureTraversal.js +100 -0
  190. package/dist/domain/javascriptNativeHandoff.js +85 -0
  191. package/dist/domain/javascriptReplay.js +361 -0
  192. package/dist/domain/javascriptRuntimeLoadState.js +106 -0
  193. package/dist/domain/javascriptRuntimeReconciliation.js +42 -0
  194. package/dist/domain/javascriptRuntimeReconciliationGraph.js +169 -0
  195. package/dist/domain/javascriptRuntimeReconciliationMatching.js +247 -0
  196. package/dist/domain/javascriptRuntimeReconciliationParsing.js +160 -0
  197. package/dist/domain/javascriptRuntimeReconciliationResult.js +119 -0
  198. package/dist/domain/javascriptRuntimeReconciliationRuntime.js +316 -0
  199. package/dist/domain/javascriptRuntimeReconciliationSchemas.js +245 -0
  200. package/dist/domain/javascriptRuntimeStaticCandidates.js +193 -0
  201. package/dist/domain/javascriptSemanticAnalysis.js +386 -0
  202. package/dist/domain/javascriptSemanticIr.js +30 -0
  203. package/dist/domain/javascriptSemanticProjection.js +366 -0
  204. package/dist/domain/javascriptSemanticState.js +40 -0
  205. package/dist/domain/javascriptSemanticTraversal.js +22 -0
  206. package/dist/domain/javascriptSemanticValues.js +352 -0
  207. package/dist/domain/javascriptStaticAnalysis.js +26 -254
  208. package/dist/domain/javascriptStaticAnalysisBundler.js +209 -0
  209. package/dist/domain/javascriptStaticAnalysisCalls.js +180 -0
  210. package/dist/domain/javascriptStaticAnalysisFindings.js +39 -0
  211. package/dist/domain/javascriptStaticAnalysisHelpers.js +81 -2
  212. package/dist/domain/javascriptStaticAnalysisState.js +6 -0
  213. package/dist/domain/knownPageCoverage.js +21 -0
  214. package/dist/domain/managedApplicationGraph.js +206 -0
  215. package/dist/domain/managedApplicationGraphCoverage.js +170 -0
  216. package/dist/domain/managedApplicationGraphNodeCoverage.js +6 -0
  217. package/dist/domain/managedApplicationGraphNodes.js +336 -0
  218. package/dist/domain/managedArtifact.js +452 -0
  219. package/dist/domain/managedMemberComparison.js +211 -0
  220. package/dist/domain/managedMemberComparisonCoverage.js +72 -0
  221. package/dist/domain/managedMemberComparisonMatch.js +356 -0
  222. package/dist/domain/managedNativeVerification.js +46 -0
  223. package/dist/domain/managedNativeVerificationMatch.js +272 -0
  224. package/dist/domain/managedNativeVerificationSchemas.js +141 -0
  225. package/dist/domain/managedReconstruction.js +196 -0
  226. package/dist/domain/managedRuntimeCorrelation.js +184 -0
  227. package/dist/domain/nodeRuntimeCharacterization.js +66 -0
  228. package/dist/domain/permissionPolicy.js +2 -0
  229. package/dist/domain/reconstructionCoverage.js +387 -0
  230. package/dist/domain/reconstructionCoverageEvaluation.js +212 -0
  231. package/dist/domain/reconstructionVerificationSchemas.js +9 -3
  232. package/dist/domain/runtimeCharacterization.js +85 -0
  233. package/dist/domain/webBundleAnalyzer.js +3 -409
  234. package/dist/domain/webBundleAnalyzerAst.js +77 -0
  235. package/dist/domain/webBundleAnalyzerInspection.js +307 -0
  236. package/dist/domain/webBundleAnalyzerResult.js +120 -0
  237. package/dist/dotnet/ManagedArtifactInspector.js +339 -0
  238. package/dist/dotnet/ManagedMemberInspector.js +153 -0
  239. package/dist/dotnet/ManagedMemberInspectorCore.js +297 -0
  240. package/dist/dotnet/ManagedMemberInstructionDecoder.js +427 -0
  241. package/dist/dotnet/ManagedMemberRows.js +120 -0
  242. package/dist/dotnet/ManagedMetadataHeaps.js +131 -0
  243. package/dist/dotnet/ManagedMetadataInventory.js +104 -0
  244. package/dist/dotnet/ManagedMetadataInventoryRows.js +292 -0
  245. package/dist/dotnet/ManagedMetadataLayout.js +259 -0
  246. package/dist/dotnet/ManagedMetadataRowSizes.js +54 -0
  247. package/dist/dotnet/ManagedMethodBodyReader.js +143 -0
  248. package/dist/dotnet/ManagedNativeBoundaryHelpers.js +311 -0
  249. package/dist/dotnet/ManagedNativeBoundaryInspector.js +143 -0
  250. package/dist/dotnet/ManagedPeReader.js +188 -0
  251. package/dist/dotnet/ManagedReaderFailure.js +10 -0
  252. package/dist/dotnet/ManagedStaticProvider.js +203 -0
  253. package/dist/generatedPackageMetadata.js +2 -2
  254. package/dist/ghidra/GhidraClient.js +76 -91
  255. package/dist/ghidra/GhidraClientStartup.js +29 -0
  256. package/dist/ghidra/GhidraClientWire.js +34 -0
  257. package/dist/ghidra/GhidraDefaults.js +1 -1
  258. package/dist/ghidra/GhidraDiagnostics.js +6 -1
  259. package/dist/ghidra/GhidraInstallation.js +20 -15
  260. package/dist/ghidra/GhidraLauncher.js +93 -29
  261. package/dist/ghidra/GhidraProvider.js +67 -161
  262. package/dist/ghidra/GhidraProviderCapabilities.js +173 -0
  263. package/dist/ghidra/GhidraSessionValues.js +2 -0
  264. package/dist/ghidra/GhidraSocketConnection.js +44 -7
  265. package/dist/ghidra/GhidraTargetSnapshot.js +30 -0
  266. package/dist/ghidra/GhidraTransport.js +71 -0
  267. package/dist/identity.js +3 -2
  268. package/dist/main/messages.js +5 -0
  269. package/dist/main/reload.js +49 -0
  270. package/dist/main/shutdown.js +25 -0
  271. package/dist/main/startup.js +14 -0
  272. package/dist/main/state.js +26 -0
  273. package/dist/main/transport.js +61 -0
  274. package/dist/main/types.js +1 -0
  275. package/dist/main.js +35 -132
  276. package/dist/process/PrivateRuntimeRoot.js +3 -2
  277. package/dist/process/ProcessOwnership.js +35 -0
  278. package/dist/process/ProviderProcess.js +2 -0
  279. package/dist/replay/JavaScriptReplayWorker.js +300 -0
  280. package/dist/replay/LinuxJavaScriptReplayRunner.js +217 -0
  281. package/dist/replay/LinuxJavaScriptReplaySandbox.js +140 -0
  282. package/dist/replay/LinuxRuntimeClosure.js +46 -0
  283. package/dist/replay/LinuxSeccompPolicy.js +40 -0
  284. package/dist/replay/ReplayOutcome.js +95 -0
  285. package/dist/replay/ReplayProcessLifecycle.js +71 -0
  286. package/dist/replay/ReplayWorkerProtocol.js +55 -0
  287. package/dist/replay/SystemJavaScriptReplayHost.js +182 -0
  288. package/dist/server/ProcessCaptureElicitation.js +157 -0
  289. package/dist/server/createServer.js +158 -41
  290. package/dist/server/registerApplicationTools/characterization.js +57 -0
  291. package/dist/server/registerApplicationTools/compareVersions.js +34 -0
  292. package/dist/server/registerApplicationTools/controlledReplay.js +38 -0
  293. package/dist/server/registerApplicationTools/coverage.js +84 -0
  294. package/dist/server/registerApplicationTools/helpers.js +42 -0
  295. package/dist/server/registerApplicationTools/traceFeature.js +26 -0
  296. package/dist/server/registerApplicationTools/types.js +1 -0
  297. package/dist/server/registerApplicationTools.js +13 -0
  298. package/dist/server/registerArtifactComparisonTool.js +16 -9
  299. package/dist/server/registerBrowserTools.js +61 -60
  300. package/dist/server/registerBundleComparisonTool.js +17 -20
  301. package/dist/server/registerElectronTools.js +39 -12
  302. package/dist/server/registerEnhancedTools.js +52 -15
  303. package/dist/server/registerEvidenceResources.js +54 -0
  304. package/dist/server/registerEvidenceTools.js +5 -1
  305. package/dist/server/registerFunctionComparisonTool.js +14 -7
  306. package/dist/server/registerInvestigationTools/helpers.js +74 -0
  307. package/dist/server/registerInvestigationTools/types.js +1 -0
  308. package/dist/server/registerInvestigationTools.js +103 -132
  309. package/dist/server/registerManagedTools.js +6 -0
  310. package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +65 -0
  311. package/dist/server/registerManagedWorkflowTools/contract.js +8 -0
  312. package/dist/server/registerManagedWorkflowTools/evidence.js +43 -0
  313. package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +39 -0
  314. package/dist/server/registerManagedWorkflowTools/planManagedRuntimeCorrelation.js +39 -0
  315. package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +52 -0
  316. package/dist/server/registerManagedWorkflowTools/types.js +1 -0
  317. package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +75 -0
  318. package/dist/server/registerManagedWorkflowTools.js +13 -0
  319. package/dist/server/registerOfficialTools.js +81 -67
  320. package/dist/server/registerProcessComparisonTool.js +25 -47
  321. package/dist/server/registerSessionRecordTools.js +137 -0
  322. package/dist/server/registerSessionStatusTool.js +9 -8
  323. package/dist/server/registerSessionTools.js +77 -216
  324. package/dist/server/sessionAvailabilityPolicy.js +10 -0
  325. package/dist/server/sessionEvidence.js +14 -19
  326. package/dist/server/toolInputValidation.js +77 -0
  327. package/dist/server/toolRegistrationOptions.js +177 -2
  328. package/dist/server/toolResult.js +30 -17
  329. package/package.json +21 -14
  330. package/scripts/rea.mjs +1 -1
  331. package/skills/{rea-analysis → reverse-engineer-anything}/SKILL.md +75 -6
  332. package/scripts/prepare-node-pty.mjs +0 -35
  333. package/scripts/rebuild-native.mjs +0 -22
@@ -0,0 +1,182 @@
1
+ import { constants } from "node:fs";
2
+ import { mkdtemp, open, readFile, realpath, rm, stat, writeFile, } from "node:fs/promises";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+ import { spawn } from "node:child_process";
7
+ import { digestBytes } from "../application/JavaScriptReplayPlanning.js";
8
+ import { buildLinuxX64ReplaySeccomp, linuxX64ReplaySeccompDigest, } from "./LinuxSeccompPolicy.js";
9
+ import { resolveLinuxRuntimeClosure } from "./LinuxRuntimeClosure.js";
10
+ const VERSION_OUTPUT_LIMIT = 16 * 1024;
11
+ /** Production planning host for descriptor-backed reads and fail-closed probes. */
12
+ export class SystemJavaScriptReplayHost {
13
+ async readSource(path, maximumBytes) {
14
+ const canonicalPath = await realpath(path);
15
+ const handle = await open(canonicalPath, constants.O_RDONLY | constants.O_NOFOLLOW);
16
+ try {
17
+ const metadata = await handle.stat();
18
+ if (!metadata.isFile() || metadata.size > maximumBytes)
19
+ throw new RangeError(`Replay source exceeds its declared limit: ${canonicalPath}`);
20
+ const bytes = await handle.readFile();
21
+ return { canonicalPath, bytes };
22
+ }
23
+ finally {
24
+ await handle.close();
25
+ }
26
+ }
27
+ async identifyExecutable(path, versionArguments) {
28
+ const canonicalPath = await realpath(path);
29
+ const metadata = await stat(canonicalPath);
30
+ if (!metadata.isFile())
31
+ throw new TypeError(`Replay executable is not a file: ${canonicalPath}`);
32
+ const [bytes, version] = await Promise.all([
33
+ readFile(canonicalPath),
34
+ capture(canonicalPath, versionArguments, VERSION_OUTPUT_LIMIT),
35
+ ]);
36
+ return {
37
+ path: canonicalPath,
38
+ version: version.trim(),
39
+ sha256: digestBytes(bytes),
40
+ };
41
+ }
42
+ identifyWorker() {
43
+ return this.identifyExecutable(fileURLToPath(new URL("./JavaScriptReplayWorker.js", import.meta.url)), []);
44
+ }
45
+ identifyRuntimeClosure(nodePath) {
46
+ return resolveLinuxRuntimeClosure(nodePath);
47
+ }
48
+ seccompDigest() {
49
+ return linuxX64ReplaySeccompDigest();
50
+ }
51
+ async probe(policy) {
52
+ if (process.platform !== "linux" || process.arch !== "x64")
53
+ throw new TypeError("Controlled replay requires Linux x86_64 in v1");
54
+ const bwrapMetadata = await stat(policy.bubblewrapPath);
55
+ if ((bwrapMetadata.mode & 0o4000) !== 0)
56
+ throw new TypeError("Setuid Bubblewrap is not admitted by replay policy");
57
+ if ((await readFile("/sys/fs/cgroup/cgroup.controllers", "utf8")).trim()
58
+ .length === 0)
59
+ throw new TypeError("Controlled replay requires delegated cgroup v2");
60
+ const directory = await mkdtemp(join(tmpdir(), "rea-replay-probe-"));
61
+ const filterPath = join(directory, "seccomp.bpf");
62
+ await writeFile(filterPath, buildLinuxX64ReplaySeccomp(), { mode: 0o600 });
63
+ const filter = await open(filterPath, "r");
64
+ try {
65
+ await run(policy.bubblewrapPath, [
66
+ "--unshare-all",
67
+ "--unshare-user",
68
+ "--disable-userns",
69
+ "--new-session",
70
+ "--die-with-parent",
71
+ "--cap-drop",
72
+ "ALL",
73
+ "--ro-bind",
74
+ "/usr",
75
+ "/usr",
76
+ "--ro-bind",
77
+ "/lib",
78
+ "/lib",
79
+ "--ro-bind-try",
80
+ "/lib64",
81
+ "/lib64",
82
+ "--proc",
83
+ "/proc",
84
+ "--dev",
85
+ "/dev",
86
+ "--seccomp",
87
+ "3",
88
+ "--",
89
+ "/usr/bin/true",
90
+ ], ["ignore", "pipe", "pipe", filter.fd]);
91
+ await runExpectFailure(policy.bubblewrapPath, [
92
+ "--unshare-all",
93
+ "--unshare-user",
94
+ "--disable-userns",
95
+ "--new-session",
96
+ "--die-with-parent",
97
+ "--cap-drop",
98
+ "ALL",
99
+ "--ro-bind",
100
+ "/usr",
101
+ "/usr",
102
+ "--ro-bind",
103
+ "/lib",
104
+ "/lib",
105
+ "--ro-bind-try",
106
+ "/lib64",
107
+ "/lib64",
108
+ "--proc",
109
+ "/proc",
110
+ "--dev",
111
+ "/dev",
112
+ "--seccomp",
113
+ "3",
114
+ "--",
115
+ "/usr/bin/unshare",
116
+ "--mount",
117
+ "/usr/bin/true",
118
+ ], ["ignore", "pipe", "pipe", filter.fd]);
119
+ await run(policy.systemdRunPath, [
120
+ "--user",
121
+ "--pipe",
122
+ "--wait",
123
+ "--service-type=exec",
124
+ "--quiet",
125
+ "--property=MemoryMax=16777216",
126
+ "--property=MemorySwapMax=0",
127
+ "--property=TasksMax=2",
128
+ "--",
129
+ "/usr/bin/true",
130
+ ]);
131
+ }
132
+ finally {
133
+ await filter.close();
134
+ await rm(directory, { recursive: true, force: true });
135
+ }
136
+ }
137
+ }
138
+ const capture = async (executable, arguments_, maximumBytes) => {
139
+ if (arguments_.length === 0)
140
+ return "content-addressed-worker-v1";
141
+ const result = await collect(executable, arguments_, maximumBytes);
142
+ if (result.code !== 0)
143
+ throw new TypeError(`Replay executable probe failed: ${executable}`);
144
+ return result.stdout.length > 0 ? result.stdout : result.stderr;
145
+ };
146
+ const run = async (executable, arguments_, stdio) => {
147
+ const result = await collect(executable, arguments_, VERSION_OUTPUT_LIMIT, stdio);
148
+ if (result.code !== 0)
149
+ throw new TypeError(`Replay feature probe failed (${String(result.code)}): ${executable}: ${result.stderr.trim()}`);
150
+ };
151
+ const runExpectFailure = async (executable, arguments_, stdio) => {
152
+ const result = await collect(executable, arguments_, VERSION_OUTPUT_LIMIT, stdio);
153
+ if (result.code === 0)
154
+ throw new TypeError(`Replay denial probe unexpectedly succeeded: ${executable}`);
155
+ };
156
+ const collect = async (executable, arguments_, maximumBytes, stdio = ["ignore", "pipe", "pipe"]) => new Promise((resolve, reject) => {
157
+ const child = spawn(executable, [...arguments_], { stdio });
158
+ const timeout = setTimeout(() => child.kill("SIGKILL"), 5_000);
159
+ timeout.unref();
160
+ let stdout = "";
161
+ let stderr = "";
162
+ const retain = (current, chunk) => {
163
+ const remaining = Math.max(0, maximumBytes - Buffer.byteLength(current));
164
+ return current + chunk.subarray(0, remaining).toString("utf8");
165
+ };
166
+ if (child.stdout !== null)
167
+ child.stdout.on("data", (chunk) => {
168
+ stdout = retain(stdout, chunk);
169
+ });
170
+ if (child.stderr !== null)
171
+ child.stderr.on("data", (chunk) => {
172
+ stderr = retain(stderr, chunk);
173
+ });
174
+ child.once("error", (error) => {
175
+ clearTimeout(timeout);
176
+ reject(error);
177
+ });
178
+ child.once("close", (code) => {
179
+ clearTimeout(timeout);
180
+ resolve({ code, stdout, stderr });
181
+ });
182
+ });
@@ -0,0 +1,157 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { acceptedContent, inputRequired, inputResponse, } from "@modelcontextprotocol/server";
3
+ import { z } from "zod";
4
+ import { PermissionRequiredError } from "../domain/errors.js";
5
+ import { isPermissionRequestWithinCeiling, } from "../domain/permissionPolicy.js";
6
+ const RESPONSE_KEY = "process_capture_grant";
7
+ const STATE_VERSION = 1;
8
+ /** Shared continuation, replay, and round limits for process capture consent. */
9
+ export const PROCESS_CAPTURE_ELICITATION_POLICY = {
10
+ protocolVersions: ["2026-07-28"],
11
+ stateTtlSeconds: 600,
12
+ roundTimeoutMs: 600_000,
13
+ maxConsumedNonces: 4_096,
14
+ };
15
+ const grantResponseSchema = z.strictObject({
16
+ lifetime: z.enum(["once", "session"]).meta({ default: "session" }),
17
+ });
18
+ const grantResponseJsonSchema = { ...z.toJSONSchema(grantResponseSchema) };
19
+ // MCP elicitation accepts a reduced JSON Schema subset. These generator
20
+ // annotations do not change the schema's fields or validation semantics; the
21
+ // Standard Schema marker would make the SDK regenerate the removed keywords.
22
+ Reflect.deleteProperty(grantResponseJsonSchema, "$schema");
23
+ Reflect.deleteProperty(grantResponseJsonSchema, "additionalProperties");
24
+ const stateSchema = z.strictObject({
25
+ version: z.literal(STATE_VERSION),
26
+ nonce: z.string().uuid(),
27
+ request: z.strictObject({
28
+ capability: z.literal("process_capture"),
29
+ roots: z.array(z.string()),
30
+ executables: z.array(z.string()),
31
+ environment_names: z.array(z.string()),
32
+ origins: z.array(z.string()).optional(),
33
+ network: z.enum(["none", "loopback", "external"]),
34
+ mount: z.boolean(),
35
+ operation_identity: z.string(),
36
+ }),
37
+ });
38
+ /** Authorize capture or return a signed MCP input-required continuation. */
39
+ export const authorizeProcessCaptureWithElicitation = async (authority, request, context, elicitation) => {
40
+ const supported = elicitation.supported(context);
41
+ const initial = await authority.authorize(request, "read", {
42
+ elicitationSupported: supported,
43
+ });
44
+ if (initial.ok || !(initial.error instanceof PermissionRequiredError))
45
+ return initial;
46
+ const denied = initial.error;
47
+ if (!supported ||
48
+ denied.requested.capability !== "process_capture" ||
49
+ denied.ceiling === null ||
50
+ !isPermissionRequestWithinCeiling(denied.requested, denied.ceiling))
51
+ return initial;
52
+ const encodedState = context.mcpReq.requestState();
53
+ if (encodedState !== undefined) {
54
+ const state = stateSchema.safeParse(encodedState);
55
+ if (!state.success || !sameRequest(state.data.request, denied.requested))
56
+ return initial;
57
+ const response = inputResponse(context.mcpReq.inputResponses, RESPONSE_KEY);
58
+ if (response.kind === "elicit") {
59
+ if (!consumeNonce(elicitation.consumedNonces, state.data.nonce, elicitation.now()))
60
+ return initial;
61
+ }
62
+ if (response.kind === "elicit" && response.action === "accept") {
63
+ const content = acceptedContent(context.mcpReq.inputResponses, RESPONSE_KEY, grantResponseSchema);
64
+ if (content === undefined)
65
+ return initial;
66
+ return grantAndAuthorize(authority, state.data.request, content.lifetime);
67
+ }
68
+ if (response.kind === "elicit" &&
69
+ (response.action === "decline" || response.action === "cancel"))
70
+ return initial;
71
+ }
72
+ const state = await elicitation.stateCodec.mint({
73
+ version: STATE_VERSION,
74
+ nonce: randomUUID(),
75
+ request: {
76
+ capability: "process_capture",
77
+ roots: [...denied.requested.roots],
78
+ executables: [...denied.requested.executables],
79
+ environment_names: [...denied.requested.environment_names],
80
+ network: denied.requested.network,
81
+ mount: denied.requested.mount,
82
+ operation_identity: denied.requested.operation_identity,
83
+ ...(denied.requested.origins === undefined
84
+ ? {}
85
+ : { origins: [...denied.requested.origins] }),
86
+ },
87
+ });
88
+ return inputRequired({
89
+ inputRequests: {
90
+ [RESPONSE_KEY]: inputRequired.elicit({
91
+ message: permissionMessage(denied.requested),
92
+ requestedSchema: grantResponseJsonSchema,
93
+ }),
94
+ },
95
+ requestState: state,
96
+ });
97
+ };
98
+ const grantAndAuthorize = async (authority, request, lifetime) => {
99
+ const grant = {
100
+ ...request,
101
+ grant_id: `elicited:${randomUUID()}`,
102
+ lifetime,
103
+ operation_identity: lifetime === "once" ? request.operation_identity : null,
104
+ expires_at: null,
105
+ };
106
+ const granted = authority.grant(grant);
107
+ if (!granted.ok)
108
+ return authority.authorize(request, "read", {
109
+ elicitationSupported: true,
110
+ });
111
+ let authorized;
112
+ try {
113
+ authorized = await authority.authorize(request, "read", {
114
+ elicitationSupported: true,
115
+ });
116
+ }
117
+ catch (cause) {
118
+ authority.revoke(grant.grant_id);
119
+ throw cause;
120
+ }
121
+ if (!authorized.ok)
122
+ authority.revoke(grant.grant_id);
123
+ return authorized;
124
+ };
125
+ const sameRequest = (left, right) => left.capability === right.capability &&
126
+ left.network === right.network &&
127
+ left.mount === right.mount &&
128
+ left.operation_identity === right.operation_identity &&
129
+ sameOptionalStrings(left.origins, right.origins) &&
130
+ sameStrings(left.roots, right.roots) &&
131
+ sameStrings(left.executables, right.executables) &&
132
+ sameStrings(left.environment_names, right.environment_names);
133
+ const sameStrings = (left, right) => left.length === right.length &&
134
+ left.every((value, index) => value === right[index]);
135
+ const sameOptionalStrings = (left, right) => left === undefined
136
+ ? right === undefined
137
+ : right !== undefined && sameStrings(left, right);
138
+ const consumeNonce = (consumed, nonce, now) => {
139
+ for (const [candidate, expiresAt] of consumed)
140
+ if (expiresAt <= now)
141
+ consumed.delete(candidate);
142
+ if (consumed.has(nonce) ||
143
+ consumed.size >= PROCESS_CAPTURE_ELICITATION_POLICY.maxConsumedNonces)
144
+ return false;
145
+ consumed.set(nonce, now + PROCESS_CAPTURE_ELICITATION_POLICY.stateTtlSeconds * 1_000);
146
+ return true;
147
+ };
148
+ const permissionMessage = (request) => [
149
+ "Allow REA to run this exact process-capture scope?",
150
+ `Executable: ${request.executables.join(", ") || "none"}`,
151
+ `Filesystem roots: ${request.roots.join(", ") || "none"}`,
152
+ `Environment names: ${request.environment_names.join(", ") || "none"}`,
153
+ `Origins: ${request.origins?.join(", ") || "none"}`,
154
+ `Network: ${request.network}`,
155
+ `Mount access: ${request.mount ? "yes" : "no"}`,
156
+ "Choose whether the grant applies once or for this MCP session.",
157
+ ].join("\n");
@@ -1,16 +1,23 @@
1
- import { McpServer } from "@modelcontextprotocol/server";
1
+ import { randomBytes } from "node:crypto";
2
+ import { CLIENT_CAPABILITIES_META_KEY, createRequestStateCodec, McpServer, PROTOCOL_VERSION_META_KEY, } from "@modelcontextprotocol/server";
2
3
  import { PRODUCT_IDENTITY } from "../identity.js";
3
4
  import { registerEnhancedTools } from "./registerEnhancedTools.js";
4
5
  import { registerOfficialTools } from "./registerOfficialTools.js";
5
6
  import { registerSessionTools } from "./registerSessionTools.js";
6
7
  import { registerNativeTools } from "./registerNativeTools.js";
7
8
  import { registerArtifactTools } from "./registerArtifactTools.js";
9
+ import { registerManagedTools } from "./registerManagedTools.js";
10
+ import { registerManagedWorkflowTools } from "./registerManagedWorkflowTools.js";
8
11
  import { silentLogger } from "../logger.js";
9
12
  import { registerGuidedPrompts } from "./registerPrompts.js";
10
13
  import { registerEvidenceResources } from "./registerEvidenceResources.js";
11
14
  import { createServerIdentity } from "../serverIdentity.js";
12
15
  import { registerBrowserTools } from "./registerBrowserTools.js";
13
16
  import { registerElectronTools } from "./registerElectronTools.js";
17
+ import { registerApplicationTools } from "./registerApplicationTools.js";
18
+ import { LinuxJavaScriptReplayRunner } from "../replay/LinuxJavaScriptReplayRunner.js";
19
+ import { SystemJavaScriptReplayHost } from "../replay/SystemJavaScriptReplayHost.js";
20
+ import { PROCESS_CAPTURE_ELICITATION_POLICY, } from "./ProcessCaptureElicitation.js";
14
21
  /**
15
22
  * Construct one MCP server without acquiring subprocess resources.
16
23
  * Supplying a session adds target lifecycle tools; omitting it retains the
@@ -19,6 +26,11 @@ import { registerElectronTools } from "./registerElectronTools.js";
19
26
  export const createServer = (analysis, session, options = {}) => {
20
27
  const startedAt = new Date().toISOString();
21
28
  const logger = options.logger ?? silentLogger;
29
+ const permissionAuthority = options.permissionAuthority?.createConnectionAuthority();
30
+ const processCaptureStateCodec = createRequestStateCodec({
31
+ key: randomBytes(32),
32
+ ttlSeconds: PROCESS_CAPTURE_ELICITATION_POLICY.stateTtlSeconds,
33
+ });
22
34
  const server = new McpServer({
23
35
  name: PRODUCT_IDENTITY.mcpServerKey,
24
36
  version: PRODUCT_IDENTITY.packageVersion,
@@ -27,17 +39,88 @@ export const createServer = (analysis, session, options = {}) => {
27
39
  tools: { listChanged: true },
28
40
  resources: { listChanged: true },
29
41
  },
42
+ inputRequired: {
43
+ maxRounds: 3,
44
+ roundTimeoutMs: PROCESS_CAPTURE_ELICITATION_POLICY.roundTimeoutMs,
45
+ },
46
+ requestState: { verify: processCaptureStateCodec.verify },
30
47
  instructions: session === undefined
31
48
  ? "Reverse-engineering tools for an active analysis target. Start with binary_overview."
32
49
  : "Reverse-engineering tools for configured analysis providers. Open a target with open_binary, then start with binary_overview.",
33
50
  });
51
+ server.server.onclose = () => {
52
+ permissionAuthority?.clearSessionGrants();
53
+ };
34
54
  session?.onAvailabilityChanged?.(() => server.sendToolListChanged());
55
+ registerServerIdentityResource(server, startedAt);
56
+ const toolLogger = logger.child({ layer: "server" });
57
+ const { activeTarget, recordEvidence, recordEvidenceWithUnknown } = createSessionRecorders(server, session);
58
+ const toolContext = {
59
+ server,
60
+ analysis,
61
+ session,
62
+ options,
63
+ logger: toolLogger,
64
+ permissionAuthority,
65
+ activeTarget,
66
+ recordEvidence,
67
+ recordEvidenceWithUnknown,
68
+ };
69
+ registerBinaryAnalysisTools(toolContext);
70
+ registerObservationTools(toolContext);
71
+ registerGuidedPrompts(server, analysis, session);
72
+ if (session !== undefined) {
73
+ registerEvidenceResources(server, session);
74
+ registerSessionTools(server, session, toolLogger, {
75
+ ...options,
76
+ ...(permissionAuthority === undefined ? {} : { permissionAuthority }),
77
+ startedAt,
78
+ processCaptureElicitation: {
79
+ stateCodec: processCaptureStateCodec,
80
+ supported: (context) => {
81
+ const envelope = context.mcpReq.envelope;
82
+ const version = envelope?.[PROTOCOL_VERSION_META_KEY];
83
+ const capabilities = envelope?.[CLIENT_CAPABILITIES_META_KEY];
84
+ return (typeof version === "string" &&
85
+ PROCESS_CAPTURE_ELICITATION_POLICY.protocolVersions.some((supported) => supported === version) &&
86
+ isRecord(capabilities) &&
87
+ isRecord(capabilities.elicitation) &&
88
+ capabilities.elicitation.form !== undefined);
89
+ },
90
+ now: Date.now,
91
+ consumedNonces: new Map(),
92
+ },
93
+ });
94
+ }
95
+ return server;
96
+ };
97
+ const createSessionRecorders = (server, session) => ({
98
+ activeTarget: session === undefined ? undefined : () => session.activeTarget(),
99
+ recordEvidence: session === undefined
100
+ ? undefined
101
+ : (evidence) => {
102
+ const recorded = session.recordEvidence(evidence);
103
+ if (recorded.ok && recorded.value === "added")
104
+ server.sendResourceListChanged();
105
+ return recorded;
106
+ },
107
+ recordEvidenceWithUnknown: session === undefined
108
+ ? undefined
109
+ : (evidence, input) => {
110
+ const recorded = session.recordEvidenceWithUnknown(evidence, input);
111
+ if (recorded.ok)
112
+ server.sendResourceListChanged();
113
+ return recorded;
114
+ },
115
+ });
116
+ const registerServerIdentityResource = (server, startedAt) => {
35
117
  server.registerResource("server-identity", "rea://server/identity", {
36
118
  title: "REA server identity",
37
119
  description: "Live package, SDK, protocol, and catalog identity.",
38
120
  mimeType: "application/json",
39
121
  }, (uri) => {
40
122
  const client = server.server.getClientVersion();
123
+ const protocolVersion = server.server.getNegotiatedProtocolVersion();
41
124
  return {
42
125
  contents: [
43
126
  {
@@ -46,75 +129,109 @@ export const createServer = (analysis, session, options = {}) => {
46
129
  text: JSON.stringify(createServerIdentity({
47
130
  startedAt,
48
131
  ...(client === undefined ? {} : { client }),
49
- ...(server.server.getNegotiatedProtocolVersion() === undefined
50
- ? {}
51
- : {
52
- protocolVersion: server.server.getNegotiatedProtocolVersion(),
53
- }),
132
+ ...(protocolVersion === undefined ? {} : { protocolVersion }),
54
133
  }), null, 2),
55
134
  },
56
135
  ],
57
136
  };
58
137
  });
59
- const toolLogger = logger.child({ layer: "server" });
60
- const activeTarget = session === undefined ? undefined : () => session.activeTarget();
61
- const recordEvidence = session === undefined
138
+ };
139
+ const registerBinaryAnalysisTools = ({ server, analysis, session, options, logger, permissionAuthority, activeTarget, recordEvidence, recordEvidenceWithUnknown, }) => {
140
+ const recordUnknown = session === undefined
62
141
  ? undefined
63
- : (evidence) => {
64
- const recorded = session.recordEvidence(evidence);
65
- if (recorded.ok && recorded.value === "added")
66
- server.sendResourceListChanged();
67
- return recorded;
68
- };
142
+ : (input) => session.recordUnknown(input);
69
143
  registerOfficialTools(server, analysis, {
70
- logger: toolLogger,
144
+ logger,
71
145
  activeTarget,
72
146
  recordEvidence,
73
- recordUnknown: session === undefined
74
- ? undefined
75
- : (input) => session.recordUnknown(input),
147
+ recordUnknown,
76
148
  });
77
149
  registerEnhancedTools(server, analysis, {
78
- logger: toolLogger,
150
+ logger,
79
151
  activeTarget,
80
152
  analysisProfile: session === undefined ? undefined : () => session.analysisProfile(),
81
153
  recordEvidence,
82
- recordUnknown: session === undefined
83
- ? undefined
84
- : (input) => session.recordUnknown(input),
154
+ recordUnknown,
85
155
  });
86
156
  registerNativeTools(server, analysis, {
87
- logger: toolLogger,
157
+ logger,
88
158
  activeTarget,
89
159
  recordEvidence,
90
160
  });
91
161
  registerArtifactTools(server, analysis, {
92
- logger: toolLogger,
162
+ logger,
163
+ activeTarget,
164
+ recordEvidence,
165
+ ...(permissionAuthority === undefined ? {} : { permissionAuthority }),
166
+ });
167
+ registerManagedTools(server, analysis, {
168
+ logger,
93
169
  activeTarget,
94
170
  recordEvidence,
95
- ...(options.permissionAuthority === undefined
96
- ? {}
97
- : { permissionAuthority: options.permissionAuthority }),
98
171
  });
172
+ if (session !== undefined)
173
+ registerManagedWorkflowTools(server, {
174
+ logger,
175
+ recordEvidence,
176
+ recordEvidenceWithUnknown,
177
+ session,
178
+ runtime: {
179
+ policy: options.managedRuntimePolicy ?? {
180
+ enabled: false,
181
+ roots: [],
182
+ executablePath: "/usr/bin/dotnet",
183
+ },
184
+ authority: permissionAuthority,
185
+ },
186
+ });
187
+ };
188
+ const registerObservationTools = ({ server, session, options, logger, permissionAuthority, recordEvidence, recordEvidenceWithUnknown, }) => {
99
189
  registerBrowserTools(server, {
100
- logger: toolLogger,
190
+ logger,
101
191
  browser: options.browserObservation,
102
- permissionAuthority: options.permissionAuthority,
192
+ permissionAuthority,
103
193
  recordEvidence,
104
194
  });
105
195
  registerElectronTools(server, {
106
- logger: toolLogger,
196
+ logger,
107
197
  electron: options.electronObservation,
108
- permissionAuthority: options.permissionAuthority,
198
+ permissionAuthority,
109
199
  recordEvidence,
110
200
  });
111
- registerGuidedPrompts(server, analysis, session);
112
- if (session !== undefined) {
113
- registerEvidenceResources(server, session);
114
- registerSessionTools(server, session, toolLogger, {
115
- ...options,
116
- startedAt,
117
- });
118
- }
119
- return server;
201
+ registerApplicationTools(server, {
202
+ logger,
203
+ recordEvidence,
204
+ recordEvidenceWithUnknown,
205
+ evidenceFilePolicy: options.evidenceFilePolicy ?? {
206
+ roots: [],
207
+ maxBytes: 1,
208
+ maxDepth: 1,
209
+ maxStringLength: 1,
210
+ maxNodes: 1,
211
+ },
212
+ permissionAuthority,
213
+ retainCoverageWorkspace: session === undefined
214
+ ? undefined
215
+ : (workspace) => {
216
+ const retained = session.retainReconstructionCoverageWorkspace(workspace);
217
+ if (retained === "added")
218
+ server.sendResourceListChanged();
219
+ return retained;
220
+ },
221
+ replay: {
222
+ policy: options.javascriptReplayPolicy ?? {
223
+ enabled: false,
224
+ roots: [],
225
+ nodePath: process.execPath,
226
+ bubblewrapPath: "/usr/bin/bwrap",
227
+ systemdRunPath: "/usr/bin/systemd-run",
228
+ systemctlPath: "/usr/bin/systemctl",
229
+ shellPath: "/usr/bin/bash",
230
+ },
231
+ host: options.javascriptReplayHost ?? new SystemJavaScriptReplayHost(),
232
+ runner: options.javascriptReplayRunner ?? new LinuxJavaScriptReplayRunner(),
233
+ authority: permissionAuthority,
234
+ },
235
+ });
120
236
  };
237
+ const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
@@ -0,0 +1,57 @@
1
+ import { executeNodeCharacterization, prepareNodeCharacterization, } from "../../application/NodeRuntimeCharacterizationService.js";
2
+ import { APPLICATION_TOOL_CONTRACTS } from "../../contracts/applicationToolContracts.js";
3
+ import { nodeCharacterizationExecutionInputSchema, nodeCharacterizationExecutionOutputSchema, nodeCharacterizationPreparationInputSchema, nodeCharacterizationPreparationOutputSchema, } from "../../domain/nodeRuntimeCharacterization.js";
4
+ import { parseEvidence } from "../../domain/evidence.js";
5
+ import { logToolExecution } from "../toolLogging.js";
6
+ import { toCallToolResult } from "../toolResult.js";
7
+ import { toolRegistrationOptions } from "../toolRegistrationOptions.js";
8
+ import { safeParseToolInput } from "../toolInputValidation.js";
9
+ import { mcpProgressReporter } from "../mcpProgress.js";
10
+ import { recordSources } from "./helpers.js";
11
+ const prepareContract = APPLICATION_TOOL_CONTRACTS[3];
12
+ const executeContract = APPLICATION_TOOL_CONTRACTS[4];
13
+ /** Register node runtime characterization prepare and execute tools. */
14
+ export const registerCharacterizationTools = (server, options) => {
15
+ server.registerTool(prepareContract.name, toolRegistrationOptions(prepareContract), async (input, context) => {
16
+ const parsed = safeParseToolInput(nodeCharacterizationPreparationInputSchema, input, prepareContract.name);
17
+ if (!parsed.ok)
18
+ return toCallToolResult(parsed, prepareContract);
19
+ const result = await logToolExecution(options.logger, prepareContract.name, () => prepareNodeCharacterization(options.replay, parsed.value, {
20
+ signal: context.mcpReq.signal,
21
+ progress: mcpProgressReporter(context),
22
+ }));
23
+ if (!result.ok)
24
+ return toCallToolResult(result, prepareContract);
25
+ const output = nodeCharacterizationPreparationOutputSchema.parse(result.value);
26
+ const recorded = options.recordEvidence?.(parseEvidence(output.transformation_evidence));
27
+ if (recorded !== undefined && !recorded.ok)
28
+ return toCallToolResult(recorded, prepareContract);
29
+ return toCallToolResult(result, prepareContract, {
30
+ evidenceResourcesAvailable: options.recordEvidence !== undefined,
31
+ });
32
+ });
33
+ server.registerTool(executeContract.name, toolRegistrationOptions(executeContract), async (input, context) => {
34
+ const parsed = safeParseToolInput(nodeCharacterizationExecutionInputSchema, input, executeContract.name);
35
+ if (!parsed.ok)
36
+ return toCallToolResult(parsed, executeContract);
37
+ const result = await logToolExecution(options.logger, executeContract.name, () => executeNodeCharacterization(options.replay, parsed.value, {
38
+ signal: context.mcpReq.signal,
39
+ progress: mcpProgressReporter(context),
40
+ }));
41
+ if (!result.ok)
42
+ return toCallToolResult(result, executeContract);
43
+ const output = nodeCharacterizationExecutionOutputSchema.parse(result.value);
44
+ const sources = [
45
+ output.transformation_evidence,
46
+ ...output.replay.source_evidence,
47
+ ...(output.replay.evidence === null ? [] : [output.replay.evidence]),
48
+ output.evidence,
49
+ ].map((item) => parseEvidence(item));
50
+ const recorded = recordSources(options.recordEvidence, sources);
51
+ if (!recorded.ok)
52
+ return toCallToolResult(recorded, executeContract);
53
+ return toCallToolResult(result, executeContract, {
54
+ evidenceResourcesAvailable: options.recordEvidence !== undefined,
55
+ });
56
+ });
57
+ };