rea-agents 4.0.0 → 4.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 (416) hide show
  1. package/README.md +93 -30
  2. package/bridge/ghidra/ReaGhidraBridge.java +358 -15
  3. package/bridge/ghidra/ReaGhidraExtensions.java +113 -0
  4. package/bridge/ghidra/ReaGhidraPrepareCom.java +32 -0
  5. package/dist/android/AndroidTargetSnapshot.js +34 -0
  6. package/dist/android/JadxAnalysis.js +191 -0
  7. package/dist/android/JadxConfiguration.js +41 -0
  8. package/dist/android/JadxMcpTransport.js +145 -0
  9. package/dist/android/JadxProtocol.js +101 -0
  10. package/dist/android/JadxProvider.js +170 -0
  11. package/dist/android/JadxRelease.js +19 -0
  12. package/dist/android/JadxSession.js +97 -0
  13. package/dist/application/AnalysisContextQueries.js +2 -1
  14. package/dist/application/AnalysisProviderEvaluation.js +5 -3
  15. package/dist/application/AnalysisProviderRegistry.js +2 -1
  16. package/dist/application/AnalysisSnapshotCache.js +4 -1
  17. package/dist/application/AnalysisSnapshotFiles.js +1 -1
  18. package/dist/application/AndroidAnalysisPort.js +1 -0
  19. package/dist/application/AndroidAnalysisService.js +37 -0
  20. package/dist/application/ArtifactExtraction.js +7 -4
  21. package/dist/application/ArtifactGraphConstruction.js +10 -17
  22. package/dist/application/ArtifactInventory/scanCanonical.js +8 -7
  23. package/dist/application/BinarySession.js +16 -3
  24. package/dist/application/BinarySessionExecution.js +4 -1
  25. package/dist/application/BinarySessionOpen.js +3 -2
  26. package/dist/application/BinarySessionRecords.js +9 -3
  27. package/dist/application/BinaryTargetResolver.js +25 -6
  28. package/dist/application/BrowserObservationService.js +2 -1
  29. package/dist/application/BrowserScenarioCaptureService.js +2 -1
  30. package/dist/application/BrowserScenarioEvidence.js +2 -2
  31. package/dist/application/CallPathTracing.js +2 -1
  32. package/dist/application/CapabilityInventory.js +18 -0
  33. package/dist/application/ClientConfigPath.js +3 -1
  34. package/dist/application/ClientConfigurationDocument.js +11 -1
  35. package/dist/application/ClientRegistrationStatus.js +8 -1
  36. package/dist/application/CompositeProvider.js +1 -1
  37. package/dist/application/DirectAnalysis.js +23 -7
  38. package/dist/application/DirectAnalysisStatus.js +3 -3
  39. package/dist/application/Doctor.js +48 -8
  40. package/dist/application/DoctorDiagnostics.js +7 -5
  41. package/dist/application/DoctorScope.js +1 -1
  42. package/dist/application/ElectronActiveEvidence.js +2 -2
  43. package/dist/application/ElectronActiveObservationService.js +2 -1
  44. package/dist/application/ElectronBoundaryAnalysis.js +1 -1
  45. package/dist/application/ElectronObservationService.js +2 -1
  46. package/dist/application/EnhancedLiteralTracing.js +2 -1
  47. package/dist/application/EnhancedToolTypes.js +2 -1
  48. package/dist/application/EnhancedTools.js +3 -1
  49. package/dist/application/EvidenceBundleCommands.js +2 -1
  50. package/dist/application/EvidenceBundleFiles.js +1 -1
  51. package/dist/application/EvidenceInputResolver.js +30 -0
  52. package/dist/application/EvidenceLedger.js +2 -1
  53. package/dist/application/FirmwareAnalysisPort.js +1 -0
  54. package/dist/application/FirmwareAnalysisService.js +35 -0
  55. package/dist/application/FunctionAnalysisEvidence.js +32 -0
  56. package/dist/application/InventoryProjectionEvidence.js +2 -1
  57. package/dist/application/JavaScriptApplicationService.js +50 -3
  58. package/dist/application/JavaScriptApplicationWorkflowService.js +2 -1
  59. package/dist/application/JavaScriptArtifactAnalysis.js +4 -2
  60. package/dist/application/JavaScriptArtifactFiles.js +4 -2
  61. package/dist/application/JavaScriptArtifactPathResolution.js +6 -2
  62. package/dist/application/JavaScriptJsonModules.js +3 -2
  63. package/dist/application/JavaScriptModuleRelationships.js +4 -2
  64. package/dist/application/JavaScriptRuntimeObservationService.js +2 -1
  65. package/dist/application/JavaScriptRuntimeReconciliationService.js +2 -1
  66. package/dist/application/JavaScriptSemanticGraphProjection.js +1 -1
  67. package/dist/application/JavaScriptSemanticTraceService.js +2 -1
  68. package/dist/application/JsonFiles.js +1 -1
  69. package/dist/application/LazyAnalysisProvider.js +3 -1
  70. package/dist/application/LinuxHopper.js +12 -4
  71. package/dist/application/MacHopper.js +20 -7
  72. package/dist/application/ManagedApplicationGraphService.js +2 -1
  73. package/dist/application/ManagedMemberComparisonService.js +3 -1
  74. package/dist/application/ManagedNativeVerificationService.js +2 -1
  75. package/dist/application/ManagedReconstructionService.js +2 -1
  76. package/dist/application/NativeCallRoutes.js +1 -1
  77. package/dist/application/NativeDispatchMetadataInspection.js +1 -1
  78. package/dist/application/NativeUiActionTrace.js +2 -1
  79. package/dist/application/NativeValueTrace.js +1 -1
  80. package/dist/application/ProcessCaptureError.js +1 -1
  81. package/dist/application/ProcessCaptureJournal.js +3 -1
  82. package/dist/application/ProcessCaptureLifecycle.js +6 -3
  83. package/dist/application/ProcessCli.js +9 -5
  84. package/dist/application/ProcessEvidence.js +2 -6
  85. package/dist/application/ProcessHarness.js +3 -2
  86. package/dist/application/ProcessNormalization.js +12 -5
  87. package/dist/application/ProcessSampling.js +3 -1
  88. package/dist/application/ReconstructionCoverageService.js +2 -1
  89. package/dist/application/ReconstructionObligationLedgerService.js +2 -1
  90. package/dist/application/ReferenceSourceImportEntries.js +2 -0
  91. package/dist/application/ReferenceSourceImportPolicy.js +4 -2
  92. package/dist/application/ReferenceSourceVcsAdapter.js +35 -4
  93. package/dist/application/SessionProviderRouter.js +4 -1
  94. package/dist/application/Setup.js +1 -128
  95. package/dist/application/SetupClientConfiguration.js +17 -6
  96. package/dist/application/SetupHost.js +111 -0
  97. package/dist/application/SetupRegistrationEnvironment.js +1 -2
  98. package/dist/application/SetupSkill.js +9 -3
  99. package/dist/application/SetupTypes.js +17 -0
  100. package/dist/application/StoreFileLock.js +7 -2
  101. package/dist/application/SupportedClients.js +8 -0
  102. package/dist/application/Uninstall.js +9 -4
  103. package/dist/application/UpdateRuntime.js +5 -2
  104. package/dist/application/WindowsCapabilities.js +7 -7
  105. package/dist/application/runtime.js +3 -1
  106. package/dist/artifacts/ArtifactProvider.js +3 -1
  107. package/dist/artifacts/DirectoryArtifactReader.js +2 -0
  108. package/dist/artifacts/NativeDmgArtifactReader.js +10 -3
  109. package/dist/artifacts/NibArchive.js +4 -2
  110. package/dist/artifacts/SafeOutputTree.js +26 -10
  111. package/dist/artifacts/ZipArtifactReader.js +1 -0
  112. package/dist/browser/BrowserProcessStartup.js +3 -1
  113. package/dist/browser/CdpAuthorizedMainFrame.js +1 -1
  114. package/dist/browser/CdpBrowserProvider.js +4 -1
  115. package/dist/browser/CdpCaptureDocuments.js +3 -1
  116. package/dist/browser/CdpCaptureEventHandlers.js +6 -2
  117. package/dist/browser/CdpCaptureStorageFingerprints.js +1 -1
  118. package/dist/browser/CdpCaptureValues.js +6 -2
  119. package/dist/browser/CdpConnection.js +8 -6
  120. package/dist/browser/CdpElectronInspection.js +3 -3
  121. package/dist/browser/CdpElectronProvider.js +4 -1
  122. package/dist/browser/CdpElectronScripts.js +2 -2
  123. package/dist/browser/CdpEndpoint.js +22 -10
  124. package/dist/browser/CdpObservationSession.js +2 -1
  125. package/dist/browser/CdpOptionalCommand.js +1 -1
  126. package/dist/browser/CdpPageCapture.js +2 -1
  127. package/dist/browser/CdpSafeMetadata.js +53 -8
  128. package/dist/browser/CdpScreenshot.js +1 -1
  129. package/dist/browser/CdpTargetSession.js +8 -5
  130. package/dist/browser/CdpWebMcpDiscovery.js +1 -1
  131. package/dist/browser/ElectronFileScope.js +9 -3
  132. package/dist/browser/JavaScriptRuntimeScope.js +3 -1
  133. package/dist/browser/PlaywrightBrowserScenarioProvider.js +3 -1
  134. package/dist/browser/PlaywrightElectronActiveActions.js +1 -1
  135. package/dist/browser/PlaywrightElectronActiveProvider.js +6 -2
  136. package/dist/browser/PlaywrightExecutionBoundary.js +1 -1
  137. package/dist/browser/PlaywrightScenarioArtifacts.js +10 -5
  138. package/dist/browser/PlaywrightScenarioBrowser.js +3 -1
  139. package/dist/browser/PlaywrightScenarioEvents.js +6 -2
  140. package/dist/browser/PlaywrightScenarioSession.js +5 -2
  141. package/dist/browser/V8InspectorEndpoint.js +2 -1
  142. package/dist/browser/V8InspectorProvider.js +6 -1
  143. package/dist/browser/WebSourceMapFetcher.js +24 -11
  144. package/dist/cli/androidCommands.js +81 -0
  145. package/dist/{cliApplicationCommands.js → cli/applicationCommands.js} +18 -16
  146. package/dist/{cliBrowserAdvancedCommands.js → cli/browserAdvancedCommands.js} +13 -16
  147. package/dist/{cliBrowserCommands.js → cli/browserCommands.js} +9 -9
  148. package/dist/cli/commandCancellation.js +24 -0
  149. package/dist/cli/coreAnalysisCommands.js +110 -17
  150. package/dist/{cliElectronCommands.js → cli/electronCommands.js} +14 -13
  151. package/dist/cli/firmwareCommands.js +75 -0
  152. package/dist/{cliSetup.js → cli/interactiveSetup.js} +1 -1
  153. package/dist/cli/javascriptApplicationAnalysis.js +1 -1
  154. package/dist/cli/managedCommands.js +1 -1
  155. package/dist/cli/managedProjectGraphCommand.js +1 -1
  156. package/dist/cli/options.js +7 -1
  157. package/dist/{cliProcessCommands.js → cli/processCommands.js} +3 -3
  158. package/dist/cli/referenceSourceImportStatus.js +10 -0
  159. package/dist/cli/setupCommands.js +4 -2
  160. package/dist/cli/utilityCommands.js +3 -2
  161. package/dist/cli.js +10 -15
  162. package/dist/cliBrowserContext.js +1 -1
  163. package/dist/cliBrowserScenarioCommands.js +2 -1
  164. package/dist/cliCommandNames.js +11 -2
  165. package/dist/cliEvidenceCommands.js +2 -1
  166. package/dist/cliJavaScriptRuntimeCommands.js +2 -1
  167. package/dist/cliJsonInput.js +26 -11
  168. package/dist/cliLogging.js +2 -1
  169. package/dist/cliOutput.js +15 -16
  170. package/dist/config/environment.js +11 -1
  171. package/dist/config/parseConfig.js +7 -1
  172. package/dist/config/parsers.js +1 -1
  173. package/dist/contracts/androidToolContracts.js +77 -0
  174. package/dist/contracts/applicationToolContracts.js +32 -5
  175. package/dist/contracts/applicationWorkflowInputContracts.js +13 -13
  176. package/dist/contracts/artifactComparisonExample.js +7 -14
  177. package/dist/contracts/enhancedToolContracts.js +31 -0
  178. package/dist/contracts/errorSchemas.js +4 -2
  179. package/dist/contracts/evidenceInputContracts.js +13 -0
  180. package/dist/contracts/firmwareToolContracts.js +38 -0
  181. package/dist/contracts/officialToolContracts.js +66 -0
  182. package/dist/contracts/promptContracts.js +1 -1
  183. package/dist/contracts/sessionLifecycleInputs.js +4 -0
  184. package/dist/contracts/sessionToolContracts.js +43 -0
  185. package/dist/contracts/sessionToolSchemas.js +1 -1
  186. package/dist/contracts/toolContractExamples.js +5 -0
  187. package/dist/contracts/toolContractTypes.js +2 -0
  188. package/dist/contracts/toolContracts.js +7 -130
  189. package/dist/contracts/toolEffects.js +43 -0
  190. package/dist/contracts/toolOutputSchemaGroups.js +4 -0
  191. package/dist/contracts/toolOutputSchemaPrimitives.js +1 -0
  192. package/dist/doctorRuntime.js +5 -1
  193. package/dist/domain/analysisErrorBase.js +33 -0
  194. package/dist/domain/analysisErrorCore.js +60 -0
  195. package/dist/domain/analysisErrorPresentation.js +22 -2
  196. package/dist/domain/analysisErrorProjection.js +24 -3
  197. package/dist/domain/analysisSnapshot.js +1 -0
  198. package/dist/domain/androidAnalysis.js +141 -0
  199. package/dist/domain/appleAssetCatalog.js +1 -1
  200. package/dist/domain/artifactGraph.js +1 -0
  201. package/dist/domain/artifactInspection.js +19 -17
  202. package/dist/domain/artifactInventoryEvidence.js +20 -25
  203. package/dist/domain/artifactOperationError.js +16 -0
  204. package/dist/domain/browserObservation.js +12 -4
  205. package/dist/domain/browserObservationError.js +23 -0
  206. package/dist/domain/browserScenario.js +1 -1
  207. package/dist/domain/browserScenarioCapture.js +1 -1
  208. package/dist/domain/browserScenarioDiff.js +1 -1
  209. package/dist/domain/browserScenarioNormalization.js +6 -11
  210. package/dist/domain/browserScenarioValues.js +3 -1
  211. package/dist/domain/callPath.js +47 -7
  212. package/dist/domain/canonicalDigest.js +65 -0
  213. package/dist/domain/canonicalOrdering.js +11 -0
  214. package/dist/domain/changedBehavior.js +8 -7
  215. package/dist/domain/comparisonSemantics.js +2 -4
  216. package/dist/domain/configurationErrors.js +25 -0
  217. package/dist/domain/dosCom.js +8 -0
  218. package/dist/domain/electronActiveObservation.js +3 -1
  219. package/dist/domain/electronStaticAnalysisBrowser.js +13 -23
  220. package/dist/domain/electronStaticAnalysisNative.js +2 -1
  221. package/dist/domain/electronStaticAnalysisValues.js +23 -3
  222. package/dist/domain/evidence.js +3 -11
  223. package/dist/domain/evidenceErrors.js +30 -0
  224. package/dist/domain/firmwareAnalysis.js +121 -0
  225. package/dist/domain/functionComparison.js +4 -2
  226. package/dist/domain/functionComparisonDimensions.js +6 -4
  227. package/dist/domain/functionComparisonNormalization.js +8 -1
  228. package/dist/domain/functionComparisonResults.js +1 -4
  229. package/dist/domain/hopperErrors.js +78 -0
  230. package/dist/domain/hopperValues.js +2 -1
  231. package/dist/domain/interfaceBuilderGraph.js +3 -1
  232. package/dist/domain/javascriptApplicationChangeGraph.js +2 -2
  233. package/dist/domain/javascriptApplicationGraph.js +13 -22
  234. package/dist/domain/javascriptApplicationVersionComparison.js +3 -11
  235. package/dist/domain/javascriptApplicationVersionItems.js +3 -3
  236. package/dist/domain/javascriptApplicationVersionKeys.js +1 -1
  237. package/dist/domain/javascriptAstFingerprint.js +1 -1
  238. package/dist/domain/javascriptExportShapeComparison.js +1 -2
  239. package/dist/domain/javascriptExportShapeSelection.js +1 -1
  240. package/dist/domain/javascriptExportShapeVariants.js +7 -3
  241. package/dist/domain/javascriptFeatureSeed.js +29 -9
  242. package/dist/domain/javascriptFeatureTrace.js +9 -13
  243. package/dist/domain/javascriptFeatureTraversal.js +2 -1
  244. package/dist/domain/javascriptNativeHandoff.js +2 -1
  245. package/dist/domain/javascriptRuntimeLoadState.js +2 -2
  246. package/dist/domain/javascriptRuntimeReconciliationActive.js +3 -10
  247. package/dist/domain/javascriptRuntimeReconciliationGraph.js +2 -2
  248. package/dist/domain/javascriptRuntimeReconciliationMatching.js +4 -3
  249. package/dist/domain/javascriptRuntimeReconciliationParsing.js +8 -14
  250. package/dist/domain/javascriptRuntimeReconciliationResult.js +4 -4
  251. package/dist/domain/javascriptRuntimeReconciliationSchemas.js +5 -2
  252. package/dist/domain/javascriptRuntimeStaticCandidates.js +8 -4
  253. package/dist/domain/javascriptSemanticAnalysis.js +40 -3
  254. package/dist/domain/javascriptSemanticCallResolution.js +2 -1
  255. package/dist/domain/javascriptSemanticChildProcesses.js +2 -1
  256. package/dist/domain/javascriptSemanticDataEffects.js +2 -1
  257. package/dist/domain/javascriptSemanticFingerprints.js +1 -1
  258. package/dist/domain/javascriptSemanticGraph.js +23 -28
  259. package/dist/domain/javascriptSemanticPrimitives.js +9 -2
  260. package/dist/domain/javascriptSemanticProjection.js +2 -1
  261. package/dist/domain/javascriptSemanticPromises.js +2 -1
  262. package/dist/domain/javascriptSemanticProvenance.js +1 -1
  263. package/dist/domain/javascriptSemanticQuery.js +7 -8
  264. package/dist/domain/javascriptSemanticQueryAssessment.js +1 -2
  265. package/dist/domain/javascriptSemanticQueryIdentity.js +1 -2
  266. package/dist/domain/javascriptSemanticReturns.js +2 -1
  267. package/dist/domain/javascriptSemanticValues.js +50 -16
  268. package/dist/domain/javascriptSourceParser.js +4 -2
  269. package/dist/domain/javascriptStaticAnalysis.js +1 -1
  270. package/dist/domain/javascriptStaticAnalysisBundler.js +2 -1
  271. package/dist/domain/javascriptStaticAnalysisCalls.js +14 -6
  272. package/dist/domain/javascriptStaticAnalysisHelpers.js +31 -4
  273. package/dist/domain/jsonShape.js +6 -2
  274. package/dist/domain/managedMemberComparison.js +1 -0
  275. package/dist/domain/managedMemberComparisonItems.js +2 -0
  276. package/dist/domain/managedNativeVerificationMatch.js +5 -3
  277. package/dist/domain/nativeDataType.js +2 -0
  278. package/dist/domain/nativeFunctionAnnotations.js +43 -0
  279. package/dist/domain/nativeLoadImage.js +95 -0
  280. package/dist/domain/nativeMetadataRecovery.js +55 -0
  281. package/dist/domain/processCapture.js +0 -1
  282. package/dist/domain/processEvidenceProvider.js +11 -0
  283. package/dist/domain/processTraceComparison.js +1 -1
  284. package/dist/domain/providerAdapterError.js +17 -0
  285. package/dist/domain/providerCleanupError.js +1 -1
  286. package/dist/domain/providerSelectionError.js +44 -0
  287. package/dist/domain/reconstructionUnknowns.js +1 -1
  288. package/dist/domain/reconstructionVerification.js +22 -8
  289. package/dist/domain/referenceSourceClassification.js +5 -6
  290. package/dist/domain/referenceSourceGraph.js +9 -17
  291. package/dist/domain/referenceSourceImportParsing.js +38 -23
  292. package/dist/domain/runtimeIdentification.js +1 -1
  293. package/dist/domain/runtimeVersion.js +4 -7
  294. package/dist/domain/safeJson.js +13 -0
  295. package/dist/domain/sourceToBundleComparison.js +5 -7
  296. package/dist/domain/sourceToBundleSignals.js +6 -6
  297. package/dist/domain/staticRuntimeCorrelation.js +9 -7
  298. package/dist/domain/unknownRegistryError.js +10 -0
  299. package/dist/domain/webBundleAnalyzerAst.js +22 -5
  300. package/dist/domain/webBundleAnalyzerInspection.js +20 -14
  301. package/dist/dotnet/ManagedMemberRows.js +1 -1
  302. package/dist/dotnet/ManagedMetadataHeaps.js +3 -2
  303. package/dist/dotnet/ManagedMetadataInventoryRows.js +4 -2
  304. package/dist/dotnet/ManagedMethodBodyReader.js +8 -1
  305. package/dist/dotnet/ManagedStaticProvider.js +3 -1
  306. package/dist/firmware/FirmwareCommand.js +163 -0
  307. package/dist/firmware/FirmwareFiles.js +190 -0
  308. package/dist/firmware/FirmwareProvider.js +258 -0
  309. package/dist/firmware/FirmwarePublication.js +84 -0
  310. package/dist/firmware/FirmwareRelease.js +32 -0
  311. package/dist/firmware/FirmwareReports.js +223 -0
  312. package/dist/generatedMcpToolCatalog.js +1 -1
  313. package/dist/generatedPackageMetadata.js +5 -5
  314. package/dist/ghidra/GhidraAnalysisProfile.js +37 -8
  315. package/dist/ghidra/GhidraClient.js +52 -6
  316. package/dist/ghidra/GhidraDiagnostics.js +3 -0
  317. package/dist/ghidra/GhidraDoctor.js +38 -14
  318. package/dist/ghidra/GhidraFunctionValues.js +10 -4
  319. package/dist/ghidra/GhidraInstallation.js +10 -4
  320. package/dist/ghidra/GhidraInventoryValues.js +39 -2
  321. package/dist/ghidra/GhidraLauncher.js +91 -26
  322. package/dist/ghidra/GhidraLoadImageValues.js +199 -0
  323. package/dist/ghidra/GhidraProvider.js +129 -13
  324. package/dist/ghidra/GhidraProviderCapabilities.js +52 -15
  325. package/dist/ghidra/GhidraRequestQueue.js +2 -2
  326. package/dist/ghidra/GhidraSessionError.js +31 -4
  327. package/dist/ghidra/GhidraSessionValues.js +10 -7
  328. package/dist/ghidra/GhidraTargetSnapshot.js +16 -2
  329. package/dist/ghidra/GhidraTransport.js +12 -0
  330. package/dist/ghidra/extensions/GhidraExtensionFailures.js +20 -0
  331. package/dist/ghidra/extensions/GhidraExtensions.js +170 -0
  332. package/dist/ghidra/extensions/nativeaot/NativeAotAdapter.js +21 -0
  333. package/dist/ghidra/extensions/nativeaot/NativeAotReport.js +84 -0
  334. package/dist/hopper/BridgeLauncher.js +4 -2
  335. package/dist/hopper/HopperAnalysisProfile.js +7 -2
  336. package/dist/hopper/HopperCleanup.js +55 -9
  337. package/dist/hopper/HopperClient.js +14 -4
  338. package/dist/hopper/HopperProcessDiagnostic.js +1 -1
  339. package/dist/hopper/HopperProvider.js +8 -4
  340. package/dist/hopper/HopperRequestQueue.js +7 -3
  341. package/dist/hopper/HopperSessionValues.js +1 -1
  342. package/dist/hopper/HopperSocketConnection.js +1 -1
  343. package/dist/hopper/HopperTargetLease.js +23 -15
  344. package/dist/hopper/LinuxPrivateDisplayDiagnostic.js +7 -8
  345. package/dist/hopper/LinuxPrivateDisplayProbe.js +6 -2
  346. package/dist/hopper/protocol.js +8 -8
  347. package/dist/ida/IdaConfiguration.js +56 -0
  348. package/dist/ida/IdaDoctor.js +53 -0
  349. package/dist/ida/IdaInput.js +62 -0
  350. package/dist/ida/IdaMcpConnection.js +111 -0
  351. package/dist/ida/IdaOperationRunner.js +299 -0
  352. package/dist/ida/IdaProtocolValues.js +178 -0
  353. package/dist/ida/IdaProvider.js +126 -0
  354. package/dist/ida/IdaProviderCapabilities.js +60 -0
  355. package/dist/ida/IdaSessionClient.js +306 -0
  356. package/dist/ida/IdaWorkspace.js +54 -0
  357. package/dist/main/shutdown.js +21 -1
  358. package/dist/main/startup.js +1 -1
  359. package/dist/main/transport.js +8 -4
  360. package/dist/main.js +5 -2
  361. package/dist/native/AppleDispatchMetadata.js +31 -10
  362. package/dist/native/NativeMacOSProvider.js +87 -15
  363. package/dist/native/NativeMachoInspection.js +42 -12
  364. package/dist/native/NativeUiHelperRuntime.js +7 -1
  365. package/dist/native/NativeUiObservation.js +6 -2
  366. package/dist/native/parsers/demangle.js +1 -1
  367. package/dist/native/parsers/dyldInfo.js +3 -3
  368. package/dist/native/parsers/otool.js +4 -1
  369. package/dist/native/parsers/plist.js +11 -3
  370. package/dist/process/PrivateRuntimeRoot.js +13 -3
  371. package/dist/process/ProcessOwnership.js +5 -73
  372. package/dist/process/ProcessOwnershipObservation.js +62 -2
  373. package/dist/process/ProcessOwnershipProcessTree.js +13 -0
  374. package/dist/process/ProviderProcess.js +24 -7
  375. package/dist/process/ProviderRunLineage.js +1 -1
  376. package/dist/process/WindowsAuthority.js +20 -1
  377. package/dist/reference/ReferenceSourceReaderEntries.js +5 -1
  378. package/dist/reference/ReferenceSourceReaderFile.js +1 -0
  379. package/dist/server/createServer.js +25 -2
  380. package/dist/server/mcpProgress.js +2 -1
  381. package/dist/server/promptCompletion.js +3 -3
  382. package/dist/server/registerAndroidTools.js +30 -0
  383. package/dist/server/registerApplicationTools/compareExportShapes.js +5 -1
  384. package/dist/server/registerApplicationTools/compareSourceToBundle.js +7 -2
  385. package/dist/server/registerApplicationTools/compareVersions.js +5 -1
  386. package/dist/server/registerApplicationTools/traceFeature.js +7 -2
  387. package/dist/server/registerApplicationTools/traceSemantics.js +7 -2
  388. package/dist/server/registerEnhancedTools.js +28 -1
  389. package/dist/server/registerFirmwareTools.js +22 -0
  390. package/dist/server/registerFunctionComparisonTool.js +1 -1
  391. package/dist/server/registerInvestigationTools/helpers.js +2 -1
  392. package/dist/server/registerManagedTools.js +1 -1
  393. package/dist/server/registerManagedWorkflowTools/evidence.js +1 -1
  394. package/dist/server/registerOfficialTools.js +4 -1
  395. package/dist/server/registerProcessComparisonTool.js +5 -2
  396. package/dist/server/registerSessionTools.js +3 -1
  397. package/dist/server/runDerivedOperation.js +1 -1
  398. package/dist/server/sessionAvailabilityPolicy.js +3 -0
  399. package/dist/server/sessionEvidence.js +1 -1
  400. package/dist/server/toolResult.js +2 -1
  401. package/dist/windows/WindowsNativeLoader.js +108 -0
  402. package/dist/windows/WindowsOwnedProcess.js +168 -0
  403. package/dist/windows/WindowsPrivateRuntime.js +137 -0
  404. package/install.sh +4 -6
  405. package/native/windows/README.md +102 -0
  406. package/native/windows/build/manifest.json +9 -0
  407. package/native/windows/build/rea-windows-x64.node +0 -0
  408. package/package.json +38 -24
  409. package/scripts/rea.mjs +1 -1
  410. package/scripts/verify-windows-native-artifact.mjs +39 -0
  411. package/skills/reverse-engineer-anything/SKILL.md +92 -24
  412. package/skills/reverse-engineer-anything/references/android-applications.md +31 -0
  413. package/skills/reverse-engineer-anything/references/javascript-applications.md +19 -2
  414. package/skills/reverse-engineer-anything/references/native-and-artifacts.md +52 -4
  415. package/dist/browser/CdpCanonicalJsonDigest.js +0 -9
  416. package/dist/domain/errors.js +0 -324
