rea-agents 5.0.0 → 6.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 (507) hide show
  1. package/README.md +168 -655
  2. package/bridge/android/ReaJadxBridge.java +14 -5
  3. package/bridge/ghidra/ReaGhidraBridge.java +173 -47
  4. package/bridge/hopper_bridge.py +310 -128
  5. package/bridge/mitmproxy/capture.py +208 -0
  6. package/bridge/native/rea_lldb_tracer.py +839 -0
  7. package/bridge/process/ProcessRunTokenReader.swift +297 -0
  8. package/bridge/process/ProcessRunTokenReaderMain.swift +35 -0
  9. package/bridge/pwndbg/core_context.py +101 -0
  10. package/bridge/pwndbg/launch.py +39 -0
  11. package/bridge/pwndbg/launch_impl.py +34 -0
  12. package/bridge/pwntools/decoder_runtime.py +59 -0
  13. package/bridge/pwntools/layout.py +39 -0
  14. package/bridge/pwntools/layout_impl.py +309 -0
  15. package/bridge/pwntools/recorded_crash.py +39 -0
  16. package/bridge/pwntools/recorded_crash_impl.py +147 -0
  17. package/dist/android/JadxConfiguration.js +196 -33
  18. package/dist/android/JadxMcpTransport.js +4 -0
  19. package/dist/android/JadxProtocol.js +6 -0
  20. package/dist/android/JadxProvider.js +20 -2
  21. package/dist/android/JadxSession.js +23 -4
  22. package/dist/application/AnalysisContextQueries.js +8 -35
  23. package/dist/application/AnalysisDocument.js +32 -0
  24. package/dist/application/AppBundleExecutable.js +67 -21
  25. package/dist/application/CallPathTracing.js +19 -3
  26. package/dist/application/CapabilityInventory.js +27 -3
  27. package/dist/application/ClientConfigurationDocument.js +871 -6
  28. package/dist/application/ClientRegistrationIdentity.js +26 -5
  29. package/dist/application/ClientRegistrationStatus.js +29 -14
  30. package/dist/application/DirectAnalysis.js +97 -33
  31. package/dist/application/Doctor.js +4 -2
  32. package/dist/application/DoctorScope.js +25 -13
  33. package/dist/application/EnhancedLiteralTracing.js +22 -25
  34. package/dist/application/EnhancedTools.js +13 -11
  35. package/dist/application/EvidenceBundleFiles.js +24 -12
  36. package/dist/application/FunctionAnalysisEvidence.js +2 -3
  37. package/dist/application/InventoryProjectionEvidence.js +4 -3
  38. package/dist/application/InvestigationProviders.js +3 -2
  39. package/dist/application/JsonFiles.js +50 -28
  40. package/dist/application/ProcedureAddressResolution.js +11 -0
  41. package/dist/application/ReconstructionCoverageService.js +7 -4
  42. package/dist/application/ReconstructionObligationCandidates.js +5 -1
  43. package/dist/application/ReconstructionObligationLedgerService.js +4 -3
  44. package/dist/application/Setup.js +13 -1
  45. package/dist/application/SetupClientConfiguration.js +10 -15
  46. package/dist/application/SetupHost.js +5 -2
  47. package/dist/application/SetupPlan.js +5 -3
  48. package/dist/application/SupportedClients.js +34 -1
  49. package/dist/application/Uninstall.js +4 -3
  50. package/dist/application/Update.js +18 -3
  51. package/dist/application/UpdateRuntime.js +46 -25
  52. package/dist/application/WebModuleTraceService.js +4 -2
  53. package/dist/application/WebNetworkCapturePort.js +1 -0
  54. package/dist/application/WebNetworkCaptureService.js +134 -0
  55. package/dist/application/WebRuntimeService.js +5 -3
  56. package/dist/application/WebScriptExportService.js +2 -2
  57. package/dist/application/WebSourceLocationService.js +4 -2
  58. package/dist/application/WindowsCapabilities.js +1 -1
  59. package/dist/application/WorkflowEvidence.js +82 -0
  60. package/dist/application/binary/AnalysisProviderEvaluation.js +21 -5
  61. package/dist/application/binary/AnalysisProviderRegistry.js +2 -0
  62. package/dist/application/binary/AnalysisSnapshotCache.js +52 -12
  63. package/dist/application/binary/BinarySession.js +131 -76
  64. package/dist/application/binary/BinarySessionOpen.js +19 -6
  65. package/dist/application/binary/BinarySessionRecords.js +45 -3
  66. package/dist/application/binary/BinarySessionStatus.js +17 -1
  67. package/dist/application/binary/CompositeProvider.js +13 -0
  68. package/dist/application/binary/LazyAnalysisProvider.js +3 -0
  69. package/dist/application/binaryDiagnostics/BinaryLayoutPort.js +1 -0
  70. package/dist/application/binaryDiagnostics/BinaryLayoutService.js +59 -0
  71. package/dist/application/binaryDiagnostics/RecordedCrashPort.js +1 -0
  72. package/dist/application/binaryDiagnostics/RecordedCrashService.js +62 -0
  73. package/dist/application/evm/EvmInterfacePort.js +1 -0
  74. package/dist/application/evm/EvmInterfaceService.js +64 -0
  75. package/dist/application/investigation/EvidenceLedger.js +21 -7
  76. package/dist/application/investigation/InvestigationRecords.js +8 -0
  77. package/dist/application/javascript/JavaScriptAnalysisControl.js +34 -0
  78. package/dist/application/javascript/JavaScriptApplicationEvidence.js +25 -5
  79. package/dist/application/javascript/JavaScriptApplicationEvidenceGraph.js +19 -2
  80. package/dist/application/javascript/JavaScriptApplicationService.js +34 -14
  81. package/dist/application/javascript/JavaScriptApplicationWorkflowService.js +5 -5
  82. package/dist/application/javascript/JavaScriptArtifactAnalysis.js +47 -27
  83. package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +39 -7
  84. package/dist/application/javascript/JavaScriptArtifactGraphDocuments.js +26 -2
  85. package/dist/application/javascript/JavaScriptArtifactPathResolution.js +80 -27
  86. package/dist/application/javascript/JavaScriptArtifactReconstruction.js +33 -12
  87. package/dist/application/javascript/JavaScriptModuleRelationships.js +37 -8
  88. package/dist/application/javascript/JavaScriptRecoveryService.js +4 -2
  89. package/dist/application/javascript/JavaScriptRuntimeObservationService.js +3 -1
  90. package/dist/application/javascript/JavaScriptRuntimeReconciliationService.js +3 -3
  91. package/dist/application/javascript/JavaScriptSemanticGraphAsyncProjection.js +7 -7
  92. package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +149 -72
  93. package/dist/application/javascript/JavaScriptSemanticGraphChildProcessProjection.js +14 -15
  94. package/dist/application/javascript/JavaScriptSemanticGraphConstruction.js +41 -1
  95. package/dist/application/javascript/JavaScriptSemanticGraphDataProjection.js +7 -7
  96. package/dist/application/javascript/JavaScriptSemanticGraphFlowProjection.js +5 -9
  97. package/dist/application/javascript/JavaScriptSemanticGraphObjectProjection.js +3 -3
  98. package/dist/application/javascript/JavaScriptSemanticGraphProjection.js +118 -12
  99. package/dist/application/javascript/JavaScriptSemanticGraphResourceProjection.js +3 -3
  100. package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +27 -5
  101. package/dist/application/managed/ManagedApplicationGraphService.js +4 -3
  102. package/dist/application/managed/ManagedMemberComparisonService.js +7 -4
  103. package/dist/application/managed/ManagedNativeVerificationService.js +4 -3
  104. package/dist/application/managed/ManagedReconstructionService.js +4 -3
  105. package/dist/application/{ProcessCli.js → process/ProcessCli.js} +23 -15
  106. package/dist/application/{ProcessEvidence.js → process/ProcessEvidence.js} +8 -7
  107. package/dist/application/workflowInputError.js +18 -0
  108. package/dist/artifacts/ArtifactProvider.js +42 -5
  109. package/dist/artifacts/ArtifactProviderMetadata.js +2 -1
  110. package/dist/artifacts/MachOSliceArtifactReader.js +98 -14
  111. package/dist/artifacts/NativeDmgArtifactReader.js +13 -6
  112. package/dist/artifacts/ZipArtifactReader.js +3 -0
  113. package/dist/artifacts/apple/AppleAssetCatalogAnalysis.js +22 -3
  114. package/dist/artifacts/apple/DylibResolutionReader.js +259 -0
  115. package/dist/artifacts/apple/InterfaceBuilderAnalysis.js +176 -56
  116. package/dist/artifacts/apple/InterfaceBuilderDecodeBudget.js +195 -0
  117. package/dist/artifacts/apple/KeyedArchiveReader.js +36 -22
  118. package/dist/artifacts/apple/MachoLoadCommandReader.js +355 -0
  119. package/dist/artifacts/apple/NibArchive.js +81 -14
  120. package/dist/artifacts/apple/NibViewHierarchy.js +10 -3
  121. package/dist/artifacts/apple/PlistNumberLiterals.js +164 -0
  122. package/dist/{application → artifacts/extraction}/ArtifactExtraction.js +10 -10
  123. package/dist/{application → artifacts/inventory}/ArtifactGraphConstruction.js +16 -11
  124. package/dist/{application → artifacts/inventory}/ArtifactInventory.js +4 -4
  125. package/dist/{application/ArtifactInventory → artifacts/inventory}/classify.js +2 -2
  126. package/dist/{application/ArtifactInventory → artifacts/inventory}/reader.js +5 -5
  127. package/dist/{application/ArtifactInventory → artifacts/inventory}/scanCanonical.js +14 -17
  128. package/dist/{application/ArtifactInventory → artifacts/inventory}/scanReader.js +5 -5
  129. package/dist/artifacts/javascript/JavaScriptArtifactFiles.js +6 -2
  130. package/dist/artifacts/readStableArtifact.js +20 -4
  131. package/dist/browser/CdpCaptureCompleteness.js +2 -0
  132. package/dist/browser/CdpCaptureEventHandlers.js +165 -12
  133. package/dist/browser/CdpCaptureEventTypes.js +5 -1
  134. package/dist/browser/CdpCaptureEvents.js +34 -0
  135. package/dist/browser/CdpConnection.js +30 -11
  136. package/dist/browser/CdpOptionalCommand.js +2 -3
  137. package/dist/browser/CdpPageCapture.js +23 -1
  138. package/dist/browser/PlaywrightElectronActiveActions.js +32 -23
  139. package/dist/browser/PlaywrightElectronActiveProjection.js +141 -0
  140. package/dist/browser/PlaywrightElectronActiveProvider.js +130 -122
  141. package/dist/browser/WebSourceMapFetcher.js +426 -72
  142. package/dist/browser/assets/LocalWebScriptArtifacts.js +2 -2
  143. package/dist/browser/history/CaptureFailures.js +137 -0
  144. package/dist/browser/history/CaptureFormatError.js +10 -0
  145. package/dist/browser/history/CaptureRedaction.js +65 -0
  146. package/dist/browser/history/CaptureRelease.js +17 -0
  147. package/dist/browser/history/HarCapture.js +165 -0
  148. package/dist/browser/history/HarCaptureAdapter.js +20 -0
  149. package/dist/browser/history/HarCaptureProcess.js +57 -0
  150. package/dist/browser/history/HarJson.js +92 -0
  151. package/dist/browser/history/HarSchema.js +72 -0
  152. package/dist/browser/history/HistoricalCaptureDecoder.js +188 -0
  153. package/dist/browser/history/HistoricalCaptureFormatAdapter.js +1 -0
  154. package/dist/browser/history/MitmproxyCaptureAdapter.js +42 -0
  155. package/dist/cli/analysisSelector.js +23 -0
  156. package/dist/cli/applicationCommands.js +2 -3
  157. package/dist/cli/artifactCommands.js +26 -1
  158. package/dist/cli/binaryDiagnosticsCommands.js +39 -0
  159. package/dist/cli/coreAnalysisCommands.js +2 -2
  160. package/dist/cli/coreBinaryCommands.js +78 -20
  161. package/dist/cli/electronCommands.js +21 -13
  162. package/dist/cli/evmCommands.js +24 -0
  163. package/dist/cli/firmwareCommands.js +6 -3
  164. package/dist/cli/javascriptApplicationAnalysis.js +20 -3
  165. package/dist/cli/jsonOutput.js +38 -0
  166. package/dist/cli/nativeCallCommands.js +34 -0
  167. package/dist/cli/processCommands.js +1 -1
  168. package/dist/cli/streamedJsonOutput.js +56 -0
  169. package/dist/cli/utilityCommands.js +2 -0
  170. package/dist/cli/webNetworkCaptureCommands.js +40 -0
  171. package/dist/cli/webRuntimeCommands.js +8 -8
  172. package/dist/cli.js +11 -4
  173. package/dist/cliBrowserScenarioCommands.js +2 -2
  174. package/dist/cliCommandNames.js +6 -1
  175. package/dist/cliJsonInput.js +35 -1
  176. package/dist/cliOutput.js +21 -6
  177. package/dist/composition/binaryDiagnostics.js +8 -0
  178. package/dist/composition/evm.js +4 -0
  179. package/dist/composition/webNetworkCaptures.js +6 -0
  180. package/dist/config/environment.js +4 -0
  181. package/dist/config/ghidraStartupTimeout.js +17 -0
  182. package/dist/config/mcpResponseBudget.js +22 -0
  183. package/dist/config/parseConfig.js +2 -1
  184. package/dist/contracts/artifactToolContracts.js +6 -0
  185. package/dist/contracts/browserCaptureToolInputSchema.js +43 -0
  186. package/dist/contracts/browserToolContracts.js +4 -3
  187. package/dist/contracts/enhancedInputs.js +5 -3
  188. package/dist/contracts/enhancedToolContracts.js +3 -3
  189. package/dist/contracts/errorSchemas.js +8 -1
  190. package/dist/contracts/evm/evmToolContracts.js +20 -0
  191. package/dist/contracts/hopperMemoryContracts.js +2 -5
  192. package/dist/contracts/investigationExamples.js +2 -2
  193. package/dist/contracts/javascript/electronToolContracts.js +1 -1
  194. package/dist/contracts/managed/managedToolContracts.js +8 -6
  195. package/dist/contracts/native/binaryDiagnosticsToolContracts.js +42 -0
  196. package/dist/contracts/native/nativeToolContracts.js +21 -3
  197. package/dist/contracts/officialToolContracts.js +26 -24
  198. package/dist/contracts/process/processCaptureExample.js +2 -0
  199. package/dist/contracts/promptContracts.js +3 -3
  200. package/dist/contracts/sessionLifecycleInputs.js +18 -5
  201. package/dist/contracts/sessionStatusContract.js +8 -2
  202. package/dist/contracts/sessionToolContracts.js +8 -3
  203. package/dist/contracts/sessionToolSchemas.js +8 -4
  204. package/dist/contracts/toolContractExamples.js +1 -2
  205. package/dist/contracts/toolContractHelpers.js +4 -1
  206. package/dist/contracts/toolContracts.js +6 -0
  207. package/dist/contracts/toolEffects.js +30 -1
  208. package/dist/contracts/toolOutputSchemaGroups.js +33 -28
  209. package/dist/contracts/toolOutputSchemaPrimitives.js +19 -1
  210. package/dist/contracts/toolSchemaMetadata.js +69 -10
  211. package/dist/contracts/webNetworkCaptureToolContracts.js +24 -0
  212. package/dist/domain/analysisErrorBase.js +22 -2
  213. package/dist/domain/analysisErrorCore.js +61 -5
  214. package/dist/domain/analysisErrorPresentation.js +95 -12
  215. package/dist/domain/analysisErrorProjection.js +148 -19
  216. package/dist/domain/analysisSnapshot.js +166 -2
  217. package/dist/domain/android/androidAnalysis.js +2 -4
  218. package/dist/domain/android/androidApplication.js +17 -9
  219. package/dist/domain/apple/appleApplication.js +41 -14
  220. package/dist/domain/apple/dyldEnvironment.js +73 -0
  221. package/dist/domain/apple/dyldPaths.js +81 -0
  222. package/dist/domain/apple/dylibResolution.js +478 -0
  223. package/dist/domain/apple/dylibResolutionFindings.js +77 -0
  224. package/dist/domain/apple/interfaceBuilderGraph.js +25 -13
  225. package/dist/domain/apple/interfaceBuilderKeyedArchive.js +13 -3
  226. package/dist/domain/apple/keyedArchive.js +9 -1
  227. package/dist/domain/apple/machoContainer.js +54 -0
  228. package/dist/domain/apple/plistNumbers.js +76 -0
  229. package/dist/domain/artifactIdentity.js +29 -0
  230. package/dist/domain/artifactInventoryEvidence.js +19 -24
  231. package/dist/domain/artifactPathSyntax.js +1 -1
  232. package/dist/domain/bridgeCandidateProjection.js +71 -0
  233. package/dist/domain/browserCompleteness.js +1 -0
  234. package/dist/domain/browserObservation.js +1 -1
  235. package/dist/domain/browserObservationError.js +24 -5
  236. package/dist/domain/browserObservationSchemas.js +13 -0
  237. package/dist/domain/browserScenarioValues.js +5 -2
  238. package/dist/domain/bundleComparison.js +3 -2
  239. package/dist/domain/callPathSchemas.js +1 -1
  240. package/dist/domain/canonicalDigest.js +13 -1
  241. package/dist/domain/canonicalJsonDigestSteps.js +133 -0
  242. package/dist/domain/canonicalOrdering.js +9 -5
  243. package/dist/domain/changedBehavior.js +9 -9
  244. package/dist/domain/comparisonSourceEvidence.js +40 -0
  245. package/dist/domain/comparisonStatus.js +2 -30
  246. package/dist/domain/configurationErrors.js +1 -1
  247. package/dist/domain/conformanceTrustGate.js +0 -16
  248. package/dist/domain/evidence.js +78 -11
  249. package/dist/domain/evidenceBundle.js +42 -1
  250. package/dist/domain/evidenceErrors.js +12 -1
  251. package/dist/domain/evm/evmInterface.js +63 -0
  252. package/dist/domain/explicitSensitiveFailure.js +108 -0
  253. package/dist/domain/explicitSensitiveValues.js +10 -0
  254. package/dist/domain/firmware/firmwareAnalysis.js +10 -4
  255. package/dist/domain/hopperErrors.js +23 -2
  256. package/dist/domain/hopperValues.js +51 -8
  257. package/dist/domain/immutableJson.js +114 -0
  258. package/dist/domain/inputIssueProjection.js +3 -0
  259. package/dist/domain/javascript/electronActiveObservation.js +37 -6
  260. package/dist/domain/javascript/electronStaticAnalysisValues.js +6 -12
  261. package/dist/domain/javascript/htmlArtifactReferences.js +40 -0
  262. package/dist/domain/javascript/javascriptApplicationAnalysis.js +71 -23
  263. package/dist/domain/javascript/javascriptApplicationGraph.js +13 -0
  264. package/dist/domain/javascript/javascriptAstValues.js +20 -0
  265. package/dist/domain/javascript/javascriptExportShapeComparison.js +21 -5
  266. package/dist/domain/javascript/javascriptExportShapeVariants.js +0 -10
  267. package/dist/domain/javascript/javascriptRecovery.js +3 -8
  268. package/dist/domain/javascript/javascriptSemanticAnalysis.js +97 -2
  269. package/dist/domain/javascript/javascriptSemanticCoverage.js +6 -5
  270. package/dist/domain/javascript/javascriptSemanticDataEffectHelpers.js +9 -17
  271. package/dist/domain/javascript/javascriptSemanticDataEffects.js +22 -5
  272. package/dist/domain/javascript/javascriptSemanticGraph.js +34 -5
  273. package/dist/domain/javascript/javascriptSemanticGraphSchemas.js +1 -0
  274. package/dist/domain/javascript/javascriptSemanticPrimitives.js +25 -17
  275. package/dist/domain/javascript/javascriptSemanticQuerySchemas.js +8 -4
  276. package/dist/domain/javascript/javascriptSemanticResourceLimits.js +77 -0
  277. package/dist/domain/javascript/javascriptSemanticValues.js +83 -11
  278. package/dist/domain/javascript/javascriptSourceParser.js +6 -2
  279. package/dist/domain/javascript/javascriptStaticAnalysis.js +22 -17
  280. package/dist/domain/javascript/javascriptStaticAnalysisBundler.js +5 -3
  281. package/dist/domain/javascript/javascriptStaticAnalysisCalls.js +14 -4
  282. package/dist/domain/javascript/javascriptStaticAnalysisFindings.js +66 -7
  283. package/dist/domain/javascript/javascriptStaticAnalysisHelpers.js +28 -16
  284. package/dist/domain/javascript/javascriptStaticAnalysisState.js +3 -2
  285. package/dist/domain/jsonSerialization.js +109 -0
  286. package/dist/domain/jsonValue.js +91 -3
  287. package/dist/domain/localPath.js +8 -0
  288. package/dist/domain/managed/managedApplicationGraph.js +10 -10
  289. package/dist/domain/managed/managedInspectionEvidence.js +16 -0
  290. package/dist/domain/managed/managedMemberComparisonMatch.js +5 -9
  291. package/dist/domain/managed/managedNativeVerification.js +3 -9
  292. package/dist/domain/native/binaryLayout.js +357 -0
  293. package/dist/domain/native/fileOffsetPartialObservation.js +1 -0
  294. package/dist/domain/native/nativeCallObservation.js +186 -0
  295. package/dist/domain/native/nativeCallPartialObservation.js +33 -0
  296. package/dist/domain/native/objcSwiftMetadata.js +0 -39
  297. package/dist/domain/native/recordedCrash.js +266 -0
  298. package/dist/domain/native/recordedCrashNoteCoverage.js +73 -0
  299. package/dist/domain/{processCapture.js → process/processCapture.js} +143 -2
  300. package/dist/domain/{processCaptureExample.js → process/processCaptureExample.js} +5 -0
  301. package/dist/domain/process/processCaptureParsing.js +54 -0
  302. package/dist/domain/{processCaptureValidation.js → process/processCaptureValidation.js} +18 -2
  303. package/dist/domain/{processComparison.js → process/processComparison.js} +39 -5
  304. package/dist/domain/{processObservation.js → process/processObservation.js} +1 -1
  305. package/dist/domain/{processScenario.js → process/processScenario.js} +11 -10
  306. package/dist/domain/{processTraceSpecification.js → process/processTraceSpecification.js} +1 -1
  307. package/dist/domain/propertyListKeys.js +1 -1
  308. package/dist/domain/propertyListXmlText.js +19 -0
  309. package/dist/domain/providerAdapterError.js +1 -1
  310. package/dist/domain/providerOperationHealth.js +54 -0
  311. package/dist/domain/providerSelectionError.js +4 -2
  312. package/dist/domain/reconstructionVerification.js +9 -46
  313. package/dist/domain/reconstructionVerificationSchemas.js +3 -3
  314. package/dist/domain/residualUnknown.js +3 -2
  315. package/dist/domain/staticRuntimeCorrelation.js +9 -46
  316. package/dist/domain/webBundleAnalysis.js +20 -8
  317. package/dist/domain/webBundleAnalyzerInspection.js +13 -8
  318. package/dist/domain/webBundleAnalyzerResult.js +41 -2
  319. package/dist/domain/webCaptureDiff.js +1 -0
  320. package/dist/domain/webNetworkCapture.js +118 -0
  321. package/dist/domain/webNetworkCaptureCoordinates.js +58 -0
  322. package/dist/domain/webRuntime.js +19 -5
  323. package/dist/domain/webSourceLocation.js +1 -0
  324. package/dist/dotnet/ManagedExceptionRegionValidation.js +41 -0
  325. package/dist/dotnet/ManagedMemberInspector.js +4 -2
  326. package/dist/dotnet/ManagedMemberInspectorCore.js +38 -32
  327. package/dist/dotnet/ManagedMemberInstructionDecoder.js +23 -7
  328. package/dist/dotnet/ManagedMemberRows.js +14 -3
  329. package/dist/dotnet/ManagedMetadataHeaps.js +20 -2
  330. package/dist/dotnet/ManagedMetadataInventory.js +38 -28
  331. package/dist/dotnet/ManagedMetadataInventoryRows.js +24 -10
  332. package/dist/dotnet/ManagedMethodBodyReader.js +7 -1
  333. package/dist/dotnet/ManagedNativeBoundaryHelpers.js +15 -3
  334. package/dist/dotnet/ManagedNativeBoundaryInspector.js +3 -1
  335. package/dist/dotnet/ManagedPeReader.js +11 -0
  336. package/dist/evm/EvmBytecodeCarrier.js +21 -0
  337. package/dist/evm/EvmWorkerLimits.js +40 -0
  338. package/dist/evm/EvmoleFailures.js +126 -0
  339. package/dist/evm/EvmoleInterfaceAdapter.js +53 -0
  340. package/dist/evm/EvmoleInterfaceProvider.js +273 -0
  341. package/dist/evm/EvmoleInterfaceWorker.js +87 -0
  342. package/dist/evm/EvmoleRelease.js +16 -0
  343. package/dist/firmware/FirmwareCommand.js +1 -0
  344. package/dist/firmware/FirmwareFiles.js +1 -1
  345. package/dist/generatedPackageMetadata.js +2 -2
  346. package/dist/ghidra/GhidraAnalysisProfile.js +5 -0
  347. package/dist/ghidra/GhidraClient.js +47 -14
  348. package/dist/ghidra/GhidraDiagnostics.js +7 -7
  349. package/dist/ghidra/GhidraFunctionValues.js +10 -7
  350. package/dist/ghidra/GhidraInstallation.js +18 -21
  351. package/dist/ghidra/GhidraInventoryValues.js +14 -4
  352. package/dist/ghidra/GhidraJavaLaunch.js +62 -0
  353. package/dist/ghidra/GhidraLauncher.js +34 -16
  354. package/dist/ghidra/GhidraProvider.js +2 -2
  355. package/dist/ghidra/GhidraProviderCapabilities.js +15 -3
  356. package/dist/ghidra/GhidraProviderClient.js +23 -12
  357. package/dist/ghidra/GhidraSessionError.js +11 -7
  358. package/dist/ghidra/GhidraTargetSnapshot.js +47 -12
  359. package/dist/ghidra/GhidraTransport.js +20 -0
  360. package/dist/hopper/BridgeLauncher.js +33 -11
  361. package/dist/hopper/HopperAnalysisProfile.js +62 -4
  362. package/dist/hopper/HopperCleanup.js +15 -3
  363. package/dist/hopper/HopperClient.js +222 -14
  364. package/dist/hopper/HopperFileOffset.js +237 -0
  365. package/dist/hopper/HopperMachOImage.js +196 -0
  366. package/dist/hopper/HopperOperationStage.js +6 -0
  367. package/dist/hopper/HopperProvider.js +63 -9
  368. package/dist/hopper/HopperProviderCapabilities.js +19 -1
  369. package/dist/hopper/HopperRegexSearch.js +137 -0
  370. package/dist/hopper/HopperRegexWorker.js +27 -0
  371. package/dist/hopper/HopperRequestQueue.js +68 -19
  372. package/dist/hopper/HopperTargetLease.js +3 -2
  373. package/dist/hopper/LinuxPrivateDisplayProbe.js +4 -2
  374. package/dist/inspector/JavaScriptRuntimeScope.js +9 -1
  375. package/dist/inspector/V8InspectorCaptureProjection.js +8 -3
  376. package/dist/inspector/V8InspectorProvider.js +47 -11
  377. package/dist/javascript/recovery/WakaruCommand.js +3 -0
  378. package/dist/javascript/sourceMaps/DecodedSourceMap.js +47 -0
  379. package/dist/javascript/sourceMaps/SourceMapCommand.js +17 -0
  380. package/dist/javascript/sourceMaps/SourceMapFormat.js +79 -31
  381. package/dist/javascript/sourceMaps/TraceSourceMap.js +14 -28
  382. package/dist/mcpDoctor.js +62 -2
  383. package/dist/native/AppleDispatchCoverage.js +47 -6
  384. package/dist/native/AppleDispatchDecodeFacts.js +6 -0
  385. package/dist/native/AppleDispatchMetadata.js +6 -3
  386. package/dist/native/AppleMachoFixups.js +48 -24
  387. package/dist/native/AppleMachoSelection.js +32 -16
  388. package/dist/native/AppleObjcCategories.js +6 -2
  389. package/dist/native/AppleObjcDispatchFacets.js +5 -2
  390. package/dist/native/AppleObjcProperties.js +2 -1
  391. package/dist/native/AppleSwiftDispatchFacets.js +27 -21
  392. package/dist/native/AppleSwiftVtables.js +21 -15
  393. package/dist/native/CommandRunner.js +82 -84
  394. package/dist/native/LldbCallTracer.js +541 -0
  395. package/dist/native/LldbRetainedObservations.js +178 -0
  396. package/dist/native/NativeCallObservation.js +194 -0
  397. package/dist/native/NativeMacOSProvider.js +117 -20
  398. package/dist/native/NativeMacOSProviderMetadata.js +8 -3
  399. package/dist/native/SignatureTargetBinding.js +155 -0
  400. package/dist/native/parsers/lipo.js +71 -1
  401. package/dist/native/pwndbg/PwndbgCoreContext.js +180 -0
  402. package/dist/native/pwntools/PwntoolsDecoder.js +203 -0
  403. package/dist/native/pwntools/PwntoolsFailures.js +180 -0
  404. package/dist/native/pwntools/PwntoolsLayoutProvider.js +36 -0
  405. package/dist/native/pwntools/PwntoolsRecordedCrashProvider.js +75 -0
  406. package/dist/native/pwntools/PwntoolsRelease.js +19 -0
  407. package/dist/native/pwntools/PwntoolsResourceLimits.js +76 -0
  408. package/dist/native/pwntools/RecordedCrashSourceBindings.js +46 -0
  409. package/dist/native/pwntools/RecordedCrashStructureBindings.js +103 -0
  410. package/dist/process/DarwinProcessRunTokenReader.js +293 -0
  411. package/dist/process/ExecFileOutput.js +20 -0
  412. package/dist/process/OwnedCommand.js +118 -0
  413. package/dist/process/ProcessOwnership.js +431 -51
  414. package/dist/process/ProcessOwnershipObservation.js +209 -27
  415. package/dist/process/ProviderProcess.js +68 -10
  416. package/dist/{application → process/capture}/ProcessCaptureCapability.js +15 -0
  417. package/dist/{application → process/capture}/ProcessCaptureError.js +18 -2
  418. package/dist/process/capture/ProcessCaptureLifecycle.js +681 -0
  419. package/dist/{application → process/capture}/ProcessHarness.js +195 -29
  420. package/dist/{application → process/capture}/ProcessSampling.js +2 -2
  421. package/dist/server/EvidenceMcpServer.js +146 -0
  422. package/dist/server/createServer.js +37 -8
  423. package/dist/server/promptCompletion.js +10 -3
  424. package/dist/server/registerAndroidTools.js +2 -4
  425. package/dist/server/registerApplicationTools/helpers.js +2 -4
  426. package/dist/server/registerArtifactComparisonTool.js +11 -7
  427. package/dist/server/registerBinaryDiagnosticsTools.js +15 -0
  428. package/dist/server/registerBrowserScenarioTool.js +2 -4
  429. package/dist/server/registerBrowserTools.js +2 -4
  430. package/dist/server/registerBundleComparisonTool.js +2 -3
  431. package/dist/server/registerCloseLifecycleTool.js +8 -18
  432. package/dist/server/registerElectronTools.js +2 -4
  433. package/dist/server/registerEnhancedTools.js +18 -59
  434. package/dist/server/registerEvidenceTools.js +3 -5
  435. package/dist/server/registerEvmTools.js +15 -0
  436. package/dist/server/registerFirmwareTools.js +2 -4
  437. package/dist/server/registerFunctionComparisonTool.js +10 -6
  438. package/dist/server/registerInvestigationTools.js +7 -7
  439. package/dist/server/registerJavaScriptRecoveryTool.js +2 -4
  440. package/dist/server/registerJavaScriptRuntimeObservationTools.js +2 -4
  441. package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +2 -4
  442. package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +2 -4
  443. package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +2 -4
  444. package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +2 -4
  445. package/dist/server/registerOfficialTools.js +2 -4
  446. package/dist/server/registerProcessComparisonTool.js +72 -46
  447. package/dist/server/registerRecordedCrashTools.js +15 -0
  448. package/dist/server/registerSessionRecordTools.js +5 -6
  449. package/dist/server/registerSessionStatusTool.js +17 -3
  450. package/dist/server/registerSessionTools.js +13 -5
  451. package/dist/server/registerWebModuleTool.js +2 -4
  452. package/dist/server/registerWebNetworkCaptureTool.js +26 -0
  453. package/dist/server/registerWebRuntimeTools.js +3 -7
  454. package/dist/server/registerWebScriptTool.js +2 -4
  455. package/dist/server/registerWebSourceLocationTool.js +2 -4
  456. package/dist/server/runDerivedOperation.js +15 -3
  457. package/dist/server/sessionAvailabilityPolicy.js +3 -1
  458. package/dist/server/sessionToolPolicies.js +1 -1
  459. package/dist/server/toolRegistrationOptions.js +2 -2
  460. package/dist/server/toolResult.js +63 -11
  461. package/dist/server/toolResultEncoding.js +33 -0
  462. package/install.sh +1 -1
  463. package/native/windows/build/manifest.json +2 -2
  464. package/native/windows/build/rea-windows-x64.node +0 -0
  465. package/package.json +42 -9
  466. package/scripts/electron-active-hook-boundaries.cjs +18 -20
  467. package/scripts/electron-active-hook.cjs +241 -37
  468. package/scripts/rea.mjs +11 -3
  469. package/skills/reverse-engineer-anything/SKILL.md +32 -4
  470. package/skills/reverse-engineer-anything/references/javascript-applications.md +8 -1
  471. package/skills/reverse-engineer-anything/references/native-and-artifacts.md +29 -0
  472. package/third_party/README.md +60 -0
  473. package/third_party/evmole/LICENSE +21 -0
  474. package/third_party/evmole/README.md +22 -0
  475. package/third_party/pwndbg/LICENSE.md +21 -0
  476. package/third_party/pwndbg/README.md +23 -0
  477. package/third_party/pwntools/README.md +40 -0
  478. package/dist/application/AuthorizedArtifactInventory.js +0 -7
  479. package/dist/application/ProcessCaptureLifecycle.js +0 -299
  480. package/dist/application/StoreFileLock.js +0 -124
  481. package/dist/contracts/processCaptureExample.js +0 -2
  482. package/dist/domain/bytecodeProvider.js +0 -178
  483. package/dist/domain/customProtocolCapture.js +0 -137
  484. package/dist/domain/eventProcessTree.js +0 -225
  485. package/dist/domain/mobileApplicationInvestigation.js +0 -159
  486. package/dist/domain/packageAnalysis.js +0 -123
  487. package/dist/domain/peInspection.js +0 -197
  488. package/dist/domain/processCaptureParsing.js +0 -21
  489. package/dist/domain/protocolCapture.js +0 -217
  490. package/dist/domain/runtimeIdentification.js +0 -212
  491. package/dist/generatedMcpToolCatalog.js +0 -37
  492. package/dist/ghidra/GhidraDefaults.js +0 -2
  493. /package/dist/application/{ArtifactExtractionDestination.js → artifacts/ArtifactExtractionDestination.js} +0 -0
  494. /package/dist/{application/ArtifactInventory → artifacts/inventory}/policy.js +0 -0
  495. /package/dist/{application/ArtifactInventory → artifacts/inventory}/types.js +0 -0
  496. /package/dist/domain/{processEvidenceProvider.js → process/processEvidenceProvider.js} +0 -0
  497. /package/dist/domain/{processTraceComparison.js → process/processTraceComparison.js} +0 -0
  498. /package/dist/domain/{processTraceDimensionProjection.js → process/processTraceDimensionProjection.js} +0 -0
  499. /package/dist/domain/{processTraceEvaluation.js → process/processTraceEvaluation.js} +0 -0
  500. /package/dist/{application → process/capture}/FilesystemSnapshot.js +0 -0
  501. /package/dist/{application → process/capture}/ProcessCaptureEnvironment.js +0 -0
  502. /package/dist/{application → process/capture}/ProcessCaptureJournal.js +0 -0
  503. /package/dist/{application → process/capture}/ProcessFilesystemEffects.js +0 -0
  504. /package/dist/{application → process/capture}/ProcessNormalization.js +0 -0
  505. /package/dist/{application → process/capture}/ProcessScenarioRuntimeValidation.js +0 -0
  506. /package/dist/{application → process/capture}/ProcessTimer.js +0 -0
  507. /package/dist/{application → process/capture}/TerminalRenderer.js +0 -0
