rea-agents 3.2.0 → 4.0.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 +183 -332
- package/bridge/ghidra/ReaGhidraBridge.java +561 -74
- package/bridge/hopper_bridge.py +70 -27
- package/bridge/native/ReaNativeUI.swift +157 -0
- package/dist/application/AnalysisContextQueries.js +19 -5
- package/dist/application/AnalysisSnapshotCache.js +30 -11
- package/dist/application/AppleAssetCatalogAnalysis.js +171 -0
- package/dist/application/ArtifactExtractionDestination.js +0 -12
- package/dist/application/ArtifactGraphConstruction.js +44 -11
- package/dist/application/ArtifactInventory/classify.js +7 -15
- package/dist/application/ArtifactInventory/hash.js +4 -2
- package/dist/application/ArtifactInventory/policy.js +2 -17
- package/dist/application/ArtifactInventory/reader.js +3 -3
- package/dist/application/ArtifactInventory/scanCanonical.js +2 -2
- package/dist/application/ArtifactInventory/scanReader.js +12 -4
- package/dist/application/ArtifactInventory/types.js +0 -3
- package/dist/application/BinarySession.js +28 -43
- package/dist/application/BinarySessionExecution.js +37 -1
- package/dist/application/BinaryTargetResolver.js +50 -4
- package/dist/application/BrowserEvidence.js +36 -7
- package/dist/application/BrowserObservationService.js +17 -44
- package/dist/application/BrowserScenarioCaptureService.js +2 -35
- package/dist/application/BrowserScenarioEvidence.js +13 -9
- package/dist/application/CapabilityClientRequirements.js +2 -11
- package/dist/application/CapabilityInventory.js +21 -35
- package/dist/application/ClientConfigurationDocument.js +84 -7
- package/dist/application/ClientRegistrationIdentity.js +32 -0
- package/dist/application/ClientRegistrationStatus.js +59 -6
- package/dist/application/DirectAnalysis.js +37 -58
- package/dist/application/DirectAnalysisStatus.js +4 -4
- package/dist/application/Doctor.js +89 -80
- package/dist/application/DoctorDiagnostics.js +2 -26
- package/dist/application/DoctorScope.js +8 -14
- package/dist/application/ElectronActiveEvidence.js +10 -27
- package/dist/application/ElectronActiveObservationService.js +9 -36
- package/dist/application/ElectronBoundaryAnalysis.js +2 -0
- package/dist/application/ElectronBoundaryGraphNative.js +1 -1
- package/dist/application/ElectronEvidence.js +8 -3
- package/dist/application/ElectronObservationService.js +9 -25
- package/dist/application/EnhancedLiteralTracing.js +4 -8
- package/dist/application/EnhancedTools.js +15 -35
- package/dist/application/FilesystemSnapshot.js +7 -8
- package/dist/application/JavaScriptApplicationEvidenceGraph.js +2 -1
- package/dist/application/JavaScriptApplicationWorkflowService.js +31 -7
- package/dist/application/JavaScriptArtifactAnalysis.js +6 -4
- package/dist/application/JavaScriptArtifactFiles.js +5 -0
- package/dist/application/JavaScriptArtifactPathResolution.js +179 -47
- package/dist/application/JavaScriptRuntimeObservationEvidence.js +6 -3
- package/dist/application/JavaScriptRuntimeObservationService.js +9 -25
- package/dist/application/JavaScriptRuntimeReconciliationService.js +45 -4
- package/dist/application/JavaScriptSemanticGraphAsyncProjection.js +11 -0
- package/dist/application/JavaScriptSemanticGraphChildProcessProjection.js +11 -0
- package/dist/application/JavaScriptSemanticGraphDataProjection.js +11 -0
- package/dist/application/JavaScriptSemanticGraphFlowProjection.js +14 -5
- package/dist/application/JsonFiles.js +1 -1
- package/dist/application/LazyAnalysisProvider.js +27 -6
- package/dist/application/ManagedMemberComparisonService.js +19 -6
- package/dist/application/NativeApiInspection.js +2 -0
- package/dist/application/NativeCallRoutes.js +72 -0
- package/dist/application/NativeDispatchMetadataInspection.js +33 -0
- package/dist/application/NativeUiActionTrace.js +73 -49
- package/dist/application/NativeValueTrace.js +320 -0
- package/dist/application/ProcessCaptureCapability.js +32 -5
- package/dist/application/ProcessCaptureEnvironment.js +9 -26
- package/dist/application/ProcessCaptureError.js +1 -5
- package/dist/application/ProcessCaptureJournal.js +3 -40
- package/dist/application/ProcessCaptureLifecycle.js +102 -111
- package/dist/application/ProcessCli.js +18 -25
- package/dist/application/ProcessEvidence.js +5 -7
- package/dist/application/ProcessFilesystemEffects.js +36 -0
- package/dist/application/ProcessHarness.js +41 -120
- package/dist/application/ProcessNormalization.js +2 -17
- package/dist/application/ProcessScenarioRuntimeValidation.js +76 -0
- package/dist/application/ReferenceSourceImport.js +3 -4
- package/dist/application/Setup.js +236 -84
- package/dist/application/SetupClientConfiguration.js +14 -9
- package/dist/application/SetupPlan.js +138 -86
- package/dist/application/SetupSkill.js +0 -1
- package/dist/application/SupportedClients.js +102 -21
- package/dist/application/Uninstall.js +31 -20
- package/dist/application/Update.js +93 -0
- package/dist/application/UpdateMaintenance.js +108 -0
- package/dist/application/UpdateRuntime.js +126 -0
- package/dist/application/runtime.js +13 -2
- package/dist/artifacts/ArtifactPaths.js +6 -8
- package/dist/artifacts/ArtifactProvider.js +94 -41
- package/dist/artifacts/AsarArtifactReader.js +19 -4
- package/dist/artifacts/KeyedArchiveReader.js +110 -0
- package/dist/artifacts/MachOSliceArtifactReader.js +53 -5
- package/dist/artifacts/ZipArtifactReader.js +18 -1
- package/dist/browser/BrowserScenarioSecrets.js +28 -1
- package/dist/browser/CdpBrowserProvider.js +36 -15
- package/dist/browser/CdpCaptureDocuments.js +22 -8
- package/dist/browser/CdpCaptureEventHandlers.js +14 -5
- package/dist/browser/CdpCaptureEventHelpers.js +13 -0
- package/dist/browser/CdpCaptureEvents.js +10 -1
- package/dist/browser/CdpElectronInspection.js +5 -10
- package/dist/browser/CdpElectronProvider.js +1 -5
- package/dist/browser/CdpElectronScripts.js +1 -1
- package/dist/browser/CdpEndpoint.js +3 -2
- package/dist/browser/CdpObservationSession.js +14 -10
- package/dist/browser/CdpPageCapture.js +1 -1
- package/dist/browser/CdpPageCaptureScripts.js +1 -1
- package/dist/browser/CdpSafeMetadata.js +5 -4
- package/dist/browser/CdpScreenshot.js +16 -5
- package/dist/browser/CdpTargetSession.js +25 -4
- package/dist/browser/CdpWebMcpDiscovery.js +93 -20
- package/dist/browser/JavaScriptRuntimeScope.js +28 -2
- package/dist/browser/PlaywrightBrowserScenarioProvider.js +9 -8
- package/dist/browser/PlaywrightElectronActiveActions.js +3 -10
- package/dist/browser/PlaywrightElectronActiveProvider.js +5 -5
- package/dist/browser/PlaywrightScenarioActions.js +1 -1
- package/dist/browser/PlaywrightScenarioArtifacts.js +13 -25
- package/dist/browser/PlaywrightScenarioBrowser.js +28 -25
- package/dist/browser/PlaywrightScenarioEvents.js +82 -93
- package/dist/browser/PlaywrightScenarioSession.js +27 -123
- package/dist/browser/PngVisualDiff.js +22 -3
- package/dist/browser/V8InspectorCaptureProjection.js +7 -1
- package/dist/browser/V8InspectorProvider.js +60 -7
- package/dist/browser/WebSourceMapFetcher.js +99 -53
- package/dist/cli/artifactCommands.js +56 -12
- package/dist/cli/coreAnalysisCommands.js +110 -0
- package/dist/cli/managedCommands.js +1 -31
- package/dist/cli/setupCommands.js +16 -14
- package/dist/cli/utilityCommands.js +61 -4
- package/dist/cli.js +5 -7
- package/dist/cliApplicationCommands.js +0 -83
- package/dist/cliBrowserAdvancedCommands.js +7 -11
- package/dist/cliBrowserCommands.js +15 -23
- package/dist/cliBrowserContext.js +3 -24
- package/dist/cliBrowserScenarioCommands.js +2 -10
- package/dist/cliCommandNames.js +82 -7
- package/dist/cliElectronCommands.js +10 -36
- package/dist/cliJavaScriptRuntimeCommands.js +6 -30
- package/dist/cliJsonInput.js +4 -2
- package/dist/cliLogging.js +16 -7
- package/dist/cliObservationOptions.js +1 -1
- package/dist/cliOutput.js +2 -4
- package/dist/cliProcessCommands.js +6 -33
- package/dist/cliSetup.js +90 -160
- package/dist/config/environment.js +2 -78
- package/dist/config/parseConfig.js +18 -109
- package/dist/config/parsers.js +0 -23
- package/dist/contracts/applicationToolContracts.js +1 -118
- package/dist/contracts/artifactToolContracts.js +11 -19
- package/dist/contracts/browserScenarioToolContracts.js +1 -5
- package/dist/contracts/browserToolContracts.js +9 -16
- package/dist/contracts/electronToolContracts.js +5 -6
- package/dist/contracts/enhancedInputs.js +3 -2
- package/dist/contracts/errorSchemas.js +16 -40
- package/dist/contracts/functionWorkflowToolContracts.js +2 -2
- package/dist/contracts/javascriptApplicationWorkflowExamples.js +2 -2
- package/dist/contracts/javascriptRuntimeObservationToolContracts.js +4 -4
- package/dist/contracts/javascriptRuntimeReconciliationExample.js +1 -1
- package/dist/contracts/managedToolContracts.js +7 -4
- package/dist/contracts/managedWorkflowExamples.js +0 -22
- package/dist/contracts/managedWorkflowToolContracts.js +16 -31
- package/dist/contracts/nativeToolContracts.js +9 -0
- package/dist/contracts/promptContracts.js +6 -6
- package/dist/contracts/sessionToolSchemas.js +3 -3
- package/dist/contracts/toolContractExamples.js +4 -3
- package/dist/contracts/toolContracts.js +18 -7
- package/dist/contracts/toolEffects.js +34 -21
- package/dist/contracts/toolOutputSchemaGroups.js +18 -5
- package/dist/contracts/toolOutputSchemaPrimitives.js +9 -6
- package/dist/contracts/toolSchemaMetadata.js +5 -8
- package/dist/doctorRuntime.js +0 -41
- package/dist/domain/analysisErrorPresentation.js +4 -28
- package/dist/domain/analysisErrorProjection.js +33 -50
- package/dist/domain/analysisProfile.js +1 -1
- package/dist/domain/analysisSnapshot.js +77 -3
- package/dist/domain/androidApplication.js +5 -4
- package/dist/domain/appleApplication.js +5 -4
- package/dist/domain/appleAssetCatalog.js +127 -0
- package/dist/domain/artifactComparison.js +7 -11
- package/dist/domain/artifactGraph.js +8 -6
- package/dist/domain/artifactInspection.js +13 -12
- package/dist/domain/binaryTarget.js +23 -9
- package/dist/domain/browserObservation.js +43 -24
- package/dist/domain/browserObservationSchemas.js +2 -1
- package/dist/domain/browserScenario.js +7 -107
- package/dist/domain/browserScenarioCapture.js +0 -1
- package/dist/domain/browserScenarioCaptureValues.js +5 -4
- package/dist/domain/browserScenarioDiff.js +1 -3
- package/dist/domain/browserScenarioValues.js +16 -107
- package/dist/domain/bundleComparison.js +18 -17
- package/dist/domain/callPathSchemas.js +17 -7
- package/dist/domain/changedBehavior.js +2 -3
- package/dist/domain/comparisonSemantics.js +19 -0
- package/dist/domain/completionLedgerGeneration.js +3 -2
- package/dist/domain/conformancePackage.js +2 -1
- package/dist/domain/conformanceTrustGate.js +3 -5
- package/dist/domain/customProtocolCapture.js +2 -2
- package/dist/domain/digests.js +30 -0
- package/dist/domain/dosMz.js +83 -0
- package/dist/domain/electronActiveObservation.js +7 -5
- package/dist/domain/electronObservation.js +3 -2
- package/dist/domain/electronStaticAnalysisNative.js +15 -6
- package/dist/domain/emptyArraySchema.js +3 -0
- package/dist/domain/errors.js +10 -28
- package/dist/domain/evidence.js +5 -3
- package/dist/domain/evidenceCompletionLedger.js +3 -2
- package/dist/domain/functionComparisonNormalization.js +24 -18
- package/dist/domain/functionComparisonResults.js +3 -7
- package/dist/domain/functionComparisonSchemas.js +3 -2
- package/dist/domain/hopperValues.js +108 -8
- package/dist/domain/javascriptApplicationAnalysis.js +4 -7
- package/dist/domain/javascriptApplicationEvidenceSchemas.js +4 -3
- package/dist/domain/javascriptApplicationGraphSchemas.js +8 -7
- package/dist/domain/javascriptApplicationVersionComparisonSchemas.js +9 -7
- package/dist/domain/javascriptApplicationVersionItems.js +12 -18
- package/dist/domain/javascriptAstValues.js +4 -0
- package/dist/domain/javascriptExportShapeComparison.js +1 -6
- package/dist/domain/javascriptExportShapeComparisonSchemas.js +6 -10
- package/dist/domain/javascriptExportShapeVariants.js +15 -2
- package/dist/domain/javascriptFeatureTraceSchemas.js +8 -7
- package/dist/domain/javascriptRuntimeObservation.js +14 -2
- package/dist/domain/javascriptRuntimeReconciliationMatching.js +8 -0
- package/dist/domain/javascriptRuntimeReconciliationParsing.js +4 -2
- package/dist/domain/javascriptRuntimeReconciliationResult.js +6 -4
- package/dist/domain/javascriptRuntimeReconciliationRuntime.js +15 -4
- package/dist/domain/javascriptRuntimeReconciliationSchemas.js +19 -18
- package/dist/domain/javascriptRuntimeStaticCandidates.js +18 -6
- package/dist/domain/javascriptSemanticAnalysis.js +57 -19
- package/dist/domain/javascriptSemanticAsyncEffects.js +39 -40
- package/dist/domain/javascriptSemanticCalls.js +46 -27
- package/dist/domain/javascriptSemanticChildProcesses.js +43 -50
- package/dist/domain/javascriptSemanticDataEffectHelpers.js +91 -18
- package/dist/domain/javascriptSemanticDataEffects.js +22 -10
- package/dist/domain/javascriptSemanticGraphSchemas.js +8 -6
- package/dist/domain/javascriptSemanticObjects.js +13 -3
- package/dist/domain/javascriptSemanticProjection.js +144 -38
- package/dist/domain/javascriptSemanticPromises.js +14 -27
- package/dist/domain/javascriptSemanticQuerySchemas.js +6 -9
- package/dist/domain/javascriptSemanticResources.js +2 -5
- package/dist/domain/javascriptSemanticState.js +4 -0
- package/dist/domain/javascriptSemanticTraceSchemas.js +2 -1
- package/dist/domain/javascriptSemanticTraversal.js +13 -5
- package/dist/domain/javascriptSemanticValues.js +10 -9
- package/dist/domain/javascriptSourceParser.js +5 -1
- package/dist/domain/javascriptStaticAnalysisCalls.js +8 -5
- package/dist/domain/javascriptStaticAnalysisHelpers.js +16 -7
- package/dist/domain/keyedArchive.js +181 -0
- package/dist/domain/managedApplicationGraph.js +4 -3
- package/dist/domain/managedArtifact.js +2 -1
- package/dist/domain/managedMemberComparison.js +18 -13
- package/dist/domain/managedMemberComparisonCoverage.js +2 -1
- package/dist/domain/managedMemberComparisonItems.js +27 -7
- package/dist/domain/managedMemberComparisonMatch.js +22 -6
- package/dist/domain/managedNativeVerificationMatch.js +2 -2
- package/dist/domain/managedNativeVerificationSchemas.js +7 -5
- package/dist/domain/managedReconstruction.js +6 -5
- package/dist/domain/nativeApiBoundary.js +7 -0
- package/dist/domain/nativeDataType.js +51 -0
- package/dist/domain/nativeInspection.js +0 -1
- package/dist/domain/nativeInstruction.js +82 -0
- package/dist/domain/nativeInvestigationGraph.js +9 -5
- package/dist/domain/nativeUiObservation.js +123 -0
- package/dist/domain/nativeValueFlow.js +17 -0
- package/dist/domain/nativeValueTrace.js +64 -0
- package/dist/domain/objcSwiftMetadata.js +39 -0
- package/dist/domain/peInspection.js +1 -0
- package/dist/domain/processCapture.js +5 -55
- package/dist/domain/processCaptureExample.js +0 -9
- package/dist/domain/processCaptureValidation.js +13 -144
- package/dist/domain/processComparison.js +3 -25
- package/dist/domain/processObservation.js +0 -29
- package/dist/domain/processScenario.js +28 -228
- package/dist/domain/processTraceDimensionProjection.js +0 -15
- package/dist/domain/processTraceEvaluation.js +0 -6
- package/dist/domain/protocolCapture.js +8 -36
- package/dist/domain/reconstructionCoverage.js +3 -2
- package/dist/domain/reconstructionObligationLedgerSchemas.js +4 -12
- package/dist/domain/reconstructionReadinessSchemas.js +4 -3
- package/dist/domain/reconstructionVerification.js +2 -1
- package/dist/domain/reconstructionVerificationSchemas.js +6 -13
- package/dist/domain/referenceSourceClassification.js +0 -110
- package/dist/domain/referenceSourceGraph.js +15 -5
- package/dist/domain/residualUnknown.js +3 -2
- package/dist/domain/runtimeIdentification.js +6 -5
- package/dist/domain/sourceMapContents.js +5 -0
- package/dist/domain/sourceToBundleComparison.js +3 -10
- package/dist/domain/sourceToBundleComparisonSchemas.js +7 -6
- package/dist/domain/sourceToBundleSignals.js +9 -3
- package/dist/domain/staticRuntimeCorrelation.js +5 -11
- package/dist/domain/webBundleAnalysis.js +17 -9
- package/dist/domain/webBundleAnalyzer.js +1 -1
- package/dist/domain/webCaptureDiff.js +5 -11
- package/dist/domain/webCaptureDiffSchemas.js +2 -1
- package/dist/domain/webMcpDiscovery.js +2 -1
- package/dist/dotnet/ManagedMemberInspectorCore.js +15 -7
- package/dist/dotnet/ManagedMemberInstructionDecoder.js +57 -40
- package/dist/dotnet/ManagedMemberRows.js +2 -0
- package/dist/dotnet/ManagedMethodBodyReader.js +15 -8
- package/dist/dotnet/ManagedPeReader.js +2 -0
- package/dist/generatedMcpToolCatalog.js +1 -1
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraAnalysisProfile.js +15 -5
- package/dist/ghidra/GhidraClient.js +38 -8
- package/dist/ghidra/GhidraFunctionValues.js +56 -20
- package/dist/ghidra/GhidraInstallation.js +7 -4
- package/dist/ghidra/GhidraInventoryValues.js +44 -9
- package/dist/ghidra/GhidraLauncher.js +18 -3
- package/dist/ghidra/GhidraProvider.js +23 -2
- package/dist/ghidra/GhidraRequestQueue.js +45 -4
- package/dist/ghidra/GhidraSessionValues.js +5 -0
- package/dist/hopper/HopperAnalysisProfile.js +2 -0
- package/dist/hopper/HopperProvider.js +29 -6
- package/dist/hopper/HopperTargetLease.js +18 -4
- package/dist/logger.js +0 -13
- package/dist/main/messages.js +0 -1
- package/dist/main/reload.js +3 -32
- package/dist/main/shutdown.js +1 -2
- package/dist/main/transport.js +0 -17
- package/dist/main.js +0 -10
- package/dist/native/AppleDispatchMetadata.js +582 -0
- package/dist/native/AppleObjcProtocols.js +88 -0
- package/dist/native/AppleSwiftVtables.js +86 -0
- package/dist/native/CommandRunner.js +1 -1
- package/dist/native/NativeHostCapabilities.js +23 -0
- package/dist/native/NativeMacOSProvider.js +61 -9
- package/dist/native/NativeMachoInspection.js +39 -6
- package/dist/native/NativeUiHelperRuntime.js +42 -0
- package/dist/native/NativeUiObservation.js +174 -0
- package/dist/native/parsers/codesign.js +4 -1
- package/dist/native/parsers/dyldInfo.js +51 -25
- package/dist/native/parsers/lipo.js +13 -4
- package/dist/native/parsers/otool.js +84 -39
- package/dist/native/parsers/plist.js +2 -1
- package/dist/process/ExecFileOutput.js +5 -1
- package/dist/process/ProcessOwnership.js +69 -33
- package/dist/process/ProcessOwnershipObservation.js +31 -12
- package/dist/process/ProviderProcess.js +4 -2
- package/dist/reference/ReferenceSourceReaderEntries.js +48 -31
- package/dist/reference/ReferenceSourceReaderErrors.js +24 -0
- package/dist/reference/ReferenceSourceReaderFile.js +11 -5
- package/dist/reference/ReferenceSourceReaderValidate.js +22 -8
- package/dist/server/createServer.js +7 -62
- package/dist/server/registerApplicationTools/helpers.js +2 -9
- package/dist/server/registerApplicationTools.js +0 -4
- package/dist/server/registerArtifactComparisonTool.js +1 -1
- package/dist/server/registerBrowserScenarioTool.js +4 -2
- package/dist/server/registerBrowserTools.js +7 -7
- package/dist/server/registerBundleComparisonTool.js +1 -1
- package/dist/server/registerCloseLifecycleTool.js +1 -1
- package/dist/server/registerElectronTools.js +10 -4
- package/dist/server/registerEnhancedTools.js +20 -12
- package/dist/server/registerEvidenceTools.js +4 -28
- package/dist/server/registerFunctionComparisonTool.js +1 -1
- package/dist/server/registerInvestigationTools.js +6 -6
- package/dist/server/registerJavaScriptRuntimeObservationTools.js +2 -2
- package/dist/server/registerManagedTools.js +28 -14
- package/dist/server/registerManagedWorkflowTools.js +0 -2
- package/dist/server/registerProcessComparisonTool.js +1 -3
- package/dist/server/registerSessionRecordTools.js +9 -9
- package/dist/server/registerSessionStatusTool.js +1 -1
- package/dist/server/registerSessionTools.js +28 -57
- package/dist/server/sessionAvailabilityPolicy.js +2 -3
- package/dist/server/sessionToolPolicies.js +0 -4
- package/dist/server/toolResult.js +8 -10
- package/package.json +32 -22
- package/skills/reverse-engineer-anything/SKILL.md +15 -11
- package/skills/reverse-engineer-anything/references/evidence-workflows.md +3 -2
- package/skills/reverse-engineer-anything/references/javascript-applications.md +3 -2
- package/skills/reverse-engineer-anything/references/native-and-artifacts.md +8 -6
- package/skills/reverse-engineer-anything/references/runtime-observation.md +15 -11
- package/dist/application/CommandShimReplay.js +0 -152
- package/dist/application/ConfiguredRoots.js +0 -19
- package/dist/application/InstrumentedJavaScriptReplayHost.js +0 -36
- package/dist/application/JavaScriptReplayPermission.js +0 -16
- package/dist/application/JavaScriptReplayPlanning.js +0 -207
- package/dist/application/JavaScriptReplayService.js +0 -274
- package/dist/application/LoopbackReplay.js +0 -389
- package/dist/application/LoopbackReplayRecorder.js +0 -129
- package/dist/application/ManagedRuntimeCorrelationService.js +0 -104
- package/dist/application/NodeRuntimeCharacterizationService.js +0 -191
- package/dist/application/PermissionAuthority.js +0 -268
- package/dist/application/PermissionConfiguration.js +0 -26
- package/dist/application/PermissionFailure.js +0 -5
- package/dist/application/ProcessCaptureAuthority.js +0 -24
- package/dist/application/ProcessCapturePermission.js +0 -13
- package/dist/application/ProcessCheckpoints.js +0 -178
- package/dist/application/ProcessReactiveCoordinator.js +0 -223
- package/dist/application/ProcessReactiveEffects.js +0 -153
- package/dist/application/ProcessReactiveHarness.js +0 -106
- package/dist/application/ProcessReactiveObservations.js +0 -105
- package/dist/application/ProjectPermissionStore.js +0 -199
- package/dist/application/RuntimeExecutableDiagnostics.js +0 -198
- package/dist/application/Upgrade.js +0 -134
- package/dist/browser/SensitiveTextCapture.js +0 -8
- package/dist/cliPolicyCommands.js +0 -185
- package/dist/config/browserScenario.js +0 -77
- package/dist/config/electronAutomation.js +0 -35
- package/dist/config/javascriptReplay.js +0 -41
- package/dist/config/managedRuntime.js +0 -25
- package/dist/config/passiveObservation.js +0 -87
- package/dist/config/permissions.js +0 -23
- package/dist/config/processCapture.js +0 -47
- package/dist/contracts/replayMachineExample.js +0 -37
- package/dist/domain/javascriptExportInstrumentation.js +0 -95
- package/dist/domain/javascriptReplay.js +0 -360
- package/dist/domain/managedRuntimeCorrelation.js +0 -181
- package/dist/domain/nodeRuntimeCharacterization.js +0 -63
- package/dist/domain/permissionPolicy.js +0 -176
- package/dist/domain/processCaptureReactiveSchema.js +0 -68
- package/dist/domain/processCaptureReactiveValidation.js +0 -180
- package/dist/domain/processReactiveCheckpointDataflow.js +0 -32
- package/dist/domain/processReactiveMatching.js +0 -196
- package/dist/domain/processReactiveRuntime.js +0 -116
- package/dist/domain/processReactiveScenario.js +0 -296
- package/dist/domain/processReactiveScenarioPreflight.js +0 -95
- package/dist/domain/processReactiveTransition.js +0 -187
- package/dist/domain/replayMachine.js +0 -320
- package/dist/domain/replayMachineRun.js +0 -168
- package/dist/domain/replayMachineRuntime.js +0 -296
- package/dist/domain/replayMachineValues.js +0 -84
- package/dist/domain/runtimeCharacterization.js +0 -84
- package/dist/replay/JavaScriptReplayWorker.js +0 -382
- package/dist/replay/JavaScriptReplayWorkerTypes.js +0 -1
- package/dist/replay/LinuxJavaScriptReplayRunner.js +0 -216
- package/dist/replay/LinuxJavaScriptReplaySandbox.js +0 -121
- package/dist/replay/LinuxRuntimeClosure.js +0 -44
- package/dist/replay/LinuxSeccompPolicy.js +0 -40
- package/dist/replay/ReplayOutcome.js +0 -104
- package/dist/replay/ReplayProcessLifecycle.js +0 -96
- package/dist/replay/ReplaySeccompFile.js +0 -29
- package/dist/replay/ReplayWorkerProtocol.js +0 -58
- package/dist/replay/SystemJavaScriptReplayHost.js +0 -153
- package/dist/server/ProcessCaptureElicitation.js +0 -153
- package/dist/server/registerApplicationTools/characterization.js +0 -46
- package/dist/server/registerApplicationTools/controlledReplay.js +0 -31
- package/dist/server/registerManagedWorkflowTools/planManagedRuntimeCorrelation.js +0 -29
- package/dist/server/registerReplayMachineTool.js +0 -14
- package/skills/reverse-engineer-anything/references/controlled-replay.md +0 -12
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
import { sanitizeBrowserUrl } from "../domain/browserObservation.js";
|
|
4
3
|
import { browserStepArtifactsSchema, } from "../domain/browserScenarioCapture.js";
|
|
5
4
|
const historyValueSchema = z.strictObject({
|
|
6
5
|
length: z.number().int().min(0),
|
|
@@ -79,7 +78,7 @@ const navigationType = (value) => {
|
|
|
79
78
|
return "unknown";
|
|
80
79
|
}
|
|
81
80
|
};
|
|
82
|
-
const captureHistory = async (page) => {
|
|
81
|
+
const captureHistory = async (page, secrets) => {
|
|
83
82
|
try {
|
|
84
83
|
const raw = historyValueSchema.parse(await page.evaluate(`(() => ({
|
|
85
84
|
length: window.history.length,
|
|
@@ -92,10 +91,10 @@ const captureHistory = async (page) => {
|
|
|
92
91
|
}))()`));
|
|
93
92
|
const value = {
|
|
94
93
|
length: raw.length,
|
|
95
|
-
current_url:
|
|
94
|
+
current_url: secrets.sanitizeUrl(page.url()),
|
|
96
95
|
navigation_entries: raw.navigation_entries.map(({ type, name }) => ({
|
|
97
96
|
type: navigationType(type),
|
|
98
|
-
name:
|
|
97
|
+
name: secrets.sanitizeUrl(name),
|
|
99
98
|
})),
|
|
100
99
|
};
|
|
101
100
|
return { state: "captured", value };
|
|
@@ -105,9 +104,12 @@ const captureHistory = async (page) => {
|
|
|
105
104
|
}
|
|
106
105
|
};
|
|
107
106
|
const captureStorage = async (input) => {
|
|
108
|
-
const { context, page,
|
|
107
|
+
const { context, page, secrets } = input;
|
|
109
108
|
try {
|
|
110
|
-
const
|
|
109
|
+
const pageUrl = new URL(page.url());
|
|
110
|
+
const cookies = pageUrl.protocol === "http:" || pageUrl.protocol === "https:"
|
|
111
|
+
? await context.cookies(pageUrl.href)
|
|
112
|
+
: [];
|
|
111
113
|
const pageStorage = storageValueSchema.parse(await page.evaluate(`(() => ({
|
|
112
114
|
local_storage: Object.entries(window.localStorage),
|
|
113
115
|
session_storage: Object.entries(window.sessionStorage)
|
|
@@ -137,33 +139,19 @@ const captureStorage = async (input) => {
|
|
|
137
139
|
return missing("storage capture failed");
|
|
138
140
|
}
|
|
139
141
|
};
|
|
140
|
-
const isAllowedPage = (page, allowedOrigins) => {
|
|
141
|
-
try {
|
|
142
|
-
return allowedOrigins.has(new URL(page.url()).origin);
|
|
143
|
-
}
|
|
144
|
-
catch {
|
|
145
|
-
return false;
|
|
146
|
-
}
|
|
147
|
-
};
|
|
148
142
|
/** Capture selected step artifacts without retaining data after scope loss. */
|
|
149
143
|
export const capturePlaywrightStepArtifacts = async (input) => {
|
|
150
|
-
const { context, page,
|
|
151
|
-
const
|
|
152
|
-
const denied = () => missing("current page is outside approved origins");
|
|
153
|
-
const state = (kind, capture) => !requested.has(kind)
|
|
154
|
-
? Promise.resolve(notRequested())
|
|
155
|
-
: allowed || kind === "url"
|
|
156
|
-
? capture()
|
|
157
|
-
: Promise.resolve(denied());
|
|
144
|
+
const { context, page, secrets, requested } = input;
|
|
145
|
+
const state = (kind, capture) => (!requested.has(kind) ? Promise.resolve(notRequested()) : capture());
|
|
158
146
|
return browserStepArtifactsSchema.parse({
|
|
159
147
|
screenshot: await state("screenshot", () => captureScreenshot(page)),
|
|
160
148
|
dom: await state("dom", () => captureDom({ page, secrets })),
|
|
161
149
|
accessibility: await state("accessibility", () => captureAccessibility({ page, secrets })),
|
|
162
150
|
url: await state("url", async () => ({
|
|
163
151
|
state: "captured",
|
|
164
|
-
value:
|
|
152
|
+
value: secrets.sanitizeUrl(page.url()),
|
|
165
153
|
})),
|
|
166
|
-
history: await state("history", () => captureHistory(page)),
|
|
167
|
-
storage: await state("storage", () => captureStorage({ context, page,
|
|
154
|
+
history: await state("history", () => captureHistory(page, secrets)),
|
|
155
|
+
storage: await state("storage", () => captureStorage({ context, page, secrets })),
|
|
168
156
|
});
|
|
169
157
|
};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { chmod, mkdtemp, rm } from "node:fs/promises";
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
|
-
import { join } from "node:path";
|
|
3
|
+
import { join, resolve } from "node:path";
|
|
4
4
|
import { chromium, } from "playwright-core";
|
|
5
5
|
import { BrowserObservationError } from "../domain/errors.js";
|
|
6
|
+
import { withPlaywrightExecutionBoundary } from "./PlaywrightExecutionBoundary.js";
|
|
6
7
|
const OPERATION = "capture_browser_scenario";
|
|
7
8
|
const allowedBrowserEnvironment = (environment) => {
|
|
8
9
|
const allowed = [
|
|
@@ -24,15 +25,7 @@ const allowedBrowserEnvironment = (environment) => {
|
|
|
24
25
|
.map((name) => [name, environment[name]])
|
|
25
26
|
.filter((entry) => entry[1] !== undefined));
|
|
26
27
|
};
|
|
27
|
-
const
|
|
28
|
-
try {
|
|
29
|
-
return allowedOrigins.has(new URL(value).origin);
|
|
30
|
-
}
|
|
31
|
-
catch {
|
|
32
|
-
return false;
|
|
33
|
-
}
|
|
34
|
-
};
|
|
35
|
-
const findConnectedPage = async (browser, targetId, allowedOrigins) => {
|
|
28
|
+
const findConnectedPage = async (browser, targetId) => {
|
|
36
29
|
for (const context of browser.contexts())
|
|
37
30
|
for (const page of context.pages()) {
|
|
38
31
|
const session = await context.newCDPSession(page);
|
|
@@ -40,9 +33,6 @@ const findConnectedPage = async (browser, targetId, allowedOrigins) => {
|
|
|
40
33
|
const { targetInfo } = await session.send("Target.getTargetInfo");
|
|
41
34
|
if (targetInfo.targetId !== targetId)
|
|
42
35
|
continue;
|
|
43
|
-
if (page.url() !== "about:blank" &&
|
|
44
|
-
!originAllowed(page.url(), allowedOrigins))
|
|
45
|
-
throw new BrowserObservationError(OPERATION, "target_not_allowed");
|
|
46
36
|
return { context, page };
|
|
47
37
|
}
|
|
48
38
|
finally {
|
|
@@ -83,7 +73,7 @@ export const openPlaywrightScenarioBrowser = async (scenario, environment) => {
|
|
|
83
73
|
if (scenario.browser.mode === "connect") {
|
|
84
74
|
const browser = await chromium.connectOverCDP(scenario.browser.cdp_endpoint, { timeout: 0 });
|
|
85
75
|
try {
|
|
86
|
-
const target = await findConnectedPage(browser, scenario.browser.target_id
|
|
76
|
+
const target = await findConnectedPage(browser, scenario.browser.target_id);
|
|
87
77
|
await configureAttachedEnvironment(target.context, target.page, scenario);
|
|
88
78
|
return { ...target, browser, profilePath: undefined };
|
|
89
79
|
}
|
|
@@ -96,8 +86,8 @@ export const openPlaywrightScenarioBrowser = async (scenario, environment) => {
|
|
|
96
86
|
await chmod(profilePath, 0o700);
|
|
97
87
|
try {
|
|
98
88
|
const context = await chromium.launchPersistentContext(profilePath, {
|
|
99
|
-
executablePath: scenario.browser.executable_path,
|
|
100
|
-
headless:
|
|
89
|
+
executablePath: resolve(scenario.browser.executable_path),
|
|
90
|
+
headless: scenario.browser.headless,
|
|
101
91
|
acceptDownloads: false,
|
|
102
92
|
viewport: {
|
|
103
93
|
width: scenario.environment.viewport.width,
|
|
@@ -108,7 +98,7 @@ export const openPlaywrightScenarioBrowser = async (scenario, environment) => {
|
|
|
108
98
|
timezoneId: scenario.environment.timezone,
|
|
109
99
|
colorScheme: scenario.environment.color_scheme,
|
|
110
100
|
reducedMotion: scenario.environment.reduced_motion,
|
|
111
|
-
serviceWorkers:
|
|
101
|
+
serviceWorkers: scenario.environment.service_workers,
|
|
112
102
|
env: allowedBrowserEnvironment(environment),
|
|
113
103
|
handleSIGHUP: false,
|
|
114
104
|
handleSIGINT: false,
|
|
@@ -128,15 +118,28 @@ export const openPlaywrightScenarioBrowser = async (scenario, environment) => {
|
|
|
128
118
|
throw cause;
|
|
129
119
|
}
|
|
130
120
|
};
|
|
131
|
-
export const closePlaywrightScenarioBrowser = async ({ context, browser, profilePath,
|
|
121
|
+
export const closePlaywrightScenarioBrowser = async ({ context, browser, profilePath }, signal) => {
|
|
122
|
+
const cleanup = (async () => {
|
|
123
|
+
try {
|
|
124
|
+
// In connect mode Playwright's Browser.close disconnects its CDP client;
|
|
125
|
+
// it does not close the externally owned browser process.
|
|
126
|
+
if (profilePath === undefined)
|
|
127
|
+
await browser.close();
|
|
128
|
+
else
|
|
129
|
+
await context.close();
|
|
130
|
+
}
|
|
131
|
+
finally {
|
|
132
|
+
if (profilePath !== undefined)
|
|
133
|
+
await rm(profilePath, { recursive: true, force: true, maxRetries: 3 });
|
|
134
|
+
}
|
|
135
|
+
})();
|
|
136
|
+
void cleanup.catch(() => undefined);
|
|
137
|
+
// The shared execution boundary rejects cancellation/timeouts instead of
|
|
138
|
+
// returning a successful capture whose browser or profile may still exist.
|
|
132
139
|
try {
|
|
133
|
-
|
|
134
|
-
await browser.close();
|
|
135
|
-
else
|
|
136
|
-
await context.close();
|
|
140
|
+
await withPlaywrightExecutionBoundary(() => cleanup, 1_000, signal);
|
|
137
141
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
await rm(profilePath, { recursive: true, force: true, maxRetries: 3 });
|
|
142
|
+
catch (cause) {
|
|
143
|
+
throw new BrowserObservationError(OPERATION, "cleanup_failed", { cause });
|
|
141
144
|
}
|
|
142
145
|
};
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { sanitizeBrowserUrl } from "../domain/browserObservation.js";
|
|
2
1
|
import { browserScenarioEventSchema, } from "../domain/browserScenarioCapture.js";
|
|
3
2
|
/** Arrival-ordered Playwright event capture with current-step attribution. */
|
|
4
3
|
export class PlaywrightScenarioEvents {
|
|
@@ -7,11 +6,43 @@ export class PlaywrightScenarioEvents {
|
|
|
7
6
|
sequence = 0;
|
|
8
7
|
enabled;
|
|
9
8
|
secrets;
|
|
10
|
-
|
|
9
|
+
ownsContext;
|
|
10
|
+
pages = new Set();
|
|
11
|
+
incompleteFamilies = new Set();
|
|
11
12
|
constructor(options) {
|
|
12
13
|
this.enabled = options.enabled;
|
|
13
14
|
this.secrets = options.secrets;
|
|
14
|
-
this.
|
|
15
|
+
this.ownsContext = options.ownsContext === true;
|
|
16
|
+
this.pages.add(options.page);
|
|
17
|
+
if (this.ownsContext && this.enabled.size > 0)
|
|
18
|
+
(options.context ?? options.page.context()).on("page", (page) => this.popup(page));
|
|
19
|
+
if (this.enabled.has("network")) {
|
|
20
|
+
const context = options.context ?? options.page.context();
|
|
21
|
+
const inScope = (request) => {
|
|
22
|
+
if (this.ownsContext)
|
|
23
|
+
return true;
|
|
24
|
+
try {
|
|
25
|
+
return this.pages.has(request.frame().page());
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
// Initial popup navigations can lack a frame. Never guess ownership
|
|
29
|
+
// from a URL in a shared context; connect captures are attach-limited.
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
context.on("request", (request) => {
|
|
34
|
+
if (inScope(request))
|
|
35
|
+
this.request("request", request);
|
|
36
|
+
});
|
|
37
|
+
context.on("response", (response) => {
|
|
38
|
+
if (inScope(response.request()))
|
|
39
|
+
this.response(response);
|
|
40
|
+
});
|
|
41
|
+
context.on("requestfailed", (request) => {
|
|
42
|
+
if (inScope(request))
|
|
43
|
+
this.request("request-failed", request);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
15
46
|
this.observePage(options.page);
|
|
16
47
|
}
|
|
17
48
|
setStep(index) {
|
|
@@ -23,6 +54,16 @@ export class PlaywrightScenarioEvents {
|
|
|
23
54
|
lastSequence() {
|
|
24
55
|
return this.sequence;
|
|
25
56
|
}
|
|
57
|
+
/** Report selected popup event families with unrecoverable pre-discovery gaps. */
|
|
58
|
+
limitations() {
|
|
59
|
+
const popupGaps = [...this.incompleteFamilies].map((family) => `Popup ${family} events before Page discovery are unavailable; later events are retained.`);
|
|
60
|
+
return this.enabled.has("network") && !this.ownsContext
|
|
61
|
+
? [
|
|
62
|
+
"Shared-context network capture excludes requests without a known root or descendant Page frame.",
|
|
63
|
+
...popupGaps,
|
|
64
|
+
]
|
|
65
|
+
: popupGaps;
|
|
66
|
+
}
|
|
26
67
|
result() {
|
|
27
68
|
return {
|
|
28
69
|
retained: this.items.length,
|
|
@@ -41,80 +82,33 @@ export class PlaywrightScenarioEvents {
|
|
|
41
82
|
}
|
|
42
83
|
observePage(page) {
|
|
43
84
|
if (this.enabled.has("console"))
|
|
44
|
-
page.on("console", (message) =>
|
|
45
|
-
if (this.pageInScope(page))
|
|
46
|
-
this.console(message);
|
|
47
|
-
});
|
|
85
|
+
page.on("console", (message) => this.console(message));
|
|
48
86
|
if (this.enabled.has("page-errors"))
|
|
49
87
|
page.on("pageerror", (error) => {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
? null
|
|
56
|
-
: this.secrets.redact(error.stack),
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
if (this.enabled.has("network")) {
|
|
60
|
-
page.on("request", (request) => {
|
|
61
|
-
if (this.pageInScope(page))
|
|
62
|
-
this.request("request", request);
|
|
63
|
-
});
|
|
64
|
-
page.on("response", (response) => {
|
|
65
|
-
if (this.pageInScope(page))
|
|
66
|
-
this.response(response);
|
|
67
|
-
});
|
|
68
|
-
page.on("requestfailed", (request) => {
|
|
69
|
-
if (this.pageInScope(page))
|
|
70
|
-
this.request("request-failed", request);
|
|
88
|
+
this.push({
|
|
89
|
+
kind: "page-error",
|
|
90
|
+
message: this.secrets.redact(error.message),
|
|
91
|
+
stack: error.stack === undefined ? null : this.secrets.redact(error.stack),
|
|
92
|
+
});
|
|
71
93
|
});
|
|
72
|
-
}
|
|
73
94
|
if (this.enabled.has("websockets"))
|
|
74
|
-
page.on("websocket", (socket) =>
|
|
75
|
-
if (this.pageInScope(page))
|
|
76
|
-
this.webSocket(page, socket);
|
|
77
|
-
});
|
|
95
|
+
page.on("websocket", (socket) => this.webSocket(socket));
|
|
78
96
|
if (this.enabled.has("frames")) {
|
|
79
|
-
page.on("frameattached", (frame) =>
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
});
|
|
83
|
-
page.on("framedetached", (frame) => {
|
|
84
|
-
if (this.pageInScope(page))
|
|
85
|
-
this.frame("frame-detached", frame);
|
|
86
|
-
});
|
|
87
|
-
page.on("framenavigated", (frame) => {
|
|
88
|
-
if (this.pageInScope(page))
|
|
89
|
-
this.frame("frame-navigated", frame);
|
|
90
|
-
});
|
|
97
|
+
page.on("frameattached", (frame) => this.frame("frame-attached", frame));
|
|
98
|
+
page.on("framedetached", (frame) => this.frame("frame-detached", frame));
|
|
99
|
+
page.on("framenavigated", (frame) => this.frame("frame-navigated", frame));
|
|
91
100
|
}
|
|
92
101
|
if (this.enabled.has("workers"))
|
|
93
|
-
page.on("worker", (worker) =>
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
page.on("popup", (popup) => {
|
|
99
|
-
if (this.pageInScope(page))
|
|
100
|
-
this.popup(popup);
|
|
101
|
-
});
|
|
102
|
+
page.on("worker", (worker) => this.worker(worker));
|
|
103
|
+
// Any selected family needs descendant discovery in shared contexts.
|
|
104
|
+
// Popup lifecycle records remain gated on their own selector below.
|
|
105
|
+
if (this.enabled.size > 0)
|
|
106
|
+
page.on("popup", (popup) => this.popup(popup));
|
|
102
107
|
if (this.enabled.has("downloads"))
|
|
103
|
-
page.on("download", (download) =>
|
|
104
|
-
if (this.pageInScope(page))
|
|
105
|
-
this.download(download);
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
pageInScope(page) {
|
|
109
|
-
try {
|
|
110
|
-
return this.allowedOrigins.has(new URL(page.url()).origin);
|
|
111
|
-
}
|
|
112
|
-
catch {
|
|
113
|
-
return false;
|
|
114
|
-
}
|
|
108
|
+
page.on("download", (download) => this.download(download));
|
|
115
109
|
}
|
|
116
110
|
safeUrl(value) {
|
|
117
|
-
return
|
|
111
|
+
return this.secrets.sanitizeUrl(value);
|
|
118
112
|
}
|
|
119
113
|
console(message) {
|
|
120
114
|
const location = message.location();
|
|
@@ -164,21 +158,12 @@ export class PlaywrightScenarioEvents {
|
|
|
164
158
|
failure: null,
|
|
165
159
|
});
|
|
166
160
|
}
|
|
167
|
-
webSocket(
|
|
161
|
+
webSocket(socket) {
|
|
168
162
|
const url = this.safeUrl(socket.url());
|
|
169
163
|
this.push({ kind: "websocket-opened", url });
|
|
170
|
-
socket.on("framesent", ({ payload }) =>
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
});
|
|
174
|
-
socket.on("framereceived", ({ payload }) => {
|
|
175
|
-
if (this.pageInScope(page))
|
|
176
|
-
this.webSocketFrame("websocket-frame-received", url, payload);
|
|
177
|
-
});
|
|
178
|
-
socket.on("close", () => {
|
|
179
|
-
if (this.pageInScope(page))
|
|
180
|
-
this.push({ kind: "websocket-closed", url });
|
|
181
|
-
});
|
|
164
|
+
socket.on("framesent", ({ payload }) => this.webSocketFrame("websocket-frame-sent", url, payload));
|
|
165
|
+
socket.on("framereceived", ({ payload }) => this.webSocketFrame("websocket-frame-received", url, payload));
|
|
166
|
+
socket.on("close", () => this.push({ kind: "websocket-closed", url }));
|
|
182
167
|
}
|
|
183
168
|
webSocketFrame(kind, url, payload) {
|
|
184
169
|
const bytes = Buffer.byteLength(payload);
|
|
@@ -211,34 +196,38 @@ export class PlaywrightScenarioEvents {
|
|
|
211
196
|
name: frame.name() === "" ? null : this.secrets.redact(frame.name()),
|
|
212
197
|
});
|
|
213
198
|
}
|
|
214
|
-
worker(
|
|
199
|
+
worker(worker) {
|
|
215
200
|
const details = {
|
|
216
201
|
url: this.safeUrl(worker.url()),
|
|
217
202
|
name: null,
|
|
218
203
|
};
|
|
219
204
|
this.push({ kind: "worker-created", ...details });
|
|
220
|
-
worker.on("close", () => {
|
|
221
|
-
if (this.pageInScope(page))
|
|
222
|
-
this.push({ kind: "worker-closed", ...details });
|
|
223
|
-
});
|
|
205
|
+
worker.on("close", () => this.push({ kind: "worker-closed", ...details }));
|
|
224
206
|
}
|
|
225
207
|
popup(page) {
|
|
226
|
-
if (
|
|
227
|
-
void page.close().catch(() => undefined);
|
|
208
|
+
if (this.pages.has(page))
|
|
228
209
|
return;
|
|
229
|
-
|
|
210
|
+
this.pages.add(page);
|
|
211
|
+
for (const family of [
|
|
212
|
+
"frames",
|
|
213
|
+
"workers",
|
|
214
|
+
"websockets",
|
|
215
|
+
"downloads",
|
|
216
|
+
])
|
|
217
|
+
if (this.enabled.has(family))
|
|
218
|
+
this.incompleteFamilies.add(family);
|
|
230
219
|
const opened = {
|
|
231
220
|
url: page.url() === "" ? null : this.safeUrl(page.url()),
|
|
232
221
|
name: null,
|
|
233
222
|
};
|
|
234
|
-
this.
|
|
235
|
-
|
|
236
|
-
|
|
223
|
+
if (this.enabled.has("popups")) {
|
|
224
|
+
this.push({ kind: "popup-opened", ...opened });
|
|
225
|
+
page.on("close", () => this.push({
|
|
237
226
|
kind: "popup-closed",
|
|
238
227
|
url: page.url() === "" ? null : this.safeUrl(page.url()),
|
|
239
228
|
name: null,
|
|
240
|
-
})
|
|
241
|
-
|
|
229
|
+
}));
|
|
230
|
+
}
|
|
242
231
|
this.observePage(page);
|
|
243
232
|
}
|
|
244
233
|
download(download) {
|
|
@@ -7,14 +7,6 @@ import { capturePlaywrightStepArtifacts } from "./PlaywrightScenarioArtifacts.js
|
|
|
7
7
|
import { PlaywrightScenarioEvents } from "./PlaywrightScenarioEvents.js";
|
|
8
8
|
import { withPlaywrightExecutionBoundary } from "./PlaywrightExecutionBoundary.js";
|
|
9
9
|
const OPERATION = "capture_browser_scenario";
|
|
10
|
-
const originAllowed = (value, allowedOrigins) => {
|
|
11
|
-
try {
|
|
12
|
-
return allowedOrigins.has(new URL(value).origin);
|
|
13
|
-
}
|
|
14
|
-
catch {
|
|
15
|
-
return false;
|
|
16
|
-
}
|
|
17
|
-
};
|
|
18
10
|
const storageSeeds = (blocks, secrets) => {
|
|
19
11
|
const seeds = {};
|
|
20
12
|
for (const { origin, entries } of blocks)
|
|
@@ -44,78 +36,6 @@ const installStorageSeeds = async (context, page, scenario, secrets) => {
|
|
|
44
36
|
window.sessionStorage.setItem(name, value);
|
|
45
37
|
})()`);
|
|
46
38
|
};
|
|
47
|
-
const installHttpPolicy = async (input) => {
|
|
48
|
-
const { context, scenario, secrets, ownedPages, claimOwnedPage } = input;
|
|
49
|
-
const routes = scenario.request_replay.mode === "exact"
|
|
50
|
-
? new Map(scenario.request_replay.routes.map((route) => [
|
|
51
|
-
`${route.method} ${secrets.url(route.request)}`,
|
|
52
|
-
route,
|
|
53
|
-
]))
|
|
54
|
-
: new Map();
|
|
55
|
-
await context.route("**/*", async (route, request) => {
|
|
56
|
-
let requestPage;
|
|
57
|
-
try {
|
|
58
|
-
requestPage = request.frame().page();
|
|
59
|
-
}
|
|
60
|
-
catch {
|
|
61
|
-
requestPage = undefined;
|
|
62
|
-
}
|
|
63
|
-
if (scenario.browser.mode === "connect" &&
|
|
64
|
-
requestPage !== undefined &&
|
|
65
|
-
!ownedPages.has(requestPage))
|
|
66
|
-
await claimOwnedPage(requestPage);
|
|
67
|
-
if (scenario.browser.mode === "connect" &&
|
|
68
|
-
(requestPage === undefined || !ownedPages.has(requestPage))) {
|
|
69
|
-
await route.continue();
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
if (!originAllowed(request.url(), new Set(scenario.allowed_origins))) {
|
|
73
|
-
await route.abort("blockedbyclient");
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
const replay = routes.get(`${request.method()} ${request.url()}`);
|
|
77
|
-
if (replay !== undefined) {
|
|
78
|
-
await fulfillReplayRoute(route, replay.response, secrets);
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
if (scenario.request_replay.mode === "exact" &&
|
|
82
|
-
scenario.request_replay.unmatched === "abort") {
|
|
83
|
-
await route.abort("blockedbyclient");
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
await route.continue();
|
|
87
|
-
});
|
|
88
|
-
};
|
|
89
|
-
const fulfillReplayRoute = async (route, response, secrets) => {
|
|
90
|
-
if (response.kind === "redirect") {
|
|
91
|
-
await route.fulfill({
|
|
92
|
-
status: response.status,
|
|
93
|
-
headers: { location: secrets.url(response.destination) },
|
|
94
|
-
});
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
await route.fulfill({
|
|
98
|
-
status: response.status,
|
|
99
|
-
headers: Object.fromEntries(response.headers.map(({ name, value }) => [name, secrets.value(value)])),
|
|
100
|
-
...(response.body === undefined
|
|
101
|
-
? {}
|
|
102
|
-
: { body: secrets.value(response.body) }),
|
|
103
|
-
});
|
|
104
|
-
};
|
|
105
|
-
const installWebSocketPolicy = async (owner, scenario) => {
|
|
106
|
-
const allowed = new Set(scenario.allowed_origins);
|
|
107
|
-
await owner.routeWebSocket("**/*", async (route) => {
|
|
108
|
-
const url = new URL(route.url());
|
|
109
|
-
const httpOrigin = `${url.protocol === "wss:" ? "https:" : "http:"}//${url.host}`;
|
|
110
|
-
if (!allowed.has(httpOrigin) ||
|
|
111
|
-
(scenario.request_replay.mode === "exact" &&
|
|
112
|
-
scenario.request_replay.unmatched === "abort")) {
|
|
113
|
-
await route.close({ code: 1008, reason: "outside scenario policy" });
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
route.connectToServer();
|
|
117
|
-
});
|
|
118
|
-
};
|
|
119
39
|
const blockAttachedServiceWorkers = async (page) => {
|
|
120
40
|
const controller = await page.evaluate("Boolean(navigator.serviceWorker?.controller)");
|
|
121
41
|
if (controller)
|
|
@@ -135,57 +55,29 @@ const blockAttachedServiceWorkers = async (page) => {
|
|
|
135
55
|
const initializePage = async (context, page, scenario, secrets) => {
|
|
136
56
|
context.setDefaultTimeout(0);
|
|
137
57
|
context.setDefaultNavigationTimeout(0);
|
|
138
|
-
const ownedPages = new Set([page]);
|
|
139
58
|
if (scenario.browser.mode === "connect")
|
|
140
59
|
await blockAttachedServiceWorkers(page);
|
|
141
|
-
await installWebSocketPolicy(scenario.browser.mode === "launch" ? context : page, scenario);
|
|
142
|
-
const claimOwnedPage = async (candidate) => {
|
|
143
|
-
if (ownedPages.has(candidate))
|
|
144
|
-
return true;
|
|
145
|
-
const opener = await candidate.opener();
|
|
146
|
-
if (opener === null || !ownedPages.has(opener))
|
|
147
|
-
return false;
|
|
148
|
-
await installWebSocketPolicy(candidate, scenario);
|
|
149
|
-
ownedPages.add(candidate);
|
|
150
|
-
return true;
|
|
151
|
-
};
|
|
152
|
-
await installHttpPolicy({
|
|
153
|
-
context,
|
|
154
|
-
scenario,
|
|
155
|
-
secrets,
|
|
156
|
-
ownedPages,
|
|
157
|
-
claimOwnedPage,
|
|
158
|
-
});
|
|
159
|
-
page.on("popup", (popup) => {
|
|
160
|
-
if (scenario.browser.mode === "connect")
|
|
161
|
-
void claimOwnedPage(popup).catch(async () => {
|
|
162
|
-
await popup.close().catch(() => undefined);
|
|
163
|
-
});
|
|
164
|
-
else
|
|
165
|
-
ownedPages.add(popup);
|
|
166
|
-
});
|
|
167
60
|
await installStorageSeeds(context, page, scenario, secrets);
|
|
168
|
-
return ownedPages;
|
|
169
61
|
};
|
|
170
62
|
export class PlaywrightScenarioSession {
|
|
171
63
|
opened;
|
|
172
|
-
scenario;
|
|
173
|
-
secrets;
|
|
174
|
-
eventCapture;
|
|
175
64
|
mode;
|
|
176
65
|
processOwnership;
|
|
177
66
|
product = "Chromium";
|
|
178
67
|
version;
|
|
179
68
|
initialUrl;
|
|
180
69
|
closed = false;
|
|
181
|
-
|
|
70
|
+
secrets;
|
|
71
|
+
eventCapture;
|
|
72
|
+
signal;
|
|
73
|
+
constructor(opened, options) {
|
|
182
74
|
this.opened = opened;
|
|
183
|
-
this.
|
|
184
|
-
this.secrets = secrets;
|
|
185
|
-
this.eventCapture = eventCapture;
|
|
186
|
-
this.mode = scenario.browser.mode;
|
|
75
|
+
this.mode = options.mode;
|
|
187
76
|
this.processOwnership =
|
|
188
|
-
|
|
77
|
+
options.mode === "launch" ? "provider-owned" : "external";
|
|
78
|
+
this.secrets = options.secrets;
|
|
79
|
+
this.eventCapture = options.eventCapture;
|
|
80
|
+
this.signal = options.signal;
|
|
189
81
|
this.version = opened.browser.version();
|
|
190
82
|
this.initialUrl = opened.page.url();
|
|
191
83
|
}
|
|
@@ -202,7 +94,7 @@ export class PlaywrightScenarioSession {
|
|
|
202
94
|
}
|
|
203
95
|
catch (cause) {
|
|
204
96
|
void opening
|
|
205
|
-
.then((lateOpened) => closePlaywrightScenarioBrowser(lateOpened))
|
|
97
|
+
.then((lateOpened) => closePlaywrightScenarioBrowser(lateOpened, options.signal))
|
|
206
98
|
.catch(() => undefined);
|
|
207
99
|
throw cause;
|
|
208
100
|
}
|
|
@@ -210,11 +102,17 @@ export class PlaywrightScenarioSession {
|
|
|
210
102
|
await withPlaywrightExecutionBoundary(() => initializePage(opened.context, opened.page, scenario, secrets), undefined, options.signal);
|
|
211
103
|
const events = new PlaywrightScenarioEvents({
|
|
212
104
|
page: opened.page,
|
|
105
|
+
context: opened.context,
|
|
106
|
+
ownsContext: scenario.browser.mode === "launch",
|
|
213
107
|
enabled: new Set(scenario.capture.events),
|
|
214
108
|
secrets,
|
|
215
|
-
allowedOrigins: scenario.allowed_origins,
|
|
216
109
|
});
|
|
217
|
-
const session = new PlaywrightScenarioSession(opened,
|
|
110
|
+
const session = new PlaywrightScenarioSession(opened, {
|
|
111
|
+
mode: scenario.browser.mode,
|
|
112
|
+
secrets,
|
|
113
|
+
eventCapture: events,
|
|
114
|
+
...(options.signal === undefined ? {} : { signal: options.signal }),
|
|
115
|
+
});
|
|
218
116
|
await withPlaywrightExecutionBoundary(() => opened.page.goto(secrets.url(scenario.start_url), {
|
|
219
117
|
waitUntil: "load",
|
|
220
118
|
timeout: 0,
|
|
@@ -222,13 +120,16 @@ export class PlaywrightScenarioSession {
|
|
|
222
120
|
return session;
|
|
223
121
|
}
|
|
224
122
|
catch (cause) {
|
|
225
|
-
await closePlaywrightScenarioBrowser(opened);
|
|
123
|
+
await closePlaywrightScenarioBrowser(opened, options.signal);
|
|
226
124
|
throw cause;
|
|
227
125
|
}
|
|
228
126
|
}
|
|
229
127
|
currentUrl() {
|
|
230
128
|
return this.opened.page.url();
|
|
231
129
|
}
|
|
130
|
+
sanitizeUrl(value) {
|
|
131
|
+
return this.secrets.sanitizeUrl(value);
|
|
132
|
+
}
|
|
232
133
|
setStep(index) {
|
|
233
134
|
this.eventCapture.setStep(index);
|
|
234
135
|
}
|
|
@@ -241,6 +142,10 @@ export class PlaywrightScenarioSession {
|
|
|
241
142
|
events() {
|
|
242
143
|
return this.eventCapture.result();
|
|
243
144
|
}
|
|
145
|
+
/** Preserve event coverage gaps for the aggregate capture's completeness. */
|
|
146
|
+
eventLimitations() {
|
|
147
|
+
return this.eventCapture.limitations();
|
|
148
|
+
}
|
|
244
149
|
async perform(action, signal) {
|
|
245
150
|
await withPlaywrightExecutionBoundary(() => performPlaywrightScenarioAction({
|
|
246
151
|
page: this.opened.page,
|
|
@@ -252,7 +157,6 @@ export class PlaywrightScenarioSession {
|
|
|
252
157
|
return withPlaywrightExecutionBoundary(() => capturePlaywrightStepArtifacts({
|
|
253
158
|
context: this.opened.context,
|
|
254
159
|
page: this.opened.page,
|
|
255
|
-
scenario: this.scenario,
|
|
256
160
|
secrets: this.secrets,
|
|
257
161
|
requested,
|
|
258
162
|
}), undefined, signal);
|
|
@@ -263,7 +167,7 @@ export class PlaywrightScenarioSession {
|
|
|
263
167
|
? "terminated-owned-process"
|
|
264
168
|
: "disconnected-external";
|
|
265
169
|
this.closed = true;
|
|
266
|
-
await closePlaywrightScenarioBrowser(this.opened);
|
|
170
|
+
await closePlaywrightScenarioBrowser(this.opened, this.signal);
|
|
267
171
|
return this.mode === "launch"
|
|
268
172
|
? "terminated-owned-process"
|
|
269
173
|
: "disconnected-external";
|