@@ -0,0 +1,170 @@
1
+ import { createHash } from "node:crypto";
2
+ import { constants } from "node:fs";
3
+ import { open, realpath, writeFile, mkdir } from "node:fs/promises";
4
+ import { isAbsolute, join } from "node:path";
5
+ import { z } from "zod";
6
+ import { AnalysisCancelledError } from "../../domain/analysisErrorCore.js";
7
+ import { ProviderAdapterError } from "../../domain/providerAdapterError.js";
8
+ import { jsonObjectSchema } from "../../domain/jsonValue.js";
9
+ import { err, ok } from "../../domain/result.js";
10
+ import { nativeAotAdapter } from "./nativeaot/NativeAotAdapter.js";
11
+ const digest = z.string().regex(/^[a-f0-9]{64}$/u);
12
+ /** Exact executable extension artifact committed before the session starts. */
13
+ export const ghidraExtensionSchema = z.strictObject({
14
+ id: z.string().regex(/^[a-z][a-z0-9-]*$/u),
15
+ path: z.string().refine(isAbsolute, "Extension path must be absolute"),
16
+ configured_path: z
17
+ .string()
18
+ .refine(isAbsolute, "Extension path must be absolute"),
19
+ sha256: digest,
20
+ entry_class: z.string().min(1),
21
+ integration_api: z.literal(1),
22
+ });
23
+ /** Shared extension envelope; each adapter validates its own producer result. */
24
+ export const ghidraExtensionResultSchema = z.strictObject({
25
+ id: z.string().min(1),
26
+ sha256: digest,
27
+ status: z.enum([
28
+ "complete",
29
+ "partial",
30
+ "not_applicable",
31
+ "unsupported",
32
+ "failed",
33
+ ]),
34
+ reason: z.string().nullable(),
35
+ result: jsonObjectSchema,
36
+ });
37
+ const adapters = [nativeAotAdapter];
38
+ const MAX_EXTENSION_BYTES = 8 * 1024 * 1024;
39
+ /** Read a bounded regular artifact through its open handle, without ambient state changes. */
40
+ const readJar = async (path) => {
41
+ const file = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
42
+ try {
43
+ const stat = await file.stat();
44
+ if (!stat.isFile() || stat.size < 4 || stat.size > MAX_EXTENSION_BYTES)
45
+ throw new Error(`Ghidra extension must be a regular JAR of 4..${MAX_EXTENSION_BYTES} bytes: ${path}`);
46
+ const bytes = Buffer.alloc(stat.size);
47
+ let offset = 0;
48
+ while (offset < bytes.length) {
49
+ const read = await file.read(bytes, offset, bytes.length - offset, offset);
50
+ if (read.bytesRead === 0)
51
+ throw new Error(`Incomplete Ghidra extension read: ${path}`);
52
+ offset += read.bytesRead;
53
+ }
54
+ const extra = Buffer.alloc(1);
55
+ if ((await file.read(extra, 0, 1, offset)).bytesRead !== 0 ||
56
+ bytes.readUInt32LE(0) !== 0x04034b50)
57
+ throw new Error(`Ghidra extension changed during read or is not a JAR: ${path}`);
58
+ return bytes;
59
+ }
60
+ finally {
61
+ await file.close();
62
+ }
63
+ };
64
+ /** Resolve explicitly configured optional extensions into the immutable analysis profile. */
65
+ export const resolveGhidraExtensions = async (config, target, platform, signal) => {
66
+ const extensions = [];
67
+ for (const adapter of adapters) {
68
+ if (signal?.aborted)
69
+ return err(new AnalysisCancelledError("open_binary"));
70
+ const configured = adapter.configuredPath(config);
71
+ if (configured === undefined)
72
+ continue;
73
+ const reason = adapter.unsupportedReason(target, platform);
74
+ if (reason !== null)
75
+ return err(new ProviderAdapterError("ghidra", "resolve_analysis_profile", {
76
+ diagnostics: { extension: adapter.id, reason, path: configured },
77
+ }));
78
+ try {
79
+ const path = await realpath(configured);
80
+ const bytes = await readJar(path);
81
+ extensions.push({
82
+ id: adapter.id,
83
+ path,
84
+ configured_path: configured,
85
+ sha256: createHash("sha256").update(bytes).digest("hex"),
86
+ entry_class: adapter.entryClass,
87
+ integration_api: 1,
88
+ });
89
+ }
90
+ catch (cause) {
91
+ return err(new ProviderAdapterError("ghidra", "resolve_analysis_profile", {
92
+ cause,
93
+ diagnostics: {
94
+ extension: adapter.id,
95
+ path: configured,
96
+ reason: cause instanceof Error ? cause.message : String(cause),
97
+ },
98
+ }));
99
+ }
100
+ }
101
+ if (signal?.aborted)
102
+ return err(new AnalysisCancelledError("open_binary"));
103
+ return ok(extensions);
104
+ };
105
+ /** Require explicit local configuration before admitting executable code from a profile. */
106
+ export const validateGhidraExtensionProfile = (extensions, config, target, platform) => {
107
+ const enabled = adapters.filter((adapter) => adapter.configuredPath(config) !== undefined);
108
+ if (enabled.length !== extensions.length ||
109
+ new Set(extensions.map((extension) => extension.id)).size !==
110
+ extensions.length)
111
+ return "Configured Ghidra extension inventory differs from the resolved analysis profile.";
112
+ for (const extension of extensions) {
113
+ const adapter = enabled.find((value) => value.id === extension.id);
114
+ if (adapter === undefined ||
115
+ adapter.entryClass !== extension.entry_class ||
116
+ adapter.configuredPath(config) !== extension.configured_path)
117
+ return `Ghidra extension profile lacks matching explicit local configuration: ${extension.id}`;
118
+ const reason = adapter.unsupportedReason(target, platform);
119
+ if (reason !== null)
120
+ return reason;
121
+ }
122
+ return null;
123
+ };
124
+ /** Snapshot committed extension bytes into the private runtime before Java loads them. */
125
+ export const snapshotGhidraExtensions = async (extensions, runtimeRoot) => {
126
+ if (extensions.length === 0)
127
+ return [];
128
+ for (const extension of extensions) {
129
+ ghidraExtensionSchema.parse(extension);
130
+ const adapter = adapters.find((value) => value.id === extension.id);
131
+ if (adapter === undefined || adapter.entryClass !== extension.entry_class)
132
+ throw new Error(`Unregistered Ghidra extension identity: ${extension.id}`);
133
+ if ((await realpath(extension.configured_path)) !== extension.path)
134
+ throw new Error(`Ghidra extension resolved path differs from explicit configuration: ${extension.id}`);
135
+ }
136
+ const directory = join(runtimeRoot, "extensions");
137
+ await mkdir(directory, { mode: 0o700 });
138
+ const result = [];
139
+ for (const extension of extensions) {
140
+ const bytes = await readJar(extension.path);
141
+ if (createHash("sha256").update(bytes).digest("hex") !== extension.sha256)
142
+ throw new Error(`Ghidra extension digest differs from committed profile: ${extension.id} (${extension.path})`);
143
+ const path = join(directory, `${extension.id}.jar`);
144
+ await writeFile(path, bytes, { flag: "wx", mode: 0o600 });
145
+ result.push({ ...extension, path });
146
+ }
147
+ return result;
148
+ };
149
+ /** Require every configured producer result to match its artifact and registered ABI. */
150
+ export const validateGhidraExtensionResults = (expected, results) => {
151
+ if (results.length !== expected.length ||
152
+ new Set(results.map((result) => result.id)).size !== results.length)
153
+ return "Ghidra extension result inventory differs from its committed profile.";
154
+ for (const extension of expected) {
155
+ const result = results.find((value) => value.id === extension.id);
156
+ const adapter = adapters.find((value) => value.id === extension.id);
157
+ if (result === undefined ||
158
+ adapter === undefined ||
159
+ result.sha256 !== extension.sha256)
160
+ return `Ghidra extension identity mismatch: ${extension.id}`;
161
+ const invalid = adapter.validate(result);
162
+ if (invalid !== null)
163
+ return invalid;
164
+ }
165
+ return null;
166
+ };
167
+ /** Exact adapter limitations for explicitly configured session extensions. */
168
+ export const ghidraExtensionLimitations = (extensions) => adapters
169
+ .filter((adapter) => extensions.some((extension) => extension.id === adapter.id))
170
+ .flatMap((adapter) => adapter.limitations);
@@ -0,0 +1,21 @@
1
+ import { validateNativeAotReport } from "./NativeAotReport.js";
2
+ /** NativeAOT-specific prerequisites and report interpretation behind the extension boundary. */
3
+ export const nativeAotAdapter = {
4
+ id: "nativeaot",
5
+ entryClass: "rea.extensions.nativeaot.NativeAotExtension",
6
+ configuredPath: (config) => config.ghidraNativeAotJar,
7
+ unsupportedReason: (target, platform) => platform !== "linux"
8
+ ? "NativeAOT recovery is verified on Linux only; omit REA_GHIDRA_NATIVEAOT_JAR for ordinary native analysis."
9
+ : !["elf", "pe"].includes(target.format) ||
10
+ target.architecture !== "x86_64" ||
11
+ target.managed === true
12
+ ? "NativeAOT recovery requires an x86-64 ELF or native PE target on Linux; PE/CLI and ReadyToRun assemblies use inspect_managed_artifact; omit REA_GHIDRA_NATIVEAOT_JAR for ordinary native analysis."
13
+ : null,
14
+ validate: validateNativeAotReport,
15
+ limitations: [
16
+ "Optional NativeAOT recovery is verified for .NET 8.0.22 RTR 9.1 Linux x64 ELF and Windows x64 PE targets on a Linux host. Other runtime layouts, target architectures and hosts are unsupported.",
17
+ "Type names and relationships use recovery heuristics; original C# source and custom field layouts are not recovered. Rehydrated analysis-memory bytes are derived, without original file offsets or runtime observations.",
18
+ "Method prototypes are Ghidra inferences, not original signatures. Pre-recovery conventions are retained; new functions use the loaded compiler default. Verify parameter roles against instructions and call sites.",
19
+ "The configured extension retains its actual JAR digest. Its reported source revision is not an attestation of caller-supplied build bytes.",
20
+ ],
21
+ };
@@ -0,0 +1,84 @@
1
+ import { z } from "zod";
2
+ const report = z
3
+ .object({
4
+ id: z.literal("nativeaot"),
5
+ integration_api: z.literal(1),
6
+ source_revision: z.literal("effeb734fc570c32650f88b159608979dc7b423e"),
7
+ source_revision_authority: z.literal("build-reported-unattested"),
8
+ status: z.enum([
9
+ "complete",
10
+ "partial",
11
+ "not_applicable",
12
+ "unsupported",
13
+ "failed",
14
+ ]),
15
+ reason: z.string().nullable(),
16
+ method_tables: z.number().int().nonnegative(),
17
+ diagnostics: z.array(z.string()),
18
+ header_address: z
19
+ .string()
20
+ .regex(/^0x[0-9a-f]+$/u)
21
+ .optional(),
22
+ discovery: z.enum(["symbol", "signature-heuristic"]).optional(),
23
+ format_major: z.number().int().optional(),
24
+ format_minor: z.number().int().optional(),
25
+ derived_memory: z
26
+ .object({
27
+ address: z.string().regex(/^0x[0-9a-f]+$/u),
28
+ size_bytes: z.number().int().nonnegative(),
29
+ sha256: z.string().regex(/^[a-f0-9]{64}$/u),
30
+ file_offset: z.null(),
31
+ })
32
+ .optional(),
33
+ coverage: z
34
+ .strictObject({
35
+ frozen_object_candidates: z.number().int().nonnegative(),
36
+ frozen_objects_annotated: z.number().int().nonnegative(),
37
+ basis: z.literal("rehydrated-pointer-candidates-and-committed-instance-types"),
38
+ })
39
+ .optional(),
40
+ types: z
41
+ .array(z.object({
42
+ address: z.string().regex(/^0x[0-9a-f]+$/u),
43
+ type: z.string().min(1),
44
+ }))
45
+ .optional(),
46
+ })
47
+ .strict();
48
+ /** Validate the pinned producer representation before its result enters Evidence. */
49
+ export const validateNativeAotReport = (value) => {
50
+ if (value.status === "failed" &&
51
+ typeof value.result.loader_failure === "string" &&
52
+ value.result.loader_failure === value.reason)
53
+ return null;
54
+ const parsed = report.safeParse(value.result);
55
+ if (!parsed.success ||
56
+ parsed.data.status !== value.status ||
57
+ parsed.data.reason !== value.reason)
58
+ return "NativeAOT extension returned a malformed or inconsistent producer report.";
59
+ return validateRecoveredMetadata(parsed.data);
60
+ };
61
+ const validateRecoveredMetadata = (value) => {
62
+ if (["complete", "partial"].includes(value.status) &&
63
+ (value.method_tables === 0 ||
64
+ value.format_major !== 9 ||
65
+ value.format_minor !== 1 ||
66
+ value.types?.length !== value.method_tables ||
67
+ value.derived_memory === undefined ||
68
+ value.header_address === undefined ||
69
+ value.discovery === undefined ||
70
+ value.coverage === undefined ||
71
+ value.reason !== null))
72
+ return "NativeAOT recovery omitted its supported format, method-table inventory or derived-memory identity.";
73
+ const coverage = value.coverage;
74
+ if (coverage !== undefined &&
75
+ (coverage.frozen_objects_annotated > coverage.frozen_object_candidates ||
76
+ (value.status === "complete" &&
77
+ coverage.frozen_objects_annotated !==
78
+ coverage.frozen_object_candidates)))
79
+ return "NativeAOT recovery coverage contradicts its reported completion status.";
80
+ const types = value.types ?? [];
81
+ if (new Set(types.map((type) => type.address)).size !== types.length)
82
+ return "NativeAOT recovery repeated a method-table identity.";
83
+ return null;
84
+ };
@@ -2,7 +2,7 @@ import { execFile } from "node:child_process";
2
2
  import { chmod, writeFile } from "node:fs/promises";