@@ -10,6 +10,7 @@ import { spawnOwnedProviderProcess, } from "../process/ProviderProcess.js";
10
10
  import { waitForAbortableDelay } from "../process/ProviderDeadline.js";
11
11
  import { selectLinuxPrivateDisplayStrategy, } from "./LinuxPrivateDisplayProbe.js";
12
12
  import writeFileAtomic from "write-file-atomic";
13
+ import { prepareHopperMachOImage, } from "./HopperMachOImage.js";
13
14
  import { acquireHopperTargetLease } from "./HopperTargetLease.js";
14
15
  const execFileAsync = promisify(execFile);
15
16
  const HOPPER_BACKGROUND_STARTUP_MS = 5_000;
@@ -41,14 +42,22 @@ export class HopperApplicationLauncher {
41
42
  const lease = leaseResult.value;
42
43
  let leaseTransferred = false;
43
44
  try {
45
+ let loadedPath = this.options.targetPath;
46
+ if (this.options.preparedImage !== undefined) {
47
+ const prepared = await prepareHopperMachOImage(this.options.targetPath, this.options.preparedImage.sourceSha256, this.options.preparedImage.image, join(session.directory, "image.macho"), options.signal);
48
+ if (!prepared.ok)
49
+ return prepared;
50
+ loadedPath = prepared.value;
51
+ }
44
52
  const ownsProcessLifetime = usesLinuxDemo(this.options);
45
- const bootstrap = await this.#writeBootstrap(session, ownsProcessLifetime);
53
+ const bootstrap = await this.#writeBootstrap(session, ownsProcessLifetime, loadedPath);
46
54
  if (!bootstrap.ok)
47
55
  return bootstrap;
48
56
  const launched = await this.#launchPreparedTarget({
49
57
  session,
50
58
  signal: options.signal,
51
59
  bootstrapPath: bootstrap.value,
60
+ loadedPath,
52
61
  ownsProcessLifetime,
53
62
  lease,
54
63
  });
