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.
- package/README.md +168 -655
- package/bridge/android/ReaJadxBridge.java +14 -5
- package/bridge/ghidra/ReaGhidraBridge.java +173 -47
- package/bridge/hopper_bridge.py +310 -128
- package/bridge/mitmproxy/capture.py +208 -0
- package/bridge/native/rea_lldb_tracer.py +839 -0
- package/bridge/process/ProcessRunTokenReader.swift +297 -0
- package/bridge/process/ProcessRunTokenReaderMain.swift +35 -0
- package/bridge/pwndbg/core_context.py +101 -0
- package/bridge/pwndbg/launch.py +39 -0
- package/bridge/pwndbg/launch_impl.py +34 -0
- package/bridge/pwntools/decoder_runtime.py +59 -0
- package/bridge/pwntools/layout.py +39 -0
- package/bridge/pwntools/layout_impl.py +309 -0
- package/bridge/pwntools/recorded_crash.py +39 -0
- package/bridge/pwntools/recorded_crash_impl.py +147 -0
- package/dist/android/JadxConfiguration.js +196 -33
- package/dist/android/JadxMcpTransport.js +4 -0
- package/dist/android/JadxProtocol.js +6 -0
- package/dist/android/JadxProvider.js +20 -2
- package/dist/android/JadxSession.js +23 -4
- package/dist/application/AnalysisContextQueries.js +8 -35
- package/dist/application/AnalysisDocument.js +32 -0
- package/dist/application/AppBundleExecutable.js +67 -21
- package/dist/application/CallPathTracing.js +19 -3
- package/dist/application/CapabilityInventory.js +27 -3
- package/dist/application/ClientConfigurationDocument.js +871 -6
- package/dist/application/ClientRegistrationIdentity.js +26 -5
- package/dist/application/ClientRegistrationStatus.js +29 -14
- package/dist/application/DirectAnalysis.js +97 -33
- package/dist/application/Doctor.js +4 -2
- package/dist/application/DoctorScope.js +25 -13
- package/dist/application/EnhancedLiteralTracing.js +22 -25
- package/dist/application/EnhancedTools.js +13 -11
- package/dist/application/EvidenceBundleFiles.js +24 -12
- package/dist/application/FunctionAnalysisEvidence.js +2 -3
- package/dist/application/InventoryProjectionEvidence.js +4 -3
- package/dist/application/InvestigationProviders.js +3 -2
- package/dist/application/JsonFiles.js +50 -28
- package/dist/application/ProcedureAddressResolution.js +11 -0
- package/dist/application/ReconstructionCoverageService.js +7 -4
- package/dist/application/ReconstructionObligationCandidates.js +5 -1
- package/dist/application/ReconstructionObligationLedgerService.js +4 -3
- package/dist/application/Setup.js +13 -1
- package/dist/application/SetupClientConfiguration.js +10 -15
- package/dist/application/SetupHost.js +5 -2
- package/dist/application/SetupPlan.js +5 -3
- package/dist/application/SupportedClients.js +34 -1
- package/dist/application/Uninstall.js +4 -3
- package/dist/application/Update.js +18 -3
- package/dist/application/UpdateRuntime.js +46 -25
- package/dist/application/WebModuleTraceService.js +4 -2
- package/dist/application/WebNetworkCapturePort.js +1 -0
- package/dist/application/WebNetworkCaptureService.js +134 -0
- package/dist/application/WebRuntimeService.js +5 -3
- package/dist/application/WebScriptExportService.js +2 -2
- package/dist/application/WebSourceLocationService.js +4 -2
- package/dist/application/WindowsCapabilities.js +1 -1
- package/dist/application/WorkflowEvidence.js +82 -0
- package/dist/application/binary/AnalysisProviderEvaluation.js +21 -5
- package/dist/application/binary/AnalysisProviderRegistry.js +2 -0
- package/dist/application/binary/AnalysisSnapshotCache.js +52 -12
- package/dist/application/binary/BinarySession.js +131 -76
- package/dist/application/binary/BinarySessionOpen.js +19 -6
- package/dist/application/binary/BinarySessionRecords.js +45 -3
- package/dist/application/binary/BinarySessionStatus.js +17 -1
- package/dist/application/binary/CompositeProvider.js +13 -0
- package/dist/application/binary/LazyAnalysisProvider.js +3 -0
- package/dist/application/binaryDiagnostics/BinaryLayoutPort.js +1 -0
- package/dist/application/binaryDiagnostics/BinaryLayoutService.js +59 -0
- package/dist/application/binaryDiagnostics/RecordedCrashPort.js +1 -0
- package/dist/application/binaryDiagnostics/RecordedCrashService.js +62 -0
- package/dist/application/evm/EvmInterfacePort.js +1 -0
- package/dist/application/evm/EvmInterfaceService.js +64 -0
- package/dist/application/investigation/EvidenceLedger.js +21 -7
- package/dist/application/investigation/InvestigationRecords.js +8 -0
- package/dist/application/javascript/JavaScriptAnalysisControl.js +34 -0
- package/dist/application/javascript/JavaScriptApplicationEvidence.js +25 -5
- package/dist/application/javascript/JavaScriptApplicationEvidenceGraph.js +19 -2
- package/dist/application/javascript/JavaScriptApplicationService.js +34 -14
- package/dist/application/javascript/JavaScriptApplicationWorkflowService.js +5 -5
- package/dist/application/javascript/JavaScriptArtifactAnalysis.js +47 -27
- package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +39 -7
- package/dist/application/javascript/JavaScriptArtifactGraphDocuments.js +26 -2
- package/dist/application/javascript/JavaScriptArtifactPathResolution.js +80 -27
- package/dist/application/javascript/JavaScriptArtifactReconstruction.js +33 -12
- package/dist/application/javascript/JavaScriptModuleRelationships.js +37 -8
- package/dist/application/javascript/JavaScriptRecoveryService.js +4 -2
- package/dist/application/javascript/JavaScriptRuntimeObservationService.js +3 -1
- package/dist/application/javascript/JavaScriptRuntimeReconciliationService.js +3 -3
- package/dist/application/javascript/JavaScriptSemanticGraphAsyncProjection.js +7 -7
- package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +149 -72
- package/dist/application/javascript/JavaScriptSemanticGraphChildProcessProjection.js +14 -15
- package/dist/application/javascript/JavaScriptSemanticGraphConstruction.js +41 -1
- package/dist/application/javascript/JavaScriptSemanticGraphDataProjection.js +7 -7
- package/dist/application/javascript/JavaScriptSemanticGraphFlowProjection.js +5 -9
- package/dist/application/javascript/JavaScriptSemanticGraphObjectProjection.js +3 -3
- package/dist/application/javascript/JavaScriptSemanticGraphProjection.js +118 -12
- package/dist/application/javascript/JavaScriptSemanticGraphResourceProjection.js +3 -3
- package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +27 -5
- package/dist/application/managed/ManagedApplicationGraphService.js +4 -3
- package/dist/application/managed/ManagedMemberComparisonService.js +7 -4
- package/dist/application/managed/ManagedNativeVerificationService.js +4 -3
- package/dist/application/managed/ManagedReconstructionService.js +4 -3
- package/dist/application/{ProcessCli.js → process/ProcessCli.js} +23 -15
- package/dist/application/{ProcessEvidence.js → process/ProcessEvidence.js} +8 -7
- package/dist/application/workflowInputError.js +18 -0
- package/dist/artifacts/ArtifactProvider.js +42 -5
- package/dist/artifacts/ArtifactProviderMetadata.js +2 -1
- package/dist/artifacts/MachOSliceArtifactReader.js +98 -14
- package/dist/artifacts/NativeDmgArtifactReader.js +13 -6
- package/dist/artifacts/ZipArtifactReader.js +3 -0
- package/dist/artifacts/apple/AppleAssetCatalogAnalysis.js +22 -3
- package/dist/artifacts/apple/DylibResolutionReader.js +259 -0
- package/dist/artifacts/apple/InterfaceBuilderAnalysis.js +176 -56
- package/dist/artifacts/apple/InterfaceBuilderDecodeBudget.js +195 -0
- package/dist/artifacts/apple/KeyedArchiveReader.js +36 -22
- package/dist/artifacts/apple/MachoLoadCommandReader.js +355 -0
- package/dist/artifacts/apple/NibArchive.js +81 -14
- package/dist/artifacts/apple/NibViewHierarchy.js +10 -3
- package/dist/artifacts/apple/PlistNumberLiterals.js +164 -0
- package/dist/{application → artifacts/extraction}/ArtifactExtraction.js +10 -10
- package/dist/{application → artifacts/inventory}/ArtifactGraphConstruction.js +16 -11
- package/dist/{application → artifacts/inventory}/ArtifactInventory.js +4 -4
- package/dist/{application/ArtifactInventory → artifacts/inventory}/classify.js +2 -2
- package/dist/{application/ArtifactInventory → artifacts/inventory}/reader.js +5 -5
- package/dist/{application/ArtifactInventory → artifacts/inventory}/scanCanonical.js +14 -17
- package/dist/{application/ArtifactInventory → artifacts/inventory}/scanReader.js +5 -5
- package/dist/artifacts/javascript/JavaScriptArtifactFiles.js +6 -2
- package/dist/artifacts/readStableArtifact.js +20 -4
- package/dist/browser/CdpCaptureCompleteness.js +2 -0
- package/dist/browser/CdpCaptureEventHandlers.js +165 -12
- package/dist/browser/CdpCaptureEventTypes.js +5 -1
- package/dist/browser/CdpCaptureEvents.js +34 -0
- package/dist/browser/CdpConnection.js +30 -11
- package/dist/browser/CdpOptionalCommand.js +2 -3
- package/dist/browser/CdpPageCapture.js +23 -1
- package/dist/browser/PlaywrightElectronActiveActions.js +32 -23
- package/dist/browser/PlaywrightElectronActiveProjection.js +141 -0
- package/dist/browser/PlaywrightElectronActiveProvider.js +130 -122
- package/dist/browser/WebSourceMapFetcher.js +426 -72
- package/dist/browser/assets/LocalWebScriptArtifacts.js +2 -2
- package/dist/browser/history/CaptureFailures.js +137 -0
- package/dist/browser/history/CaptureFormatError.js +10 -0
- package/dist/browser/history/CaptureRedaction.js +65 -0
- package/dist/browser/history/CaptureRelease.js +17 -0
- package/dist/browser/history/HarCapture.js +165 -0
- package/dist/browser/history/HarCaptureAdapter.js +20 -0
- package/dist/browser/history/HarCaptureProcess.js +57 -0
- package/dist/browser/history/HarJson.js +92 -0
- package/dist/browser/history/HarSchema.js +72 -0
- package/dist/browser/history/HistoricalCaptureDecoder.js +188 -0
- package/dist/browser/history/HistoricalCaptureFormatAdapter.js +1 -0
- package/dist/browser/history/MitmproxyCaptureAdapter.js +42 -0
- package/dist/cli/analysisSelector.js +23 -0
- package/dist/cli/applicationCommands.js +2 -3
- package/dist/cli/artifactCommands.js +26 -1
- package/dist/cli/binaryDiagnosticsCommands.js +39 -0
- package/dist/cli/coreAnalysisCommands.js +2 -2
- package/dist/cli/coreBinaryCommands.js +78 -20
- package/dist/cli/electronCommands.js +21 -13
- package/dist/cli/evmCommands.js +24 -0
- package/dist/cli/firmwareCommands.js +6 -3
- package/dist/cli/javascriptApplicationAnalysis.js +20 -3
- package/dist/cli/jsonOutput.js +38 -0
- package/dist/cli/nativeCallCommands.js +34 -0
- package/dist/cli/processCommands.js +1 -1
- package/dist/cli/streamedJsonOutput.js +56 -0
- package/dist/cli/utilityCommands.js +2 -0
- package/dist/cli/webNetworkCaptureCommands.js +40 -0
- package/dist/cli/webRuntimeCommands.js +8 -8
- package/dist/cli.js +11 -4
- package/dist/cliBrowserScenarioCommands.js +2 -2
- package/dist/cliCommandNames.js +6 -1
- package/dist/cliJsonInput.js +35 -1
- package/dist/cliOutput.js +21 -6
- package/dist/composition/binaryDiagnostics.js +8 -0
- package/dist/composition/evm.js +4 -0
- package/dist/composition/webNetworkCaptures.js +6 -0
- package/dist/config/environment.js +4 -0
- package/dist/config/ghidraStartupTimeout.js +17 -0
- package/dist/config/mcpResponseBudget.js +22 -0
- package/dist/config/parseConfig.js +2 -1
- package/dist/contracts/artifactToolContracts.js +6 -0
- package/dist/contracts/browserCaptureToolInputSchema.js +43 -0
- package/dist/contracts/browserToolContracts.js +4 -3
- package/dist/contracts/enhancedInputs.js +5 -3
- package/dist/contracts/enhancedToolContracts.js +3 -3
- package/dist/contracts/errorSchemas.js +8 -1
- package/dist/contracts/evm/evmToolContracts.js +20 -0
- package/dist/contracts/hopperMemoryContracts.js +2 -5
- package/dist/contracts/investigationExamples.js +2 -2
- package/dist/contracts/javascript/electronToolContracts.js +1 -1
- package/dist/contracts/managed/managedToolContracts.js +8 -6
- package/dist/contracts/native/binaryDiagnosticsToolContracts.js +42 -0
- package/dist/contracts/native/nativeToolContracts.js +21 -3
- package/dist/contracts/officialToolContracts.js +26 -24
- package/dist/contracts/process/processCaptureExample.js +2 -0
- package/dist/contracts/promptContracts.js +3 -3
- package/dist/contracts/sessionLifecycleInputs.js +18 -5
- package/dist/contracts/sessionStatusContract.js +8 -2
- package/dist/contracts/sessionToolContracts.js +8 -3
- package/dist/contracts/sessionToolSchemas.js +8 -4
- package/dist/contracts/toolContractExamples.js +1 -2
- package/dist/contracts/toolContractHelpers.js +4 -1
- package/dist/contracts/toolContracts.js +6 -0
- package/dist/contracts/toolEffects.js +30 -1
- package/dist/contracts/toolOutputSchemaGroups.js +33 -28
- package/dist/contracts/toolOutputSchemaPrimitives.js +19 -1
- package/dist/contracts/toolSchemaMetadata.js +69 -10
- package/dist/contracts/webNetworkCaptureToolContracts.js +24 -0
- package/dist/domain/analysisErrorBase.js +22 -2
- package/dist/domain/analysisErrorCore.js +61 -5
- package/dist/domain/analysisErrorPresentation.js +95 -12
- package/dist/domain/analysisErrorProjection.js +148 -19
- package/dist/domain/analysisSnapshot.js +166 -2
- package/dist/domain/android/androidAnalysis.js +2 -4
- package/dist/domain/android/androidApplication.js +17 -9
- package/dist/domain/apple/appleApplication.js +41 -14
- package/dist/domain/apple/dyldEnvironment.js +73 -0
- package/dist/domain/apple/dyldPaths.js +81 -0
- package/dist/domain/apple/dylibResolution.js +478 -0
- package/dist/domain/apple/dylibResolutionFindings.js +77 -0
- package/dist/domain/apple/interfaceBuilderGraph.js +25 -13
- package/dist/domain/apple/interfaceBuilderKeyedArchive.js +13 -3
- package/dist/domain/apple/keyedArchive.js +9 -1
- package/dist/domain/apple/machoContainer.js +54 -0
- package/dist/domain/apple/plistNumbers.js +76 -0
- package/dist/domain/artifactIdentity.js +29 -0
- package/dist/domain/artifactInventoryEvidence.js +19 -24
- package/dist/domain/artifactPathSyntax.js +1 -1
- package/dist/domain/bridgeCandidateProjection.js +71 -0
- package/dist/domain/browserCompleteness.js +1 -0
- package/dist/domain/browserObservation.js +1 -1
- package/dist/domain/browserObservationError.js +24 -5
- package/dist/domain/browserObservationSchemas.js +13 -0
- package/dist/domain/browserScenarioValues.js +5 -2
- package/dist/domain/bundleComparison.js +3 -2
- package/dist/domain/callPathSchemas.js +1 -1
- package/dist/domain/canonicalDigest.js +13 -1
- package/dist/domain/canonicalJsonDigestSteps.js +133 -0
- package/dist/domain/canonicalOrdering.js +9 -5
- package/dist/domain/changedBehavior.js +9 -9
- package/dist/domain/comparisonSourceEvidence.js +40 -0
- package/dist/domain/comparisonStatus.js +2 -30
- package/dist/domain/configurationErrors.js +1 -1
- package/dist/domain/conformanceTrustGate.js +0 -16
- package/dist/domain/evidence.js +78 -11
- package/dist/domain/evidenceBundle.js +42 -1
- package/dist/domain/evidenceErrors.js +12 -1
- package/dist/domain/evm/evmInterface.js +63 -0
- package/dist/domain/explicitSensitiveFailure.js +108 -0
- package/dist/domain/explicitSensitiveValues.js +10 -0
- package/dist/domain/firmware/firmwareAnalysis.js +10 -4
- package/dist/domain/hopperErrors.js +23 -2
- package/dist/domain/hopperValues.js +51 -8
- package/dist/domain/immutableJson.js +114 -0
- package/dist/domain/inputIssueProjection.js +3 -0
- package/dist/domain/javascript/electronActiveObservation.js +37 -6
- package/dist/domain/javascript/electronStaticAnalysisValues.js +6 -12
- package/dist/domain/javascript/htmlArtifactReferences.js +40 -0
- package/dist/domain/javascript/javascriptApplicationAnalysis.js +71 -23
- package/dist/domain/javascript/javascriptApplicationGraph.js +13 -0
- package/dist/domain/javascript/javascriptAstValues.js +20 -0
- package/dist/domain/javascript/javascriptExportShapeComparison.js +21 -5
- package/dist/domain/javascript/javascriptExportShapeVariants.js +0 -10
- package/dist/domain/javascript/javascriptRecovery.js +3 -8
- package/dist/domain/javascript/javascriptSemanticAnalysis.js +97 -2
- package/dist/domain/javascript/javascriptSemanticCoverage.js +6 -5
- package/dist/domain/javascript/javascriptSemanticDataEffectHelpers.js +9 -17
- package/dist/domain/javascript/javascriptSemanticDataEffects.js +22 -5
- package/dist/domain/javascript/javascriptSemanticGraph.js +34 -5
- package/dist/domain/javascript/javascriptSemanticGraphSchemas.js +1 -0
- package/dist/domain/javascript/javascriptSemanticPrimitives.js +25 -17
- package/dist/domain/javascript/javascriptSemanticQuerySchemas.js +8 -4
- package/dist/domain/javascript/javascriptSemanticResourceLimits.js +77 -0
- package/dist/domain/javascript/javascriptSemanticValues.js +83 -11
- package/dist/domain/javascript/javascriptSourceParser.js +6 -2
- package/dist/domain/javascript/javascriptStaticAnalysis.js +22 -17
- package/dist/domain/javascript/javascriptStaticAnalysisBundler.js +5 -3
- package/dist/domain/javascript/javascriptStaticAnalysisCalls.js +14 -4
- package/dist/domain/javascript/javascriptStaticAnalysisFindings.js +66 -7
- package/dist/domain/javascript/javascriptStaticAnalysisHelpers.js +28 -16
- package/dist/domain/javascript/javascriptStaticAnalysisState.js +3 -2
- package/dist/domain/jsonSerialization.js +109 -0
- package/dist/domain/jsonValue.js +91 -3
- package/dist/domain/localPath.js +8 -0
- package/dist/domain/managed/managedApplicationGraph.js +10 -10
- package/dist/domain/managed/managedInspectionEvidence.js +16 -0
- package/dist/domain/managed/managedMemberComparisonMatch.js +5 -9
- package/dist/domain/managed/managedNativeVerification.js +3 -9
- package/dist/domain/native/binaryLayout.js +357 -0
- package/dist/domain/native/fileOffsetPartialObservation.js +1 -0
- package/dist/domain/native/nativeCallObservation.js +186 -0
- package/dist/domain/native/nativeCallPartialObservation.js +33 -0
- package/dist/domain/native/objcSwiftMetadata.js +0 -39
- package/dist/domain/native/recordedCrash.js +266 -0
- package/dist/domain/native/recordedCrashNoteCoverage.js +73 -0
- package/dist/domain/{processCapture.js → process/processCapture.js} +143 -2
- package/dist/domain/{processCaptureExample.js → process/processCaptureExample.js} +5 -0
- package/dist/domain/process/processCaptureParsing.js +54 -0
- package/dist/domain/{processCaptureValidation.js → process/processCaptureValidation.js} +18 -2
- package/dist/domain/{processComparison.js → process/processComparison.js} +39 -5
- package/dist/domain/{processObservation.js → process/processObservation.js} +1 -1
- package/dist/domain/{processScenario.js → process/processScenario.js} +11 -10
- package/dist/domain/{processTraceSpecification.js → process/processTraceSpecification.js} +1 -1
- package/dist/domain/propertyListKeys.js +1 -1
- package/dist/domain/propertyListXmlText.js +19 -0
- package/dist/domain/providerAdapterError.js +1 -1
- package/dist/domain/providerOperationHealth.js +54 -0
- package/dist/domain/providerSelectionError.js +4 -2
- package/dist/domain/reconstructionVerification.js +9 -46
- package/dist/domain/reconstructionVerificationSchemas.js +3 -3
- package/dist/domain/residualUnknown.js +3 -2
- package/dist/domain/staticRuntimeCorrelation.js +9 -46
- package/dist/domain/webBundleAnalysis.js +20 -8
- package/dist/domain/webBundleAnalyzerInspection.js +13 -8
- package/dist/domain/webBundleAnalyzerResult.js +41 -2
- package/dist/domain/webCaptureDiff.js +1 -0
- package/dist/domain/webNetworkCapture.js +118 -0
- package/dist/domain/webNetworkCaptureCoordinates.js +58 -0
- package/dist/domain/webRuntime.js +19 -5
- package/dist/domain/webSourceLocation.js +1 -0
- package/dist/dotnet/ManagedExceptionRegionValidation.js +41 -0
- package/dist/dotnet/ManagedMemberInspector.js +4 -2
- package/dist/dotnet/ManagedMemberInspectorCore.js +38 -32
- package/dist/dotnet/ManagedMemberInstructionDecoder.js +23 -7
- package/dist/dotnet/ManagedMemberRows.js +14 -3
- package/dist/dotnet/ManagedMetadataHeaps.js +20 -2
- package/dist/dotnet/ManagedMetadataInventory.js +38 -28
- package/dist/dotnet/ManagedMetadataInventoryRows.js +24 -10
- package/dist/dotnet/ManagedMethodBodyReader.js +7 -1
- package/dist/dotnet/ManagedNativeBoundaryHelpers.js +15 -3
- package/dist/dotnet/ManagedNativeBoundaryInspector.js +3 -1
- package/dist/dotnet/ManagedPeReader.js +11 -0
- package/dist/evm/EvmBytecodeCarrier.js +21 -0
- package/dist/evm/EvmWorkerLimits.js +40 -0
- package/dist/evm/EvmoleFailures.js +126 -0
- package/dist/evm/EvmoleInterfaceAdapter.js +53 -0
- package/dist/evm/EvmoleInterfaceProvider.js +273 -0
- package/dist/evm/EvmoleInterfaceWorker.js +87 -0
- package/dist/evm/EvmoleRelease.js +16 -0
- package/dist/firmware/FirmwareCommand.js +1 -0
- package/dist/firmware/FirmwareFiles.js +1 -1
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraAnalysisProfile.js +5 -0
- package/dist/ghidra/GhidraClient.js +47 -14
- package/dist/ghidra/GhidraDiagnostics.js +7 -7
- package/dist/ghidra/GhidraFunctionValues.js +10 -7
- package/dist/ghidra/GhidraInstallation.js +18 -21
- package/dist/ghidra/GhidraInventoryValues.js +14 -4
- package/dist/ghidra/GhidraJavaLaunch.js +62 -0
- package/dist/ghidra/GhidraLauncher.js +34 -16
- package/dist/ghidra/GhidraProvider.js +2 -2
- package/dist/ghidra/GhidraProviderCapabilities.js +15 -3
- package/dist/ghidra/GhidraProviderClient.js +23 -12
- package/dist/ghidra/GhidraSessionError.js +11 -7
- package/dist/ghidra/GhidraTargetSnapshot.js +47 -12
- package/dist/ghidra/GhidraTransport.js +20 -0
- package/dist/hopper/BridgeLauncher.js +33 -11
- package/dist/hopper/HopperAnalysisProfile.js +62 -4
- package/dist/hopper/HopperCleanup.js +15 -3
- package/dist/hopper/HopperClient.js +222 -14
- package/dist/hopper/HopperFileOffset.js +237 -0
- package/dist/hopper/HopperMachOImage.js +196 -0
- package/dist/hopper/HopperOperationStage.js +6 -0
- package/dist/hopper/HopperProvider.js +63 -9
- package/dist/hopper/HopperProviderCapabilities.js +19 -1
- package/dist/hopper/HopperRegexSearch.js +137 -0
- package/dist/hopper/HopperRegexWorker.js +27 -0
- package/dist/hopper/HopperRequestQueue.js +68 -19
- package/dist/hopper/HopperTargetLease.js +3 -2
- package/dist/hopper/LinuxPrivateDisplayProbe.js +4 -2
- package/dist/inspector/JavaScriptRuntimeScope.js +9 -1
- package/dist/inspector/V8InspectorCaptureProjection.js +8 -3
- package/dist/inspector/V8InspectorProvider.js +47 -11
- package/dist/javascript/recovery/WakaruCommand.js +3 -0
- package/dist/javascript/sourceMaps/DecodedSourceMap.js +47 -0
- package/dist/javascript/sourceMaps/SourceMapCommand.js +17 -0
- package/dist/javascript/sourceMaps/SourceMapFormat.js +79 -31
- package/dist/javascript/sourceMaps/TraceSourceMap.js +14 -28
- package/dist/mcpDoctor.js +62 -2
- package/dist/native/AppleDispatchCoverage.js +47 -6
- package/dist/native/AppleDispatchDecodeFacts.js +6 -0
- package/dist/native/AppleDispatchMetadata.js +6 -3
- package/dist/native/AppleMachoFixups.js +48 -24
- package/dist/native/AppleMachoSelection.js +32 -16
- package/dist/native/AppleObjcCategories.js +6 -2
- package/dist/native/AppleObjcDispatchFacets.js +5 -2
- package/dist/native/AppleObjcProperties.js +2 -1
- package/dist/native/AppleSwiftDispatchFacets.js +27 -21
- package/dist/native/AppleSwiftVtables.js +21 -15
- package/dist/native/CommandRunner.js +82 -84
- package/dist/native/LldbCallTracer.js +541 -0
- package/dist/native/LldbRetainedObservations.js +178 -0
- package/dist/native/NativeCallObservation.js +194 -0
- package/dist/native/NativeMacOSProvider.js +117 -20
- package/dist/native/NativeMacOSProviderMetadata.js +8 -3
- package/dist/native/SignatureTargetBinding.js +155 -0
- package/dist/native/parsers/lipo.js +71 -1
- package/dist/native/pwndbg/PwndbgCoreContext.js +180 -0
- package/dist/native/pwntools/PwntoolsDecoder.js +203 -0
- package/dist/native/pwntools/PwntoolsFailures.js +180 -0
- package/dist/native/pwntools/PwntoolsLayoutProvider.js +36 -0
- package/dist/native/pwntools/PwntoolsRecordedCrashProvider.js +75 -0
- package/dist/native/pwntools/PwntoolsRelease.js +19 -0
- package/dist/native/pwntools/PwntoolsResourceLimits.js +76 -0
- package/dist/native/pwntools/RecordedCrashSourceBindings.js +46 -0
- package/dist/native/pwntools/RecordedCrashStructureBindings.js +103 -0
- package/dist/process/DarwinProcessRunTokenReader.js +293 -0
- package/dist/process/ExecFileOutput.js +20 -0
- package/dist/process/OwnedCommand.js +118 -0
- package/dist/process/ProcessOwnership.js +431 -51
- package/dist/process/ProcessOwnershipObservation.js +209 -27
- package/dist/process/ProviderProcess.js +68 -10
- package/dist/{application → process/capture}/ProcessCaptureCapability.js +15 -0
- package/dist/{application → process/capture}/ProcessCaptureError.js +18 -2
- package/dist/process/capture/ProcessCaptureLifecycle.js +681 -0
- package/dist/{application → process/capture}/ProcessHarness.js +195 -29
- package/dist/{application → process/capture}/ProcessSampling.js +2 -2
- package/dist/server/EvidenceMcpServer.js +146 -0
- package/dist/server/createServer.js +37 -8
- package/dist/server/promptCompletion.js +10 -3
- package/dist/server/registerAndroidTools.js +2 -4
- package/dist/server/registerApplicationTools/helpers.js +2 -4
- package/dist/server/registerArtifactComparisonTool.js +11 -7
- package/dist/server/registerBinaryDiagnosticsTools.js +15 -0
- package/dist/server/registerBrowserScenarioTool.js +2 -4
- package/dist/server/registerBrowserTools.js +2 -4
- package/dist/server/registerBundleComparisonTool.js +2 -3
- package/dist/server/registerCloseLifecycleTool.js +8 -18
- package/dist/server/registerElectronTools.js +2 -4
- package/dist/server/registerEnhancedTools.js +18 -59
- package/dist/server/registerEvidenceTools.js +3 -5
- package/dist/server/registerEvmTools.js +15 -0
- package/dist/server/registerFirmwareTools.js +2 -4
- package/dist/server/registerFunctionComparisonTool.js +10 -6
- package/dist/server/registerInvestigationTools.js +7 -7
- package/dist/server/registerJavaScriptRecoveryTool.js +2 -4
- package/dist/server/registerJavaScriptRuntimeObservationTools.js +2 -4
- package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +2 -4
- package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +2 -4
- package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +2 -4
- package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +2 -4
- package/dist/server/registerOfficialTools.js +2 -4
- package/dist/server/registerProcessComparisonTool.js +72 -46
- package/dist/server/registerRecordedCrashTools.js +15 -0
- package/dist/server/registerSessionRecordTools.js +5 -6
- package/dist/server/registerSessionStatusTool.js +17 -3
- package/dist/server/registerSessionTools.js +13 -5
- package/dist/server/registerWebModuleTool.js +2 -4
- package/dist/server/registerWebNetworkCaptureTool.js +26 -0
- package/dist/server/registerWebRuntimeTools.js +3 -7
- package/dist/server/registerWebScriptTool.js +2 -4
- package/dist/server/registerWebSourceLocationTool.js +2 -4
- package/dist/server/runDerivedOperation.js +15 -3
- package/dist/server/sessionAvailabilityPolicy.js +3 -1
- package/dist/server/sessionToolPolicies.js +1 -1
- package/dist/server/toolRegistrationOptions.js +2 -2
- package/dist/server/toolResult.js +63 -11
- package/dist/server/toolResultEncoding.js +33 -0
- package/install.sh +1 -1
- package/native/windows/build/manifest.json +2 -2
- package/native/windows/build/rea-windows-x64.node +0 -0
- package/package.json +42 -9
- package/scripts/electron-active-hook-boundaries.cjs +18 -20
- package/scripts/electron-active-hook.cjs +241 -37
- package/scripts/rea.mjs +11 -3
- package/skills/reverse-engineer-anything/SKILL.md +32 -4
- package/skills/reverse-engineer-anything/references/javascript-applications.md +8 -1
- package/skills/reverse-engineer-anything/references/native-and-artifacts.md +29 -0
- package/third_party/README.md +60 -0
- package/third_party/evmole/LICENSE +21 -0
- package/third_party/evmole/README.md +22 -0
- package/third_party/pwndbg/LICENSE.md +21 -0
- package/third_party/pwndbg/README.md +23 -0
- package/third_party/pwntools/README.md +40 -0
- package/dist/application/AuthorizedArtifactInventory.js +0 -7
- package/dist/application/ProcessCaptureLifecycle.js +0 -299
- package/dist/application/StoreFileLock.js +0 -124
- package/dist/contracts/processCaptureExample.js +0 -2
- package/dist/domain/bytecodeProvider.js +0 -178
- package/dist/domain/customProtocolCapture.js +0 -137
- package/dist/domain/eventProcessTree.js +0 -225
- package/dist/domain/mobileApplicationInvestigation.js +0 -159
- package/dist/domain/packageAnalysis.js +0 -123
- package/dist/domain/peInspection.js +0 -197
- package/dist/domain/processCaptureParsing.js +0 -21
- package/dist/domain/protocolCapture.js +0 -217
- package/dist/domain/runtimeIdentification.js +0 -212
- package/dist/generatedMcpToolCatalog.js +0 -37
- package/dist/ghidra/GhidraDefaults.js +0 -2
- /package/dist/application/{ArtifactExtractionDestination.js → artifacts/ArtifactExtractionDestination.js} +0 -0
- /package/dist/{application/ArtifactInventory → artifacts/inventory}/policy.js +0 -0
- /package/dist/{application/ArtifactInventory → artifacts/inventory}/types.js +0 -0
- /package/dist/domain/{processEvidenceProvider.js → process/processEvidenceProvider.js} +0 -0
- /package/dist/domain/{processTraceComparison.js → process/processTraceComparison.js} +0 -0
- /package/dist/domain/{processTraceDimensionProjection.js → process/processTraceDimensionProjection.js} +0 -0
- /package/dist/domain/{processTraceEvaluation.js → process/processTraceEvaluation.js} +0 -0
- /package/dist/{application → process/capture}/FilesystemSnapshot.js +0 -0
- /package/dist/{application → process/capture}/ProcessCaptureEnvironment.js +0 -0
- /package/dist/{application → process/capture}/ProcessCaptureJournal.js +0 -0
- /package/dist/{application → process/capture}/ProcessFilesystemEffects.js +0 -0
- /package/dist/{application → process/capture}/ProcessNormalization.js +0 -0
- /package/dist/{application → process/capture}/ProcessScenarioRuntimeValidation.js +0 -0
- /package/dist/{application → process/capture}/ProcessTimer.js +0 -0
- /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
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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 (
|
|
59
|
-
|
|
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
|
-
|
|
291
|
-
|
|
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(
|
|
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
|
|
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.
|
|
398
|
-
this.#
|
|
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()
|