3
3
  import { basename, dirname, extname, join } from "node:path";
4
4
  import { promisify } from "node:util";
5
- import { HopperCancelledError, HopperProcessError, HopperStartError, } from "../domain/errors.js";
5
+ import { HopperCancelledError, HopperProcessError, HopperStartError, } from "../domain/hopperErrors.js";
6
6
  import { err, ok } from "../domain/result.js";
7
7
  import { cleanupOwnedProcessGroup } from "../process/ProcessOwnership.js";
8
8
  import { execFileOutput } from "../process/ExecFileOutput.js";
@@ -275,7 +275,9 @@ const processIsRunning = async (executablePath) => {
275
275
  .split("\n")
276
276
  .some((command) => command.trim() === executablePath);
277
277
  }
278
- catch {
278
+ catch (cause) {
279
+ // best-effort cleanup: optional process probing; failure means not running.
280
+ void cause;
279
281
  return false;
280
282
  }
281
283
  };
@@ -1,7 +1,9 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import { createReadStream } from "node:fs";
3
3
  import { createAnalysisProfile } from "../domain/analysisProfile.js";
4
- import { AnalysisCancelledError, ProviderAdapterError, } from "../domain/errors.js";
4
+ import { AnalysisCancelledError } from "../domain/analysisErrorCore.js";
5
+ import { ProviderAdapterError } from "../domain/providerAdapterError.js";
6
+ import {} from "../domain/analysisErrorBase.js";
5
7
  import { err, ok } from "../domain/result.js";