@@ -69,7 +78,7 @@ export class HopperApplicationLauncher {
69
78
  "-Y",
70
79
  bootstrapPath,
71
80
  action,
72
- this.options.targetPath,
81
+ input.loadedPath,
73
82
  ];
74
83
  try {
75
84
  if (signal?.aborted === true)
@@ -108,15 +117,26 @@ export class HopperApplicationLauncher {
108
117
  await cleanupOwnedProcessGroup(started.ownership);
109
118
  return err(new HopperStartError({ cause }));
110
119
  }
111
- return ok({
120
+ const ownedLauncher = {
121
+ ...(this.options.preparedImage === undefined
122
+ ? {}
123
+ : { preparedImagePath: input.loadedPath }),
112
124
  process: started.process,
113
125
  ownsProcessLifetime: true,
114
126
  ownership: started.ownership,
115
- shutdownMode: ownsProcessLifetime
116
- ? "process-cleanup"
117
- : "bridge-request",
118
127
  cleanup,
119
- });
128
+ };
129
+ return ownsProcessLifetime
130
+ ? ok({
131
+ ...ownedLauncher,
132
+ providerLifetime: "launcher-process",
133
+ shutdownMode: "process-cleanup",
134
+ })
135
+ : ok({
136
+ ...ownedLauncher,
137
+ providerLifetime: "external-application",
138
+ shutdownMode: "bridge-request",
139
+ });
120
140
  }
