rea-agents 6.0.0 → 6.2.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 +26 -18
- package/bridge/android/ReaJadxBridge.java +14 -5
- package/bridge/ghidra/ReaGhidraBridge.java +205 -51
- package/bridge/hopper_bridge.py +314 -127
- 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 +274 -31
- package/dist/android/JadxMcpTransport.js +18 -2
- package/dist/android/JadxProtocol.js +6 -0
- package/dist/android/JadxProvider.js +76 -37
- 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/BinaryTargetResolver.js +5 -3
- package/dist/application/BrowserEvidence.js +3 -8
- package/dist/application/BrowserScenarioEvidence.js +2 -18
- package/dist/application/CallPathTracing.js +19 -3
- package/dist/application/CapabilityInventory.js +48 -11
- package/dist/application/ClientConfigurationDocument.js +917 -8
- package/dist/application/ClientRegistrationIdentity.js +26 -5
- package/dist/application/ClientRegistrationStatus.js +29 -14
- package/dist/application/DirectAnalysis.js +56 -51
- package/dist/application/DirectAnalysisCleanup.js +72 -0
- package/dist/application/DirectAnalysisStatus.js +4 -5
- package/dist/application/Doctor.js +19 -21
- package/dist/application/DoctorDiagnostics.js +1 -2
- package/dist/application/DoctorScope.js +25 -13
- package/dist/application/EnhancedLiteralTracing.js +22 -25
- package/dist/application/EnhancedTools.js +64 -17
- package/dist/application/EvidenceBundleFiles.js +30 -13
- package/dist/application/FunctionAnalysisEvidence.js +2 -3
- package/dist/application/InventoryProjectionEvidence.js +4 -3
- package/dist/application/InvestigationProviders.js +11 -2
- package/dist/application/JsonFiles.js +83 -28
- package/dist/application/LinuxHopper.js +9 -6
- package/dist/application/MacHopper.js +15 -18
- package/dist/application/ProcedureAddressResolution.js +11 -0
- package/dist/application/RealHopperAssertions.js +0 -11
- package/dist/application/ReconstructionCoverageService.js +7 -4
- package/dist/application/ReconstructionObligationCandidates.js +1 -1
- package/dist/application/ReconstructionObligationLedgerService.js +4 -3
- package/dist/application/ReferenceSourceImportEntries.js +1 -1
- package/dist/application/Setup.js +21 -17
- package/dist/application/SetupClientConfiguration.js +10 -15
- package/dist/application/SetupHost.js +21 -29
- package/dist/application/SetupPlan.js +11 -9
- package/dist/application/SupportedClients.js +34 -1
- package/dist/application/Uninstall.js +82 -29
- package/dist/application/Update.js +18 -3
- package/dist/application/UpdateMaintenance.js +7 -5
- package/dist/application/UpdateRuntime.js +57 -36
- 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 +32 -6
- package/dist/application/WebSourceLocationService.js +4 -2
- package/dist/application/WorkflowEvidence.js +105 -0
- package/dist/application/XrefsAddressResolution.js +45 -0
- package/dist/application/analysisView/AnalysisViewService.js +76 -0
- package/dist/application/binary/AnalysisClientCleanup.js +30 -5
- package/dist/application/binary/AnalysisProviderEvaluation.js +22 -7
- package/dist/application/binary/AnalysisProviderRegistry.js +4 -6
- package/dist/application/binary/AnalysisSnapshotCache.js +13 -14
- package/dist/application/binary/BinarySession.js +161 -93
- package/dist/application/binary/BinarySessionComposition.js +1 -3
- package/dist/application/binary/BinarySessionExecution.js +3 -5
- package/dist/application/binary/BinarySessionOpen.js +4 -4
- package/dist/application/binary/BinarySessionRecords.js +26 -4
- package/dist/application/binary/BinarySessionStatus.js +18 -7
- package/dist/application/binary/CompositeProvider.js +16 -17
- package/dist/application/binary/LazyAnalysisProvider.js +8 -5
- package/dist/application/binary/SessionProviderRouter.js +27 -135
- 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/homebrew.js +48 -0
- package/dist/application/investigation/EvidenceLedger.js +21 -7
- package/dist/application/investigation/InvestigationRecords.js +8 -0
- package/dist/application/javascript/ElectronActiveEvidence.js +9 -13
- package/dist/application/javascript/JavaScriptAnalysisControl.js +34 -0
- package/dist/application/javascript/JavaScriptApplicationEvidence.js +21 -4
- package/dist/application/javascript/JavaScriptApplicationEvidenceGraph.js +19 -2
- package/dist/application/javascript/JavaScriptApplicationService.js +27 -15
- package/dist/application/javascript/JavaScriptApplicationWorkflowService.js +5 -5
- package/dist/application/javascript/JavaScriptArtifactAnalysis.js +10 -7
- package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +44 -10
- package/dist/application/javascript/JavaScriptArtifactGraphBundlers.js +11 -3
- package/dist/application/javascript/JavaScriptArtifactGraphContext.js +9 -0
- package/dist/application/javascript/JavaScriptArtifactGraphDocuments.js +8 -5
- package/dist/application/javascript/JavaScriptArtifactGraphFindings.js +12 -3
- package/dist/application/javascript/JavaScriptArtifactGraphStructure.js +0 -1
- package/dist/application/javascript/JavaScriptArtifactPathResolution.js +49 -19
- package/dist/application/javascript/JavaScriptArtifactReconstruction.js +56 -8
- package/dist/application/javascript/JavaScriptModuleRelationships.js +38 -9
- package/dist/application/javascript/JavaScriptRecoveryService.js +4 -2
- package/dist/application/javascript/JavaScriptRuntimeObservationService.js +6 -4
- package/dist/application/javascript/JavaScriptRuntimeReconciliationService.js +3 -3
- package/dist/application/javascript/JavaScriptSemanticGraphAsyncProjection.js +2 -3
- package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +63 -61
- package/dist/application/javascript/JavaScriptSemanticGraphChildProcessProjection.js +1 -2
- package/dist/application/javascript/JavaScriptSemanticGraphDataProjection.js +2 -3
- package/dist/application/javascript/JavaScriptSemanticGraphFlowProjection.js +1 -5
- package/dist/application/javascript/JavaScriptSemanticGraphObjectProjection.js +75 -46
- package/dist/application/javascript/JavaScriptSemanticGraphResourceProjection.js +2 -3
- package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +64 -19
- package/dist/application/managed/ManagedApplicationGraphService.js +4 -3
- package/dist/application/managed/ManagedMemberComparisonService.js +9 -5
- package/dist/application/managed/ManagedNativeVerificationService.js +6 -4
- package/dist/application/managed/ManagedReconstructionService.js +4 -3
- package/dist/application/process/ProcessCli.js +25 -17
- package/dist/application/process/ProcessEvidence.js +4 -4
- package/dist/application/workflowInputError.js +18 -0
- package/dist/artifacts/ArtifactProvider.js +48 -13
- package/dist/artifacts/ArtifactReader.js +31 -0
- package/dist/artifacts/DirectoryArtifactReader.js +2 -1
- package/dist/artifacts/MachOSliceArtifactReader.js +106 -15
- package/dist/artifacts/NativeDmgArtifactReader.js +73 -21
- package/dist/artifacts/SafeOutputTree.js +16 -2
- package/dist/artifacts/ZipArtifactReader.js +11 -4
- package/dist/artifacts/apple/AppleAssetCatalogAnalysis.js +26 -5
- package/dist/artifacts/apple/DylibResolutionReader.js +17 -7
- package/dist/artifacts/apple/InterfaceBuilderAnalysis.js +176 -56
- package/dist/artifacts/apple/InterfaceBuilderDecodeBudget.js +195 -0
- package/dist/artifacts/apple/KeyedArchiveReader.js +55 -23
- 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/extraction/ArtifactExtraction.js +78 -21
- package/dist/artifacts/inventory/ArtifactGraphConstruction.js +79 -68
- package/dist/artifacts/inventory/ArtifactInventory.js +0 -1
- package/dist/artifacts/inventory/reader.js +3 -3
- package/dist/artifacts/inventory/scanCanonical.js +59 -38
- package/dist/artifacts/inventory/scanReader.js +5 -9
- package/dist/artifacts/javascript/JavaScriptArtifactFiles.js +6 -2
- package/dist/browser/BrowserScenarioPartialObservation.js +106 -0
- package/dist/browser/CdpBrowserProvider.js +2 -3
- package/dist/browser/CdpCaptureCompleteness.js +2 -0
- package/dist/browser/CdpCaptureEventHandlers.js +78 -15
- package/dist/browser/CdpCaptureEventTypes.js +5 -1
- package/dist/browser/CdpCaptureEvents.js +25 -1
- package/dist/browser/CdpCaptureValues.js +20 -0
- package/dist/browser/CdpConnection.js +30 -11
- package/dist/browser/CdpElectronProvider.js +0 -2
- package/dist/browser/CdpElectronScriptEvents.js +2 -8
- package/dist/browser/CdpElectronScripts.js +2 -3
- package/dist/browser/CdpOptionalCommand.js +2 -3
- package/dist/browser/CdpPageCapture.js +23 -1
- package/dist/browser/CdpPageCaptureScripts.js +2 -3
- package/dist/browser/CdpSafeMetadata.js +10 -10
- package/dist/browser/PlaywrightBrowserScenarioProvider.js +59 -44
- package/dist/browser/PlaywrightElectronActiveActions.js +34 -79
- package/dist/browser/PlaywrightElectronActiveProjection.js +141 -0
- package/dist/browser/PlaywrightElectronActiveProvider.js +133 -130
- package/dist/browser/PlaywrightScenarioArtifacts.js +1 -1
- package/dist/browser/PlaywrightScenarioBrowser.js +139 -39
- package/dist/browser/PlaywrightScenarioEvents.js +1 -1
- package/dist/browser/PlaywrightScenarioSession.js +39 -22
- package/dist/browser/WebSourceMapFetcher.js +426 -72
- package/dist/browser/assets/LocalWebScriptArtifacts.js +2 -2
- package/dist/browser/assets/ScriptCaptureAdapters.js +1 -1
- package/dist/browser/history/CaptureFailures.js +41 -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/browser/history/MitmproxyCaptureAdapter.js +4 -2
- package/dist/catalogIdentity.js +0 -1
- package/dist/cli/analysisSelector.js +23 -0
- package/dist/cli/analysisViewCommands.js +36 -0
- package/dist/cli/applicationCommands.js +2 -3
- package/dist/cli/artifactCommands.js +11 -12
- package/dist/cli/coreAnalysisCommands.js +3 -3
- package/dist/cli/coreBinaryCommands.js +100 -37
- package/dist/cli/coreNativeCommands.js +9 -10
- package/dist/cli/electronCommands.js +10 -9
- package/dist/cli/interactiveSetup.js +6 -6
- package/dist/cli/javascriptApplicationAnalysis.js +7 -3
- package/dist/cli/jsonOutput.js +4 -99
- package/dist/cli/managedCommands.js +7 -8
- package/dist/cli/nativeCallCommands.js +3 -5
- package/dist/cli/omittableDefaults.js +50 -0
- package/dist/cli/processCommands.js +3 -2
- package/dist/cli/setupCommands.js +16 -15
- package/dist/cli/utilityCommands.js +9 -9
- package/dist/cli/webRuntimeCommands.js +8 -8
- package/dist/cli.js +18 -9
- package/dist/cliBrowserScenarioCommands.js +2 -2
- package/dist/cliCommandNames.js +1 -1
- package/dist/cliJsonInput.js +24 -5
- package/dist/cliOutput.js +0 -38
- package/dist/composition/auxiliaryAnalysisProviders.js +27 -23
- package/dist/composition/binary.js +9 -9
- package/dist/composition/browserScenario.js +2 -1
- package/dist/composition/directAnalysis.js +20 -13
- package/dist/composition/electronScenario.js +1 -1
- package/dist/composition/optionalObservationProviders.js +12 -7
- package/dist/config/environment.js +10 -0
- package/dist/config/ghidraStartupTimeout.js +12 -0
- package/dist/config/homeDirectory.js +12 -0
- package/dist/config/mcpResponseBudget.js +30 -0
- package/dist/config/parseConfig.js +8 -3
- package/dist/config/parsers.js +19 -22
- package/dist/contracts/analysisViewToolContracts.js +56 -0
- package/dist/contracts/applicationToolContracts.js +5 -4
- package/dist/contracts/artifactComparisonExample.js +2 -2
- package/dist/contracts/artifactToolContracts.js +1 -1
- package/dist/contracts/browserScenarioToolContracts.js +1 -1
- package/dist/contracts/browserToolContracts.js +19 -15
- package/dist/contracts/enhancedInputs.js +7 -5
- package/dist/contracts/enhancedToolContracts.js +7 -6
- package/dist/contracts/evm/evmToolContracts.js +1 -1
- package/dist/contracts/functionWorkflowToolContracts.js +1 -1
- package/dist/contracts/hopperMemoryContracts.js +2 -5
- package/dist/contracts/inputSchemaPresentation.js +90 -0
- package/dist/contracts/investigationExamples.js +4 -3
- package/dist/contracts/javascript/electronToolContracts.js +2 -2
- package/dist/contracts/javascript/javascriptApplicationWorkflowExamples.js +0 -20
- package/dist/contracts/javascript/javascriptExportShapeComparisonExample.js +245 -0
- package/dist/contracts/javascript/javascriptRuntimeObservationToolContracts.js +1 -1
- package/dist/contracts/managed/managedToolContracts.js +7 -14
- package/dist/contracts/managed/managedWorkflowToolContracts.js +1 -1
- package/dist/contracts/mobileApplicationGraphExamples.js +3 -3
- package/dist/contracts/native/binaryDiagnosticsToolContracts.js +1 -1
- package/dist/contracts/native/nativeToolContracts.js +5 -3
- package/dist/contracts/officialToolContracts.js +16 -16
- package/dist/contracts/promptContracts.js +5 -5
- package/dist/contracts/providerSelection.js +1 -1
- package/dist/contracts/sessionLifecycleInputs.js +3 -7
- package/dist/contracts/sessionStatusContract.js +2 -4
- package/dist/contracts/sessionToolContracts.js +18 -8
- package/dist/contracts/sessionToolSchemas.js +3 -19
- package/dist/contracts/toolContractExamples.js +0 -1
- package/dist/contracts/toolContractHelpers.js +4 -1
- package/dist/contracts/toolContracts.js +2 -0
- package/dist/contracts/toolEffects.js +1 -1
- package/dist/contracts/toolOutputSchemaGroups.js +160 -115
- package/dist/contracts/toolOutputSchemaPrimitives.js +28 -20
- package/dist/contracts/toolSchemaMetadata.js +41 -33
- package/dist/contracts/webNetworkCaptureToolContracts.js +2 -2
- package/dist/contracts/webRuntimeToolContracts.js +1 -1
- package/dist/contracts/webScriptToolContracts.js +1 -1
- package/dist/doctorRuntime.js +7 -5
- package/dist/domain/analysisErrorBase.js +8 -3
- package/dist/domain/analysisErrorCore.js +6 -1
- package/dist/domain/analysisErrorPresentation.js +90 -20
- package/dist/domain/analysisErrorProjection.js +130 -32
- package/dist/domain/analysisSnapshot.js +29 -31
- package/dist/domain/analysisView/analysisView.js +243 -0
- package/dist/domain/analysisView/analysisViewCoverage.js +19 -0
- package/dist/domain/analysisView/binaryLayoutView.js +159 -0
- package/dist/domain/analysisView/javascriptApplicationView.js +238 -0
- package/dist/domain/android/androidAnalysis.js +2 -4
- package/dist/domain/android/androidApplication.js +18 -10
- package/dist/domain/apple/appleApplication.js +42 -15
- package/dist/domain/apple/dyldEnvironment.js +73 -0
- package/dist/domain/apple/dylibResolution.js +130 -12
- package/dist/domain/apple/dylibResolutionFindings.js +9 -7
- package/dist/domain/apple/interfaceBuilderGraph.js +25 -14
- package/dist/domain/apple/interfaceBuilderKeyedArchive.js +13 -3
- package/dist/domain/apple/keyedArchive.js +35 -3
- package/dist/domain/apple/machoContainer.js +54 -0
- package/dist/domain/apple/plistNumbers.js +76 -0
- package/dist/domain/artifactComparison.js +15 -6
- package/dist/domain/artifactGraph.js +16 -3
- package/dist/domain/artifactIdentity.js +29 -0
- package/dist/domain/artifactInventoryEvidence.js +28 -40
- package/dist/domain/artifactOperationError.js +3 -3
- package/dist/domain/artifactPartialObservation.js +1 -0
- package/dist/domain/artifactPathSyntax.js +49 -0
- package/dist/domain/binaryTarget.js +39 -13
- package/dist/domain/bridgeCandidateProjection.js +71 -0
- package/dist/domain/browserCaptureComparison.js +13 -49
- package/dist/domain/browserCompleteness.js +1 -0
- package/dist/domain/browserNetworkEvidence.js +10 -4
- package/dist/domain/browserObservation.js +0 -1
- package/dist/domain/browserObservationError.js +24 -5
- package/dist/domain/browserObservationSchemas.js +14 -3
- package/dist/domain/browserScenario.js +0 -1
- package/dist/domain/browserScenarioCapture.js +1 -2
- package/dist/domain/browserScenarioDiff.js +0 -2
- package/dist/domain/browserScenarioDiffEvidence.js +0 -12
- package/dist/domain/browserScenarioDiffValues.js +2 -2
- package/dist/domain/browserScenarioValues.js +5 -10
- package/dist/domain/bundleComparison.js +3 -2
- package/dist/domain/callPath.js +8 -9
- package/dist/domain/callPathSchemas.js +2 -2
- 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/completionLedgerGeneration.js +2 -1
- package/dist/domain/configurationErrors.js +13 -1
- package/dist/domain/conformancePackage.js +4 -3
- package/dist/domain/evidence.js +65 -36
- package/dist/domain/evidenceBundle.js +47 -8
- package/dist/domain/evidenceCompletionLedger.js +2 -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/functionComparison.js +4 -5
- package/dist/domain/functionComparisonDimensions.js +120 -87
- package/dist/domain/functionComparisonNormalization.js +23 -34
- package/dist/domain/functionComparisonResults.js +1 -4
- package/dist/domain/functionComparisonSchemas.js +2 -8
- package/dist/domain/functionDossierEvidence.js +2 -37
- 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 +47 -64
- package/dist/domain/javascript/electronObservation.js +14 -3
- package/dist/domain/javascript/electronStaticAnalysisBrowser.js +10 -9
- package/dist/domain/javascript/electronStaticAnalysisIpc.js +2 -1
- package/dist/domain/javascript/electronStaticAnalysisNative.js +2 -1
- package/dist/domain/javascript/electronStaticAnalysisValues.js +6 -12
- package/dist/domain/javascript/javascriptApplicationAnalysis.js +71 -23
- package/dist/domain/javascript/javascriptApplicationEvidenceSchemas.js +2 -0
- package/dist/domain/javascript/javascriptApplicationGraph.js +39 -3
- package/dist/domain/javascript/javascriptApplicationGraphSchemas.js +9 -2
- package/dist/domain/javascript/javascriptApplicationVersionItems.js +5 -2
- package/dist/domain/javascript/javascriptApplicationVersionKeys.js +2 -1
- package/dist/domain/javascript/javascriptAstValues.js +20 -0
- package/dist/{application/javascript/JavaScriptReturnShapeProjection.js → domain/javascript/javascriptExportReturnShapeProjection.js} +4 -4
- package/dist/domain/javascript/javascriptExportShapeComparison.js +7 -1
- package/dist/domain/javascript/javascriptExportShapeComparisonIdentity.js +6 -1
- package/dist/domain/javascript/javascriptExportShapeComparisonSchemas.js +29 -1
- package/dist/domain/javascript/javascriptExportShapeSelection.js +5 -5
- package/dist/domain/javascript/javascriptExportShapeVariants.js +67 -14
- package/dist/domain/javascript/javascriptFeatureSeed.js +20 -0
- package/dist/domain/javascript/javascriptFeatureTraversal.js +0 -1
- package/dist/domain/javascript/javascriptNativeHandoff.js +1 -1
- package/dist/domain/javascript/javascriptRecovery.js +3 -8
- package/dist/domain/javascript/javascriptRuntimeLoadState.js +0 -1
- package/dist/domain/javascript/javascriptRuntimeObservation.js +10 -2
- package/dist/domain/javascript/javascriptRuntimeReconciliationMatching.js +1 -1
- package/dist/domain/javascript/javascriptRuntimeReconciliationParsing.js +3 -2
- package/dist/domain/javascript/javascriptRuntimeStaticCandidates.js +0 -1
- package/dist/domain/javascript/javascriptSemanticAnalysis.js +106 -5
- package/dist/domain/javascript/javascriptSemanticAsyncEffects.js +2 -1
- package/dist/domain/javascript/javascriptSemanticCalls.js +2 -1
- package/dist/domain/javascript/javascriptSemanticChildProcesses.js +2 -1
- package/dist/domain/javascript/javascriptSemanticCoverage.js +6 -5
- package/dist/domain/javascript/javascriptSemanticDataEffectHelpers.js +9 -17
- package/dist/domain/javascript/javascriptSemanticDataEffects.js +23 -6
- package/dist/domain/javascript/javascriptSemanticGraph.js +98 -43
- package/dist/domain/javascript/javascriptSemanticGraphSchemas.js +1 -0
- package/dist/domain/javascript/javascriptSemanticMemberMutations.js +77 -20
- package/dist/domain/javascript/javascriptSemanticMutationValues.js +21 -27
- package/dist/domain/javascript/javascriptSemanticObjects.js +83 -42
- package/dist/domain/javascript/javascriptSemanticPrimitives.js +18 -21
- package/dist/domain/javascript/javascriptSemanticProjection.js +2 -3
- package/dist/domain/javascript/javascriptSemanticPromises.js +2 -1
- package/dist/domain/javascript/javascriptSemanticQuerySchemas.js +8 -4
- package/dist/domain/javascript/javascriptSemanticResourceLimits.js +77 -0
- package/dist/domain/javascript/javascriptSemanticResources.js +1 -1
- package/dist/domain/javascript/javascriptSemanticReturns.js +32 -17
- package/dist/domain/javascript/javascriptSemanticSlots.js +72 -0
- package/dist/domain/javascript/javascriptSemanticValues.js +126 -61
- package/dist/domain/javascript/javascriptSourceMapPaths.js +104 -0
- 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 +16 -5
- package/dist/domain/javascript/javascriptStaticAnalysisFindings.js +66 -7
- package/dist/domain/javascript/javascriptStaticAnalysisHelpers.js +28 -17
- package/dist/domain/javascript/javascriptStaticAnalysisState.js +3 -2
- package/dist/domain/javascript/sourceToBundleComparison.js +12 -3
- package/dist/domain/javascript/sourceToBundleSignals.js +47 -19
- 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/managedArtifact.js +6 -4
- package/dist/domain/managed/managedInspectionEvidence.js +16 -0
- package/dist/domain/managed/managedMemberComparison.js +2 -9
- package/dist/domain/managed/managedMemberComparisonMatch.js +5 -9
- package/dist/domain/managed/managedNativeVerification.js +3 -11
- package/dist/domain/managed/managedNativeVerificationMatch.js +9 -3
- package/dist/domain/native/binaryLayout.js +2 -3
- package/dist/domain/native/fileOffsetPartialObservation.js +1 -0
- package/dist/domain/native/nativeApiBoundary.js +1 -1
- package/dist/domain/native/nativeCallObservation.js +37 -13
- package/dist/domain/native/nativeCallPartialObservation.js +33 -0
- package/dist/domain/native/nativeInstruction.js +7 -0
- package/dist/domain/native/recordedCrash.js +2 -3
- package/dist/domain/offsetDateTime.js +17 -0
- package/dist/domain/process/processCapture.js +21 -16
- package/dist/domain/process/processCaptureCoverage.js +67 -0
- package/dist/domain/process/processCaptureExample.js +2 -1
- package/dist/domain/process/processCaptureParsing.js +1 -34
- package/dist/domain/process/processCaptureValidation.js +81 -13
- package/dist/domain/process/processComparison.js +79 -26
- package/dist/domain/process/processObservation.js +10 -2
- package/dist/domain/process/processScenario.js +35 -12
- package/dist/domain/process/processTraceComparison.js +0 -2
- package/dist/domain/process/processTraceDimensionProjection.js +1 -1
- package/dist/domain/process/processTraceEvaluation.js +15 -11
- package/dist/domain/process/processTraceSpecification.js +3 -4
- package/dist/domain/propertyListKeys.js +1 -1
- package/dist/domain/propertyListXmlText.js +19 -0
- package/dist/domain/providerAdapterError.js +3 -1
- package/dist/domain/providerOperationHealth.js +54 -0
- package/dist/domain/reconstructionCoverage.js +5 -2
- package/dist/domain/reconstructionObligationLedgerSchemas.js +2 -1
- package/dist/domain/reconstructionReadinessSchemas.js +2 -1
- package/dist/domain/reconstructionVerification.js +9 -46
- package/dist/domain/reconstructionVerificationSchemas.js +4 -3
- package/dist/domain/referenceSourceGraph.js +20 -21
- package/dist/domain/staticRuntimeCorrelation.js +8 -45
- package/dist/domain/stringPatterns.js +6 -0
- package/dist/domain/swiftSymbolClassification.js +61 -0
- package/dist/domain/symbolAnalysis.js +66 -18
- 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 +0 -1
- package/dist/domain/webCaptureDiffSchemas.js +6 -3
- package/dist/domain/webEventListeners.js +3 -2
- package/dist/domain/webExecution.js +3 -2
- package/dist/domain/webRuntime.js +19 -7
- package/dist/domain/webScriptExport.js +1 -1
- package/dist/domain/webSourceLocation.js +1 -0
- package/dist/dotnet/ManagedArtifactInspector.js +2 -19
- package/dist/dotnet/ManagedMemberInspector.js +12 -18
- package/dist/dotnet/ManagedMemberInspectorCore.js +47 -44
- package/dist/dotnet/ManagedMemberRows.js +75 -62
- package/dist/dotnet/ManagedMetadataInventory.js +16 -22
- package/dist/dotnet/ManagedMethodBodyReader.js +4 -0
- package/dist/dotnet/ManagedNativeBoundaryHelpers.js +109 -94
- package/dist/dotnet/ManagedNativeBoundaryInspector.js +12 -21
- package/dist/dotnet/ManagedReaderFailure.js +16 -0
- package/dist/dotnet/ManagedStaticProvider.js +3 -5
- package/dist/evaluation/AgentEvaluationFixtures.js +250 -0
- package/dist/evaluation/AgentEvaluationReport.js +28 -0
- package/dist/evaluation/CodexAgentEval.js +12 -8
- package/dist/evaluation/KnownAnswerEvaluation.js +281 -0
- package/dist/evm/EvmoleInterfaceProvider.js +2 -1
- package/dist/firmware/FirmwareCommand.js +9 -5
- package/dist/firmware/FirmwareFiles.js +1 -1
- package/dist/firmware/FirmwareProvider.js +4 -4
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraAnalysisProfile.js +7 -5
- package/dist/ghidra/GhidraClient.js +126 -34
- package/dist/ghidra/GhidraClientStartup.js +0 -2
- package/dist/ghidra/GhidraDiagnostics.js +7 -7
- package/dist/ghidra/GhidraDoctor.js +6 -5
- package/dist/ghidra/GhidraFunctionValues.js +13 -12
- package/dist/ghidra/GhidraInstallation.js +58 -33
- package/dist/ghidra/GhidraInventoryValues.js +14 -4
- package/dist/ghidra/GhidraJavaLaunch.js +66 -0
- package/dist/ghidra/GhidraLauncher.js +47 -22
- package/dist/ghidra/GhidraProvider.js +6 -2
- package/dist/ghidra/GhidraProviderCapabilities.js +20 -2
- package/dist/ghidra/GhidraProviderClient.js +36 -15
- package/dist/ghidra/GhidraSessionError.js +13 -7
- package/dist/ghidra/GhidraSessionRoot.js +39 -0
- package/dist/ghidra/GhidraTargetSnapshot.js +47 -12
- package/dist/ghidra/GhidraTransport.js +20 -0
- package/dist/ghidra/extensions/GhidraExtensions.js +17 -10
- package/dist/ghidra/extensions/nativeaot/NativeAotAdapter.js +8 -2
- package/dist/hopper/BridgeLauncher.js +65 -56
- package/dist/hopper/HopperAnalysisProfile.js +65 -12
- package/dist/hopper/HopperCleanup.js +63 -22
- package/dist/hopper/HopperClient.js +288 -59
- package/dist/hopper/HopperFileOffset.js +237 -0
- package/dist/hopper/HopperMachOImage.js +197 -0
- package/dist/hopper/HopperOperationStage.js +6 -0
- package/dist/hopper/HopperProvider.js +71 -19
- package/dist/hopper/HopperProviderCapabilities.js +19 -1
- package/dist/hopper/HopperRegexSearch.js +134 -0
- package/dist/hopper/HopperRegexWorker.js +27 -0
- package/dist/hopper/HopperRequestQueue.js +68 -19
- package/dist/hopper/HopperTargetLease.js +133 -49
- package/dist/hopper/LinuxPrivateDisplayProbe.js +6 -0
- package/dist/ida/IdaConfiguration.js +8 -3
- package/dist/ida/IdaInput.js +1 -7
- package/dist/ida/IdaMcpConnection.js +8 -4
- package/dist/ida/IdaOperationRunner.js +3 -3
- package/dist/ida/IdaProvider.js +8 -12
- package/dist/ida/IdaSessionClient.js +20 -18
- package/dist/ida/IdaWorkspace.js +12 -13
- package/dist/inspector/JavaScriptRuntimeScope.js +9 -1
- package/dist/inspector/V8InspectorCaptureProjection.js +9 -4
- package/dist/inspector/V8InspectorProvider.js +82 -36
- package/dist/javascript/recovery/WakaruCommand.js +7 -2
- package/dist/javascript/recovery/WakaruExecution.js +5 -2
- 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/main/shutdown.js +11 -3
- package/dist/main/startup.js +9 -2
- package/dist/main/transport.js +22 -2
- package/dist/main.js +11 -18
- 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 +48 -22
- 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 +87 -88
- package/dist/native/LldbCallTracer.js +372 -103
- package/dist/native/LldbRetainedObservations.js +178 -0
- package/dist/native/NativeCallObservation.js +62 -3
- package/dist/native/NativeMacOSProvider.js +122 -31
- package/dist/native/NativeUiHelperRuntime.js +11 -2
- package/dist/native/NativeUiObservation.js +2 -2
- 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/PwntoolsDecoder.js +2 -1
- package/dist/native/pwntools/RecordedCrashStructureBindings.js +2 -0
- package/dist/process/DarwinProcessRunTokenReader.js +23 -10
- package/dist/process/ExecFileOutput.js +108 -6
- package/dist/process/OwnedCommand.js +7 -2
- package/dist/process/PrivateRuntimeRoot.js +10 -5
- package/dist/process/ProcessOwnership.js +204 -57
- package/dist/process/ProcessOwnershipObservation.js +60 -9
- package/dist/process/ProviderProcess.js +39 -10
- package/dist/process/capture/FilesystemSnapshot.js +50 -13
- package/dist/process/capture/ProcessCaptureError.js +15 -2
- package/dist/process/capture/ProcessCaptureLifecycle.js +235 -81
- package/dist/process/capture/ProcessFilesystemEffects.js +33 -3
- package/dist/process/capture/ProcessHarness.js +21 -25
- package/dist/process/capture/ProcessNormalization.js +20 -2
- package/dist/process/capture/ProcessSampling.js +25 -2
- package/dist/process/capture/TerminalRenderer.js +14 -0
- package/dist/process/snapshotEnvironment.js +14 -0
- package/dist/server/EvidenceMcpServer.js +157 -0
- package/dist/server/createServer.js +61 -41
- package/dist/server/mcpClientMetadata.js +12 -5
- package/dist/server/promptCompletion.js +3 -8
- package/dist/server/registerAnalysisViewTool.js +15 -0
- package/dist/server/registerAndroidTools.js +2 -5
- package/dist/server/registerApplicationTools/compareExportShapes.js +4 -5
- package/dist/server/registerApplicationTools/compareSourceToBundle.js +4 -5
- package/dist/server/registerApplicationTools/compareVersions.js +4 -5
- package/dist/server/registerApplicationTools/coverage.js +1 -2
- package/dist/server/registerApplicationTools/helpers.js +1 -4
- package/dist/server/registerApplicationTools/obligationLedger.js +4 -5
- package/dist/server/registerApplicationTools/projectMobileApplicationGraph.js +3 -4
- package/dist/server/registerApplicationTools/traceFeature.js +4 -5
- package/dist/server/registerApplicationTools/traceSemantics.js +4 -5
- package/dist/server/registerArtifactComparisonTool.js +13 -10
- package/dist/server/registerBinaryDiagnosticsTools.js +2 -5
- package/dist/server/registerBrowserScenarioTool.js +3 -6
- package/dist/server/registerBrowserTools.js +13 -18
- package/dist/server/registerBundleComparisonTool.js +5 -7
- package/dist/server/registerCloseLifecycleTool.js +9 -20
- package/dist/server/registerElectronTools.js +10 -15
- package/dist/server/registerEnhancedTools.js +36 -77
- package/dist/server/registerEvidenceTools.js +3 -6
- package/dist/server/registerEvmTools.js +2 -5
- package/dist/server/registerFirmwareTools.js +2 -5
- package/dist/server/registerFunctionComparisonTool.js +15 -12
- package/dist/server/registerInvestigationTools.js +16 -17
- package/dist/server/registerJavaScriptRecoveryTool.js +2 -5
- package/dist/server/registerJavaScriptRuntimeObservationTools.js +6 -8
- package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +5 -8
- package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +4 -7
- package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +6 -9
- package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +6 -9
- package/dist/server/registerOfficialTools.js +4 -21
- package/dist/server/registerProcessComparisonTool.js +74 -48
- package/dist/server/registerRecordedCrashTools.js +2 -5
- package/dist/server/registerSessionRecordTools.js +19 -24
- package/dist/server/registerSessionStatusTool.js +19 -6
- package/dist/server/registerSessionTools.js +20 -18
- package/dist/server/registerWebModuleTool.js +2 -5
- package/dist/server/registerWebNetworkCaptureTool.js +2 -5
- package/dist/server/registerWebRuntimeTools.js +4 -9
- package/dist/server/registerWebScriptTool.js +2 -5
- package/dist/server/registerWebSourceLocationTool.js +2 -5
- 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 +75 -51
- package/dist/server/toolResultEncoding.js +34 -0
- package/dist/windows/WindowsNativeLoader.js +1 -0
- package/dist/windows/WindowsOwnedProcess.js +60 -15
- package/dist/windows/WindowsPrivateRuntime.js +7 -8
- package/install.sh +1 -1
- package/native/windows/README.md +3 -1
- package/native/windows/build/manifest.json +2 -2
- package/native/windows/build/rea-windows-x64.node +0 -0
- package/package.json +44 -30
- package/scripts/electron-active-hook-boundaries.cjs +18 -20
- package/scripts/electron-active-hook.cjs +241 -37
- package/scripts/rea.mjs +3 -6
- package/skills/reverse-engineer-anything/SKILL.md +12 -3
- package/skills/reverse-engineer-anything/references/android-applications.md +6 -3
- package/skills/reverse-engineer-anything/references/evidence-workflows.md +8 -4
- package/skills/reverse-engineer-anything/references/javascript-applications.md +20 -3
- package/skills/reverse-engineer-anything/references/native-and-artifacts.md +9 -0
- package/dist/config.js +0 -1
- package/dist/contracts/browserCaptureToolInputSchema.js +0 -43
- package/dist/contracts/process/processCaptureExample.js +0 -2
- package/dist/contracts/toolOutputSchemas.js +0 -2
- package/dist/ghidra/GhidraDefaults.js +0 -2
- package/dist/main/reload.js +0 -12
- package/dist/main/state.js +0 -3
- package/dist/server/sessionToolPolicies.js +0 -2
|
@@ -19,12 +19,9 @@ export const cleanupWindowsProcessTree = async (rootPid, host = systemWindowsPro
|
|
|
19
19
|
return { cleaned: true, signaled: result === "terminated" };
|
|
20
20
|
}
|
|
21
21
|
catch (cause) {
|
|
22
|
-
// The reason string is a pinned validation contract; keep it stable and
|
|
23
|
-
// do not interpolate the cause into caller-visible diagnostics here.
|
|
24
|
-
void cause;
|
|
25
22
|
return {
|
|
26
23
|
cleaned: false,
|
|
27
|
-
reason:
|
|
24
|
+
reason: `Windows process-tree termination failed for PID ${String(rootPid)}: ${errorMessage(cause)}`,
|
|
28
25
|
};
|
|
29
26
|
}
|
|
30
27
|
};
|
|
@@ -77,23 +74,35 @@ export const cleanupOwnedProcessGroup = async (ownership, host = systemHost) =>
|
|
|
77
74
|
}
|
|
78
75
|
}
|
|
79
76
|
if (plan.unresolved.length > 0)
|
|
80
|
-
return cleanupValidationFailure(plan.unresolved);
|
|
81
|
-
return {
|
|
77
|
+
return cleanupValidationFailure(plan.unresolved, plan.unverified);
|
|
78
|
+
return {
|
|
79
|
+
cleaned: true,
|
|
80
|
+
signaled,
|
|
81
|
+
...(plan.unverified.length === 0 ? {} : { unverified: plan.unverified }),
|
|
82
|
+
};
|
|
82
83
|
};
|
|
83
84
|
/** Verify that no live process still carries an owned capture run token. */
|
|
84
|
-
export const verifyNoTokenOwnedProcesses = async (runId, host = systemHost, captureBaseline) => {
|
|
85
|
+
export const verifyNoTokenOwnedProcesses = async (runId, host = systemHost, captureBaseline, relation) => {
|
|
85
86
|
const processTable = await readLiveProcessTable(host);
|
|
86
87
|
if (!processTable.available)
|
|
87
88
|
return {
|
|
88
89
|
cleaned: false,
|
|
89
90
|
reason: `process table could not be inspected: ${processTable.reason}`,
|
|
90
91
|
};
|
|
91
|
-
const scan = await scanTokenOwnedProcesses(processTable.processes, runId, host, captureBaseline);
|
|
92
|
+
const scan = await scanTokenOwnedProcesses(processTable.processes, runId, host, captureBaseline, relation);
|
|
92
93
|
if (scan.failures.length > 0)
|
|
93
|
-
return cleanupValidationFailure(scan.failures);
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
94
|
+
return cleanupValidationFailure(scan.failures, scan.unverified);
|
|
95
|
+
if (scan.owned.length > 0)
|
|
96
|
+
return {
|
|
97
|
+
cleaned: false,
|
|
98
|
+
reason: "token-owned process remained after cleanup",
|
|
99
|
+
...(scan.unverified.length === 0 ? {} : { unverified: scan.unverified }),
|
|
100
|
+
};
|
|
101
|
+
return {
|
|
102
|
+
cleaned: true,
|
|
103
|
+
signaled: false,
|
|
104
|
+
...(scan.unverified.length === 0 ? {} : { unverified: scan.unverified }),
|
|
105
|
+
};
|
|
97
106
|
};
|
|
98
107
|
const readLiveProcessTable = async (host) => {
|
|
99
108
|
try {
|
|
@@ -109,8 +118,14 @@ const readLiveProcessTable = async (host) => {
|
|
|
109
118
|
const createOwnedCleanupPlan = async (ownership, processes, host) => {
|
|
110
119
|
const sampledProcessGroupIds = new Set((ownership.sampledProcessGroupIds ?? []).filter((processGroupId) => Number.isSafeInteger(processGroupId) && processGroupId > 0));
|
|
111
120
|
const tokenOwned = ownership.sweepTokenOwnedProcesses === true
|
|
112
|
-
? await scanTokenOwnedProcesses(processes, ownership.runId, host, ownership.captureBaseline
|
|
113
|
-
|
|
121
|
+
? await scanTokenOwnedProcesses(processes, ownership.runId, host, ownership.captureBaseline, {
|
|
122
|
+
leaderPid: ownership.leaderPid,
|
|
123
|
+
processGroupId: ownership.processGroupId,
|
|
124
|
+
...(sampledProcessGroupIds.size === 0
|
|
125
|
+
? {}
|
|
126
|
+
: { sampledProcessGroupIds: [...sampledProcessGroupIds] }),
|
|
127
|
+
})
|
|
128
|
+
: { owned: [], failures: [], unverified: [], identities: new Map() };
|
|
114
129
|
const tokenOwnedGroupIds = new Set(tokenOwned.owned.map(({ processGroupId }) => processGroupId));
|
|
115
130
|
const launcher = processes.find(({ pid }) => pid === ownership.leaderPid);
|
|
116
131
|
const rootMembers = processes.filter(({ processGroupId }) => processGroupId === ownership.processGroupId);
|
|
@@ -123,8 +138,15 @@ const createOwnedCleanupPlan = async (ownership, processes, host) => {
|
|
|
123
138
|
signalOrder: [],
|
|
124
139
|
tokenOwnedIdentities: tokenOwned.identities,
|
|
125
140
|
unresolved: tokenOwned.failures,
|
|
141
|
+
unverified: tokenOwned.unverified,
|
|
126
142
|
}
|
|
127
|
-
: {
|
|
143
|
+
: {
|
|
144
|
+
cleaned: true,
|
|
145
|
+
signaled: false,
|
|
146
|
+
...(tokenOwned.unverified.length === 0
|
|
147
|
+
? {}
|
|
148
|
+
: { unverified: tokenOwned.unverified }),
|
|
149
|
+
};
|
|
128
150
|
let descendants = [];
|
|
129
151
|
if (launcher !== undefined) {
|
|
130
152
|
const identityFailure = launcherIdentityFailure(launcher, ownership);
|
|
@@ -179,7 +201,7 @@ const createOwnedCleanupPlan = async (ownership, processes, host) => {
|
|
|
179
201
|
signalableGroups.add(processGroupId);
|
|
180
202
|
}
|
|
181
203
|
if (ownership.sweepTokenOwnedProcesses !== true && unresolved.length > 0)
|
|
182
|
-
return cleanupValidationFailure(unresolved);
|
|
204
|
+
return cleanupValidationFailure(unresolved, tokenOwned.unverified);
|
|
183
205
|
return {
|
|
184
206
|
signalOrder: [...signalableGroups]
|
|
185
207
|
.filter((groupId) => processGroupIds.has(groupId))
|
|
@@ -190,6 +212,7 @@ const createOwnedCleanupPlan = async (ownership, processes, host) => {
|
|
|
190
212
|
: left - right),
|
|
191
213
|
tokenOwnedIdentities: tokenOwned.identities,
|
|
192
214
|
unresolved,
|
|
215
|
+
unverified: tokenOwned.unverified,
|
|
193
216
|
};
|
|
194
217
|
};
|
|
195
218
|
const revalidateOwnedProcessGroup = async (processGroupId, ownership, host, expectedIdentities) => {
|
|
@@ -224,19 +247,22 @@ const revalidateOwnedProcessGroup = async (processGroupId, ownership, host, expe
|
|
|
224
247
|
};
|
|
225
248
|
return { empty: members.length === 0 };
|
|
226
249
|
};
|
|
227
|
-
const cleanupValidationFailure = (failures) => {
|
|
250
|
+
const cleanupValidationFailure = (failures, unverified = []) => {
|
|
251
|
+
const unverifiedEntry = unverified.length === 0 ? {} : { unverified };
|
|
228
252
|
const unreadable = failures.filter(({ reason }) => reason === "environment-unreadable");
|
|
229
253
|
if (failures.some(({ reason }) => reason === "run-token-mismatch"))
|
|
230
254
|
return {
|
|
231
255
|
cleaned: false,
|
|
232
256
|
reason: "process tree contains an unowned or PID-reused process",
|
|
233
257
|
failures,
|
|
258
|
+
...unverifiedEntry,
|
|
234
259
|
};
|
|
235
260
|
if (failures.some(({ reason }) => reason === "process-identity-unavailable"))
|
|
236
261
|
return {
|
|
237
262
|
cleaned: false,
|
|
238
263
|
reason: "process identity could not be revalidated",
|
|
239
264
|
failures,
|
|
265
|
+
...unverifiedEntry,
|
|
240
266
|
};
|
|
241
267
|
if (unreadable.length > 0) {
|
|
242
268
|
const counts = new Map();
|
|
@@ -248,21 +274,28 @@ const cleanupValidationFailure = (failures) => {
|
|
|
248
274
|
.sort(([left], [right]) => left.localeCompare(right))
|
|
249
275
|
.map(([category, count]) => `${category}=${String(count)}`)
|
|
250
276
|
.join(", ");
|
|
277
|
+
const candidates = unreadable
|
|
278
|
+
.map(({ pid, diagnostic }) => `${String(pid)}=${sanitizedTokenReadFailure(diagnostic)}`)
|
|
279
|
+
.sort((left, right) => left.localeCompare(right));
|
|
251
280
|
return {
|
|
252
281
|
cleaned: false,
|
|
253
|
-
reason: `process ownership token could not be read for ${String(unreadable.length)} live process(es): ${breakdown}`,
|
|
282
|
+
reason: `process ownership token could not be read for ${String(unreadable.length)} live process(es): ${breakdown}; live candidates ${candidates.join(", ")}`,
|
|
254
283
|
failures,
|
|
284
|
+
...unverifiedEntry,
|
|
255
285
|
};
|
|
256
286
|
}
|
|
257
287
|
return {
|
|
258
288
|
cleaned: false,
|
|
259
289
|
reason: "process ownership could not be revalidated",
|
|
260
290
|
failures,
|
|
291
|
+
...unverifiedEntry,
|
|
261
292
|
};
|
|
262
293
|
};
|
|
263
294
|
const sanitizedTokenReadFailure = (diagnostic) => {
|
|
264
295
|
if (diagnostic === "environment_unavailable")
|
|
265
296
|
return diagnostic;
|
|
297
|
+
if (diagnostic === "platform_binary_environment_withheld")
|
|
298
|
+
return diagnostic;
|
|
266
299
|
const environmentErrno = /^(EACCES|EPERM|ENOENT|ESRCH):/u.exec(diagnostic ?? "");
|
|
267
300
|
if (environmentErrno?.[1] !== undefined)
|
|
268
301
|
return `environment_errno_${environmentErrno[1]}`;
|
|
@@ -360,7 +393,26 @@ const processOwnershipFailures = async (members, runId, host, expectedIdentities
|
|
|
360
393
|
}
|
|
361
394
|
return failures;
|
|
362
395
|
};
|
|
363
|
-
const
|
|
396
|
+
const TOKEN_READ_RETRY_ATTEMPTS = 3;
|
|
397
|
+
const TOKEN_READ_RETRY_DELAY_MS = 40;
|
|
398
|
+
/** Darwin reports this when the kernel withholds a platform binary's environment. */
|
|
399
|
+
const PLATFORM_BINARY_ENVIRONMENT_WITHHELD = "platform_binary_environment_withheld";
|
|
400
|
+
const currentProcessUid = () => typeof process.getuid === "function" ? process.getuid() : undefined;
|
|
401
|
+
/**
|
|
402
|
+
* Whether the operating system provably withheld this candidate's run token:
|
|
403
|
+
* current macOS omits the environment of Apple platform binaries from
|
|
404
|
+
* KERN_PROCARGS2 and fails with EINVAL for processes owned by another
|
|
405
|
+
* account, and neither class can be token-verified by any caller. Such a
|
|
406
|
+
* candidate is recorded as unverified instead of failing an otherwise clean
|
|
407
|
+
* capture; every other unreadable candidate stays fail-closed.
|
|
408
|
+
*/
|
|
409
|
+
const environmentWithheldFromInspection = (entry, diagnostic) => {
|
|
410
|
+
const uid = currentProcessUid();
|
|
411
|
+
if (uid !== undefined && entry.uid !== undefined && entry.uid !== uid)
|
|
412
|
+
return true;
|
|
413
|
+
return diagnostic === PLATFORM_BINARY_ENVIRONMENT_WITHHELD;
|
|
414
|
+
};
|
|
415
|
+
const scanTokenOwnedProcesses = async (processes, runId, host, captureBaseline, relation) => {
|
|
364
416
|
let candidates = processes;
|
|
365
417
|
let candidateIdentities = new Map();
|
|
366
418
|
if (host.processIdentities !== undefined) {
|
|
@@ -395,58 +447,89 @@ const scanTokenOwnedProcesses = async (processes, runId, host, captureBaseline)
|
|
|
395
447
|
}
|
|
396
448
|
candidates = stableCandidates;
|
|
397
449
|
}
|
|
450
|
+
const owned = [];
|
|
451
|
+
const ownedIdentities = new Map();
|
|
452
|
+
const recordOwned = (process) => {
|
|
453
|
+
owned.push(process);
|
|
454
|
+
const identity = candidateIdentities.get(process.pid);
|
|
455
|
+
ownedIdentities.set(process.pid, identity?.state === "readable" ? identity.identity : null);
|
|
456
|
+
};
|
|
398
457
|
let bulkTokens;
|
|
399
458
|
if (host.runTokens !== undefined)
|
|
400
459
|
bulkTokens = await host.runTokens(candidates);
|
|
401
|
-
const
|
|
402
|
-
const ownedIdentities = new Map();
|
|
460
|
+
const unreadable = [];
|
|
403
461
|
for (const process of candidates) {
|
|
404
462
|
const bulkToken = bulkTokens?.get(process.pid);
|
|
405
463
|
if (bulkToken !== undefined) {
|
|
406
464
|
if (bulkToken.state === "readable") {
|
|
407
|
-
if (bulkToken.runId === runId)
|
|
408
|
-
|
|
409
|
-
const identity = candidateIdentities.get(process.pid);
|
|
410
|
-
ownedIdentities.set(process.pid, identity?.state === "readable" ? identity.identity : null);
|
|
411
|
-
}
|
|
465
|
+
if (bulkToken.runId === runId)
|
|
466
|
+
recordOwned(process);
|
|
412
467
|
continue;
|
|
413
468
|
}
|
|
414
|
-
|
|
415
|
-
failures.push({
|
|
416
|
-
pid: process.pid,
|
|
417
|
-
reason: "environment-unreadable",
|
|
418
|
-
diagnostic: bulkToken.reason,
|
|
419
|
-
});
|
|
469
|
+
unreadable.push({ process, diagnostic: bulkToken.reason });
|
|
420
470
|
continue;
|
|
421
471
|
}
|
|
422
472
|
try {
|
|
423
|
-
if ((await host.environment(process.pid)).REA_PROCESS_RUN_ID === runId)
|
|
424
|
-
|
|
425
|
-
const identity = candidateIdentities.get(process.pid);
|
|
426
|
-
ownedIdentities.set(process.pid, identity?.state === "readable" ? identity.identity : null);
|
|
427
|
-
}
|
|
473
|
+
if ((await host.environment(process.pid)).REA_PROCESS_RUN_ID === runId)
|
|
474
|
+
recordOwned(process);
|
|
428
475
|
}
|
|
429
476
|
catch (cause) {
|
|
430
|
-
|
|
431
|
-
const live = liveProcesses(await host.listProcesses());
|
|
432
|
-
if (!live.some(({ pid }) => pid === process.pid))
|
|
433
|
-
continue;
|
|
434
|
-
}
|
|
435
|
-
catch (recheckCause) {
|
|
436
|
-
failures.push({
|
|
437
|
-
pid: process.pid,
|
|
438
|
-
reason: "environment-unreadable",
|
|
439
|
-
diagnostic: `${errorMessage(cause)}; process liveness recheck failed: ${errorMessage(recheckCause)}`,
|
|
440
|
-
});
|
|
441
|
-
continue;
|
|
442
|
-
}
|
|
443
|
-
failures.push({
|
|
444
|
-
pid: process.pid,
|
|
445
|
-
reason: "environment-unreadable",
|
|
446
|
-
diagnostic: errorMessage(cause),
|
|
447
|
-
});
|
|
477
|
+
unreadable.push({ process, diagnostic: errorMessage(cause) });
|
|
448
478
|
}
|
|
449
479
|
}
|
|
480
|
+
const remaining = await settleUnreadableTokenCandidates(unreadable, runId, host, recordOwned);
|
|
481
|
+
const relatedPids = new Set();
|
|
482
|
+
const relatedGroupIds = new Set();
|
|
483
|
+
if (relation !== undefined) {
|
|
484
|
+
relatedPids.add(relation.leaderPid);
|
|
485
|
+
for (const descendant of descendantsOf(relation.leaderPid, processes))
|
|
486
|
+
relatedPids.add(descendant.pid);
|
|
487
|
+
relatedGroupIds.add(relation.processGroupId);
|
|
488
|
+
for (const processGroupId of relation.sampledProcessGroupIds ?? [])
|
|
489
|
+
if (Number.isSafeInteger(processGroupId) && processGroupId > 0)
|
|
490
|
+
relatedGroupIds.add(processGroupId);
|
|
491
|
+
for (const process of owned)
|
|
492
|
+
relatedGroupIds.add(process.processGroupId);
|
|
493
|
+
}
|
|
494
|
+
const unverified = [];
|
|
495
|
+
const strict = [];
|
|
496
|
+
const withheld = [];
|
|
497
|
+
for (const candidate of remaining) {
|
|
498
|
+
const isRelated = relation === undefined ||
|
|
499
|
+
relatedPids.has(candidate.process.pid) ||
|
|
500
|
+
relatedGroupIds.has(candidate.process.processGroupId);
|
|
501
|
+
if (!isRelated &&
|
|
502
|
+
environmentWithheldFromInspection(candidate.process, candidate.diagnostic)) {
|
|
503
|
+
withheld.push(candidate);
|
|
504
|
+
continue;
|
|
505
|
+
}
|
|
506
|
+
strict.push(candidate);
|
|
507
|
+
}
|
|
508
|
+
let finalLive;
|
|
509
|
+
try {
|
|
510
|
+
finalLive = new Set(liveProcesses(await host.listProcesses()).map(({ pid }) => pid));
|
|
511
|
+
}
|
|
512
|
+
catch (cause) {
|
|
513
|
+
void cause;
|
|
514
|
+
finalLive = undefined;
|
|
515
|
+
}
|
|
516
|
+
for (const candidate of strict) {
|
|
517
|
+
if (finalLive !== undefined && !finalLive.has(candidate.process.pid))
|
|
518
|
+
continue;
|
|
519
|
+
failures.push({
|
|
520
|
+
pid: candidate.process.pid,
|
|
521
|
+
reason: "environment-unreadable",
|
|
522
|
+
diagnostic: candidate.diagnostic,
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
for (const candidate of withheld) {
|
|
526
|
+
if (finalLive !== undefined && !finalLive.has(candidate.process.pid))
|
|
527
|
+
continue;
|
|
528
|
+
unverified.push({
|
|
529
|
+
pid: candidate.process.pid,
|
|
530
|
+
diagnostic: candidate.diagnostic,
|
|
531
|
+
});
|
|
532
|
+
}
|
|
450
533
|
if (candidates.length > 0 && host.processIdentities !== undefined) {
|
|
451
534
|
const afterRead = await host.processIdentities(candidates);
|
|
452
535
|
const stillOwned = [];
|
|
@@ -469,9 +552,73 @@ const scanTokenOwnedProcesses = async (processes, runId, host, captureBaseline)
|
|
|
469
552
|
diagnostic: "process identity changed or became unavailable during token validation",
|
|
470
553
|
});
|
|
471
554
|
}
|
|
472
|
-
return {
|
|
555
|
+
return {
|
|
556
|
+
owned: stillOwned,
|
|
557
|
+
failures,
|
|
558
|
+
unverified,
|
|
559
|
+
identities: ownedIdentities,
|
|
560
|
+
};
|
|
561
|
+
}
|
|
562
|
+
return { owned, failures, unverified, identities: ownedIdentities };
|
|
563
|
+
};
|
|
564
|
+
/**
|
|
565
|
+
* Re-read run tokens for unresolved sweep candidates so transient exec and
|
|
566
|
+
* exit states settle before classification. Each attempt revalidates
|
|
567
|
+
* liveness, refreshes the diagnostic, and is bounded by a fixed attempt
|
|
568
|
+
* budget; a still-unreadable candidate keeps its latest diagnostic.
|
|
569
|
+
*/
|
|
570
|
+
const settleUnreadableTokenCandidates = async (pending, runId, host, recordOwned) => {
|
|
571
|
+
let remaining = pending;
|
|
572
|
+
for (let attempt = 0; attempt < TOKEN_READ_RETRY_ATTEMPTS && remaining.length > 0; attempt += 1) {
|
|
573
|
+
await new Promise((resolve) => setTimeout(resolve, TOKEN_READ_RETRY_DELAY_MS));
|
|
574
|
+
let live;
|
|
575
|
+
try {
|
|
576
|
+
live = new Set(liveProcesses(await host.listProcesses()).map(({ pid }) => pid));
|
|
577
|
+
}
|
|
578
|
+
catch (cause) {
|
|
579
|
+
void cause;
|
|
580
|
+
live = undefined;
|
|
581
|
+
}
|
|
582
|
+
let observations;
|
|
583
|
+
if (host.runTokens !== undefined) {
|
|
584
|
+
try {
|
|
585
|
+
observations = await host.runTokens(remaining.map(({ process }) => process));
|
|
586
|
+
}
|
|
587
|
+
catch (cause) {
|
|
588
|
+
void cause;
|
|
589
|
+
observations = undefined;
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
const stillUnreadable = [];
|
|
593
|
+
for (const candidate of remaining) {
|
|
594
|
+
const pid = candidate.process.pid;
|
|
595
|
+
if (live !== undefined && !live.has(pid))
|
|
596
|
+
continue;
|
|
597
|
+
const observation = observations?.get(pid) ?? (await readEnvironmentRunToken(host, pid));
|
|
598
|
+
if (observation.state === "readable") {
|
|
599
|
+
if (observation.runId === runId)
|
|
600
|
+
recordOwned(candidate.process);
|
|
601
|
+
continue;
|
|
602
|
+
}
|
|
603
|
+
stillUnreadable.push({
|
|
604
|
+
process: candidate.process,
|
|
605
|
+
diagnostic: observation.reason,
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
remaining = stillUnreadable;
|
|
609
|
+
}
|
|
610
|
+
return remaining;
|
|
611
|
+
};
|
|
612
|
+
const readEnvironmentRunToken = async (host, pid) => {
|
|
613
|
+
try {
|
|
614
|
+
return {
|
|
615
|
+
state: "readable",
|
|
616
|
+
runId: (await host.environment(pid)).REA_PROCESS_RUN_ID,
|
|
617
|
+
};
|
|
618
|
+
}
|
|
619
|
+
catch (cause) {
|
|
620
|
+
return { state: "unavailable", reason: errorMessage(cause) };
|
|
473
621
|
}
|
|
474
|
-
return { owned, failures, identities: ownedIdentities };
|
|
475
622
|
};
|
|
476
623
|
const processIsGone = async (host, pid) => {
|
|
477
624
|
try {
|
|
@@ -1,33 +1,40 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { AnalysisCapabilityUnavailableError } from "../domain/analysisErrorCore.js";
|
|
2
3
|
import { launcherIdentityFailure } from "./ProcessOwnershipIdentity.js";
|
|
3
4
|
import { descendantsOf, liveProcesses } from "./ProcessOwnershipProcessTree.js";
|
|
4
5
|
import { execFileOutput } from "./ExecFileOutput.js";
|
|
5
6
|
import { createDarwinProcessRunTokenReader } from "./DarwinProcessRunTokenReader.js";
|
|
6
7
|
/** Observe one group without signaling it, failing closed on identity doubt. */
|
|
7
|
-
export const observeOwnedProcessGroupWithHost = async (ownership, host) => {
|
|
8
|
+
export const observeOwnedProcessGroupWithHost = async (ownership, host, signal) => {
|
|
9
|
+
signal?.throwIfAborted();
|
|
8
10
|
let members;
|
|
9
11
|
try {
|
|
10
|
-
members = (await host.listProcesses()).filter(({ processGroupId }) => processGroupId === ownership.processGroupId);
|
|
12
|
+
members = (await host.listProcesses(signal)).filter(({ processGroupId }) => processGroupId === ownership.processGroupId);
|
|
11
13
|
}
|
|
12
14
|
catch (cause) {
|
|
15
|
+
signal?.throwIfAborted();
|
|
13
16
|
return {
|
|
14
17
|
state: "unverifiable",
|
|
15
18
|
reason: `process group could not be inspected: ${errorMessage(cause)}`,
|
|
16
19
|
};
|
|
17
20
|
}
|
|
21
|
+
signal?.throwIfAborted();
|
|
18
22
|
const liveMembers = liveProcesses(members);
|
|
19
23
|
if (liveMembers.length === 0)
|
|
20
24
|
return { state: "empty" };
|
|
21
25
|
for (const member of liveMembers) {
|
|
26
|
+
signal?.throwIfAborted();
|
|
22
27
|
try {
|
|
23
|
-
|
|
24
|
-
|
|
28
|
+
const runId = (await host.environment(member.pid)).REA_PROCESS_RUN_ID;
|
|
29
|
+
signal?.throwIfAborted();
|
|
30
|
+
if (runId !== ownership.runId)
|
|
25
31
|
return {
|
|
26
32
|
state: "unverifiable",
|
|
27
33
|
reason: "process ownership did not match",
|
|
28
34
|
};
|
|
29
35
|
}
|
|
30
36
|
catch (cause) {
|
|
37
|
+
signal?.throwIfAborted();
|
|
31
38
|
if (!(await processIsGone(host, member.pid))) {
|
|
32
39
|
return {
|
|
33
40
|
state: "unverifiable",
|
|
@@ -133,17 +140,18 @@ export const createSystemProcessOwnershipHost = (platform = process.platform, ho
|
|
|
133
140
|
const listProcesses = async (signal) => {
|
|
134
141
|
if (platform === "win32")
|
|
135
142
|
return [];
|
|
136
|
-
const { stdout } = await execFileOutput("ps", ["-axo", "pid=,ppid=,pgid=,stat=,command="], { env: hostEnvironment, ...(signal === undefined ? {} : { signal }) });
|
|
143
|
+
const { stdout } = await execFileOutput("ps", ["-axo", "pid=,ppid=,pgid=,uid=,stat=,command="], { env: hostEnvironment, ...(signal === undefined ? {} : { signal }) });
|
|
137
144
|
return stdout
|
|
138
145
|
.split("\n")
|
|
139
|
-
.map((line) => /\s*(\d+)\s+(\d+)\s+(\d+)\s+(\S+)\s+(.*)/u.exec(line))
|
|
146
|
+
.map((line) => /\s*(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\S+)\s+(.*)/u.exec(line))
|
|
140
147
|
.filter((match) => match !== null)
|
|
141
148
|
.map((match) => ({
|
|
142
149
|
pid: Number(match[1]),
|
|
143
150
|
parentPid: Number(match[2]),
|
|
144
151
|
processGroupId: Number(match[3]),
|
|
145
|
-
|
|
146
|
-
|
|
152
|
+
uid: Number(match[4]),
|
|
153
|
+
state: match[5] ?? "",
|
|
154
|
+
command: match[6] ?? "",
|
|
147
155
|
}));
|
|
148
156
|
};
|
|
149
157
|
const processIdentities = async (processes, signal) => {
|
|
@@ -222,6 +230,19 @@ export const createSystemProcessOwnershipHost = (platform = process.platform, ho
|
|
|
222
230
|
platform,
|
|
223
231
|
prepare: async (signal) => {
|
|
224
232
|
await darwinTokens?.prepare(signal);
|
|
233
|
+
if (platform === "linux") {
|
|
234
|
+
try {
|
|
235
|
+
const processes = await listProcesses(signal);
|
|
236
|
+
if (!processes.some(({ pid }) => pid === process.pid))
|
|
237
|
+
throw new Error("ps did not report REA's current process");
|
|
238
|
+
}
|
|
239
|
+
catch (cause) {
|
|
240
|
+
if (isExpectedAbort(cause, signal))
|
|
241
|
+
throw cause;
|
|
242
|
+
const reason = `Linux process ownership inspection requires a procps-compatible ps on REA's PATH before launching a child: ${errorMessage(cause)}`;
|
|
243
|
+
throw new AnalysisCapabilityUnavailableError("process-ownership", "prepare_owned_process", reason, { cause, userMessage: reason });
|
|
244
|
+
}
|
|
245
|
+
}
|
|
225
246
|
},
|
|
226
247
|
listProcesses,
|
|
227
248
|
async environment(pid) {
|
|
@@ -276,12 +297,42 @@ export const createSystemProcessOwnershipHost = (platform = process.platform, ho
|
|
|
276
297
|
};
|
|
277
298
|
};
|
|
278
299
|
export const systemProcessOwnershipHost = createSystemProcessOwnershipHost();
|
|
300
|
+
/** Observe the current OS start identity for one live PID, when supported. */
|
|
301
|
+
export const observeProcessStartIdentity = async (pid, host = systemProcessOwnershipHost) => {
|
|
302
|
+
const process = (await host.listProcesses()).find((entry) => entry.pid === pid);
|
|
303
|
+
if (process === undefined || liveProcesses([process]).length === 0)
|
|
304
|
+
return undefined;
|
|
305
|
+
if (host.processIdentities === undefined)
|
|
306
|
+
return { state: "unavailable", reason: "process identity is unsupported" };
|
|
307
|
+
return ((await host.processIdentities([process])).get(pid) ?? {
|
|
308
|
+
state: "unavailable",
|
|
309
|
+
reason: "process identity was not returned",
|
|
310
|
+
});
|
|
311
|
+
};
|
|
312
|
+
/** Revalidate a launch-time start identity immediately before signaling a PID. */
|
|
313
|
+
export const signalProcessWithStartIdentity = async (pid, expectedIdentity, signal, options = {}) => {
|
|
314
|
+
const host = options.host ?? systemProcessOwnershipHost;
|
|
315
|
+
try {
|
|
316
|
+
const observed = await observeProcessStartIdentity(pid, host);
|
|
317
|
+
if (observed === undefined)
|
|
318
|
+
return "gone";
|
|
319
|
+
if (observed.state !== "readable")
|
|
320
|
+
return "unverified";
|
|
321
|
+
if (observed.identity !== expectedIdentity)
|
|
322
|
+
return "identity-changed";
|
|
323
|
+
(options.sendSignal ?? process.kill)(pid, signal);
|
|
324
|
+
return "signaled";
|
|
325
|
+
}
|
|
326
|
+
catch {
|
|
327
|
+
return "unverified";
|
|
328
|
+
}
|
|
329
|
+
};
|
|
279
330
|
/** Prepare native token inspection before REA launches a captured child. */
|
|
280
331
|
export const prepareProcessOwnershipInspection = async (signal) => {
|
|
281
332
|
await systemProcessOwnershipHost.prepare?.(signal);
|
|
282
333
|
};
|
|
283
334
|
/** Observe one group without signaling it, failing closed on identity doubt. */
|
|
284
|
-
export const observeOwnedProcessGroup = async (ownership, host = systemProcessOwnershipHost) => observeOwnedProcessGroupWithHost(ownership, host);
|
|
335
|
+
export const observeOwnedProcessGroup = async (ownership, host = systemProcessOwnershipHost, signal) => observeOwnedProcessGroupWithHost(ownership, host, signal);
|
|
285
336
|
/**
|
|
286
337
|
* Record the live launcher and descendant lineage after run-token validation.
|
|
287
338
|
*
|
|
@@ -21,9 +21,7 @@ export const spawnOwnedProviderProcess = async (options) => {
|
|
|
21
21
|
REA_PROCESS_RUN_ID: options.runId,
|
|
22
22
|
};
|
|
23
23
|
if (platform === "win32" && process.platform === "win32") {
|
|
24
|
-
|
|
25
|
-
throw new Error("Owned Windows provider processes do not support protocol stdin");
|
|
26
|
-
const child = new WindowsOwnedProcess(options.command, options.arguments, options.cwd, environment, options.windowsVerbatimArguments ?? false);
|
|
24
|
+
const child = new WindowsOwnedProcess(options.command, options.arguments, options.cwd, environment, options.windowsVerbatimArguments ?? false, options.stdin === "pipe");
|
|
27
25
|
return {
|
|
28
26
|
process: child,
|
|
29
27
|
ownership: {
|
|
@@ -83,6 +81,12 @@ export class ProviderProcessSupervisor {
|
|
|
83
81
|
#onStderr = (chunk) => {
|
|
84
82
|
this.#capture("stderr", this.#stderr, chunk);
|
|
85
83
|
};
|
|
84
|
+
#onStdoutError = (cause) => {
|
|
85
|
+
this.#recordStreamError("stdout", cause);
|
|
86
|
+
};
|
|
87
|
+
#onStderrError = (cause) => {
|
|
88
|
+
this.#recordStreamError("stderr", cause);
|
|
89
|
+
};
|
|
86
90
|
#onExit = (code, signal) => {
|
|
87
91
|
this.#recordExit(code, signal);
|
|
88
92
|
};
|
|
@@ -135,9 +139,13 @@ export class ProviderProcessSupervisor {
|
|
|
135
139
|
async waitForOutputClose(timeoutMs) {
|
|
136
140
|
return waitForProcessEvent(this.#outputClosed, this.#outputClose.promise, timeoutMs);
|
|
137
141
|
}
|
|
138
|
-
/**
|
|
142
|
+
/** Share each stop attempt; incomplete cleanup retains ownership and permits retry. */
|
|
139
143
|
stop(options = {}) {
|
|
140
|
-
this.#stopPromise ??= this.#stop(options)
|
|
144
|
+
this.#stopPromise ??= this.#stop(options).then((result) => {
|
|
145
|
+
if (result.status === "incomplete")
|
|
146
|
+
this.#stopPromise = undefined;
|
|
147
|
+
return result;
|
|
148
|
+
});
|
|
141
149
|
return this.#stopPromise;
|
|
142
150
|
}
|
|
143
151
|
/** Detach capture and process listeners after an adapter releases ownership. */
|
|
@@ -146,12 +154,26 @@ export class ProviderProcessSupervisor {
|
|
|
146
154
|
return;
|
|
147
155
|
this.#disposed = true;
|
|
148
156
|
this.launch.process.stdout?.off("data", this.#onStdout);
|
|
157
|
+
this.launch.process.stdout?.off("error", this.#onStdoutError);
|
|
149
158
|
this.launch.process.stderr?.off("data", this.#onStderr);
|
|
159
|
+
this.launch.process.stderr?.off("error", this.#onStderrError);
|
|
150
160
|
this.launch.process.off("exit", this.#onExit);
|
|
151
161
|
this.launch.process.off("close", this.#onClose);
|
|
152
162
|
this.launch.process.off("error", this.#onError);
|
|
153
163
|
}
|
|
154
164
|
async #stop(options) {
|
|
165
|
+
let completed = false;
|
|
166
|
+
try {
|
|
167
|
+
const result = await this.#stopWithin(options);
|
|
168
|
+
completed = result.status !== "incomplete";
|
|
169
|
+
return result;
|
|
170
|
+
}
|
|
171
|
+
finally {
|
|
172
|
+
if (completed)
|
|
173
|
+
this.dispose();
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
async #stopWithin(options) {
|
|
155
177
|
try {
|
|
156
178
|
if (!this.launch.ownsProcessLifetime)
|
|
157
179
|
return { status: "not-owned" };
|
|
@@ -193,9 +215,6 @@ export class ProviderProcessSupervisor {
|
|
|
193
215
|
: "owned provider process cleanup failed",
|
|
194
216
|
};
|
|
195
217
|
}
|
|
196
|
-
finally {
|
|
197
|
-
this.dispose();
|
|
198
|
-
}
|
|
199
218
|
}
|
|
200
219
|
#ownedCleanup(supplied) {
|
|
201
220
|
if (supplied !== undefined)
|
|
@@ -214,10 +233,20 @@ export class ProviderProcessSupervisor {
|
|
|
214
233
|
this.launch.process.kill(signal);
|
|
215
234
|
}
|
|
216
235
|
#attach(stream, name) {
|
|
217
|
-
if (name === "stdout")
|
|
236
|
+
if (name === "stdout") {
|
|
218
237
|
stream?.on("data", this.#onStdout);
|
|
219
|
-
|
|
238
|
+
stream?.on("error", this.#onStdoutError);
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
220
241
|
stream?.on("data", this.#onStderr);
|
|
242
|
+
stream?.on("error", this.#onStderrError);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
#recordStreamError(stream, cause) {
|
|
246
|
+
this.#options.onDiagnostic?.({
|
|
247
|
+
type: "error",
|
|
248
|
+
message: `${stream} stream failed: ${cause.message}`,
|
|
249
|
+
});
|
|
221
250
|
}
|
|
222
251
|
#capture(stream, capture, chunk) {
|
|
223
252
|
const bytes = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|