6
8
  /** Resolve Hopper open semantics without placing its CLI flags in BinaryTarget. */
7
9
  export const resolveHopperAnalysisProfile = async (target, options) => {
@@ -63,6 +65,7 @@ export const hopperLoaderArgsForTarget = (target) => {
63
65
  case "pe":
64
66
  return ok(["-l", "WinPE", flag]);
65
67
  case "dos-mz":
68
+ case "dos-com":
66
69
  return err(new ProviderAdapterError("hopper", "resolve_analysis_profile"));
67
70
  }
68
71
  };
@@ -94,7 +97,9 @@ const sha256File = async (path, signal) => {
94
97
  ? err(new AnalysisCancelledError("open_binary"))
95
98
  : ok(hash.digest("hex"));
96
99
  }
97
- catch {
100
+ catch (cause) {
101
+ // best-effort cleanup: unreadable targets mean no digest; abort still cancels.
102
+ void cause;
98
103
  return signalIsAborted(signal)
99
104
  ? err(new AnalysisCancelledError("open_binary"))
100
105
  : ok(undefined);
@@ -1,4 +1,4 @@
1
- import { HopperProcessError } from "../domain/errors.js";
1
+ import { HopperProcessError } from "../domain/hopperErrors.js";
2
2
  import { ProviderCleanupError } from "../domain/providerCleanupError.js";
3
3
  import { err, ok } from "../domain/result.js";
4
4
  import { createOwnedHopperShutdownDiagnostic, providerCleanupFailure, } from "./HopperDiagnostics.js";
@@ -34,11 +34,12 @@ const requestShutdown = async (input, state) => {
34
34
  }, "Hopper shutdown skipped because a bridge operation remained active");
35
35
  return;
36
36
  }
