rea-agents 6.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 +23 -17
- 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 +0 -2
- package/bridge/native/rea_lldb_tracer.py +630 -94
- package/bridge/process/ProcessRunTokenReader.swift +39 -5
- package/bridge/pwntools/recorded_crash_impl.py +4 -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 +19 -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 +6 -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 +27 -37
- 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 +23 -11
- 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/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/WebNetworkCaptureService.js +4 -2
- package/dist/application/WebRuntimeService.js +5 -3
- package/dist/application/WebScriptExportService.js +2 -2
- package/dist/application/WebSourceLocationService.js +4 -2
- 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 +3 -6
- package/dist/application/binary/BinarySession.js +95 -68
- package/dist/application/binary/BinarySessionOpen.js +3 -3
- package/dist/application/binary/BinarySessionRecords.js +25 -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/BinaryLayoutService.js +4 -2
- package/dist/application/binaryDiagnostics/RecordedCrashService.js +4 -2
- package/dist/application/evm/EvmInterfaceService.js +4 -2
- 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 +24 -3
- package/dist/application/javascript/JavaScriptApplicationEvidenceGraph.js +19 -2
- package/dist/application/javascript/JavaScriptApplicationService.js +22 -15
- package/dist/application/javascript/JavaScriptApplicationWorkflowService.js +5 -5
- package/dist/application/javascript/JavaScriptArtifactAnalysis.js +5 -4
- package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +39 -7
- package/dist/application/javascript/JavaScriptArtifactPathResolution.js +6 -3
- package/dist/application/javascript/JavaScriptArtifactReconstruction.js +11 -3
- 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/JavaScriptSemanticGraphBuilder.js +63 -61
- package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +23 -1
- 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/process/ProcessCli.js +14 -6
- package/dist/application/process/ProcessEvidence.js +4 -3
- package/dist/application/workflowInputError.js +18 -0
- package/dist/artifacts/ArtifactProvider.js +12 -2
- package/dist/artifacts/MachOSliceArtifactReader.js +98 -14
- package/dist/artifacts/NativeDmgArtifactReader.js +13 -6
- package/dist/artifacts/apple/AppleAssetCatalogAnalysis.js +22 -3
- 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 +92 -31
- 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/artifacts/inventory/ArtifactGraphConstruction.js +13 -8
- package/dist/artifacts/inventory/scanCanonical.js +11 -14
- package/dist/artifacts/javascript/JavaScriptArtifactFiles.js +6 -2
- package/dist/browser/CdpCaptureCompleteness.js +2 -0
- package/dist/browser/CdpCaptureEventHandlers.js +76 -11
- package/dist/browser/CdpCaptureEventTypes.js +5 -1
- package/dist/browser/CdpCaptureEvents.js +25 -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 +123 -124
- package/dist/browser/WebSourceMapFetcher.js +426 -72
- package/dist/browser/assets/LocalWebScriptArtifacts.js +2 -2
- package/dist/browser/history/CaptureFailures.js +37 -1
- package/dist/browser/history/CaptureRelease.js +5 -0
- package/dist/browser/history/HarCaptureAdapter.js +3 -3
- package/dist/browser/history/HarJson.js +3 -2
- package/dist/browser/history/HistoricalCaptureDecoder.js +4 -2
- package/dist/cli/analysisSelector.js +23 -0
- package/dist/cli/applicationCommands.js +2 -3
- package/dist/cli/coreBinaryCommands.js +70 -12
- package/dist/cli/electronCommands.js +7 -6
- package/dist/cli/javascriptApplicationAnalysis.js +7 -3
- package/dist/cli/jsonOutput.js +4 -99
- package/dist/cli/nativeCallCommands.js +2 -3
- package/dist/cli/webRuntimeCommands.js +8 -8
- package/dist/cli.js +2 -1
- package/dist/cliCommandNames.js +0 -1
- package/dist/cliJsonInput.js +9 -4
- 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/enhancedInputs.js +5 -3
- package/dist/contracts/enhancedToolContracts.js +3 -3
- package/dist/contracts/hopperMemoryContracts.js +2 -5
- package/dist/contracts/javascript/electronToolContracts.js +1 -1
- package/dist/contracts/managed/managedToolContracts.js +2 -4
- package/dist/contracts/native/nativeToolContracts.js +4 -2
- package/dist/contracts/officialToolContracts.js +14 -15
- package/dist/contracts/promptContracts.js +3 -3
- package/dist/contracts/sessionLifecycleInputs.js +3 -7
- package/dist/contracts/sessionStatusContract.js +2 -4
- package/dist/contracts/sessionToolContracts.js +4 -6
- package/dist/contracts/sessionToolSchemas.js +2 -5
- package/dist/contracts/toolContractExamples.js +0 -1
- package/dist/contracts/toolContractHelpers.js +4 -1
- package/dist/contracts/toolEffects.js +0 -1
- package/dist/contracts/toolOutputSchemaGroups.js +28 -27
- package/dist/contracts/toolOutputSchemaPrimitives.js +18 -0
- package/dist/contracts/toolSchemaMetadata.js +69 -10
- package/dist/contracts/webNetworkCaptureToolContracts.js +1 -1
- package/dist/domain/analysisErrorBase.js +8 -3
- package/dist/domain/analysisErrorCore.js +3 -1
- package/dist/domain/analysisErrorPresentation.js +72 -17
- package/dist/domain/analysisErrorProjection.js +106 -27
- 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/dylibResolution.js +120 -9
- package/dist/domain/apple/dylibResolutionFindings.js +9 -7
- 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/bridgeCandidateProjection.js +71 -0
- package/dist/domain/browserCompleteness.js +1 -0
- package/dist/domain/browserObservationError.js +24 -5
- package/dist/domain/browserScenarioValues.js +2 -6
- package/dist/domain/bundleComparison.js +3 -2
- package/dist/domain/canonicalJsonDigestSteps.js +133 -0
- package/dist/domain/canonicalOrdering.js +9 -5
- package/dist/domain/changedBehavior.js +6 -6
- package/dist/domain/comparisonSourceEvidence.js +40 -0
- package/dist/domain/configurationErrors.js +1 -1
- package/dist/domain/evidence.js +64 -9
- package/dist/domain/evidenceBundle.js +42 -1
- package/dist/domain/evidenceErrors.js +12 -1
- package/dist/domain/explicitSensitiveFailure.js +17 -1
- package/dist/domain/firmware/firmwareAnalysis.js +6 -7
- 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 +30 -4
- package/dist/domain/javascript/electronStaticAnalysisValues.js +6 -12
- 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/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 +13 -0
- 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 +90 -6
- package/dist/domain/localPath.js +6 -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/fileOffsetPartialObservation.js +1 -0
- package/dist/domain/native/nativeCallObservation.js +33 -11
- package/dist/domain/native/nativeCallPartialObservation.js +33 -0
- package/dist/domain/process/processCapture.js +8 -4
- package/dist/domain/process/processComparison.js +38 -4
- package/dist/domain/process/processScenario.js +11 -10
- 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/reconstructionVerification.js +6 -43
- package/dist/domain/reconstructionVerificationSchemas.js +2 -2
- package/dist/domain/staticRuntimeCorrelation.js +6 -43
- package/dist/domain/webBundleAnalysis.js +20 -8
- package/dist/domain/webBundleAnalyzerInspection.js +13 -8
- package/dist/domain/webBundleAnalyzerResult.js +41 -2
- package/dist/domain/webRuntime.js +19 -5
- package/dist/domain/webSourceLocation.js +1 -0
- package/dist/firmware/FirmwareFiles.js +1 -1
- package/dist/generatedPackageMetadata.js +1 -1
- 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 +33 -16
- package/dist/ghidra/GhidraProviderCapabilities.js +14 -2
- 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 +31 -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/inspector/JavaScriptRuntimeScope.js +9 -1
- package/dist/inspector/V8InspectorCaptureProjection.js +8 -3
- package/dist/inspector/V8InspectorProvider.js +47 -11
- package/dist/javascript/sourceMaps/DecodedSourceMap.js +47 -0
- package/dist/javascript/sourceMaps/SourceMapCommand.js +16 -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 +81 -84
- package/dist/native/LldbCallTracer.js +365 -102
- package/dist/native/LldbRetainedObservations.js +178 -0
- package/dist/native/NativeCallObservation.js +62 -3
- package/dist/native/NativeMacOSProvider.js +98 -17
- package/dist/native/SignatureTargetBinding.js +155 -0
- package/dist/native/parsers/lipo.js +71 -1
- package/dist/native/pwndbg/PwndbgCoreContext.js +25 -5
- package/dist/native/pwntools/RecordedCrashStructureBindings.js +2 -0
- package/dist/process/DarwinProcessRunTokenReader.js +8 -9
- package/dist/process/ExecFileOutput.js +20 -0
- package/dist/process/OwnedCommand.js +7 -2
- package/dist/process/ProcessOwnership.js +203 -53
- package/dist/process/ProcessOwnershipObservation.js +49 -4
- package/dist/process/ProviderProcess.js +38 -7
- package/dist/process/capture/ProcessCaptureError.js +2 -2
- package/dist/process/capture/ProcessCaptureLifecycle.js +100 -34
- package/dist/server/EvidenceMcpServer.js +146 -0
- package/dist/server/createServer.js +15 -8
- 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 +2 -4
- 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 +2 -4
- package/dist/server/registerEvmTools.js +2 -4
- 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 +71 -45
- package/dist/server/registerRecordedCrashTools.js +2 -4
- package/dist/server/registerSessionRecordTools.js +5 -6
- package/dist/server/registerSessionStatusTool.js +17 -3
- package/dist/server/registerSessionTools.js +11 -3
- package/dist/server/registerWebModuleTool.js +2 -4
- package/dist/server/registerWebNetworkCaptureTool.js +2 -4
- 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 +0 -1
- package/dist/server/toolRegistrationOptions.js +2 -2
- package/dist/server/toolResult.js +62 -10
- package/dist/server/toolResultEncoding.js +33 -0
- package/install.sh +1 -1
- package/native/windows/build/manifest.json +1 -1
- package/package.json +8 -3
- package/scripts/electron-active-hook-boundaries.cjs +18 -20
- package/scripts/electron-active-hook.cjs +241 -37
- package/skills/reverse-engineer-anything/SKILL.md +11 -3
- package/skills/reverse-engineer-anything/references/javascript-applications.md +8 -1
- package/dist/ghidra/GhidraDefaults.js +0 -2
|
@@ -112,6 +112,31 @@ enum RunTokenReadError: Error {
|
|
|
112
112
|
case ambiguousEnvironmentBoundary
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
+
@_silgen_name("csops")
|
|
116
|
+
private func csops(
|
|
117
|
+
_ pid: Int32,
|
|
118
|
+
_ ops: UInt32,
|
|
119
|
+
_ addr: UnsafeMutableRawPointer?,
|
|
120
|
+
_ size: Int
|
|
121
|
+
) -> Int32
|
|
122
|
+
|
|
123
|
+
private let csOpsStatus: UInt32 = 0
|
|
124
|
+
private let csPlatformBinary: UInt32 = 0x0400_0000
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Whether the target image is an Apple platform binary. Current macOS omits
|
|
128
|
+
* the environment of platform binaries from KERN_PROCARGS2 for every caller,
|
|
129
|
+
* so this distinguishes a policy-withheld environment from a process whose
|
|
130
|
+
* environment is genuinely absent or transiently unreadable.
|
|
131
|
+
*/
|
|
132
|
+
func isPlatformBinary(pid: Int32) -> Bool {
|
|
133
|
+
var flags: UInt32 = 0
|
|
134
|
+
let result = withUnsafeMutablePointer(to: &flags) { pointer in
|
|
135
|
+
csops(pid, csOpsStatus, UnsafeMutableRawPointer(pointer), MemoryLayout<UInt32>.size)
|
|
136
|
+
}
|
|
137
|
+
return result == 0 && (flags & csPlatformBinary) != 0
|
|
138
|
+
}
|
|
139
|
+
|
|
115
140
|
private func readRunToken(pid: Int32, pointerSize: Int) -> RunTokenObservation {
|
|
116
141
|
var mib = [CTL_KERN, KERN_PROCARGS2, Int32(pid)]
|
|
117
142
|
var size = 0
|
|
@@ -127,13 +152,25 @@ private func readRunToken(pid: Int32, pointerSize: Int) -> RunTokenObservation {
|
|
|
127
152
|
}
|
|
128
153
|
bytes = Array(bytes.prefix(size))
|
|
129
154
|
do {
|
|
130
|
-
|
|
155
|
+
let runId = try token(in: bytes, pointerSize: pointerSize)
|
|
156
|
+
// A complete empty environment is readable for an ordinary image. Apple
|
|
157
|
+
// platform images can expose the same layout after the kernel withholds
|
|
158
|
+
// their environment, so they remain explicitly unverified without a token.
|
|
159
|
+
if runId == nil && isPlatformBinary(pid: pid) {
|
|
160
|
+
return unavailable(pid: pid, reason: "platform_binary_environment_withheld")
|
|
161
|
+
}
|
|
162
|
+
return RunTokenObservation(pid: pid, state: "readable", run_id: runId, reason: nil)
|
|
131
163
|
} catch RunTokenReadError.duplicateToken {
|
|
132
164
|
return unavailable(pid: pid, reason: "duplicate_run_token")
|
|
133
165
|
} catch RunTokenReadError.invalidTokenEncoding {
|
|
134
166
|
return unavailable(pid: pid, reason: "invalid_run_token_encoding")
|
|
135
167
|
} catch RunTokenReadError.environmentUnavailable {
|
|
136
|
-
return unavailable(
|
|
168
|
+
return unavailable(
|
|
169
|
+
pid: pid,
|
|
170
|
+
reason: isPlatformBinary(pid: pid)
|
|
171
|
+
? "platform_binary_environment_withheld"
|
|
172
|
+
: "environment_unavailable"
|
|
173
|
+
)
|
|
137
174
|
} catch RunTokenReadError.appleVectorUnavailable {
|
|
138
175
|
return unavailable(pid: pid, reason: "apple_vector_unavailable")
|
|
139
176
|
} catch RunTokenReadError.ambiguousEnvironmentBoundary {
|
|
@@ -229,9 +266,6 @@ func token(in bytes: [UInt8], pointerSize: Int = MemoryLayout<UnsafeRawPointer>.
|
|
|
229
266
|
throw RunTokenReadError.ambiguousEnvironmentBoundary
|
|
230
267
|
}
|
|
231
268
|
let environmentEntries = trailingEntries[..<appleVectorStart]
|
|
232
|
-
guard !environmentEntries.isEmpty else {
|
|
233
|
-
throw RunTokenReadError.environmentUnavailable
|
|
234
|
-
}
|
|
235
269
|
var found: String?
|
|
236
270
|
for entry in environmentEntries {
|
|
237
271
|
if entry.starts(with: Array("REA_PROCESS_RUN_ID=".utf8)) {
|
|
@@ -43,6 +43,10 @@ def inspect_core(path, cache):
|
|
|
43
43
|
raise CoreFailure("unsupported-target", "Initial recorded-core profile requires ELF64 little-endian.")
|
|
44
44
|
if len(content) < 64:
|
|
45
45
|
raise CoreFailure("format", "Selected ELF64 core header is truncated.")
|
|
46
|
+
if content[6] != 1:
|
|
47
|
+
raise CoreFailure("format", "ELF identification version is not EV_CURRENT.")
|
|
48
|
+
if int.from_bytes(content[20:24], "little") != 1:
|
|
49
|
+
raise CoreFailure("format", "ELF header version is not EV_CURRENT.")
|
|
46
50
|
# Linux commonly emits ELFOSABI_NONE (0), also accepted as GNU/Linux (3).
|
|
47
51
|
# Other declared OSABIs must never select Linux note ctypes.
|
|
48
52
|
if content[7] not in (0, 3) or content[8] != 0:
|
|
@@ -1,44 +1,130 @@
|
|
|
1
|
-
import { access, realpath, stat } from "node:fs/promises";
|
|
2
1
|
import { constants } from "node:fs";
|
|
2
|
+
import { access, realpath, stat } from "node:fs/promises";
|
|
3
3
|
import { isAbsolute, join } from "node:path";
|
|
4
4
|
import { AnalysisCapabilityUnavailableError } from "../domain/analysisErrorCore.js";
|
|
5
|
+
import { execFileOutput, execFileOutputFailure, } from "../process/ExecFileOutput.js";
|
|
5
6
|
import { JADX_JAR_CONFIGURATION_REMEDIATION } from "./JadxRelease.js";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
const JAVA_MODULE_LISTING_TIMEOUT_MS = 10_000;
|
|
8
|
+
const JAVA_MODULE_LISTING_MAX_OUTPUT_BYTES = 1024 * 1024;
|
|
9
|
+
class JadxConfigurationFailure extends Error {
|
|
10
|
+
code;
|
|
11
|
+
diagnostics;
|
|
12
|
+
constructor(code, message, diagnostics, options) {
|
|
13
|
+
super(message, options);
|
|
14
|
+
this.code = code;
|
|
15
|
+
this.diagnostics = diagnostics;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/** Inspect the same JAR and Java prerequisites that gate actual execution. */
|
|
19
|
+
export const inspectJadxAvailability = async (environment, signal) => {
|
|
20
|
+
try {
|
|
21
|
+
const configuration = await readJadxConfiguration(environment, signal);
|
|
22
|
+
return {
|
|
23
|
+
status: "available",
|
|
24
|
+
code: null,
|
|
25
|
+
reason: null,
|
|
26
|
+
diagnostics: {
|
|
27
|
+
configured: true,
|
|
28
|
+
java_executable: configuration.java,
|
|
29
|
+
jdk_compiler: true,
|
|
30
|
+
jar_path: configuration.jar,
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
catch (cause) {
|
|
35
|
+
if (signal?.aborted === true)
|
|
36
|
+
throw cause;
|
|
37
|
+
if (cause instanceof JadxConfigurationFailure)
|
|
38
|
+
return {
|
|
39
|
+
status: "unavailable",
|
|
40
|
+
code: cause.code,
|
|
41
|
+
reason: cause.message,
|
|
42
|
+
diagnostics: cause.diagnostics,
|
|
43
|
+
};
|
|
44
|
+
throw cause;
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
/** Resolve caller-selected tools and preserve the same prerequisite diagnostics. */
|
|
48
|
+
export const resolveJadxConfiguration = async (environment, operation, signal) => {
|
|
49
|
+
try {
|
|
50
|
+
return await readJadxConfiguration(environment, signal);
|
|
51
|
+
}
|
|
52
|
+
catch (cause) {
|
|
53
|
+
if (signal?.aborted === true)
|
|
54
|
+
throw cause;
|
|
55
|
+
if (!(cause instanceof JadxConfigurationFailure))
|
|
56
|
+
throw cause;
|
|
57
|
+
const output = cause.diagnostics;
|
|
58
|
+
throw new AnalysisCapabilityUnavailableError("jadx", operation, cause.message, {
|
|
59
|
+
cause,
|
|
60
|
+
userMessage: cause.message,
|
|
61
|
+
...(typeof output.stdout === "string" &&
|
|
62
|
+
typeof output.stderr === "string"
|
|
63
|
+
? {
|
|
64
|
+
capturedOutput: {
|
|
65
|
+
stdout: output.stdout,
|
|
66
|
+
stderr: output.stderr,
|
|
67
|
+
truncated: output.output_truncated === true,
|
|
68
|
+
},
|
|
69
|
+
}
|
|
70
|
+
: {}),
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
const readJadxConfiguration = async (environment, signal) => {
|
|
75
|
+
requireSupportedHost();
|
|
76
|
+
const jar = await resolveJar(environment);
|
|
77
|
+
const java = resolveJava(environment);
|
|
78
|
+
await requireJavaHomeExecutable(environment.JAVA_HOME, java);
|
|
79
|
+
const jvmArguments = resolveJvmArguments(environment);
|
|
80
|
+
await inspectJavaRuntime(java, environment, signal);
|
|
81
|
+
return { jar, java, jvmArguments };
|
|
82
|
+
};
|
|
83
|
+
const requireSupportedHost = () => {
|
|
84
|
+
if (process.platform === "linux" || process.platform === "darwin")
|
|
85
|
+
return;
|
|
86
|
+
throw configurationFailure("unsupported_host", `Android JADX subprocess ownership is unsupported on ${process.platform}; use Linux or macOS. The metadata bridge has real-provider verification on macOS arm64.`, { platform: process.platform });
|
|
87
|
+
};
|
|
88
|
+
const resolveJar = async (environment) => {
|
|
11
89
|
const jar = environment.REA_JADX_MCP_JAR;
|
|
12
|
-
if (environment.JAVA_HOME !== undefined && !isAbsolute(environment.JAVA_HOME))
|
|
13
|
-
throw unavailable("JAVA_HOME must select an existing JDK by absolute path; omit it to use java on PATH.");
|
|
14
90
|
if (jar === undefined || !isAbsolute(jar))
|
|
15
|
-
throw
|
|
16
|
-
const java = environment.JAVA_HOME === undefined
|
|
17
|
-
? "java"
|
|
18
|
-
: join(environment.JAVA_HOME, "bin", "java");
|
|
91
|
+
throw configurationFailure("not_configured", JADX_JAR_CONFIGURATION_REMEDIATION, { jar_configured: false });
|
|
19
92
|
try {
|
|
20
93
|
await access(jar, constants.R_OK);
|
|
21
94
|
if (!(await stat(jar)).isFile())
|
|
22
|
-
throw
|
|
95
|
+
throw configurationFailure("executable_missing", `REA_JADX_MCP_JAR is not a regular file: ${jar}`, { jar_path: jar });
|
|
96
|
+
return await realpath(jar);
|
|
23
97
|
}
|
|
24
98
|
catch (cause) {
|
|
25
|
-
if (cause instanceof
|
|
99
|
+
if (cause instanceof JadxConfigurationFailure)
|
|
26
100
|
throw cause;
|
|
27
|
-
throw
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
101
|
+
throw configurationFailure("executable_missing", `Cannot read REA_JADX_MCP_JAR ${jar}: ${cause instanceof Error ? cause.message : String(cause)}`, { jar_path: jar }, cause);
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
const resolveJava = (environment) => {
|
|
105
|
+
if (environment.JAVA_HOME === undefined)
|
|
106
|
+
return "java";
|
|
107
|
+
if (isAbsolute(environment.JAVA_HOME))
|
|
108
|
+
return join(environment.JAVA_HOME, "bin", "java");
|
|
109
|
+
throw configurationFailure("open_options_invalid", "JAVA_HOME must select an existing JDK by absolute path; omit it to use java on PATH.", { java_home: environment.JAVA_HOME });
|
|
110
|
+
};
|
|
111
|
+
const requireJavaHomeExecutable = async (javaHome, java) => {
|
|
112
|
+
if (javaHome === undefined)
|
|
113
|
+
return;
|
|
114
|
+
try {
|
|
115
|
+
await access(java, constants.R_OK | constants.X_OK);
|
|
116
|
+
if ((await stat(java)).isFile())
|
|
117
|
+
return;
|
|
118
|
+
throw configurationFailure("runtime_missing", `JAVA_HOME java is not a regular file: ${java}`, { java_executable: java });
|
|
119
|
+
}
|
|
120
|
+
catch (cause) {
|
|
121
|
+
if (cause instanceof JadxConfigurationFailure)
|
|
122
|
+
throw cause;
|
|
123
|
+
throw configurationFailure("runtime_missing", `Cannot execute JAVA_HOME java ${java}: ${cause instanceof Error ? cause.message : String(cause)}`, { java_executable: java }, cause);
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
const resolveJvmArguments = (environment) => {
|
|
127
|
+
const result = [];
|
|
42
128
|
for (const [name, prefix, suffix] of [
|
|
43
129
|
["REA_JADX_HEAP_MIB", "-Xmx", "m"],
|
|
44
130
|
["REA_JADX_ACTIVE_PROCESSOR_COUNT", "-XX:ActiveProcessorCount=", ""],
|
|
@@ -47,11 +133,88 @@ export const resolveJadxConfiguration = async (environment, operation) => {
|
|
|
47
133
|
if (value === undefined)
|
|
48
134
|
continue;
|
|
49
135
|
if (!/^[1-9]\d*$/u.test(value) || !Number.isSafeInteger(Number(value)))
|
|
50
|
-
throw
|
|
136
|
+
throw configurationFailure("open_options_invalid", `${name} must be a positive safe integer; received ${value}.`, { setting: name, value });
|
|
51
137
|
if (name === "REA_JADX_ACTIVE_PROCESSOR_COUNT" &&
|
|
52
138
|
Number(value) > 2_147_483_647)
|
|
53
|
-
throw
|
|
54
|
-
|
|
139
|
+
throw configurationFailure("open_options_invalid", `${name} exceeds the JVM's signed 32-bit processor-count range.`, { setting: name, value });
|
|
140
|
+
result.push(`${prefix}${value}${suffix}`);
|
|
141
|
+
}
|
|
142
|
+
return result;
|
|
143
|
+
};
|
|
144
|
+
const inspectJavaRuntime = async (java, environment, signal) => {
|
|
145
|
+
let stdout;
|
|
146
|
+
let stderr;
|
|
147
|
+
try {
|
|
148
|
+
({ stdout, stderr } = await execFileOutput(java, ["--list-modules"], {
|
|
149
|
+
env: { ...environment },
|
|
150
|
+
timeout: JAVA_MODULE_LISTING_TIMEOUT_MS,
|
|
151
|
+
maxBuffer: JAVA_MODULE_LISTING_MAX_OUTPUT_BYTES,
|
|
152
|
+
...(signal === undefined ? {} : { signal }),
|
|
153
|
+
}));
|
|
154
|
+
}
|
|
155
|
+
catch (cause) {
|
|
156
|
+
if (signal?.aborted === true)
|
|
157
|
+
throw cause;
|
|
158
|
+
const output = execFileOutputFailure(cause);
|
|
159
|
+
if (output === undefined)
|
|
160
|
+
throw cause;
|
|
161
|
+
const diagnostics = {
|
|
162
|
+
java_executable: java,
|
|
163
|
+
phase: "module-inspection",
|
|
164
|
+
exit_code: typeof output.code === "number" ? output.code : null,
|
|
165
|
+
process_error_code: typeof output.code === "string" ? output.code : null,
|
|
166
|
+
signal: output.signal,
|
|
167
|
+
killed: output.killed,
|
|
168
|
+
stdout: output.stdout,
|
|
169
|
+
stderr: output.stderr,
|
|
170
|
+
output_truncated: output.outputTruncated,
|
|
171
|
+
};
|
|
172
|
+
if (output.outputTruncated)
|
|
173
|
+
throw configurationFailure("version_unresolved", `The selected Java launcher ${java} exceeded the ${JAVA_MODULE_LISTING_MAX_OUTPUT_BYTES / (1024 * 1024)} MiB output budget while listing modules. REA retained partial output but could not establish compiler or version availability. Inspect the selected launcher for verbose or unbounded output; ` +
|
|
174
|
+
"java --list-modules should return a concise module listing.", {
|
|
175
|
+
...diagnostics,
|
|
176
|
+
failure: "output_limit",
|
|
177
|
+
output_limit_bytes: JAVA_MODULE_LISTING_MAX_OUTPUT_BYTES,
|
|
178
|
+
}, cause);
|
|
179
|
+
if (output.killed)
|
|
180
|
+
throw configurationFailure("version_unresolved", `The selected Java launcher ${java} was terminated or did not finish the module-listing probe within ${JAVA_MODULE_LISTING_TIMEOUT_MS / 1000} seconds. Inspect the launcher and its startup responsiveness, then verify it returns compiler and version modules with java --list-modules.`, {
|
|
181
|
+
...diagnostics,
|
|
182
|
+
failure: "probe_terminated",
|
|
183
|
+
deadline_ms: JAVA_MODULE_LISTING_TIMEOUT_MS,
|
|
184
|
+
}, cause);
|
|
185
|
+
throw configurationFailure("runtime_missing", `Cannot inspect selected Java runtime ${java}: ${output.stderr.trim() || errorText(cause)}. Select a full JDK including jdk.compiler via JAVA_HOME or PATH; verify it with java --list-modules.`, diagnostics, cause);
|
|
55
186
|
}
|
|
56
|
-
|
|
187
|
+
const compiler = /^jdk\.compiler(?:@|$)/mu.test(stdout);
|
|
188
|
+
if (!compiler)
|
|
189
|
+
throw configurationFailure("runtime_missing", `Selected Java runtime ${java} does not provide jdk.compiler. Select a full JDK including jdk.compiler via JAVA_HOME or PATH; verify it with java --list-modules. A JRE cannot compile REA's source bridge.`, {
|
|
190
|
+
java_executable: java,
|
|
191
|
+
phase: "module-inspection",
|
|
192
|
+
jdk_compiler: false,
|
|
193
|
+
stdout,
|
|
194
|
+
stderr,
|
|
195
|
+
output_truncated: false,
|
|
196
|
+
});
|
|
197
|
+
const major = /^java\.base@(\d+)(?:[.+_-]|$)/mu.exec(stdout)?.[1];
|
|
198
|
+
if (major === undefined)
|
|
199
|
+
throw configurationFailure("version_unresolved", `The selected Java launcher ${java} did not report a parseable java.base version in its module listing. Inspect the launcher output and verify it with java --list-modules.`, {
|
|
200
|
+
java_executable: java,
|
|
201
|
+
phase: "module-inspection",
|
|
202
|
+
jdk_compiler: true,
|
|
203
|
+
java_major: null,
|
|
204
|
+
stdout,
|
|
205
|
+
stderr,
|
|
206
|
+
output_truncated: false,
|
|
207
|
+
});
|
|
208
|
+
if (Number(major) < 17)
|
|
209
|
+
throw configurationFailure("unsupported_version", `Selected Java runtime ${java} must be JDK 17 or newer and include jdk.compiler; verify it with java --list-modules.`, {
|
|
210
|
+
java_executable: java,
|
|
211
|
+
phase: "module-inspection",
|
|
212
|
+
jdk_compiler: true,
|
|
213
|
+
java_major: major ?? null,
|
|
214
|
+
stdout,
|
|
215
|
+
stderr,
|
|
216
|
+
output_truncated: false,
|
|
217
|
+
});
|
|
57
218
|
};
|
|
219
|
+
const configurationFailure = (code, message, diagnostics, cause) => new JadxConfigurationFailure(code, message, diagnostics, cause === undefined ? undefined : { cause });
|
|
220
|
+
const errorText = (cause) => cause instanceof Error ? cause.message : String(cause);
|
|
@@ -78,6 +78,10 @@ export class JadxMcpTransport {
|
|
|
78
78
|
diagnostics() {
|
|
79
79
|
return this.#supervisor?.snapshot().stderr.text ?? "";
|
|
80
80
|
}
|
|
81
|
+
/** Whether the retained startup/operation diagnostics lost bytes. */
|
|
82
|
+
diagnosticsTruncated() {
|
|
83
|
+
return this.#supervisor?.snapshot().diagnosticTruncated ?? false;
|
|
84
|
+
}
|
|
81
85
|
/** Preserve the failed protocol/resource constraint after the SDK closes requests. */
|
|
82
86
|
failureReason() {
|
|
83
87
|
return this.#failure;
|
|
@@ -2,6 +2,12 @@ import { z } from "zod";
|
|
|
2
2
|
import { AnalysisOutputError } from "../domain/analysisErrorCore.js";
|
|
3
3
|
import { jsonValueSchema } from "../domain/jsonValue.js";
|
|
4
4
|
const count = z.number().int().nonnegative();
|
|
5
|
+
/** Selector failures authored by REA's bridge, separate from arbitrary engine errors. */
|
|
6
|
+
export const jadxInputFailureSchema = z.strictObject({
|
|
7
|
+
kind: z.literal("invalid-input"),
|
|
8
|
+
field: z.enum(["class_name", "method_name", "overload_index"]),
|
|
9
|
+
message: z.string().min(1),
|
|
10
|
+
});
|
|
5
11
|
/** Values observed inside the exact JVM producing the analysis. */
|
|
6
12
|
export const jadxRuntimeSchema = z.object({
|
|
7
13
|
engine_reported_version: z.string().min(1),
|
|
@@ -9,7 +9,7 @@ import { ProviderCleanupError } from "../domain/providerCleanupError.js";
|
|
|
9
9
|
import { err, ok } from "../domain/result.js";
|
|
10
10
|
import { PrivateRuntimeRoot } from "../process/PrivateRuntimeRoot.js";
|
|
11
11
|
import { snapshotAndroidEngine, hashAndroidFile, snapshotAndroidTarget, } from "./AndroidTargetSnapshot.js";
|
|
12
|
-
import { resolveJadxConfiguration } from "./JadxConfiguration.js";
|
|
12
|
+
import { inspectJadxAvailability, resolveJadxConfiguration, } from "./JadxConfiguration.js";
|
|
13
13
|
import { JadxSession } from "./JadxSession.js";
|
|
14
14
|
const OPERATION_TIMEOUT_MS = 120_000;
|
|
15
15
|
const BRIDGE_SOURCE = fileURLToPath(new URL("../../bridge/android/ReaJadxBridge.java", import.meta.url));
|
|
@@ -38,6 +38,19 @@ const executionError = (context) => {
|
|
|
38
38
|
});
|
|
39
39
|
if (cause instanceof z.ZodError)
|
|
40
40
|
return new AnalysisOutputError(request.operation, "JADX response violated the pinned upstream protocol", { cause });
|
|
41
|
+
if (session !== undefined && !session.initialized()) {
|
|
42
|
+
const stderr = session.transport.diagnostics();
|
|
43
|
+
const reason = `Java could not start REA's Android bridge using ${session.transport.options.command}: ${cause instanceof Error ? cause.message : String(cause)}.${stderr.length === 0 ? "" : ` Java diagnostics: ${stderr}`} Select a full JDK including jdk.compiler via JAVA_HOME, or a working java on PATH; verify it with java --list-modules. A JRE cannot compile REA's source bridge. If the JDK works, verify the REA bridge and configured JADX JAR installation.`;
|
|
44
|
+
return new AnalysisCapabilityUnavailableError("jadx", request.operation, reason, {
|
|
45
|
+
cause,
|
|
46
|
+
userMessage: reason,
|
|
47
|
+
capturedOutput: {
|
|
48
|
+
stdout: "",
|
|
49
|
+
stderr,
|
|
50
|
+
truncated: session.transport.diagnosticsTruncated(),
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
}
|
|
41
54
|
return new ProviderAdapterError("jadx", request.operation, {
|
|
42
55
|
cause,
|
|
43
56
|
diagnostics: {
|
|
@@ -93,6 +106,10 @@ export class JadxProvider {
|
|
|
93
106
|
this.environment = environment;
|
|
94
107
|
this.launcher = launcher;
|
|
95
108
|
}
|
|
109
|
+
/** Report actual local prerequisites without starting JADX or opening a target. */
|
|
110
|
+
inspectAvailability(signal) {
|
|
111
|
+
return inspectJadxAvailability(this.environment, signal);
|
|
112
|
+
}
|
|
96
113
|
/** Serialize expensive work and bind both raw and normalized results to the APK. */
|
|
97
114
|
async execute(target, request, options) {
|
|
98
115
|
if (this.#shutdown.signal.aborted)
|
|
@@ -165,7 +182,7 @@ export class JadxProvider {
|
|
|
165
182
|
try {
|
|
166
183
|
if (target.format !== "apk")
|
|
167
184
|
throw new AnalysisCapabilityUnavailableError("jadx", request.operation, `Target ${target.path} is ${target.format}; provide one standalone APK.`);
|
|
168
|
-
const configuration = await resolveJadxConfiguration(this.environment, request.operation);
|
|
185
|
+
const configuration = await resolveJadxConfiguration(this.environment, request.operation, signal);
|
|
169
186
|
signal.throwIfAborted();
|
|
170
187
|
const jarHash = await hashAndroidFile(configuration.jar);
|
|
171
188
|
const bridgeHash = await hashAndroidFile(BRIDGE_SOURCE);
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { Client } from "@modelcontextprotocol/client";
|
|
2
2
|
import { createAnalysisExecution, } from "../application/AnalysisProvider.js";
|
|
3
|
-
import { AnalysisCapabilityUnavailableError, AnalysisOutputError, } from "../domain/analysisErrorCore.js";
|
|
3
|
+
import { AnalysisCapabilityUnavailableError, AnalysisInputError, AnalysisOutputError, } from "../domain/analysisErrorCore.js";
|
|
4
4
|
import { jsonValueSchema } from "../domain/jsonValue.js";
|
|
5
5
|
import { ProviderAdapterError } from "../domain/providerAdapterError.js";
|
|
6
6
|
import { analyzeJadxRequest } from "./JadxAnalysis.js";
|
|
7
7
|
import { JadxMcpTransport } from "./JadxMcpTransport.js";
|
|
8
|
-
import { jadxLoadSchema, jadxRuntimeSchema, parseJadxEnvelope, parseJadxJson, } from "./JadxProtocol.js";
|
|
8
|
+
import { jadxLoadSchema, jadxInputFailureSchema, jadxRuntimeSchema, parseJadxEnvelope, parseJadxJson, } from "./JadxProtocol.js";
|
|
9
9
|
import { JADX_BRIDGE_IDENTITY, JADX_RELEASE, JADX_PROVIDER_IDENTITY, JADX_LIMITATIONS, } from "./JadxRelease.js";
|
|
10
10
|
/** One owned engine connection; its wire protocol stays inside the Android adapter. */
|
|
11
11
|
export class JadxSession {
|
|
12
12
|
transport;
|
|
13
13
|
#client = new Client({ name: "rea-android-adapter", version: "1" });
|
|
14
14
|
#loaded;
|
|
15
|
+
#connected = false;
|
|
15
16
|
constructor(options, launcher) {
|
|
16
17
|
this.transport = new JadxMcpTransport(options, launcher);
|
|
17
18
|
}
|
|
@@ -26,8 +27,10 @@ export class JadxSession {
|
|
|
26
27
|
signal.throwIfAborted();
|
|
27
28
|
this.transport.beginOperation();
|
|
28
29
|
const raw = [];
|
|
29
|
-
if (this.#
|
|
30
|
+
if (!this.#connected) {
|
|
30
31
|
await this.#client.connect(this.transport, { timeout: 30_000 });
|
|
32
|
+
this.#connected = true;
|
|
33
|
+
}
|
|
31
34
|
const server = this.#client.getServerVersion();
|
|
32
35
|
if (server?.name !== JADX_BRIDGE_IDENTITY.name ||
|
|
33
36
|
server.version !== JADX_BRIDGE_IDENTITY.version)
|
|
@@ -73,6 +76,10 @@ export class JadxSession {
|
|
|
73
76
|
signal.removeEventListener("abort", abort);
|
|
74
77
|
}
|
|
75
78
|
}
|
|
79
|
+
/** Whether the selected Java runtime established the REA bridge protocol. */
|
|
80
|
+
initialized() {
|
|
81
|
+
return this.#connected;
|
|
82
|
+
}
|
|
76
83
|
/** Join owned cleanup even if SDK connection teardown itself fails. */
|
|
77
84
|
async close() {
|
|
78
85
|
try {
|
|
@@ -92,7 +99,18 @@ export class JadxSession {
|
|
|
92
99
|
input,
|
|
93
100
|
response: jsonValueSchema.parse(response),
|
|
94
101
|
});
|
|
95
|
-
if (envelope.failed)
|
|
102
|
+
if (envelope.failed) {
|
|
103
|
+
if (envelope.text.startsWith("{")) {
|
|
104
|
+
const failure = jadxInputFailureSchema.safeParse(parseJadxJson(envelope.text, request.operation));
|
|
105
|
+
if (failure.success)
|
|
106
|
+
throw new AnalysisInputError(request.operation, undefined, [
|
|
107
|
+
{
|
|
108
|
+
path: [failure.data.field],
|
|
109
|
+
reason: "invalid_value",
|
|
110
|
+
message: failure.data.message,
|
|
111
|
+
},
|
|
112
|
+
]);
|
|
113
|
+
}
|
|
96
114
|
throw new ProviderAdapterError("jadx", request.operation, {
|
|
97
115
|
diagnostics: {
|
|
98
116
|
upstream_operation: name,
|
|
@@ -101,6 +119,7 @@ export class JadxSession {
|
|
|
101
119
|
target_sha256: target.sha256,
|
|
102
120
|
},
|
|
103
121
|
});
|
|
122
|
+
}
|
|
104
123
|
return envelope.text;
|
|
105
124
|
};
|
|
106
125
|
return {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AnalysisOutputError } from "../domain/analysisErrorCore.js";
|
|
2
2
|
import {} from "../domain/analysisErrorBase.js";
|
|
3
|
-
import {
|
|
3
|
+
import { analysisBookmarkSchema } from "../domain/hopperValues.js";
|
|
4
|
+
import { resolveAnalysisDocument } from "./AnalysisDocument.js";
|
|
4
5
|
import { err, ok } from "../domain/result.js";
|
|
5
6
|
const parameters = (document, address) => ({
|
|
6
7
|
...(document === undefined ? {} : { document }),
|
|
@@ -42,7 +43,7 @@ export const getNavigationContext = async (analysis, input, signal) => {
|
|
|
42
43
|
};
|
|
43
44
|
/** Inspect bounded provider-neutral facets at one explicit reproducible address. */
|
|
44
45
|
export const inspectAddressContext = async (analysis, input, signal) => {
|
|
45
|
-
const document = await
|
|
46
|
+
const document = await resolveAnalysisDocument(analysis, input.document, signal);
|
|
46
47
|
if (!document.ok)
|
|
47
48
|
return document;
|
|
48
49
|
const args = parameters(document.value, input.address);
|
|
@@ -75,30 +76,6 @@ export const inspectAddressContext = async (analysis, input, signal) => {
|
|
|
75
76
|
: bookmarks,
|
|
76
77
|
});
|
|
77
78
|
};
|
|
78
|
-
const resolveDocument = async (analysis, document, signal) => {
|
|
79
|
-
if (document !== undefined)
|
|
80
|
-
return ok(document);
|
|
81
|
-
const current = await analysis.execute("current_document", {}, executionOptions(signal));
|
|
82
|
-
if (!current.ok) {
|
|
83
|
-
if (!(current.error instanceof AnalysisCapabilityUnavailableError))
|
|
84
|
-
return current;
|
|
85
|
-
const listed = await analysis.execute("list_documents", {}, executionOptions(signal));
|
|
86
|
-
if (!listed.ok)
|
|
87
|
-
return listed;
|
|
88
|
-
const parsed = parseDocuments(listed.value.result);
|
|
89
|
-
if (!parsed.ok)
|
|
90
|
-
return err(new AnalysisOutputError("list_documents", "expected one document identity when resolving a headless provider", { cause: parsed.error }));
|
|
91
|
-
if (parsed.value.length !== 1)
|
|
92
|
-
return err(new AnalysisOutputError("list_documents", `expected exactly one document identity for a provider without current-document selection, received ${parsed.value.length}`));
|
|
93
|
-
const [documentName] = parsed.value;
|
|
94
|
-
if (documentName === undefined)
|
|
95
|
-
return err(new AnalysisOutputError("list_documents", "provider returned no document identity"));
|
|
96
|
-
return ok(documentName);
|
|
97
|
-
}
|
|
98
|
-
return typeof current.value.result === "string"
|
|
99
|
-
? ok(current.value.result)
|
|
100
|
-
: err(new AnalysisOutputError("current_document", "expected a document identity string"));
|
|
101
|
-
};
|
|
102
79
|
const facet = (result, operation) => result?.ok === true
|
|
103
80
|
? { state: "available", value: result.value.result }
|
|
104
81
|
: {
|
|
@@ -139,19 +116,15 @@ const matchingBookmarks = (value, address) => {
|
|
|
139
116
|
reason: "list_bookmarks returned malformed output; expected an array.",
|
|
140
117
|
remediation: "Retry list_bookmarks directly and report the provider output shape if it remains malformed.",
|
|
141
118
|
};
|
|
142
|
-
|
|
119
|
+
const parsed = analysisBookmarkSchema.array().safeParse(value);
|
|
120
|
+
if (!parsed.success)
|
|
143
121
|
return {
|
|
144
122
|
state: "unavailable",
|
|
145
|
-
reason: "list_bookmarks returned malformed entries; expected address and name
|
|
123
|
+
reason: "list_bookmarks returned malformed entries; expected an address string and a string or null name.",
|
|
146
124
|
remediation: "Retry list_bookmarks directly and report the provider output shape if it remains malformed.",
|
|
147
125
|
};
|
|
148
126
|
return {
|
|
149
127
|
state: "available",
|
|
150
|
-
value:
|
|
128
|
+
value: parsed.data.filter((bookmark) => bookmark.address === address),
|
|
151
129
|
};
|
|
152
130
|
};
|
|
153
|
-
const isBookmark = (value) => typeof value === "object" &&
|
|
154
|
-
value !== null &&
|
|
155
|
-
!Array.isArray(value) &&
|
|
156
|
-
typeof value.address === "string" &&
|
|
157
|
-
typeof value.name === "string";
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { AnalysisCancelledError, AnalysisCapabilityUnavailableError, AnalysisOutputError, } from "../domain/analysisErrorCore.js";
|
|
2
|
+
import { parseDocuments } from "../domain/hopperValues.js";
|
|
3
|
+
import { err, ok } from "../domain/result.js";
|
|
4
|
+
const executionOptions = (signal) => signal === undefined ? undefined : { signal };
|
|
5
|
+
/** Resolve an explicit or provider-selected document without guessing among candidates. */
|
|
6
|
+
export const resolveAnalysisDocument = async (analysis, document, signal) => {
|
|
7
|
+
if (document !== undefined)
|
|
8
|
+
return ok(document);
|
|
9
|
+
if (signal?.aborted === true)
|
|
10
|
+
return err(new AnalysisCancelledError("current_document"));
|
|
11
|
+
const current = await analysis.execute("current_document", {}, executionOptions(signal));
|
|
12
|
+
if (!current.ok) {
|
|
13
|
+
if (!(current.error instanceof AnalysisCapabilityUnavailableError))
|
|
14
|
+
return current;
|
|
15
|
+
const listed = await analysis.execute("list_documents", {}, executionOptions(signal));
|
|
16
|
+
if (!listed.ok)
|
|
17
|
+
return listed;
|
|
18
|
+
const parsed = parseDocuments(listed.value.result);
|
|
19
|
+
if (!parsed.ok)
|
|
20
|
+
return err(new AnalysisOutputError("list_documents", "expected one document identity when resolving a headless provider", { cause: parsed.error }));
|
|
21
|
+
if (parsed.value.length !== 1)
|
|
22
|
+
return err(new AnalysisOutputError("list_documents", `expected exactly one document identity for a provider without current-document selection, received ${parsed.value.length}`));
|
|
23
|
+
const [documentName] = parsed.value;
|
|
24
|
+
if (documentName === undefined || documentName.length === 0)
|
|
25
|
+
return err(new AnalysisOutputError("list_documents", "provider returned no document identity"));
|
|
26
|
+
return ok(documentName);
|
|
27
|
+
}
|
|
28
|
+
return typeof current.value.result === "string" &&
|
|
29
|
+
current.value.result.length > 0
|
|
30
|
+
? ok(current.value.result)
|
|
31
|
+
: err(new AnalysisOutputError("current_document", "expected a nonempty document identity string"));
|
|
32
|
+
};
|