121
141
  catch (cause) {
122
142
  return err(hopperLaunchFailure(cause, signal));
@@ -144,10 +164,10 @@ export class HopperApplicationLauncher {
144
164
  return err(new HopperStartError({ cause }));
145
165
  }
146
166
  }
147
- async #writeBootstrap(session, ownsProcessLifetime) {
167
+ async #writeBootstrap(session, ownsProcessLifetime, loadedPath) {
148
168
  const bootstrapPath = `${session.directory}/bootstrap.py`;
149
169
  try {
150
- await writeFile(bootstrapPath, bridgeBootstrapSource(session, this.options, ownsProcessLifetime), { encoding: "utf8", mode: 0o600 });
170
+ await writeFile(bootstrapPath, bridgeBootstrapSource(session, this.options, ownsProcessLifetime, loadedPath), { encoding: "utf8", mode: 0o600 });
151
171
  await chmod(bootstrapPath, 0o600);
152
172
  return ok(bootstrapPath);
153
173
  }
@@ -173,11 +193,11 @@ export class HopperApplicationLauncher {
173
193
  };
174
194
  }
175
195
  }
176
- const bridgeBootstrapSource = (session, options, ownsProcessLifetime) => [
196
+ const bridgeBootstrapSource = (session, options, ownsProcessLifetime, loadedPath) => [
177
197
  `REA_SOCKET = ${JSON.stringify(session.socketPath)}`,
178
198
  `REA_TOKEN = ${JSON.stringify(session.token)}`,
179
199
  `REA_RUN_ID = ${JSON.stringify(session.runId)}`,
180
- `REA_TARGET_PATH = ${JSON.stringify(options.targetPath)}`,
200
+ `REA_TARGET_PATH = ${JSON.stringify(loadedPath)}`,
181
201
  `REA_OWNS_PROCESS_LIFETIME = ${ownsProcessLifetime ? "True" : "False"}`,
182
202
  `exec(compile(open(${JSON.stringify(options.bridgeScriptPath)}, 'rb').read(), ${JSON.stringify(options.bridgeScriptPath)}, 'exec'))`,
183
203
  "",
@@ -189,6 +209,7 @@ const launchHopperProcess = async (input) => {
189
209
  arguments: arguments_,
190
210
  runId: input.session.runId,
191
211
  expectedCommand: ownershipCommand,
212
+ ...(input.signal === undefined ? {} : { signal: input.signal }),
192
213
  });
193
214
  if (input.linuxDemo !== undefined)
194
215
  return spawnOwnedProviderProcess({
@@ -196,6 +217,7 @@ const launchHopperProcess = async (input) => {
196
217
  arguments: input.linuxDemo.args,
197
218
  runId: input.session.runId,
198
219
  expectedCommand: ownershipCommand,
220
+ ...(input.signal === undefined ? {} : { signal: input.signal }),
199
221
  });
200
222
  return spawn(input.argumentsForTarget);
201
223
  };
@@ -1,15 +1,37 @@
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 } from "../domain/analysisErrorCore.js";
4
+ import { AnalysisCancelledError, AnalysisCapabilityUnavailableError, } from "../domain/analysisErrorCore.js";
5
+ import { BinaryTargetError } from "../domain/configurationErrors.js";
5
6
  import { ProviderAdapterError } from "../domain/providerAdapterError.js";