37
- const shutdown = await input
38
- .request(input.retainDocument || input.launch?.shutdownMode === "process-cleanup"
37
+ const method = input.retainDocument || input.launch?.shutdownMode === "process-cleanup"
39
38
  ? "shutdown"
40
- : "shutdown_document")
41
- .catch(() => err(new HopperProcessError(null)));
39
+ : "shutdown_document";
40
+ const shutdown = await input
41
+ .request(method)
42
+ .catch((cause) => err(shutdownRequestFailure(method, cause)));
42
43
  if (shutdown.ok &&
43
44
  isHopperCleanupRequired(shutdown.value) &&
44
45
  input.launch?.shutdownMode === "process-cleanup") {
@@ -57,17 +58,60 @@ const requestShutdown = async (input, state) => {
57
58
  }
58
59
  if (!shutdown.ok ||
59
60
  (!state.shutdownConfirmed && state.cleanupResult === undefined))
60
- input.logger.warn({ status: shutdown.ok ? "invalid-acknowledgement" : "failed" }, "Hopper document shutdown was not confirmed");
61
+ input.logger.warn({
62
+ status: shutdown.ok ? "invalid-acknowledgement" : "failed",
63
+ ...(shutdown.ok ? {} : shutdownFailureDetails(shutdown.error)),
64
+ }, "Hopper document shutdown was not confirmed");
61
65
  };
