rea-agents 6.3.0 → 6.4.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 +7 -4
- package/bridge/ghidra/ReaGhidraApplySeeds.java +151 -0
- package/bridge/ghidra/ReaGhidraBridge.java +597 -209
- package/bridge/ghidra/ReaGhidraNoReturnFix.java +123 -0
- package/dist/adb/AdbConfiguration.js +88 -0
- package/dist/adb/AdbDeviceOutput.js +186 -0
- package/dist/adb/AdbProvider.js +1190 -0
- package/dist/adb/AdbShellOutput.js +309 -0
- package/dist/android/AndroidTargetSnapshot.js +104 -22
- package/dist/android/JadxConfiguration.js +44 -24
- package/dist/android/JadxProvider.js +51 -19
- package/dist/apktool/ApktoolConfiguration.js +84 -0
- package/dist/apktool/ApktoolDecodeOutput.js +59 -0
- package/dist/apktool/ApktoolProvider.js +506 -0
- package/dist/application/AnalysisProvider.js +8 -2
- package/dist/application/AppBundleExecutable.js +27 -22
- package/dist/application/BinaryTargetResolver.js +22 -2
- package/dist/application/CapabilityInventory.js +11 -1
- package/dist/application/ClientConfigurationDocument.js +70 -0
- package/dist/application/ClientConfigurationFiles.js +91 -0
- package/dist/application/ClientRegistrationEnvironment.js +35 -0
- package/dist/application/ClientRegistrationStatus.js +66 -31
- package/dist/application/DirectAnalysis.js +2 -2
- package/dist/application/DirectAnalysisCleanup.js +1 -1
- package/dist/application/DirectAnalysisStatus.js +1 -1
- package/dist/application/Doctor.js +5 -3
- package/dist/application/DoctorDiagnostics.js +1 -1
- package/dist/application/EvidenceBundleCommands.js +6 -12
- package/dist/application/GeminiClientSettings.js +139 -0
- package/dist/application/HermesClientHome.js +115 -0
- package/dist/application/HopperDownload.js +39 -0
- package/dist/application/InvestigationProviders.js +6 -0
- package/dist/application/JsonFiles.js +6 -5
- package/dist/{cliJsonFile.js → application/JsonInputFile.js} +108 -35
- package/dist/application/LinuxHopper.js +4 -12
- package/dist/application/MacHopper.js +172 -149
- package/dist/application/MipsElfAbiFlags.js +140 -0
- package/dist/application/ProviderOperationExecution.js +31 -0
- package/dist/application/ReconstructionObligationCandidates.js +9 -3
- package/dist/application/ReferenceSourceImport.js +76 -29
- package/dist/application/ReferenceSourceImportEntries.js +18 -9
- package/dist/application/ReferenceSourceImportPolicy.js +99 -23
- package/dist/application/ReferenceSourceImportTypes.js +30 -22
- package/dist/application/ReferenceSourceVcsAdapter.js +145 -30
- package/dist/application/RegularFileRead.js +93 -7
- package/dist/application/Setup.js +54 -6
- package/dist/application/SetupClientConfiguration.js +116 -16
- package/dist/application/SetupHost.js +102 -24
- package/dist/application/SetupPlan.js +5 -8
- package/dist/application/SetupSkill.js +58 -39
- package/dist/application/SupportedClients.js +290 -65
- package/dist/application/Uninstall.js +158 -10
- package/dist/application/UpdateMaintenance.js +17 -21
- package/dist/application/Utf8JsonInput.js +7 -0
- package/dist/application/WebScriptExportService.js +131 -65
- package/dist/application/WebSourceLocationService.js +3 -0
- package/dist/application/adb/AdbDeviceAnalysisPort.js +1 -0
- package/dist/application/adb/AdbDeviceAnalysisService.js +13 -0
- package/dist/application/analysisView/AnalysisViewService.js +40 -2
- package/dist/application/apktool/ApktoolResourceAnalysisPort.js +1 -0
- package/dist/application/apktool/ApktoolResourceAnalysisService.js +13 -0
- package/dist/application/binary/AnalysisClientCleanup.js +0 -24
- package/dist/application/binary/BinarySession.js +2 -1
- package/dist/application/binaryDiagnostics/BinaryLayoutService.js +2 -1
- package/dist/application/binaryDiagnostics/PeResourcesPort.js +1 -0
- package/dist/application/binaryDiagnostics/PeResourcesService.js +111 -0
- package/dist/application/binaryDiagnostics/RecordedCrashService.js +2 -1
- package/dist/application/evm/EvmInterfaceService.js +3 -0
- package/dist/application/firmware/FirmwareAnalysisService.js +3 -0
- package/dist/application/investigation/InspectEvidenceBundle.js +18 -0
- package/dist/application/javascript/ElectronBoundaryGraphContext.js +3 -2
- package/dist/application/javascript/ElectronBoundaryGraphIpc.js +2 -2
- package/dist/application/javascript/ElectronBoundaryGraphNative.js +19 -6
- package/dist/application/javascript/ElectronBoundaryGraphWindows.js +3 -3
- package/dist/application/javascript/JavaScriptApplicationService.js +22 -11
- package/dist/application/javascript/JavaScriptApplicationWorkflowEvidence.js +5 -6
- package/dist/application/javascript/JavaScriptArtifactAnalysis.js +171 -30
- package/dist/application/javascript/JavaScriptArtifactGraphAccumulator.js +14 -16
- package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +67 -19
- package/dist/application/javascript/JavaScriptArtifactGraphBundlers.js +4 -3
- package/dist/application/javascript/JavaScriptArtifactGraphContext.js +11 -5
- package/dist/application/javascript/JavaScriptArtifactGraphFindings.js +19 -16
- package/dist/application/javascript/JavaScriptArtifactGraphStructure.js +92 -10
- package/dist/application/javascript/JavaScriptArtifactPathResolution.js +258 -235
- package/dist/application/javascript/JavaScriptArtifactReconstruction.js +115 -26
- package/dist/application/javascript/JavaScriptArtifactReconstructionInput.js +4 -1
- package/dist/application/javascript/JavaScriptModuleRelationships.js +6 -4
- package/dist/application/javascript/JavaScriptRecoveryService.js +3 -0
- package/dist/application/javascript/JavaScriptSemanticGraphAsyncProjection.js +9 -3
- package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +199 -61
- package/dist/application/javascript/JavaScriptSemanticGraphConstruction.js +12 -19
- package/dist/application/javascript/JavaScriptSemanticGraphDataProjection.js +4 -1
- package/dist/application/javascript/JavaScriptSemanticGraphFlowProjection.js +5 -3
- package/dist/application/javascript/JavaScriptSemanticGraphObjectProjection.js +5 -3
- package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +19 -8
- package/dist/application/jeb/JebAnalysisPort.js +1 -0
- package/dist/application/jeb/JebAnalysisService.js +13 -0
- package/dist/application/managed/ManagedApplicationGraphService.js +1 -1
- package/dist/application/native/NativeUiActionTrace.js +16 -8
- package/dist/application/native/NativeValueTrace.js +23 -6
- package/dist/application/process/ProcessCli.js +25 -20
- package/dist/artifacts/ArtifactPaths.js +129 -8
- package/dist/artifacts/ArtifactProvider.js +20 -15
- package/dist/artifacts/ArtifactReader.js +23 -0
- package/dist/artifacts/ArtifactResourceScope.js +100 -0
- package/dist/artifacts/AsarArtifactReader.js +176 -102
- package/dist/artifacts/AsarHeader.js +24 -0
- package/dist/artifacts/DirectoryArtifactReader.js +168 -65
- package/dist/artifacts/MachOSliceArtifactReader.js +116 -39
- package/dist/artifacts/NativeDmgArtifactReader.js +29 -22
- package/dist/artifacts/SafeOutputTree.js +245 -70
- package/dist/artifacts/SafeOutputTreeCleanup.js +45 -0
- package/dist/artifacts/SafeOutputTreeCreationFailure.js +20 -0
- package/dist/artifacts/SafeOutputTreeIdentity.js +42 -0
- package/dist/artifacts/SafeOutputTreeReadback.js +33 -0
- package/dist/artifacts/ZipArtifactReader.js +77 -27
- package/dist/artifacts/apple/InterfaceBuilderAnalysis.js +58 -18
- package/dist/artifacts/apple/InterfaceBuilderDecodeBudget.js +62 -24
- package/dist/artifacts/apple/KeyedArchiveReader.js +32 -13
- package/dist/artifacts/extraction/ArtifactExtraction.js +110 -86
- package/dist/artifacts/inventory/ArtifactGraphConstruction.js +110 -43
- package/dist/artifacts/inventory/ArtifactInventory.js +5 -4
- package/dist/artifacts/inventory/classify.js +75 -32
- package/dist/artifacts/inventory/hashStableRootArtifact.js +48 -15
- package/dist/artifacts/inventory/reader.js +13 -5
- package/dist/artifacts/inventory/scanCanonical.js +62 -25
- package/dist/artifacts/inventory/scanReader.js +38 -11
- package/dist/artifacts/javascript/JavaScriptArtifactFiles.js +15 -9
- package/dist/artifacts/javascript/JavaScriptSourceAnalysis.js +3 -0
- package/dist/browser/BrowserScenarioPartialObservation.js +8 -2
- package/dist/browser/BrowserScenarioSecrets.js +52 -37
- package/dist/browser/CdpBrowserProvider.js +5 -0
- package/dist/browser/CdpCaptureDocuments.js +40 -6
- package/dist/browser/CdpCaptureDomSvg.js +210 -0
- package/dist/browser/CdpCaptureEventBodyShapes.js +4 -8
- package/dist/browser/CdpCaptureEventHandlers.js +26 -9
- package/dist/browser/CdpCaptureEvents.js +4 -9
- package/dist/browser/CdpConnection.js +22 -5
- package/dist/browser/CdpPageCapture.js +1 -1
- package/dist/browser/CdpTargetSession.js +30 -34
- package/dist/browser/CdpWebMcpDiscovery.js +32 -10
- package/dist/browser/ElectronFileScope.js +99 -9
- package/dist/browser/PlaywrightBrowserScenarioProvider.js +60 -4
- package/dist/browser/PlaywrightElectronActiveProvider.js +11 -6
- package/dist/browser/PlaywrightScenarioArtifacts.js +5 -5
- package/dist/browser/PlaywrightScenarioBrowser.js +69 -7
- package/dist/browser/PlaywrightScenarioSession.js +127 -54
- package/dist/browser/PlaywrightScenarioStorage.js +507 -0
- package/dist/browser/PngVisualDiff.js +198 -29
- package/dist/browser/WebSourceMapFetcher.js +3 -3
- package/dist/browser/assets/LocalWebScriptArtifacts.js +3 -1
- package/dist/browser/assets/PublishWebScripts.js +75 -20
- package/dist/browser/assets/WebArtifactReads.js +23 -1
- package/dist/browser/assets/WebSourceLocationArtifacts.js +1 -0
- package/dist/browser/execution/CdpExecutionCapture.js +3 -3
- package/dist/browser/execution/CdpPreciseCoverage.js +5 -8
- package/dist/browser/history/HarCapture.js +14 -0
- package/dist/browser/history/HarCaptureProcess.js +2 -10
- package/dist/browser/history/MitmproxyCaptureAdapter.js +3 -1
- package/dist/browser/modules/WebModuleArtifacts.js +1 -0
- package/dist/cli/adbCommands.js +337 -0
- package/dist/cli/analysisViewCommands.js +39 -1
- package/dist/cli/apktoolCommands.js +53 -0
- package/dist/cli/artifactCommands.js +8 -11
- package/dist/cli/binaryDiagnosticsCommands.js +19 -1
- package/dist/cli/browserAdvancedCommands.js +65 -36
- package/dist/cli/coreBinaryCommands.js +0 -5
- package/dist/cli/coreNativeCommands.js +1 -14
- package/dist/cli/electronCommands.js +6 -1
- package/dist/cli/evmCommands.js +13 -4
- package/dist/cli/firmwareCommands.js +7 -2
- package/dist/cli/javascriptApplicationAnalysis.js +17 -1
- package/dist/cli/javascriptRecoveryCommands.js +22 -15
- package/dist/cli/jebCommands.js +99 -0
- package/dist/cli/jsonOutput.js +11 -4
- package/dist/cli/referenceSourceImportStatus.js +7 -0
- package/dist/cli/setupCommands.js +15 -3
- package/dist/cli/utilityCommands.js +66 -18
- package/dist/cli/webScriptCommands.js +20 -1
- package/dist/cli/webSourceLocationCommands.js +21 -9
- package/dist/cli.js +6 -0
- package/dist/cliBrowserScenarioCommands.js +2 -1
- package/dist/cliCommandNames.js +32 -0
- package/dist/cliJsonInput.js +2 -2
- package/dist/cliObservationOptions.js +3 -0
- package/dist/composition/adb.js +3 -0
- package/dist/composition/apktool.js +3 -0
- package/dist/composition/binaryDiagnostics.js +4 -0
- package/dist/composition/directAnalysis.js +12 -4
- package/dist/composition/javascriptAnalysisWorkerProcess.js +48 -0
- package/dist/composition/jeb.js +6 -0
- package/dist/config/environment.js +10 -0
- package/dist/config/ghidraLanguageOverride.js +9 -0
- package/dist/config/mcpInputSchemaProfile.js +27 -0
- package/dist/config/parseConfig.js +28 -1
- package/dist/contracts/adb/adbToolContracts.js +353 -0
- package/dist/contracts/advertisedInputExamples.js +48 -0
- package/dist/contracts/analysisDetail.js +10 -0
- package/dist/contracts/analysisViewToolContracts.js +17 -2
- package/dist/contracts/apktool/apktoolToolContracts.js +33 -0
- package/dist/contracts/artifactToolContracts.js +8 -5
- package/dist/contracts/browserToolContracts.js +1 -1
- package/dist/contracts/compactInputSchema.js +256 -0
- package/dist/contracts/functionWorkflowToolContracts.js +1 -1
- package/dist/contracts/inputSchemaPresentation.js +10 -10
- package/dist/contracts/javascript/electronToolContracts.js +15 -3
- package/dist/contracts/javascript/javascriptRecoveryToolContracts.js +1 -1
- package/dist/contracts/jeb/jebToolContracts.js +64 -0
- package/dist/contracts/native/binaryDiagnosticsToolContracts.js +25 -3
- package/dist/contracts/officialToolContracts.js +5 -5
- package/dist/contracts/sessionToolContracts.js +2 -2
- package/dist/contracts/sessionToolSchemas.js +6 -2
- package/dist/contracts/toolContractExamples.js +6 -0
- package/dist/contracts/toolContractTypes.js +3 -0
- package/dist/contracts/toolContracts.js +6 -0
- package/dist/contracts/toolEffects.js +167 -0
- package/dist/contracts/toolOutputSchemaGroups.js +5 -3
- package/dist/contracts/toolSchemaMetadata.js +82 -7
- package/dist/domain/adb/adbDeviceAnalysis.js +583 -0
- package/dist/domain/analysisErrorCleanup.js +29 -0
- package/dist/domain/analysisErrorPresentation.js +18 -6
- package/dist/domain/analysisErrorProjection.js +4 -1
- package/dist/domain/analysisSnapshot.js +2 -1
- package/dist/domain/analysisView/analysisView.js +52 -2
- package/dist/domain/analysisView/binaryLayoutView.js +2 -0
- package/dist/domain/analysisView/javascriptApplicationView.js +2 -0
- package/dist/domain/analysisView/nativeFunctionView.js +155 -0
- package/dist/domain/android/androidApplication.js +25 -20
- package/dist/domain/apktool/apktoolResourceAnalysis.js +77 -0
- package/dist/domain/apple/appleApplication.js +40 -23
- package/dist/domain/apple/appleBundleAnatomy.js +95 -28
- package/dist/domain/apple/dyldPaths.js +9 -1
- package/dist/domain/apple/dylibResolution.js +2 -2
- package/dist/domain/apple/interfaceBuilderGraph.js +22 -19
- package/dist/domain/apple/interfaceBuilderKeyedArchive.js +10 -1
- package/dist/domain/artifactComparison.js +35 -7
- package/dist/domain/artifactGraph.js +5 -3
- package/dist/domain/artifactIdentity.js +30 -2
- package/dist/domain/artifactInspection.js +3 -43
- package/dist/domain/artifactIntegrityPolicy.js +10 -0
- package/dist/domain/artifactInventoryEvidence.js +11 -12
- package/dist/domain/artifactPathSyntax.js +1 -1
- package/dist/domain/binaryTarget.js +16 -0
- package/dist/domain/binaryTargetTypes.js +8 -1
- package/dist/domain/browserObservationSchemas.js +8 -4
- package/dist/domain/canonicalJsonDigestSteps.js +34 -12
- package/dist/domain/compactStringIdentity.js +9 -0
- package/dist/domain/evidence.js +2 -1
- package/dist/domain/evidenceRecordSummary.js +144 -0
- package/dist/domain/inputIssueProjection.js +16 -1
- package/dist/domain/javascript/electronStaticAnalysisBrowser.js +12 -13
- package/dist/domain/javascript/electronStaticAnalysisIpc.js +11 -20
- package/dist/domain/javascript/electronStaticAnalysisNative.js +70 -40
- package/dist/domain/javascript/electronStaticAnalysisValues.js +16 -0
- package/dist/domain/javascript/javascriptAnalysisResourceControls.js +45 -0
- package/dist/domain/javascript/javascriptApplicationAnalysis.js +4 -1
- package/dist/domain/javascript/javascriptApplicationChangeGraph.js +6 -6
- package/dist/domain/javascript/javascriptApplicationGraph.js +79 -18
- package/dist/domain/javascript/javascriptApplicationProjectionResources.js +35 -0
- package/dist/domain/javascript/javascriptApplicationVersionItems.js +28 -12
- package/dist/domain/javascript/javascriptApplicationVersionKeys.js +9 -1
- package/dist/domain/javascript/javascriptAstFingerprint.js +58 -31
- package/dist/domain/javascript/javascriptAstValues.js +32 -0
- package/dist/domain/javascript/javascriptElectronMemberWrites.js +50 -0
- package/dist/domain/javascript/javascriptModuleSemanticIr.js +15 -0
- package/dist/domain/javascript/javascriptNativeHandoff.js +6 -1
- package/dist/domain/javascript/javascriptRpcEndpoints.js +253 -0
- package/dist/domain/javascript/javascriptRuntimeLoadState.js +1 -3
- package/dist/domain/javascript/javascriptRuntimeReconciliationGraph.js +7 -2
- package/dist/domain/javascript/javascriptRuntimeStaticCandidates.js +8 -11
- package/dist/domain/javascript/javascriptSemanticAnalysis.js +190 -33
- package/dist/domain/javascript/javascriptSemanticCallableResults.js +42 -0
- package/dist/domain/javascript/javascriptSemanticCalls.js +8 -1
- package/dist/domain/javascript/javascriptSemanticDerivedAnalysis.js +15 -4
- package/dist/domain/javascript/javascriptSemanticFileProjection.js +1 -0
- package/dist/domain/javascript/javascriptSemanticFingerprints.js +42 -41
- package/dist/domain/javascript/javascriptSemanticGraph.js +69 -23
- package/dist/domain/javascript/javascriptSemanticGraphSchemas.js +2 -10
- package/dist/domain/javascript/javascriptSemanticIterationSources.js +40 -7
- package/dist/domain/javascript/javascriptSemanticMemberMutations.js +341 -87
- package/dist/domain/javascript/javascriptSemanticMutationValues.js +78 -35
- package/dist/domain/javascript/javascriptSemanticObjectReferences.js +381 -0
- package/dist/domain/javascript/javascriptSemanticObjects.js +7 -1
- package/dist/domain/javascript/javascriptSemanticProjection.js +52 -14
- package/dist/domain/javascript/javascriptSemanticPropertyPaths.js +77 -0
- package/dist/domain/javascript/javascriptSemanticQuery.js +27 -29
- package/dist/domain/javascript/javascriptSemanticQueryIdentity.js +1 -3
- package/dist/domain/javascript/javascriptSemanticReturnedReferences.js +219 -0
- package/dist/domain/javascript/javascriptSemanticReturns.js +13 -23
- package/dist/domain/javascript/javascriptSemanticState.js +22 -2
- package/dist/domain/javascript/javascriptSemanticTraversal.js +19 -1
- package/dist/domain/javascript/javascriptSemanticValues.js +47 -19
- package/dist/domain/javascript/javascriptSourceAnalysis.js +1 -0
- package/dist/domain/javascript/javascriptStaticAnalysis.js +29 -17
- package/dist/domain/javascript/javascriptStaticAnalysisBundler.js +8 -6
- package/dist/domain/javascript/javascriptStaticAnalysisCalls.js +49 -5
- package/dist/domain/javascript/javascriptStaticAnalysisFindings.js +8 -4
- package/dist/domain/javascript/javascriptStaticAnalysisState.js +1 -0
- package/dist/domain/jeb/jebAnalysis.js +114 -0
- package/dist/domain/jsonShape.js +63 -52
- package/dist/domain/jsonValue.js +3 -0
- package/dist/domain/managed/managedApplicationGraph.js +37 -0
- package/dist/domain/managed/managedApplicationGraphCoverage.js +8 -2
- package/dist/domain/managed/managedApplicationGraphNodes.js +32 -22
- package/dist/domain/managed/managedArtifact.js +1 -0
- package/dist/domain/managed/managedInspectionEvidence.js +13 -0
- package/dist/domain/native/nativeAotPe.js +1408 -0
- package/dist/domain/native/nativeInstruction.js +21 -0
- package/dist/domain/native/nativeMetadataRecovery.js +79 -6
- package/dist/domain/native/peResources.js +94 -0
- package/dist/domain/nativeConvention.js +33 -0
- package/dist/domain/process/processCapture.js +91 -1
- package/dist/domain/process/processCaptureExample.js +24 -0
- package/dist/domain/process/processCaptureValidation.js +79 -0
- package/dist/domain/process/processScenario.js +59 -7
- package/dist/domain/propertyListKeys.js +3 -1
- package/dist/domain/referenceSourceGraph.js +25 -16
- package/dist/domain/referenceSourceImportParsing.js +6 -3
- package/dist/domain/referenceSourcePathIdentity.js +22 -0
- package/dist/domain/referenceSourceRequireBindings.js +137 -0
- package/dist/domain/webBundleAnalyzerInspection.js +14 -2
- package/dist/domain/webCaptureDiff.js +102 -4
- package/dist/domain/webScriptExportError.js +10 -4
- package/dist/domain/webScriptExportPlan.js +7 -13
- package/dist/domain/zipPackageFormat.js +4 -1
- package/dist/domain/zodCollectionSteps.js +24 -0
- package/dist/dotnet/ManagedArtifactInspector.js +55 -43
- package/dist/dotnet/ManagedDecodeBudget.js +80 -0
- package/dist/dotnet/ManagedMemberInspector.js +13 -6
- package/dist/dotnet/ManagedMemberInspectorCore.js +2 -2
- package/dist/dotnet/ManagedMemberInstructionDecoder.js +4 -2
- package/dist/dotnet/ManagedMemberRows.js +9 -4
- package/dist/dotnet/ManagedMetadataHeaps.js +15 -5
- package/dist/dotnet/ManagedMetadataInventoryRows.js +20 -11
- package/dist/dotnet/ManagedMetadataLayout.js +10 -4
- package/dist/dotnet/ManagedMethodBodyReader.js +8 -3
- package/dist/dotnet/ManagedNativeBoundaryHelpers.js +3 -2
- package/dist/dotnet/ManagedNativeBoundaryInspector.js +49 -34
- package/dist/dotnet/ManagedPeReader.js +41 -25
- package/dist/dotnet/ManagedReaderFailure.js +2 -1
- package/dist/dotnet/ManagedStaticProvider.js +55 -24
- package/dist/evaluation/AgentEvaluationReport.js +9 -5
- package/dist/evaluation/CodexAgentEval.js +43 -13
- package/dist/evm/EvmoleFailures.js +0 -2
- package/dist/evm/EvmoleInterfaceProvider.js +67 -2
- package/dist/filesystem/OwnedDirectoryHandle.js +29 -0
- package/dist/filesystem/OwnedFileHandle.js +36 -0
- package/dist/filesystem/RegularFile.js +33 -1
- package/dist/filesystem/StableFileHash.js +46 -0
- package/dist/filesystem/readFileHandleChunks.js +26 -0
- package/dist/firmware/FirmwareCommand.js +25 -3
- package/dist/firmware/FirmwareFiles.js +23 -8
- package/dist/firmware/FirmwareProvider.js +156 -32
- package/dist/firmware/FirmwarePublication.js +24 -3
- package/dist/firmware/FirmwareRelease.js +1 -0
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraAnalysisProfile.js +55 -4
- package/dist/ghidra/GhidraAnalysisSeeds.js +211 -0
- package/dist/ghidra/GhidraClient.js +76 -4
- package/dist/ghidra/GhidraDiagnostics.js +11 -8
- package/dist/ghidra/GhidraFunctionValues.js +26 -2
- package/dist/ghidra/GhidraInstallation.js +1 -1
- package/dist/ghidra/GhidraInventoryValues.js +23 -1
- package/dist/ghidra/GhidraLanguageCatalog.js +99 -0
- package/dist/ghidra/GhidraLauncher.js +80 -39
- package/dist/ghidra/GhidraLoadImageAttest.js +49 -2
- package/dist/ghidra/GhidraMipsProfile.js +79 -0
- package/dist/ghidra/GhidraProvider.js +57 -9
- package/dist/ghidra/GhidraProviderCapabilities.js +18 -8
- package/dist/ghidra/GhidraProviderClient.js +282 -21
- package/dist/ghidra/GhidraSessionValues.js +9 -2
- package/dist/hopper/HopperAnalysisProfile.js +2 -0
- package/dist/hopper/HopperClient.js +15 -6
- package/dist/hopper/HopperMachOImage.js +2 -0
- package/dist/hopper/HopperProvider.js +13 -2
- package/dist/ida/IdaOperationRunner.js +8 -2
- package/dist/ida/IdaProvider.js +7 -0
- package/dist/ida/IdaSessionClient.js +3 -1
- package/dist/ida/IdaWorkspace.js +4 -2
- package/dist/javascript/analysis/JavaScriptAnalysisTransfer.js +326 -0
- package/dist/javascript/analysis/JavaScriptAnalysisWorker.js +520 -0
- package/dist/javascript/analysis/JavaScriptAnalysisWorkerProtocol.js +63 -0
- package/dist/javascript/analysis/JavaScriptAnalysisWorkerSchemas.js +521 -0
- package/dist/javascript/analysis/JavaScriptAnalysisWorkerServer.js +116 -0
- package/dist/javascript/recovery/RecoveryFiles.js +18 -7
- package/dist/javascript/recovery/WakaruCommand.js +22 -9
- package/dist/javascript/recovery/WakaruExecution.js +11 -7
- package/dist/javascript/recovery/WakaruProvider.js +139 -16
- package/dist/javascript/recovery/WakaruPublication.js +14 -4
- package/dist/javascript/recovery/WakaruRelease.js +10 -3
- package/dist/javascript/recovery/WakaruReport.js +12 -7
- package/dist/javascript/recovery/WakaruVersion.js +24 -0
- package/dist/javascript/sourceMaps/SourceMapCommand.js +16 -3
- package/dist/javascript/sourceMaps/SourceMapDecoder.js +63 -7
- package/dist/javascript/sourceMaps/SourceMapFormat.js +15 -4
- package/dist/jeb/JebMcpConnection.js +179 -0
- package/dist/jeb/JebMcpEndpoint.js +40 -0
- package/dist/jeb/JebProvider.js +299 -0
- package/dist/mcpDoctor.js +15 -6
- package/dist/native/AppleDispatchCoverage.js +25 -12
- package/dist/native/AppleDispatchMetadata.js +14 -7
- package/dist/native/AppleMachoFixups.js +71 -15
- package/dist/native/AppleMachoSelection.js +23 -3
- package/dist/native/NativeMacOSProvider.js +91 -16
- package/dist/native/NativeMachoInspection.js +11 -7
- package/dist/native/NativeUiHelperRuntime.js +6 -1
- package/dist/native/NativeUiObservation.js +4 -3
- package/dist/native/pe/PeResourceLayout.js +120 -0
- package/dist/native/pe/PeResourceParser.js +286 -0
- package/dist/native/pe/PeResourcesProvider.js +63 -0
- package/dist/process/BoundedFileBytes.js +30 -7
- package/dist/process/DarwinProcessRunTokenReader.js +8 -3
- package/dist/process/OwnedCommand.js +4 -3
- package/dist/process/ProcessOwnership.js +104 -112
- package/dist/process/ProcessOwnershipObservation.js +96 -39
- package/dist/process/ProcessOwnershipProcessTree.js +4 -4
- package/dist/process/ProcessRunTokenObservations.js +48 -0
- package/dist/process/ProviderDiagnosticRedaction.js +17 -0
- package/dist/process/ProviderProcess.js +4 -3
- package/dist/process/capture/FilesystemSnapshot.js +28 -4
- package/dist/process/capture/ProcessCaptureLifecycle.js +350 -59
- package/dist/process/capture/ProcessCaptureProgress.js +62 -0
- package/dist/process/capture/ProcessHarness.js +194 -26
- package/dist/process/capture/ProcessNormalization.js +3 -1
- package/dist/process/capture/ProcessScenarioRuntimeValidation.js +5 -2
- package/dist/process/capture/TerminalRenderer.js +24 -7
- package/dist/reference/ReferenceSourceReader.js +22 -5
- package/dist/reference/ReferenceSourceReaderEntries.js +114 -51
- package/dist/reference/ReferenceSourceReaderErrors.js +12 -0
- package/dist/reference/ReferenceSourceReaderFile.js +50 -10
- package/dist/reference/ReferenceSourceReaderValidate.js +4 -4
- package/dist/server/EvidenceMcpServer.js +36 -1
- package/dist/server/admittedToolOperation.js +9 -0
- package/dist/server/contractToolHandler.js +21 -0
- package/dist/server/createServer.js +97 -25
- package/dist/server/registerAdbTools.js +36 -0
- package/dist/server/registerAnalysisViewTool.js +4 -9
- package/dist/server/registerAndroidTools.js +3 -12
- package/dist/server/registerApktoolTools.js +14 -0
- package/dist/server/registerApplicationTools/compareExportShapes.js +4 -6
- package/dist/server/registerApplicationTools/compareSourceToBundle.js +4 -5
- package/dist/server/registerApplicationTools/compareVersions.js +3 -2
- package/dist/server/registerApplicationTools/coverage.js +3 -2
- package/dist/server/registerApplicationTools/obligationLedger.js +3 -2
- package/dist/server/registerApplicationTools/projectMobileApplicationGraph.js +3 -2
- package/dist/server/registerApplicationTools/traceFeature.js +3 -2
- package/dist/server/registerApplicationTools/traceSemantics.js +4 -5
- package/dist/server/registerArtifactComparisonTool.js +5 -2
- package/dist/server/registerBinaryDiagnosticsTools.js +16 -4
- package/dist/server/registerBrowserScenarioTool.js +10 -7
- package/dist/server/registerBrowserTools.js +12 -9
- package/dist/server/registerBundleComparisonTool.js +16 -2
- package/dist/server/registerCloseLifecycleTool.js +32 -3
- package/dist/server/registerElectronTools.js +28 -10
- package/dist/server/registerEvmTools.js +4 -9
- package/dist/server/registerFirmwareTools.js +3 -11
- package/dist/server/registerFunctionComparisonTool.js +5 -2
- package/dist/server/registerJavaScriptRecoveryTool.js +4 -9
- package/dist/server/registerJavaScriptRuntimeObservationTools.js +9 -6
- package/dist/server/registerJebTools.js +16 -0
- package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +4 -6
- package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +3 -2
- package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +3 -2
- package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +3 -2
- package/dist/server/registerPeResourcesTool.js +9 -0
- package/dist/server/registerProcessComparisonTool.js +5 -2
- package/dist/server/registerRecordedCrashTools.js +4 -9
- package/dist/server/registerSessionRecordTools.js +2 -1
- package/dist/server/registerSessionTools.js +49 -18
- package/dist/server/registerWebModuleTool.js +4 -9
- package/dist/server/registerWebNetworkCaptureTool.js +4 -9
- package/dist/server/registerWebRuntimeTools.js +6 -5
- package/dist/server/registerWebScriptTool.js +6 -3
- package/dist/server/registerWebSourceLocationTool.js +4 -9
- package/dist/server/toolResult.js +21 -2
- package/dist/windows/WindowsPrivateRuntime.js +12 -5
- package/install.sh +7 -4
- package/licenses/nativeaot-parser-MIT.txt +28 -0
- package/native/windows/build/manifest.json +2 -2
- package/native/windows/build/rea-windows-x64.node +0 -0
- package/package.json +33 -5
- package/scripts/rea.mjs +16 -1
- package/skills/reverse-engineer-anything/SKILL.md +52 -51
- package/skills/reverse-engineer-anything/references/connection-and-recovery.md +127 -0
- package/skills/reverse-engineer-anything/references/evidence-workflows.md +8 -0
- package/skills/reverse-engineer-anything/references/javascript-applications.md +92 -13
- package/skills/reverse-engineer-anything/references/native-and-artifacts.md +22 -1
|
@@ -117,8 +117,8 @@ export class ProviderProcessSupervisor {
|
|
|
117
117
|
snapshot() {
|
|
118
118
|
return {
|
|
119
119
|
...(this.#diagnosticTruncated ? { diagnosticTruncated: true } : {}),
|
|
120
|
-
stdout: this.#stdout.snapshot(),
|
|
121
|
-
stderr: this.#stderr.snapshot(),
|
|
120
|
+
stdout: this.#stdout.snapshot(this.#stdoutObservedBytes),
|
|
121
|
+
stderr: this.#stderr.snapshot(this.#stderrObservedBytes),
|
|
122
122
|
exitCode: this.#exitObservation?.code,
|
|
123
123
|
signal: this.#exitObservation?.signal,
|
|
124
124
|
};
|
|
@@ -301,11 +301,12 @@ class ProcessOutputCapture {
|
|
|
301
301
|
this.#bytes += chunk.byteLength;
|
|
302
302
|
this.#chunks.push(Buffer.from(chunk));
|
|
303
303
|
}
|
|
304
|
-
snapshot() {
|
|
304
|
+
snapshot(observedBytes) {
|
|
305
305
|
const text = Buffer.concat(this.#chunks, this.#bytes).toString("utf8");
|
|
306
306
|
return {
|
|
307
307
|
text,
|
|
308
308
|
bytes: this.#bytes,
|
|
309
|
+
observedBytes,
|
|
309
310
|
};
|
|
310
311
|
}
|
|
311
312
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { constants as fsConstants } from "node:fs";
|
|
3
|
-
import { lstat, open,
|
|
3
|
+
import { lstat, open, opendir, readlink } from "node:fs/promises";
|
|
4
4
|
import { dirname, join, relative, resolve } from "node:path";
|
|
5
5
|
const hasSameIdentity = (before, after, expected) => before.dev === after.dev &&
|
|
6
6
|
before.ino === after.ino &&
|
|
@@ -115,6 +115,7 @@ export const snapshotRoots = async (scenario, signal) => {
|
|
|
115
115
|
const entries = [];
|
|
116
116
|
const completeRoots = [];
|
|
117
117
|
let remainingBytes = scenario.limits.file_bytes;
|
|
118
|
+
let pendingNames = 0;
|
|
118
119
|
let truncated = false;
|
|
119
120
|
const enumerationReasons = new Set();
|
|
120
121
|
const hashOmissions = [];
|
|
@@ -204,15 +205,38 @@ export const snapshotRoots = async (scenario, signal) => {
|
|
|
204
205
|
});
|
|
205
206
|
if (type !== "directory")
|
|
206
207
|
return true;
|
|
207
|
-
const children =
|
|
208
|
+
const children = [];
|
|
209
|
+
let complete = true;
|
|
210
|
+
const remainingEntries = scenario.limits.files - entries.length - pendingNames;
|
|
211
|
+
const directory = await opendir(path);
|
|
212
|
+
for await (const child of directory) {
|
|
213
|
+
signal?.throwIfAborted();
|
|
214
|
+
if (children.length >= remainingEntries ||
|
|
215
|
+
depth >= scenario.limits.filesystem_depth) {
|
|
216
|
+
truncated = true;
|
|
217
|
+
complete = false;
|
|
218
|
+
if (children.length >= remainingEntries)
|
|
219
|
+
enumerationReasons.add("files_limit");
|
|
220
|
+
if (depth >= scenario.limits.filesystem_depth)
|
|
221
|
+
enumerationReasons.add("depth_limit");
|
|
222
|
+
break;
|
|
223
|
+
}
|
|
224
|
+
children.push(child.name);
|
|
225
|
+
pendingNames += 1;
|
|
226
|
+
}
|
|
208
227
|
const afterRead = await lstat(path);
|
|
209
228
|
if (!hasSameIdentity(stats, afterRead, "directory")) {
|
|
229
|
+
pendingNames -= children.length;
|
|
210
230
|
truncated = true;
|
|
211
231
|
enumerationReasons.add("identity_changed");
|
|
212
232
|
return false;
|
|
213
233
|
}
|
|
214
|
-
|
|
215
|
-
|
|
234
|
+
children.sort().reverse();
|
|
235
|
+
while (children.length > 0) {
|
|
236
|
+
const child = children.pop();
|
|
237
|
+
if (child === undefined)
|
|
238
|
+
break;
|
|
239
|
+
pendingNames -= 1;
|
|
216
240
|
if (!(await visit(root, rootAlias, join(path, child), depth + 1)))
|
|
217
241
|
complete = false;
|
|
218
242
|
}
|
|
@@ -10,7 +10,7 @@ import { PRODUCT_IDENTITY } from "../../identity.js";
|
|
|
10
10
|
import { snapshotRoots } from "./FilesystemSnapshot.js";
|
|
11
11
|
import { classifyFilesystemEffects } from "./ProcessFilesystemEffects.js";
|
|
12
12
|
import { cleanupOwnedProcessGroup, verifyNoTokenOwnedProcesses, } from "../ProcessOwnership.js";
|
|
13
|
-
import {
|
|
13
|
+
import { observeOwnedProcessGroups, prepareProcessOwnershipInspection, systemProcessOwnershipHost, } from "../ProcessOwnershipObservation.js";
|
|
14
14
|
import { describeProcessCaptureExecutionFailure, normalizeCaptureFailure, ProcessCaptureError, } from "./ProcessCaptureError.js";
|
|
15
15
|
import { assertNotCancelled } from "./ProcessScenarioRuntimeValidation.js";
|
|
16
16
|
import { normalizeProcessElapsedTime, normalizeProcessSamples, normalizeProcessText, } from "./ProcessNormalization.js";
|
|
@@ -35,6 +35,14 @@ export const createProcessCaptureObservationBuffer = (options) => ({
|
|
|
35
35
|
state: "unavailable",
|
|
36
36
|
reason: "Terminal exit was not observed before the run failed.",
|
|
37
37
|
},
|
|
38
|
+
...(options.finalizationEnabled === true
|
|
39
|
+
? {
|
|
40
|
+
finalization: {
|
|
41
|
+
state: "unavailable",
|
|
42
|
+
reason: "Finalization was not observed before capture completion finished.",
|
|
43
|
+
},
|
|
44
|
+
}
|
|
45
|
+
: {}),
|
|
38
46
|
settlement: {
|
|
39
47
|
state: "unavailable",
|
|
40
48
|
reason: "Process settlement was not observed before capture completion finished.",
|
|
@@ -109,6 +117,9 @@ export const buildCaptureResult = (options) => {
|
|
|
109
117
|
: null,
|
|
110
118
|
signal: options.exit.signal ?? null,
|
|
111
119
|
reason: options.exit.reason,
|
|
120
|
+
...(options.exit.finalization === undefined
|
|
121
|
+
? {}
|
|
122
|
+
: { finalization: options.exit.finalization }),
|
|
112
123
|
},
|
|
113
124
|
settlement: options.settlement,
|
|
114
125
|
process_samples: normalizeProcessSamples(options.samples, options.scenario, options.rootPid),
|
|
@@ -349,8 +360,9 @@ export const createRunManifest = async (scenario, startedAt, completedAt, execut
|
|
|
349
360
|
normalization_sha256: digestProcessCommitment(scenario.normalization),
|
|
350
361
|
};
|
|
351
362
|
};
|
|
352
|
-
export const observeSettlement = async (runId, processGroupIds, settleMs, recordEvent = () => undefined, platform = process.platform, signal) => {
|
|
363
|
+
export const observeSettlement = async (runId, processGroupIds, settleMs, recordEvent = () => undefined, platform = process.platform, signal, onLiveProgress) => {
|
|
353
364
|
assertNotCancelled(signal);
|
|
365
|
+
onLiveProgress?.();
|
|
354
366
|
if (platform === "win32") {
|
|
355
367
|
recordEvent("lifecycle", 1);
|
|
356
368
|
return { state: "unverifiable", elapsed_ms: 0 };
|
|
@@ -359,14 +371,15 @@ export const observeSettlement = async (runId, processGroupIds, settleMs, record
|
|
|
359
371
|
let consecutiveEmpty = 0;
|
|
360
372
|
let deadlineReached = false;
|
|
361
373
|
while (!deadlineReached) {
|
|
374
|
+
onLiveProgress?.();
|
|
362
375
|
assertNotCancelled(signal);
|
|
363
|
-
const observations = await
|
|
376
|
+
const observations = await observeOwnedProcessGroups(runId, processGroupIds, undefined, signal);
|
|
364
377
|
assertNotCancelled(signal);
|
|
365
|
-
if (observations.some(({ state }) => state === "unverifiable")) {
|
|
378
|
+
if ([...observations.values()].some(({ state }) => state === "unverifiable")) {
|
|
366
379
|
recordEvent("lifecycle", 1);
|
|
367
380
|
return { state: "unverifiable", elapsed_ms: Date.now() - started };
|
|
368
381
|
}
|
|
369
|
-
if (observations.every(({ state }) => state === "empty")) {
|
|
382
|
+
if ([...observations.values()].every(({ state }) => state === "empty")) {
|
|
370
383
|
consecutiveEmpty += 1;
|
|
371
384
|
if (consecutiveEmpty >= 2) {
|
|
372
385
|
recordEvent("lifecycle", 1);
|
|
@@ -383,12 +396,137 @@ export const observeSettlement = async (runId, processGroupIds, settleMs, record
|
|
|
383
396
|
recordEvent("lifecycle", 1);
|
|
384
397
|
return { state: "alive_at_deadline", elapsed_ms: Date.now() - started };
|
|
385
398
|
};
|
|
386
|
-
|
|
399
|
+
/** Name why an attempt is unverified; a blank message never reaches the capture schema. */
|
|
400
|
+
export const describeUnverifiedCause = (cause, fallback) => {
|
|
401
|
+
const message = cause instanceof Error ? cause.message : String(cause);
|
|
402
|
+
return message.trim() === "" ? fallback : message;
|
|
403
|
+
};
|
|
404
|
+
/**
|
|
405
|
+
* Wait for the captured terminal to exit and report how it ended.
|
|
406
|
+
*
|
|
407
|
+
* A timeout or idle deadline kills the root at once when `finalization_ms` is
|
|
408
|
+
* 0. With a positive interval it sends SIGTERM through `signalTarget`, keeps
|
|
409
|
+
* observing, and sends SIGKILL once if the interval ends first; cancellation
|
|
410
|
+
* during the interval sends that SIGKILL at once. Every attempt is recorded
|
|
411
|
+
* with its delivery result before the delivery is awaited, and each wait is
|
|
412
|
+
* bounded by the cleanup verification grace. If the SIGKILL cannot be
|
|
413
|
+
* delivered the wait ends with `unobserved: true` and no invented exit, so the
|
|
414
|
+
* caller can keep its observations and release the run through cleanup.
|
|
415
|
+
*/
|
|
416
|
+
export const awaitTerminalExit = async ({ terminal, scenario, started, lastOutput, signal, signalTarget, recordFinalization, timers, interactions, dispatchedEventIndexes, recordEvent, onLiveProgress, }) => new Promise((resolveExit) => {
|
|
387
417
|
// The kill caused by a deadline is observed later as an ordinary PTY exit.
|
|
388
418
|
// Keep the initiating lifecycle reason so comparisons distinguish a target
|
|
389
419
|
// exit from harness-owned timeout, idle-timeout, and cancellation cleanup.
|
|
390
420
|
let reason = "exited";
|
|
421
|
+
onLiveProgress?.();
|
|
422
|
+
// A deadline with a finalization interval sends SIGTERM first and keeps
|
|
423
|
+
// observing; SIGKILL follows only when the interval elapses or the request
|
|
424
|
+
// is cancelled. Both go through the identity-checked signaller.
|
|
425
|
+
// The interval is measured on the monotonic clock so a wall-clock change
|
|
426
|
+
// cannot shorten it or produce a negative elapsed time.
|
|
427
|
+
let finalizationStartedAt;
|
|
428
|
+
let escalationSent = false;
|
|
429
|
+
let settled = false;
|
|
430
|
+
let exitObserved = false;
|
|
431
|
+
const finalizationSignals = [];
|
|
432
|
+
const pendingDeliveries = [];
|
|
433
|
+
const snapshot = (elapsed, exitCode = null) => ({
|
|
434
|
+
requested_ms: scenario.finalization_ms,
|
|
435
|
+
elapsed_ms: elapsed,
|
|
436
|
+
exit_code: exitCode,
|
|
437
|
+
signals: finalizationSignals.map((attempt) => ({ ...attempt })),
|
|
438
|
+
});
|
|
439
|
+
const unobservedExit = () => {
|
|
440
|
+
if (settled || exitObserved || finalizationStartedAt === undefined)
|
|
441
|
+
return;
|
|
442
|
+
settled = true;
|
|
443
|
+
for (const timer of timers)
|
|
444
|
+
timer.cancel();
|
|
445
|
+
timers.clear();
|
|
446
|
+
resolveExit({
|
|
447
|
+
unobserved: true,
|
|
448
|
+
reason: reason === "exited" ? "timeout" : reason,
|
|
449
|
+
finalization: snapshot(null),
|
|
450
|
+
});
|
|
451
|
+
};
|
|
452
|
+
// An attempt is recorded before its delivery is awaited, so a hung or
|
|
453
|
+
// failed delivery still leaves the attempt in the observations.
|
|
454
|
+
const attempt = (finalizationSignal) => {
|
|
455
|
+
if (finalizationStartedAt === undefined)
|
|
456
|
+
return;
|
|
457
|
+
const record = {
|
|
458
|
+
signal: finalizationSignal,
|
|
459
|
+
sent_at_ms: Math.round(performance.now() - finalizationStartedAt),
|
|
460
|
+
delivery: "unverified",
|
|
461
|
+
reason: "delivery had not settled when the record was published",
|
|
462
|
+
};
|
|
463
|
+
finalizationSignals.push(record);
|
|
464
|
+
recordFinalization(snapshot(null));
|
|
465
|
+
const deliveryBound = new AbortController();
|
|
466
|
+
// The wait is bounded by the cleanup verification grace: a delivery that
|
|
467
|
+
// never settles is recorded as unverified instead of holding the capture.
|
|
468
|
+
pendingDeliveries.push(Promise.race([
|
|
469
|
+
signalTarget(finalizationSignal),
|
|
470
|
+
delay(PROCESS_CLEANUP_VERIFICATION_GRACE_MS, {
|
|
471
|
+
delivery: "unverified",
|
|
472
|
+
reason: `delivery did not settle within ${String(PROCESS_CLEANUP_VERIFICATION_GRACE_MS)} ms`,
|
|
473
|
+
}, {
|
|
474
|
+
ref: false,
|
|
475
|
+
signal: deliveryBound.signal,
|
|
476
|
+
}).catch(() => ({
|
|
477
|
+
delivery: "unverified",
|
|
478
|
+
reason: "delivery wait was interrupted",
|
|
479
|
+
})),
|
|
480
|
+
])
|
|
481
|
+
.finally(() => {
|
|
482
|
+
deliveryBound.abort();
|
|
483
|
+
})
|
|
484
|
+
.then(({ delivery, reason: deliveryReason }) => {
|
|
485
|
+
record.delivery = delivery;
|
|
486
|
+
if (deliveryReason !== undefined)
|
|
487
|
+
record.reason = deliveryReason;
|
|
488
|
+
else
|
|
489
|
+
delete record.reason;
|
|
490
|
+
}, (cause) => {
|
|
491
|
+
record.delivery = "unverified";
|
|
492
|
+
record.reason = describeUnverifiedCause(cause, "signal delivery failed without a message");
|
|
493
|
+
})
|
|
494
|
+
.then(() => {
|
|
495
|
+
recordFinalization(snapshot(null));
|
|
496
|
+
// A kill that cannot reach the root leaves no exit to wait for.
|
|
497
|
+
if (finalizationSignal === "SIGKILL" &&
|
|
498
|
+
record.delivery !== "signaled" &&
|
|
499
|
+
record.delivery !== "gone")
|
|
500
|
+
unobservedExit();
|
|
501
|
+
}));
|
|
502
|
+
};
|
|
503
|
+
const forceKill = () => {
|
|
504
|
+
if (finalizationStartedAt !== undefined) {
|
|
505
|
+
if (escalationSent)
|
|
506
|
+
return;
|
|
507
|
+
escalationSent = true;
|
|
508
|
+
attempt("SIGKILL");
|
|
509
|
+
return;
|
|
510
|
+
}
|
|
511
|
+
terminal.kill("SIGKILL");
|
|
512
|
+
};
|
|
513
|
+
const terminateAtDeadline = () => {
|
|
514
|
+
if (scenario.finalization_ms === 0) {
|
|
515
|
+
terminal.kill("SIGKILL");
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
finalizationStartedAt = performance.now();
|
|
519
|
+
attempt("SIGTERM");
|
|
520
|
+
};
|
|
391
521
|
terminal.onExit((exit) => {
|
|
522
|
+
if (settled)
|
|
523
|
+
return;
|
|
524
|
+
exitObserved = true;
|
|
525
|
+
// Measures when the exit was observed, not when the operating system
|
|
526
|
+
// ended the process; the PTY layer can deliver the notification late.
|
|
527
|
+
const finalizationElapsedMs = finalizationStartedAt === undefined
|
|
528
|
+
? undefined
|
|
529
|
+
: Math.round(performance.now() - finalizationStartedAt);
|
|
392
530
|
recordEvent("lifecycle", 0);
|
|
393
531
|
for (const [eventIndex, event] of scenario.events.entries()) {
|
|
394
532
|
if (dispatchedEventIndexes.has(eventIndex))
|
|
@@ -412,20 +550,59 @@ export const awaitTerminalExit = async ({ terminal, scenario, started, lastOutpu
|
|
|
412
550
|
timer.cancel();
|
|
413
551
|
}
|
|
414
552
|
timers.clear();
|
|
415
|
-
|
|
553
|
+
const finish = () => {
|
|
554
|
+
if (settled)
|
|
555
|
+
return;
|
|
556
|
+
settled = true;
|
|
557
|
+
resolveExit({
|
|
558
|
+
...exit,
|
|
559
|
+
reason,
|
|
560
|
+
...(finalizationElapsedMs === undefined
|
|
561
|
+
? {}
|
|
562
|
+
: {
|
|
563
|
+
finalization: snapshot(finalizationElapsedMs, exit.exitCode >= 0 && (exit.signal ?? 0) === 0
|
|
564
|
+
? exit.exitCode
|
|
565
|
+
: null),
|
|
566
|
+
}),
|
|
567
|
+
});
|
|
568
|
+
};
|
|
569
|
+
if (pendingDeliveries.length === 0) {
|
|
570
|
+
finish();
|
|
571
|
+
return;
|
|
572
|
+
}
|
|
573
|
+
// A delivery that never settles must not hold back an observed exit;
|
|
574
|
+
// its attempt stays recorded as unverified.
|
|
575
|
+
const grace = new AbortController();
|
|
576
|
+
void Promise.race([
|
|
577
|
+
Promise.allSettled(pendingDeliveries),
|
|
578
|
+
delay(PROCESS_CLEANUP_VERIFICATION_GRACE_MS, undefined, {
|
|
579
|
+
ref: false,
|
|
580
|
+
signal: grace.signal,
|
|
581
|
+
}).catch(() => undefined),
|
|
582
|
+
])
|
|
583
|
+
.finally(() => {
|
|
584
|
+
grace.abort();
|
|
585
|
+
})
|
|
586
|
+
.then(finish);
|
|
416
587
|
});
|
|
417
588
|
const timeout = scheduleProcessInterval(() => {
|
|
589
|
+
onLiveProgress?.();
|
|
418
590
|
if (signal?.aborted === true) {
|
|
419
591
|
reason = "cancelled";
|
|
420
|
-
|
|
592
|
+
forceKill();
|
|
593
|
+
}
|
|
594
|
+
else if (finalizationStartedAt !== undefined) {
|
|
595
|
+
if (performance.now() - finalizationStartedAt >=
|
|
596
|
+
scenario.finalization_ms)
|
|
597
|
+
forceKill();
|
|
421
598
|
}
|
|
422
599
|
else if (Date.now() - started >= scenario.timeout_ms) {
|
|
423
600
|
reason = "timeout";
|
|
424
|
-
|
|
601
|
+
terminateAtDeadline();
|
|
425
602
|
}
|
|
426
603
|
else if (Date.now() - lastOutput() >= scenario.idle_timeout_ms) {
|
|
427
604
|
reason = "idle_timeout";
|
|
428
|
-
|
|
605
|
+
terminateAtDeadline();
|
|
429
606
|
}
|
|
430
607
|
}, 20);
|
|
431
608
|
timers.add(timeout);
|
|
@@ -494,60 +671,170 @@ const releaseCapturedProcessGroup = async (ownership, host) => {
|
|
|
494
671
|
],
|
|
495
672
|
};
|
|
496
673
|
};
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
674
|
+
/** One capture's exact resource owner, with completion tracked per resource. */
|
|
675
|
+
class ProcessCaptureResourceOwner {
|
|
676
|
+
options;
|
|
677
|
+
#host;
|
|
678
|
+
#terminalRenderer;
|
|
679
|
+
#ownedProcessGroup;
|
|
680
|
+
#temporaryRoot;
|
|
681
|
+
constructor(options) {
|
|
682
|
+
this.options = options;
|
|
683
|
+
this.#host = options.host ?? processCaptureCleanupHost;
|
|
684
|
+
if (options.renderer === undefined)
|
|
685
|
+
this.#terminalRenderer = { state: "not_required", reason: null };
|
|
686
|
+
if (options.terminal === undefined)
|
|
687
|
+
this.#ownedProcessGroup = { state: "not_required", reason: null };
|
|
507
688
|
}
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
689
|
+
async close() {
|
|
690
|
+
for (const timer of this.options.timers)
|
|
691
|
+
timer.cancel();
|
|
692
|
+
await this.#releaseRenderer();
|
|
693
|
+
await this.#releaseOwnedProcessGroup();
|
|
694
|
+
await this.#releaseTemporaryRoot();
|
|
695
|
+
return {
|
|
696
|
+
owned_process_group: this.#ownedProcessGroup ?? {
|
|
697
|
+
state: "unverified",
|
|
698
|
+
reason: "owned process cleanup was not attempted",
|
|
699
|
+
},
|
|
700
|
+
terminal_renderer: this.#terminalRenderer ?? {
|
|
701
|
+
state: "unverified",
|
|
702
|
+
reason: "terminal renderer cleanup was not attempted",
|
|
703
|
+
},
|
|
704
|
+
temporary_root: this.#temporaryRoot ?? {
|
|
705
|
+
state: "unverified",
|
|
706
|
+
reason: "temporary root cleanup was not attempted",
|
|
707
|
+
},
|
|
514
708
|
};
|
|
515
709
|
}
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
710
|
+
async #releaseRenderer() {
|
|
711
|
+
if (this.options.renderer === undefined ||
|
|
712
|
+
this.#terminalRenderer?.state === "cleaned" ||
|
|
713
|
+
this.#terminalRenderer?.state === "not_required")
|
|
714
|
+
return;
|
|
715
|
+
try {
|
|
716
|
+
await this.options.renderer.dispose();
|
|
717
|
+
this.#terminalRenderer = { state: "cleaned", reason: null };
|
|
718
|
+
}
|
|
719
|
+
catch (cause) {
|
|
720
|
+
this.#terminalRenderer = {
|
|
721
|
+
state: "failed",
|
|
722
|
+
reason: cleanupFailureMessage(cause, "renderer dispose failed"),
|
|
723
|
+
};
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
async #releaseOwnedProcessGroup() {
|
|
727
|
+
if (this.options.terminal === undefined ||
|
|
728
|
+
this.#ownedProcessGroup?.state === "cleaned" ||
|
|
729
|
+
this.#ownedProcessGroup?.state === "not_required")
|
|
730
|
+
return;
|
|
731
|
+
this.#ownedProcessGroup = await releaseCapturedProcessGroup({
|
|
732
|
+
runId: this.options.runId,
|
|
733
|
+
leaderPid: this.options.terminal.pid,
|
|
734
|
+
processGroupId: this.options.terminal.pid,
|
|
522
735
|
sweepTokenOwnedProcesses: true,
|
|
523
|
-
...(options.sampledProcessGroupIds === undefined
|
|
736
|
+
...(this.options.sampledProcessGroupIds === undefined
|
|
524
737
|
? {}
|
|
525
|
-
: { sampledProcessGroupIds: options.sampledProcessGroupIds }),
|
|
526
|
-
...(options.captureBaseline === undefined
|
|
738
|
+
: { sampledProcessGroupIds: this.options.sampledProcessGroupIds }),
|
|
739
|
+
...(this.options.captureBaseline === undefined
|
|
527
740
|
? {}
|
|
528
|
-
: { captureBaseline: options.captureBaseline }),
|
|
529
|
-
}, host);
|
|
530
|
-
let temporaryRoot = {
|
|
531
|
-
state: "cleaned",
|
|
532
|
-
reason: null,
|
|
533
|
-
};
|
|
534
|
-
try {
|
|
535
|
-
await host.removeTemporaryRoot(options.temporaryRoot);
|
|
741
|
+
: { captureBaseline: this.options.captureBaseline }),
|
|
742
|
+
}, this.#host);
|
|
536
743
|
}
|
|
537
|
-
|
|
538
|
-
temporaryRoot
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
744
|
+
async #releaseTemporaryRoot() {
|
|
745
|
+
if (this.#temporaryRoot?.state === "cleaned")
|
|
746
|
+
return;
|
|
747
|
+
const owned = this.#ownedProcessGroup;
|
|
748
|
+
if (owned?.state === "failed" || owned?.state === "unverified") {
|
|
749
|
+
this.#temporaryRoot = {
|
|
750
|
+
state: "unverified",
|
|
751
|
+
reason: `temporary root retained because owned process cleanup is ${owned.state}: ${owned.reason ?? "ownership could not be verified"}`,
|
|
752
|
+
};
|
|
753
|
+
return;
|
|
754
|
+
}
|
|
755
|
+
try {
|
|
756
|
+
await this.#host.removeTemporaryRoot(this.options.temporaryRoot);
|
|
757
|
+
this.#temporaryRoot = { state: "cleaned", reason: null };
|
|
758
|
+
}
|
|
759
|
+
catch (cause) {
|
|
760
|
+
this.#temporaryRoot = {
|
|
761
|
+
state: "failed",
|
|
762
|
+
reason: cleanupFailureMessage(cause, "temporary root removal failed"),
|
|
763
|
+
};
|
|
764
|
+
}
|
|
544
765
|
}
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
766
|
+
}
|
|
767
|
+
const cleanupFailureMessage = (cause, fallback) => cause instanceof Error ? cause.message || cause.name || fallback : fallback;
|
|
768
|
+
/** Release one capture's resources, retaining the exact owner for scoped retry. */
|
|
769
|
+
export const releaseProcessResources = async (options) => new ProcessCaptureResourceOwner(options).close();
|
|
770
|
+
/** Run-local owner collection for resources whose first cleanup did not finish. */
|
|
771
|
+
export class ProcessCaptureResourceScope {
|
|
772
|
+
#pending = new Set();
|
|
773
|
+
#active = new Set();
|
|
774
|
+
#draining;
|
|
775
|
+
#closed = false;
|
|
776
|
+
/** Admit one capture before it starts acquiring resources. */
|
|
777
|
+
async run(operation) {
|
|
778
|
+
while (true) {
|
|
779
|
+
while (this.#draining !== undefined)
|
|
780
|
+
await this.#draining;
|
|
781
|
+
if (this.#closed)
|
|
782
|
+
throw new ProcessCaptureError("process capture lifecycle is closing; start a new server session before capturing again");
|
|
783
|
+
if (this.#pending.size === 0)
|
|
784
|
+
break;
|
|
785
|
+
await this.retryCleanup();
|
|
786
|
+
}
|
|
787
|
+
const running = Promise.resolve().then(operation);
|
|
788
|
+
this.#active.add(running);
|
|
789
|
+
try {
|
|
790
|
+
return await running;
|
|
791
|
+
}
|
|
792
|
+
finally {
|
|
793
|
+
this.#active.delete(running);
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
async release(options) {
|
|
797
|
+
const owner = new ProcessCaptureResourceOwner(options);
|
|
798
|
+
const report = await owner.close();
|
|
799
|
+
if (cleanupReportFailure(report) !== undefined) {
|
|
800
|
+
this.#pending.add(owner);
|
|
801
|
+
}
|
|
802
|
+
return report;
|
|
803
|
+
}
|
|
804
|
+
/** Drain active captures, then retry their retained resources without closing admission. */
|
|
805
|
+
retryCleanup() {
|
|
806
|
+
if (this.#draining !== undefined)
|
|
807
|
+
return this.#draining;
|
|
808
|
+
this.#draining = this.#drainAndRetry().finally(() => {
|
|
809
|
+
this.#draining = undefined;
|
|
810
|
+
});
|
|
811
|
+
return this.#draining;
|
|
812
|
+
}
|
|
813
|
+
/** Stop admitting new captures, drain active runs, and retry all retained owners. */
|
|
814
|
+
close() {
|
|
815
|
+
this.#closed = true;
|
|
816
|
+
return this.retryCleanup();
|
|
817
|
+
}
|
|
818
|
+
async #drainAndRetry() {
|
|
819
|
+
while (this.#active.size > 0)
|
|
820
|
+
await Promise.allSettled(this.#active);
|
|
821
|
+
const failures = [];
|
|
822
|
+
for (const owner of this.#pending) {
|
|
823
|
+
try {
|
|
824
|
+
const report = await owner.close();
|
|
825
|
+
if (cleanupReportFailure(report) === undefined)
|
|
826
|
+
this.#pending.delete(owner);
|
|
827
|
+
else
|
|
828
|
+
failures.push(cleanupReportFailure(report) ?? "cleanup incomplete");
|
|
829
|
+
}
|
|
830
|
+
catch (cause) {
|
|
831
|
+
failures.push(cause instanceof Error ? cause.message || cause.name : String(cause));
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
if (failures.length > 0)
|
|
835
|
+
throw new AggregateError(failures, `Process capture cleanup remains incomplete: ${failures.join("; ")}`);
|
|
836
|
+
}
|
|
837
|
+
}
|
|
551
838
|
export const cleanupReportFailure = (report) => {
|
|
552
839
|
const failures = Object.entries(report).filter(([, outcome]) => outcome.state === "failed" || outcome.state === "unverified");
|
|
553
840
|
return failures.length === 0
|
|
@@ -715,7 +1002,7 @@ export const resolveProcessResult = (capture, executionFailure, cleanup, observa
|
|
|
715
1002
|
throw new ProcessCaptureError(`process capture validation failed${cause instanceof Error ? `: ${cause.message}` : ""}`, { cause });
|
|
716
1003
|
}
|
|
717
1004
|
};
|
|
718
|
-
export const prepareProcessCapture = async (scenario, signal, captureSnapshot = snapshotRoots, host = systemProcessPreparationHost) => {
|
|
1005
|
+
export const prepareProcessCapture = async (scenario, signal, captureSnapshot = snapshotRoots, host = systemProcessPreparationHost, resourceScope) => {
|
|
719
1006
|
assertNotCancelled(signal);
|
|
720
1007
|
await host.prepareOwnershipInspector?.(signal);
|
|
721
1008
|
assertNotCancelled(signal);
|
|
@@ -729,20 +1016,24 @@ export const prepareProcessCapture = async (scenario, signal, captureSnapshot =
|
|
|
729
1016
|
return { temporaryRoot, runId, ownershipBaseline, before };
|
|
730
1017
|
}
|
|
731
1018
|
catch (cause) {
|
|
732
|
-
const
|
|
1019
|
+
const cleanupOptions = {
|
|
733
1020
|
timers: new Set(),
|
|
734
1021
|
terminal: undefined,
|
|
735
1022
|
renderer: undefined,
|
|
736
1023
|
runId,
|
|
737
1024
|
temporaryRoot,
|
|
738
1025
|
host: { ...processCaptureCleanupHost, removeTemporaryRoot: host.cleanup },
|
|
739
|
-
}
|
|
1026
|
+
};
|
|
1027
|
+
const cleanup = resourceScope === undefined
|
|
1028
|
+
? await releaseProcessResources(cleanupOptions)
|
|
1029
|
+
: await resourceScope.release(cleanupOptions);
|
|
740
1030
|
resolveProcessResult(undefined, normalizeCaptureFailure(cause, signal), cleanup, createProcessCaptureObservationBuffer({
|
|
741
1031
|
frames: [],
|
|
742
1032
|
interactions: [],
|
|
743
1033
|
samples: [],
|
|
744
1034
|
eventJournal: [],
|
|
745
1035
|
before,
|
|
1036
|
+
finalizationEnabled: scenario.finalization_ms > 0,
|
|
746
1037
|
}), { scenario });
|
|
747
1038
|
throw cause;
|
|
748
1039
|
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
const formatProgressMessage = (elapsedMs, counts, disposition, cleanup) => {
|
|
2
|
+
const status = `elapsed_ms=${String(elapsedMs)} frames=${String(counts.frames)} samples=${String(counts.samples)} interactions=${String(counts.interactions)}`;
|
|
3
|
+
const dispositionText = disposition === undefined ? "" : ` disposition=${disposition}`;
|
|
4
|
+
const cleanupText = cleanup === undefined
|
|
5
|
+
? ""
|
|
6
|
+
: ` owned_process_group=${cleanup.owned_process_group.state} terminal_renderer=${cleanup.terminal_renderer.state} temporary_root=${cleanup.temporary_root.state}`;
|
|
7
|
+
return `${status}${dispositionText}${cleanupText}`;
|
|
8
|
+
};
|
|
9
|
+
/** Serialize observed capture status through one rate-limited reporter. */
|
|
10
|
+
export const createProcessCaptureProgressTracker = (progress, now = Date.now) => {
|
|
11
|
+
const started = now();
|
|
12
|
+
let completed = 0;
|
|
13
|
+
let live = true;
|
|
14
|
+
let next;
|
|
15
|
+
let pending;
|
|
16
|
+
const flush = async () => {
|
|
17
|
+
try {
|
|
18
|
+
while (next !== undefined) {
|
|
19
|
+
const update = next;
|
|
20
|
+
next = undefined;
|
|
21
|
+
try {
|
|
22
|
+
await progress?.report(update);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
// Progress delivery is observational; capture and cleanup still finish.
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
finally {
|
|
31
|
+
pending = undefined;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
return {
|
|
35
|
+
closeLive() {
|
|
36
|
+
live = false;
|
|
37
|
+
if (next?.terminal !== true)
|
|
38
|
+
next = undefined;
|
|
39
|
+
},
|
|
40
|
+
report(update) {
|
|
41
|
+
if (progress === undefined)
|
|
42
|
+
return Promise.resolve();
|
|
43
|
+
if (update.terminal !== true && !live)
|
|
44
|
+
return Promise.resolve();
|
|
45
|
+
const units = update.counts.frames +
|
|
46
|
+
update.counts.samples +
|
|
47
|
+
update.counts.interactions;
|
|
48
|
+
if (units > completed)
|
|
49
|
+
completed = units;
|
|
50
|
+
// A slow observer needs the latest observation, not a queue of old states.
|
|
51
|
+
next = {
|
|
52
|
+
phase: update.phase,
|
|
53
|
+
completed,
|
|
54
|
+
total: null,
|
|
55
|
+
message: formatProgressMessage(Math.max(0, now() - started), update.counts, update.disposition, update.cleanup),
|
|
56
|
+
...(update.terminal === true ? { terminal: true } : {}),
|
|
57
|
+
};
|
|
58
|
+
pending ??= Promise.resolve().then(flush);
|
|
59
|
+
return pending;
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
};
|