6
7
  import {} from "../domain/analysisErrorBase.js";
7
8
  import { err, ok } from "../domain/result.js";
9
+ import { resolveHopperMachOImage, } from "./HopperMachOImage.js";
8
10
  /** Resolve Hopper open semantics without placing its CLI flags in BinaryTarget. */
9
11
  export const resolveHopperAnalysisProfile = async (target, options) => {
10
12
  if (target.kind !== "executable" && target.kind !== "database")
11
13
  return ok({ profile: null, compatibility: {} });
12
- const derived = hopperLoaderArgsForTarget(target);
14
+ let machoContainer;
15
+ if (target.kind === "executable" && target.format === "mach-o") {
16
+ const header = await readMachoMagic(target.path, options.signal);
17
+ if (!header.ok)
18
+ return header;
19
+ machoContainer = [0xcafebabf, 0xbfbafeca].includes(header.value)
20
+ ? "fat64"
21
+ : [0xcafebabe, 0xbebafeca].includes(header.value)
22
+ ? "fat32"
23
+ : "thin";
24
+ }
25
+ let preparedImage;
26
+ if (target.kind === "executable" &&
27
+ machoContainer === "fat64" &&
28
+ options.loaderArgsOverride.length === 0) {
29
+ const resolved = await resolveHopperMachOImage(target, options.signal);
30
+ if (!resolved.ok)
31
+ return resolved;
32
+ preparedImage = resolved.value;
33
+ }
34
+ const derived = hopperLoaderArgsForTarget(target, preparedImage === undefined ? machoContainer : "thin");
13
35
  if (!derived.ok)
14
36
  return derived;
15
37
  const loaderArgs = options.loaderArgsOverride.length === 0
@@ -34,6 +56,12 @@ export const resolveHopperAnalysisProfile = async (target, options) => {
34
56
  available_architectures: [
35
57
  ...(target.availableArchitectures ?? []),
36
58
  ].sort(),
59
+ ...(machoContainer === undefined
60
+ ? {}
61
+ : { macho_container: machoContainer }),
62
+ ...(preparedImage === undefined
63
+ ? {}
64
+ : { prepared_image: { ...preparedImage } }),
37
65
  loader: {
38
66
  source: options.loaderArgsOverride.length === 0
39
67
  ? "derived"
@@ -48,7 +76,7 @@ export const resolveHopperAnalysisProfile = async (target, options) => {
48
76
  });
49
77
  };
50
78
  /** Derive Hopper's complete non-interactive CLI loader selection. */
51
- export const hopperLoaderArgsForTarget = (target) => {
79
+ export const hopperLoaderArgsForTarget = (target, machoContainer) => {
52
80
  if (target.kind === "database")
53
81
  return ok([]);
54
82
  if (target.kind !== "executable")
@@ -57,7 +85,9 @@ export const hopperLoaderArgsForTarget = (target) => {
57
85
  const flag = hopperArchitectureFlag(architecture);
58
86
  switch (target.format) {
59
87
  case "mach-o":
60
- return ok((target.availableArchitectures?.length ?? 0) > 1
88
+ if (machoContainer === undefined)
89
+ return err(new AnalysisCapabilityUnavailableError("hopper", "resolve_analysis_profile", "Mach-O container kind is unknown; resolve the Hopper analysis profile before starting its client."));
90
+ return ok(machoContainer === "fat32" || machoContainer === "fat64"
61
91
  ? ["-l", "FAT", flag, "-l", "Mach-O"]
62
92
  : ["-l", "Mach-O", flag]);
63
93
  case "elf":
@@ -81,6 +111,34 @@ const hopperArchitectureFlag = (architecture) => {
81
111
  return "--aarch64";
82
112
  }
83
113
  };
114
+ const readMachoMagic = async (path, signal) => {
115
+ if (signalIsAborted(signal))
116
+ return err(new AnalysisCancelledError("open_binary"));
117
+ const stream = createReadStream(path, { start: 0, end: 3 });
118
+ const onAbort = () => {
119
+ stream.destroy();
120
+ };
121
+ signal?.addEventListener("abort", onAbort, { once: true });
122
+ try {
123
+ const chunks = [];
124
+ for await (const chunk of stream)
125
+ chunks.push(Buffer.from(chunk));
126
+ if (signalIsAborted(signal))
127
+ return err(new AnalysisCancelledError("open_binary"));
128
+ const bytes = Buffer.concat(chunks);
129
+ return bytes.length === 4
130
+ ? ok(bytes.readUInt32BE(0))
131
+ : err(new BinaryTargetError(path, "Mach-O header became truncated before Hopper loader selection"));
132
+ }
133
+ catch (cause) {
134
+ return signalIsAborted(signal)
135
+ ? err(new AnalysisCancelledError("open_binary"))
136
+ : err(new BinaryTargetError(path, `Cannot read the Mach-O container header: ${cause instanceof Error ? cause.message : String(cause)}`, { cause }));
137
+ }
138
+ finally {
139
+ signal?.removeEventListener("abort", onAbort);
140
+ }
141
+ };
84
142
  const sha256File = async (path, signal) => {
85
143
  if (signalIsAborted(signal))
86
144
  return err(new AnalysisCancelledError("open_binary"));
@@ -11,7 +11,7 @@ export const cleanupHopperSession = async (input) => {
11
11
  cleanupResult: undefined,
12
12
  shutdownConfirmed: false,
13
13
  };
14
- await report(input.progress, 0, input.retainDocument
14
+ await report(input.progress, 0, input.retainDocument && input.launch?.preparedImagePath === undefined
15
15
  ? "detaching REA from the Hopper document"
16
16
  : "requesting Hopper document shutdown");
17
17
  await requestShutdown(input, state);
@@ -20,7 +20,18 @@ export const cleanupHopperSession = async (input) => {
20
20
  await stopProcess(input, state);
21
21
  recordUnconfirmedDocument(input, state);
22
22
  await report(input.progress, 0.75, "removing Hopper private runtime files");
23
- await closeRuntimeRoot(input.runtimeRoot, state);
23
+ if (input.launch?.preparedImagePath !== undefined &&
24
+ !state.shutdownConfirmed) {
25
+ const resource = input.runtimeRoot?.path ?? input.launch.preparedImagePath;
26
+ state.resources.add(resource);
27
+ state.issues.push({
28
+ resource,
29
+ reason: "Prepared image retained because native document closure was not confirmed",
30
+ });
31
+ }
32
+ else {
33
+ await closeRuntimeRoot(input.runtimeRoot, state);
34
+ }
24
35
  return cleanupOutcome(input, state);
25
36
  };
26
37
  const requestShutdown = async (input, state) => {
@@ -34,7 +45,8 @@ const requestShutdown = async (input, state) => {
34
45
  }, "Hopper shutdown skipped because a bridge operation remained active");
35
46
  return;
36
47
  }
37
- const method = input.retainDocument || input.launch?.shutdownMode === "process-cleanup"
48
+ const method = (input.retainDocument && input.launch?.preparedImagePath === undefined) ||
49
+ input.launch?.shutdownMode === "process-cleanup"
38
50
  ? "shutdown"
39
51
  : "shutdown_document";
40
52
  const shutdown = await input
@@ -6,12 +6,14 @@ import { AnalysisCapabilityUnavailableError } from "../domain/analysisErrorCore.
6
6
  import { HopperCancelledError, HopperProcessError, HopperProtocolError, HopperRemoteError, HopperStartError, HopperTimeoutError, } from "../domain/hopperErrors.js";
7
7
  import {} from "../domain/analysisErrorBase.js";
8
8
  import { hopperStartupFailure, } from "../domain/hopperStartupFailure.js";
9
+ import { providerRetryAction, sharedProviderFailureStage, } from "../domain/providerOperationHealth.js";
9
10
  import { err, ok } from "../domain/result.js";
10
11
  import { silentLogger } from "../logger.js";
11
12
  import { PrivateRuntimeRoot } from "../process/PrivateRuntimeRoot.js";
12
13
  import { ProviderStartupDeadline } from "../process/ProviderDeadline.js";
13
14
  import { ProviderRunLineage } from "../process/ProviderRunLineage.js";
14
15
  import { ProviderProcessSupervisor, } from "../process/ProviderProcess.js";
16
+ import { hopperOperationStage } from "./HopperOperationStage.js";
15
17
  import { cleanupHopperSession } from "./HopperCleanup.js";
16
18
  import { parseHopperServerInfo, } from "./HopperSessionValues.js";
17
19
  import { connectHopperSocketOnce } from "./HopperSocketConnection.js";
@@ -21,7 +23,6 @@ import { HopperResponseStream } from "./HopperResponseStream.js";
21
23
  import { responseResult, } from "./protocol.js";
22
24
  const SHUTDOWN_TIMEOUT_MS = 30_000;
23
25
  const SESSION_ROOT = process.platform === "darwin" ? "/tmp" : tmpdir();
24
- /** Safe launcher telemetry; stderr content is intentionally never exposed. */
25
26
  /**
26
27
  * Owns one authenticated NDJSON-over-Unix-socket bridge session.
27
28
  *
@@ -45,6 +46,7 @@ export class HopperClient {
45
46
  #closing = false;
46
47
  #launcherExitCode;
47
48
  #launcherFailureDiagnostic;
49
+ #operationFailure;
48
50
  #startupController;
49
51
  #startPromise;
50
52
  #closePromise;
@@ -52,11 +54,31 @@ export class HopperClient {
52
54
  this.#responses.push(chunk);
53
55
  };
54
56
  #onSocketError = () => {
55
- this.#failAll(new HopperProcessError(null));
57
+ const error = new HopperProcessError(null, undefined, undefined, undefined, "unreachable");
58
+ this.#failAll(error);
59
+ this.#rememberProcessFailure(error, []);
56
60
  };
57
61
  #onSocketClose = () => {
58
- if (!this.#closing)
59
- this.#failAll(new HopperProcessError(null));
62
+ if (this.#closing)
63
+ return;
64
+ const launch = this.#launch;
65
+ if (launch?.providerLifetime === "launcher-process" &&
66
+ this.#launcherExitCode !== undefined)
67
+ return;
68
+ if (launch?.providerLifetime === "launcher-process") {
69
+ setImmediate(() => {
70
+ if (this.#closing || this.#launcherExitCode !== undefined)
71
+ return;
72
+ const exitCode = launch.process.exitCode ?? null;
73
+ const error = new HopperProcessError(exitCode, this.#launcherFailureDiagnostic, undefined, undefined, exitCode !== null ? "exited" : "unreachable");
74
+ this.#failAll(error);
75
+ this.#rememberProcessFailure(error, []);
76
+ });
77
+ return;
78
+ }
79
+ const error = new HopperProcessError(null, undefined, undefined, undefined, "unreachable");
80
+ this.#failAll(error);
81
+ this.#rememberProcessFailure(error, []);
60
82
  };
61
83
  constructor(options) {
62
84
  this.#logger = options.logger ?? silentLogger;
@@ -91,6 +113,56 @@ export class HopperClient {
91
113
  requestActivity() {
92
114
  return this.#requests.activity();
93
115
  }
116
+ /**
117
+ * Latest operational health for this owned bridge.
118
+ * A recorded exit remains visible after request activity returns to idle.
119
+ */
120
+ operationHealth() {
121
+ const failure = this.#operationFailure;
122
+ if (failure !== undefined) {
123
+ const requests = failure.requests.map((request) => ({
124
+ ...request,
125
+ stage: failure.startupFailure
126
+ ? "launch"
127
+ : hopperOperationStage(request.operation),
128
+ }));
129
+ return {
130
+ state: failure.state,
131
+ stage: requests.length === 0
132
+ ? failure.startupFailure
133
+ ? "launch"
134
+ : "connection"
135
+ : sharedProviderFailureStage(requests),
136
+ retryAction: providerRetryAction(failure.state, failure.startupFailure),
137
+ exitCode: failure.exitCode,
138
+ requests,
139
+ };
140
+ }
141
+ const activity = this.requestActivity();
142
+ if (activity !== null) {
143
+ const stage = hopperOperationStage(activity.operation);
144
+ return {
145
+ state: "busy",
146
+ stage,
147
+ retryAction: "wait",
148
+ exitCode: null,
149
+ requests: [
150
+ {
151
+ requestId: activity.requestId,
152
+ operation: activity.operation,
153
+ stage,
154
+ },
155
+ ],
156
+ };
157
+ }
158
+ return {
159
+ state: "idle",
160
+ stage: null,
161
+ retryAction: null,
162
+ exitCode: null,
163
+ requests: [],
164
+ };
165
+ }
94
166
  /** Launch the bridge once and complete its authenticated health handshake. */
95
167
  start(signal) {
96
168
  if (this.#closePromise !== undefined) {
@@ -120,8 +192,22 @@ export class HopperClient {
120
192
  };
121
193
  void started.then((result) => {
122
194
  release();
123
- if (!result.ok)
195
+ if (!result.ok) {
196
+ if (result.error instanceof HopperProcessError)
197
+ this.#rememberProcessFailure(result.error, []);
198
+ else if (this.#operationFailure === undefined &&
199
+ (result.error instanceof HopperTimeoutError ||
200
+ result.error instanceof HopperStartError))
201
+ this.#operationFailure = {
202
+ state: result.error instanceof HopperTimeoutError
203
+ ? "not_started"
204
+ : "unknown",
205
+ exitCode: null,
206
+ startupFailure: true,
207
+ requests: [],
208
+ };
124
209
  reset();
210
+ }
125
211
  }, (cause) => {
126
212
  this.#logger.debug({ error: cause instanceof Error ? cause.message : String(cause) }, "Hopper startup promise rejected during bookkeeping");
127
213
  release();
@@ -132,6 +218,7 @@ export class HopperClient {
132
218
  async #start(signal) {
133
219
  if (isAborted(signal))
134
220
  return err(new HopperCancelledError());
221
+ this.#operationFailure = undefined;
135
222
  if (this.#socket !== undefined || this.#runtimeRoot !== undefined) {
136
223
  return err(new HopperProtocolError("Hopper client is already started"));
137
224
  }
@@ -283,12 +370,18 @@ export class HopperClient {
283
370
  async #connect(socketPath, deadline) {
284
371
  while (deadline.remainingMs() > 0) {
285
372
  if (deadline.signal.aborted)
286
- return err(startupInterruption(deadline));
373
+ return err(await this.#startupInterruption(deadline));
287
374
  if (this.#closing)
288
375
  return err(new HopperProcessError(null));
289
376
  if (this.#launcherExitCode !== undefined &&
290
- hopperStartupFailure(this.#launcherExitCode) !== undefined)
291
- return err(new HopperProcessError(this.#launcherExitCode, this.#launcherFailureDiagnostic));
377
+ this.#launch !== undefined &&
378
+ (this.#launch.providerLifetime === "launcher-process" ||
379
+ this.#launcherExitCode !== 0)) {
380
+ const failure = await this.#launcherStartupFailure(this.#launch.providerLifetime === "launcher-process", this.#launcherExitCode, deadline);
381
+ return deadline.interruption === "cancelled"
382
+ ? err(await this.#startupInterruption(deadline))
383
+ : err(failure);
384
+ }
292
385
  try {
293
386
  await access(socketPath);
294
387
  }
@@ -296,7 +389,7 @@ export class HopperClient {
296
389
  // best-effort cleanup: socket polling; absence means keep waiting.
297
390
  void cause;
298
391
  if ((await deadline.wait(50)) === "aborted")
299
- return err(startupInterruption(deadline));
392
+ return err(await this.#startupInterruption(deadline));
300
393
  continue;
301
394
  }
302
395
  const attempt = await connectHopperSocketOnce(socketPath, deadline.signal);
@@ -306,24 +399,63 @@ export class HopperClient {
306
399
  return ok(undefined);
307
400
  }
308
401
  if ((await deadline.wait(50)) === "aborted")
309
- return err(startupInterruption(deadline));
402
+ return err(await this.#startupInterruption(deadline));
310
403
  }
311
- return err(new HopperTimeoutError(this.#options.startupTimeoutMs));
404
+ return err(await this.#startupInterruption(deadline));
405
+ }
406
+ async #startupInterruption(deadline) {
407
+ if (deadline.interruption === "cancelled")
408
+ return new HopperCancelledError();
409
+ return new HopperTimeoutError(deadline.timeoutMs, undefined, undefined, "not_started", "launch", this.#launcherOutcome((await this.#process?.waitForOutputClose(0)) ?? false));
410
+ }
411
+ #launcherOutcome(outputClosed) {
412
+ const snapshot = this.#process?.snapshot();
413
+ const token = this.#token;
414
+ if (snapshot === undefined)
415
+ return undefined;
416
+ const redact = (text) => token === undefined
417
+ ? text
418
+ : text.replaceAll(token, "[redacted transport credential]");
419
+ return {
420
+ exit_code: snapshot.exitCode ?? null,
421
+ signal: snapshot.signal ?? null,
422
+ stdout: { ...snapshot.stdout, text: redact(snapshot.stdout.text) },
423
+ stderr: { ...snapshot.stderr, text: redact(snapshot.stderr.text) },
424
+ output_closed: outputClosed,
425
+ diagnostic_truncated: snapshot.diagnosticTruncated === true,
426
+ };
427
+ }
428
+ async #launcherStartupFailure(ownsProviderLifetime, exitCode, deadline) {
429
+ const process = this.#process;
430
+ // Descendants may inherit the helper's pipes. Bound drainage independently
431
+ // from readiness, and report whether producer output actually closed.
432
+ const outputClosed = (await process?.waitForOutputClose(Math.min(1_000, deadline.remainingMs()))) ?? false;
433
+ const launcherFailure = this.#launcherOutcome(outputClosed);
434
+ if (ownsProviderLifetime)
435
+ return new HopperProcessError(exitCode, this.#launcherFailureDiagnostic, undefined, undefined, "exited", "launch", launcherFailure);
436
+ return new HopperStartError({
437
+ userMessage: "Hopper's launcher helper failed before bridge readiness. Review details.launcher and complete Hopper setup before retrying.",
438
+ ...(launcherFailure === undefined ? {} : { launcherFailure }),
439
+ });
312
440
  }
313
441
  async #request(method, params, options) {
314
442
  const id = this.#nextId++;
315
443
  const socket = this.#socket;
316
444
  const token = this.#token;
317
445
  if (socket === undefined || socket.destroyed || token === undefined) {
318
- return err(new HopperProcessError(null, undefined, method, id));
446
+ return this.#unavailableRequest(new HopperProcessError(null, undefined, method, id, "unreachable", hopperOperationStage(method)));
319
447
  }
320
448
  if (options.signal?.aborted === true)
321
449
  return err(new HopperCancelledError());
322
450
  const startedAt = performance.now();
323
451
  const result = await this.#requests.run(id, method, params, {
324
452
  ...(options.signal === undefined ? {} : { signal: options.signal }),
453
+ ...(options.timeoutMs === undefined
454
+ ? {}
455
+ : { timeoutMs: options.timeoutMs }),
325
456
  ...(options.progress !== undefined ? { progress: options.progress } : {}),
326
457
  });
458
+ this.#retainRequestHealth(result, id, method);
327
459
  this.#logger[result.ok ? "debug" : "warn"]({
328
460
  method,
329
461
  durationMs: Math.round((performance.now() - startedAt) * 100) / 100,
@@ -394,8 +526,10 @@ export class HopperClient {
394
526
  type: "launcher-exit",
395
527
  code: event.code,
396
528
  });
397
- if (launch.ownsProcessLifetime && !this.#closing)
398
- this.#failAll(new HopperProcessError(event.code, this.#launcherFailureDiagnostic));
529
+ if (launch.providerLifetime === "launcher-process" && !this.#closing) {
530
+ this.#rememberExit(event.code);
531
+ this.#failAll(new HopperProcessError(event.code, this.#launcherFailureDiagnostic, undefined, undefined, "exited"));
532
+ }
399
533
  }
400
534
  #abortProtocol(message, cause) {
401
535
  this.#failAll(new HopperProtocolError(message, { cause }));
@@ -404,7 +538,81 @@ export class HopperClient {
404
538
  #failAll(error) {
405
539
  this.#requests.failAll(error);
406
540
  }
541
+ #unavailableRequest(error) {
542
+ this.#rememberProcessFailure(error, error.requestId === undefined || error.operation === undefined
543
+ ? []
544
+ : [{ requestId: error.requestId, operation: error.operation }]);
545
+ return err(error);
546
+ }
547
+ #retainRequestHealth(result, requestId, operation) {
548
+ if (this.#closing)
549
+ return;
550
+ if (result.ok)
551
+ return;
552
+ if (!(result.error instanceof HopperProcessError))
553
+ return;
554
+ this.#rememberProcessFailure(result.error, [
555
+ {
556
+ requestId: result.error.requestId ?? requestId,
557
+ operation: result.error.operation ?? operation,
558
+ },
559
+ ]);
560
+ }
561
+ #rememberExit(code) {
562
+ if (this.#closing)
563
+ return;
564
+ const previous = this.#operationFailure;
565
+ this.#operationFailure = {
566
+ state: "exited",
567
+ exitCode: code ?? previous?.exitCode ?? null,
568
+ startupFailure: hopperStartupFailure(code) !== undefined ||
569
+ previous?.startupFailure === true,
570
+ requests: previous?.requests ?? [],
571
+ };
572
+ }
573
+ #rememberProcessFailure(error, requests) {
574
+ if (this.#closing)
575
+ return;
576
+ const previous = this.#operationFailure;
577
+ const state = processFailureState(error);
578
+ const startupFailure = error.stage === "launch" ||
579
+ error.failureCode !== undefined ||
580
+ previous?.startupFailure === true;
581
+ const merged = mergeFailedRequests(previous?.requests ?? [], requests);
582
+ if (previous !== undefined &&
583
+ PROCESS_FAILURE_RANK[previous.state] > PROCESS_FAILURE_RANK[state]) {
584
+ this.#operationFailure = {
585
+ ...previous,
586
+ startupFailure,
587
+ requests: merged,
588
+ };
589
+ return;
590
+ }
591
+ this.#operationFailure = {
592
+ state,
593
+ exitCode: state === "exited"
594
+ ? (error.exitCode ?? previous?.exitCode ?? null)
595
+ : null,
596
+ startupFailure,
597
+ requests: merged,
598
+ };
599
+ }
407
600
  }
601
+ const PROCESS_FAILURE_RANK = {
602
+ not_started: 0,
603
+ unknown: 0,
604
+ unreachable: 1,
605
+ exited: 2,
606
+ };
607
+ const processFailureState = (error) => error.providerState === "exited" || error.exitCode !== null
608
+ ? "exited"
609
+ : error.providerState;
610
+ const mergeFailedRequests = (current, added) => {
611
+ const byId = new Map();
612
+ for (const request of [...current, ...added])
613
+ byId.set(request.requestId, request);
614
+ return [...byId.values()].sort((left, right) => left.requestId - right.requestId);
615
+ };
408
616
  const isAborted = (signal) => signal?.aborted === true;
409
617
  const startupInterruption = (deadline) => deadline.interruption === "cancelled"
410
618
  ? new HopperCancelledError()