62
66
  const fallbackDocumentShutdown = async (input) => {
63
67
  const fallback = await input
64
68
  .request("shutdown_document")
65
- .catch(() => err(new HopperProcessError(null)));
69
+ .catch((cause) => err(shutdownRequestFailure("shutdown_document", cause)));
66
70
  const confirmed = fallback.ok && isHopperShutdownAcknowledgement(fallback.value);
67
71
  if (!confirmed)
68
- input.logger.warn({ status: fallback.ok ? "invalid-acknowledgement" : "failed" }, "Hopper document shutdown fallback was not confirmed");
72
+ input.logger.warn({
73
+ status: fallback.ok ? "invalid-acknowledgement" : "failed",
74
+ ...(fallback.ok ? {} : shutdownFailureDetails(fallback.error)),
75
+ }, "Hopper document shutdown fallback was not confirmed");
69
76
  return confirmed;
70
77
  };
78
+ const shutdownRequestFailure = (operation, cause) => {
79
+ const failure = new HopperProcessError(null, undefined, operation);
80
+ failure.cause = cause;
81
+ return failure;
82
+ };
83
+ const shutdownFailureDetails = (error) => ({
84
+ errorTag: error._tag,
85
+ ...(error instanceof HopperProcessError && error.operation !== undefined
86
+ ? { operation: error.operation }
87
+ : {}),
88
+ ...(error instanceof HopperProcessError && error.requestId !== undefined
89
+ ? { requestId: error.requestId }
90
+ : {}),
91
+ ...(error.cause === undefined
92
+ ? {}
93
+ : { failure_cause: describeFailureCause(error.cause) }),
94
+ });
95
+ const describeFailureCause = (cause) => {
96
+ if (cause instanceof Error) {
97
+ const code = "code" in cause ? cause.code : undefined;
98
+ return {
99
+ name: cause.name,
100
+ message: cause.message,
101
+ ...(typeof code === "string" ||
102
+ (typeof code === "number" && Number.isFinite(code))
103
+ ? { code }
104
+ : {}),
105
+ };
106
+ }
107
+ if (typeof cause === "string")
108
+ return { type: "string", message: cause };
109
+ if (cause === null ||
110
+ typeof cause === "boolean" ||
111
+ (typeof cause === "number" && Number.isFinite(cause)))
112
+ return { type: cause === null ? "null" : typeof cause, value: cause };
113
+ return { type: typeof cause };
114
+ };
71
115
  const stopProcess = async (input, state) => {
72
116
  const supervisor = input.processSupervisor;
73
117
  if (supervisor === undefined)
@@ -79,8 +123,9 @@ const stopProcess = async (input, state) => {
79
123
  try {
80
124
  input.onDiagnostic?.(diagnostic);
81
125
  }
82
- catch {
126
+ catch (cause) {
83
127
  // Diagnostic consumers cannot change the already-observed cleanup result.
128
+ void cause;
84
129
  }
85
130
  input.logger.info(diagnostic, "Owned Hopper launcher shutdown completed");
86
131
  if (stopped.status !== "incomplete") {
@@ -149,6 +194,7 @@ const activityDetails = (activity) => ({
149
194
  queued_requests: activity.queuedRequests,
150
195
  });
151
196
  const report = async (progress, completed, message) => {
197
+ // best-effort cleanup: progress reporting must not fail session cleanup.
152
198
  await progress
153
199
  ?.report({
154
200
  phase: "hopper_cleanup",
@@ -2,7 +2,10 @@ import { randomBytes, randomUUID } from "node:crypto";
2
2
  import { access } from "node:fs/promises";
3
3
  import { tmpdir } from "node:os";
4
4
  import { join } from "node:path";
5
- import { AnalysisCapabilityUnavailableError, HopperCancelledError, HopperProcessError, HopperProtocolError, HopperRemoteError, HopperStartError, hopperStartupFailure, HopperTimeoutError, } from "../domain/errors.js";
5
+ import { AnalysisCapabilityUnavailableError } from "../domain/analysisErrorCore.js";
6
+ import { HopperCancelledError, HopperProcessError, HopperProtocolError, HopperRemoteError, HopperStartError, HopperTimeoutError, } from "../domain/hopperErrors.js";
7
+ import {} from "../domain/analysisErrorBase.js";
8
+ import { hopperStartupFailure, } from "../domain/hopperStartupFailure.js";
6
9
  import { err, ok } from "../domain/result.js";
7
10
  import { silentLogger } from "../logger.js";
8
11
  import { PrivateRuntimeRoot } from "../process/PrivateRuntimeRoot.js";
@@ -119,7 +122,8 @@ export class HopperClient {
119
122
  release();
120
123
  if (!result.ok)
121
124
  reset();
122
- }, () => {
125
+ }, (cause) => {
126
+ this.#logger.debug({ error: cause instanceof Error ? cause.message : String(cause) }, "Hopper startup promise rejected during bookkeeping");
123
127
  release();
124
128
  reset();
125
129
  });
@@ -228,6 +232,8 @@ export class HopperClient {
228
232
  }
229
233
  async #close(starting, controller, options) {
230
234
  try {
235
+ // best-effort cleanup: a rejected startup must not mask close/cleanup;
236
+ // #cleanup reports the authoritative close result.
231
237
  await starting?.catch(() => undefined);
232
238
  return await this.#cleanup(options);
233
239
  }
@@ -286,7 +292,9 @@ export class HopperClient {
286
292
  try {
287
293
  await access(socketPath);
288
294
  }
289
- catch {
295
+ catch (cause) {
296
+ // best-effort cleanup: socket polling; absence means keep waiting.
297
+ void cause;
290
298
  if ((await deadline.wait(50)) === "aborted")
291
299
  return err(startupInterruption(deadline));
292
300
  continue;
@@ -350,7 +358,9 @@ export class HopperClient {
350
358
  message: message.event.error.message,
351
359
  });
352
360
  }
353
- catch {
361
+ catch (cause) {
362
+ // best-effort cleanup: diagnostic consumers must not break the client.
363
+ void cause;
354
364
  this.#logger.warn({ requestId: message.id }, "Hopper bridge diagnostic consumer rejected an event");
355
365
  }
356
366
  }
@@ -1,4 +1,4 @@
1
- import { hopperStartupFailure, } from "../domain/errors.js";
1
+ import { hopperStartupFailure, } from "../domain/hopperStartupFailure.js";
2
2
  import { parseLinuxPrivateDisplayDiagnostic } from "./LinuxPrivateDisplayDiagnostic.js";
3
3
  /** Extract only a matching Linux adapter failure record. */
4
4
  export const hopperLauncherFailureDiagnostic = (event) => {
@@ -1,7 +1,7 @@
1
1
  import { fileURLToPath } from "node:url";
2
2
  import { accessSync, constants } from "node:fs";
3
3
  import { createAnalysisExecution } from "../application/AnalysisProvider.js";
4
- import { AnalysisCapabilityUnavailableError } from "../domain/errors.js";
4
+ import { AnalysisCapabilityUnavailableError } from "../domain/analysisErrorCore.js";
5
5
  import { err } from "../domain/result.js";
6
6
  import { GENERATED_MCP_TOOL_CATALOG } from "../generatedMcpToolCatalog.js";
7
7
  import { HopperApplicationLauncher } from "./BridgeLauncher.js";
@@ -25,6 +25,8 @@ const MUTATING_OPERATIONS = new Set([
25
25
  /** Tool contracts implemented directly by the Hopper adapter. */
26
26
  export const HOPPER_PROVIDER_TOOL_CONTRACTS = Object.freeze([
27
27
  ...GENERATED_MCP_TOOL_CATALOG.filter(({ kind, name }) => kind === "official-proxy" &&
28
+ name !== "annotate_native_function" &&
29
+ name !== "inspect_native_load_image" &&
28
30
  name !== "inspect_native_data_type" &&
29
31
  name !== "inspect_native_instruction" &&
30
32
  name !== "resolve_native_call_targets"),
@@ -96,7 +98,9 @@ export class HopperProvider {
96
98
  diagnostics,
97
99
  };
98
100
  }
99
- catch {
101
+ catch (cause) {
102
+ // best-effort cleanup: optional launcher probing; failure means unavailable.
103
+ void cause;
100
104
  return {
101
105
  status: "unavailable",
102
106
  code: "executable_missing",
@@ -125,11 +129,11 @@ export class HopperProvider {
125
129
  reason: null,
126
130
  diagnostics,
127
131
  };
128
- if (target.format === "dos-mz")
132
+ if (target.format === "dos-mz" || target.format === "dos-com")
129
133
  return {
130
134
  status: "unsupported",
131
135
  code: "target_format_unsupported",
132
- reason: "DOS MZ analysis requires the Ghidra 16-bit real-mode adapter.",
136
+ reason: "DOS MZ/COM analysis requires the Ghidra 16-bit real-mode adapter.",
133
137
  diagnostics,
134
138
  };
135
139
  return {
@@ -1,4 +1,4 @@
1
- import { HopperCancelledError, HopperProcessError, HopperProtocolError, HopperRemoteError, } from "../domain/errors.js";
1
+ import { HopperCancelledError, HopperProcessError, HopperProtocolError, HopperRemoteError, } from "../domain/hopperErrors.js";
2
2
  import { err } from "../domain/result.js";
3
3
  /** FIFO that keeps the wire serialized until Hopper actually replies. */
4
4
  export class HopperRequestQueue {
@@ -184,10 +184,14 @@ export class HopperRequestQueue {
184
184
  }
185
185
  #reportUpdate(entry, update) {
186
186
  try {
187
- void Promise.resolve(entry.progress?.report(update)).catch(() => undefined);
187
+ void Promise.resolve(entry.progress?.report(update)).catch((cause) => {
188
+ // best-effort cleanup: progress rejection bookkeeping only.
189
+ void cause;
190
+ });
188
191
  }
189
- catch {
192
+ catch (cause) {
190
193
  // Progress observation cannot change the request outcome.
194
+ void cause;
191
195
  }
192
196
  }
193
197
  }
@@ -1,4 +1,4 @@
1
- import { HopperProtocolError } from "../domain/errors.js";
1
+ import { HopperProtocolError } from "../domain/hopperErrors.js";
2
2
  import { err, ok } from "../domain/result.js";
3
3
  /** Validate the bridge identity and exact per-launch run identifier. */
4
4
  export const parseHopperServerInfo = (value, expectedRunId) => {
@@ -1,5 +1,5 @@
1
1
  import { createConnection } from "node:net";
2
- import { HopperCancelledError, HopperStartError } from "../domain/errors.js";
2
+ import { HopperCancelledError, HopperStartError, } from "../domain/hopperErrors.js";
3
3
  import { err, ok } from "../domain/result.js";
4
4
  /** Open one abort-aware Hopper Unix-socket connection attempt. */
5
5
  export const connectHopperSocketOnce = (socketPath, signal) => new Promise((resolve) => {
@@ -2,12 +2,20 @@ import { createHash } from "node:crypto";
2
2
  import { chmod, lstat, mkdir, realpath, rm } from "node:fs/promises";
3
3
  import { createConnection, createServer, } from "node:net";
4
4
  import { join, resolve } from "node:path";
5
- import { HopperStartError } from "../domain/errors.js";
5
+ import { HopperStartError } from "../domain/hopperErrors.js";
6
+ import { safeParseJson } from "../domain/safeJson.js";
6
7
  const leaseDirectory = join("/tmp", `rea-hopper-${process.getuid?.() ?? 0}`);
7
8
  /** Keep two REA processes from opening duplicate Hopper documents for one target/profile. */
8
9
  export const acquireHopperTargetLease = async (input) => {
9
10
  const directory = input.directory ?? leaseDirectory;
10
11
  await ensureLeaseDirectory(directory);
12
+ // The canonical path only derives the lease key; it never authorizes access.
13
+ // Common expected `realpath` failures include a missing target or path
14
+ // component (ENOENT, ENOTDIR), an unreadable component (EACCES), or a
15
+ // symlink loop (ELOOP). This catch also falls back for every other error,
16
+ // which may hide a real filesystem problem. The lexical `resolve` fallback
17
+ // still yields a deterministic key, but aliases may take separate leases
18
+ // whenever `realpath` cannot resolve them.
11
19
  const targetPath = await realpath(input.targetPath).catch(() => resolve(input.targetPath));
12
20
  const key = createHash("sha256")
13
21
  .update(JSON.stringify({
@@ -104,22 +112,22 @@ const readOwner = (socketPath) => new Promise((resolveOwner) => {
104
112
  const newline = response.indexOf("\n");
105
113
  if (newline < 0)
106
114
  return;
107
- try {
108
- const value = JSON.parse(response.slice(0, newline));
109
- if (typeof value === "object" &&
110
- value !== null &&
111
- typeof Reflect.get(value, "runId") === "string" &&
112
- typeof Reflect.get(value, "processId") === "number")
113
- finish({
114
- runId: Reflect.get(value, "runId"),
115
- processId: Reflect.get(value, "processId"),
116
- });
117
- else
118
- finish(undefined);
119
- }
120
- catch {
115
+ const parsed = safeParseJson(response.slice(0, newline));
116
+ if (!parsed.ok) {
121
117
  finish(undefined);
118
+ return;
122
119
  }
120
+ const value = parsed.value;
121
+ if (typeof value === "object" &&
122
+ value !== null &&
123
+ typeof Reflect.get(value, "runId") === "string" &&
124
+ typeof Reflect.get(value, "processId") === "number")
125
+ finish({
126
+ runId: Reflect.get(value, "runId"),
127
+ processId: Reflect.get(value, "processId"),
128
+ });
129
+ else
130
+ finish(undefined);
123
131
  });
124
132
  socket.on("error", () => finish(undefined));
125
133
  socket.on("end", () => finish(undefined));
@@ -1,5 +1,6 @@
1
1
  import { z } from "zod";
2
2
  import { isHopperStartupFailureCode, } from "../domain/hopperStartupFailure.js";
3
+ import { safeParseJson } from "../domain/safeJson.js";
3
4
  export const LINUX_PRIVATE_DISPLAY_DIAGNOSTIC_PREFIX = "REA_X11_DIAGNOSTIC=";
4
5
  const diagnosticContextSchema = z.object({
5
6
  component: z.literal("hopper_private_display"),
@@ -53,13 +54,11 @@ export const parseLinuxPrivateDisplayDiagnostic = (stderr) => {
53
54
  const record = records[0];
54
55
  if (record === undefined)
55
56
  return { ok: false, reason: "diagnostic_missing" };
56
- try {
57
- const parsed = diagnosticSchema.safeParse(JSON.parse(record.slice(LINUX_PRIVATE_DISPLAY_DIAGNOSTIC_PREFIX.length)));
58
- if (!parsed.success)
59
- return { ok: false, reason: "diagnostic_malformed" };
60
- return { ok: true, value: parsed.data };
61
- }
62
- catch {
57
+ const decoded = safeParseJson(record.slice(LINUX_PRIVATE_DISPLAY_DIAGNOSTIC_PREFIX.length));
58
+ if (!decoded.ok)
63
59
  return { ok: false, reason: "diagnostic_malformed" };
64
- }
60
+ const parsed = diagnosticSchema.safeParse(decoded.value);
61
+ if (!parsed.success)
62
+ return { ok: false, reason: "diagnostic_malformed" };
63
+ return { ok: true, value: parsed.data };
65
64
  };