rea-agents 6.2.0 → 6.3.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 +18 -20
- package/bridge/hopper_bridge.py +2 -0
- package/dist/android/JadxProvider.js +8 -2
- package/dist/android/JadxSession.js +51 -9
- package/dist/application/BinaryTargetResolver.js +63 -17
- package/dist/application/BrowserScenarioEvidence.js +2 -2
- package/dist/application/ClientConfigurationDocument.js +28 -0
- package/dist/application/ClientRegistrationStatus.js +19 -6
- package/dist/application/DirectAnalysis.js +12 -6
- package/dist/application/DirectAnalysisCleanup.js +0 -1
- package/dist/application/DirectAnalysisStatus.js +2 -5
- package/dist/application/Doctor.js +25 -34
- package/dist/application/DoctorDiagnostics.js +1 -1
- package/dist/application/EvidenceBundleFiles.js +1 -1
- package/dist/application/InvestigationProviders.js +4 -4
- package/dist/application/JsonFiles.js +15 -15
- package/dist/application/LinuxHopper.js +2 -1
- package/dist/application/ReconstructionObligationCandidates.js +9 -2
- package/dist/application/ReconstructionObligationLedgerProjection.js +3 -1
- package/dist/application/RegularFileRead.js +17 -0
- package/dist/application/Setup.js +18 -7
- package/dist/application/SetupClientConfiguration.js +18 -7
- package/dist/application/SetupHost.js +6 -4
- package/dist/application/SetupPlan.js +19 -15
- package/dist/application/SetupSkill.js +57 -8
- package/dist/application/SupportedClients.js +43 -0
- package/dist/application/Uninstall.js +18 -2
- package/dist/application/UpdateMaintenance.js +6 -2
- package/dist/application/Utf8JsonInput.js +64 -0
- package/dist/application/WebScriptExportService.js +13 -6
- package/dist/application/android/AndroidAnalysisService.js +1 -1
- package/dist/application/binary/AnalysisSnapshotCache.js +5 -4
- package/dist/application/binary/BinarySession.js +16 -0
- package/dist/application/binary/BinarySessionOpen.js +9 -1
- package/dist/application/javascript/ElectronActiveEvidence.js +2 -2
- package/dist/application/javascript/ElectronBoundaryAnalysis.js +2 -2
- package/dist/application/javascript/ElectronBoundaryGraphNative.js +5 -1
- package/dist/application/javascript/JavaScriptApplicationEvidence.js +1 -0
- package/dist/application/javascript/JavaScriptApplicationEvidenceGraph.js +107 -46
- package/dist/application/javascript/JavaScriptApplicationService.js +1 -0
- package/dist/application/javascript/JavaScriptApplicationWorkflowService.js +59 -45
- package/dist/application/javascript/JavaScriptArtifactAnalysis.js +0 -6
- package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +8 -18
- package/dist/application/javascript/JavaScriptArtifactGraphFindings.js +34 -26
- package/dist/application/javascript/JavaScriptArtifactPathResolution.js +44 -12
- package/dist/application/javascript/JavaScriptArtifactReconstruction.js +6 -3
- package/dist/application/javascript/JavaScriptArtifactReconstructionInput.js +1 -0
- package/dist/application/javascript/JavaScriptJsonModules.js +2 -2
- package/dist/application/javascript/JavaScriptModuleRelationships.js +5 -17
- package/dist/application/javascript/JavaScriptRuntimeReconciliationService.js +11 -27
- package/dist/application/javascript/JavaScriptSemanticGraphAsyncProjection.js +2 -2
- package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +8 -6
- package/dist/application/javascript/JavaScriptSemanticGraphChildProcessProjection.js +1 -1
- package/dist/application/javascript/JavaScriptSemanticGraphConstruction.js +7 -5
- package/dist/application/javascript/JavaScriptSemanticGraphDataProjection.js +1 -1
- package/dist/application/javascript/JavaScriptSemanticGraphEvidence.js +1 -1
- package/dist/application/javascript/JavaScriptSemanticGraphFingerprintProjection.js +2 -2
- package/dist/application/javascript/JavaScriptSemanticGraphFlowProjection.js +2 -2
- package/dist/application/javascript/JavaScriptSemanticGraphObjectProjection.js +1 -1
- package/dist/application/javascript/JavaScriptSemanticGraphProjection.js +4 -4
- package/dist/application/javascript/JavaScriptSemanticGraphResourceProjection.js +1 -1
- package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +10 -7
- package/dist/application/javascript/JavaScriptSemanticTraceService.js +15 -10
- package/dist/application/native/NativeCallRoutes.js +2 -4
- package/dist/artifacts/ArtifactProvider.js +14 -16
- package/dist/artifacts/ArtifactProviderMetadata.js +1 -4
- package/dist/artifacts/AsarArtifactReader.js +81 -17
- package/dist/artifacts/DirectoryArtifactReader.js +2 -2
- package/dist/artifacts/NativeDmgArtifactReader.js +152 -67
- package/dist/artifacts/NativeDmgOwnership.js +109 -0
- package/dist/artifacts/apple/KeyedArchiveReader.js +54 -46
- package/dist/artifacts/apple/MachoLoadCommandReader.js +36 -6
- package/dist/artifacts/extraction/ArtifactExtraction.js +29 -11
- package/dist/artifacts/inventory/ArtifactGraphConstruction.js +7 -8
- package/dist/artifacts/inventory/classify.js +33 -14
- package/dist/artifacts/inventory/hashStableRootArtifact.js +37 -0
- package/dist/artifacts/inventory/scanCanonical.js +28 -22
- package/dist/artifacts/inventory/scanReader.js +7 -11
- package/dist/artifacts/javascript/JavaScriptArtifactFiles.js +65 -27
- package/dist/browser/CdpBrowserProvider.js +4 -3
- package/dist/browser/CdpCaptureStorageFingerprints.js +3 -3
- package/dist/browser/CdpElectronInspection.js +2 -2
- package/dist/browser/CdpElectronProvider.js +4 -3
- package/dist/browser/CdpElectronScripts.js +2 -2
- package/dist/browser/CdpWebMcpDiscovery.js +16 -13
- package/dist/browser/PlaywrightBrowserScenarioProvider.js +6 -6
- package/dist/browser/PlaywrightScenarioBrowser.js +145 -42
- package/dist/browser/PlaywrightScenarioSession.js +3 -11
- package/dist/browser/WebSourceMapFetcher.js +32 -6
- package/dist/browser/assets/ScenarioScriptCapture.js +8 -12
- package/dist/cli/coreAnalysisCommands.js +2 -2
- package/dist/cli/coreBinaryCommands.js +13 -9
- package/dist/cli/electronCommands.js +9 -10
- package/dist/cli/javascriptApplicationAnalysis.js +2 -12
- package/dist/cli/jsonOutput.js +3 -2
- package/dist/cli/streamedJsonOutput.js +83 -4
- package/dist/cli/utilityCommands.js +2 -4
- package/dist/cli.js +5 -2
- package/dist/cliJsonFile.js +179 -0
- package/dist/cliJsonInput.js +47 -34
- package/dist/cliObservationOptions.js +4 -0
- package/dist/composition/auxiliaryAnalysisProviders.js +5 -4
- package/dist/composition/browserScenario.js +2 -2
- package/dist/composition/directAnalysis.js +2 -3
- package/dist/contracts/artifactComparisonExample.js +5 -5
- package/dist/contracts/errorSchemas.js +3 -1
- package/dist/contracts/functionComparisonExample.js +8 -0
- package/dist/contracts/inputSchemaPresentation.js +94 -3
- package/dist/contracts/javascript/electronToolContracts.js +2 -1
- package/dist/contracts/javascript/javascriptApplicationWorkflowExamples.js +3 -2
- package/dist/contracts/javascript/javascriptExportShapeComparisonExample.js +6 -3
- package/dist/contracts/javascript/javascriptRuntimeReconciliationExample.js +8 -7
- package/dist/contracts/managed/managedToolContracts.js +3 -2
- package/dist/contracts/mobileApplicationGraphExamples.js +5 -5
- package/dist/contracts/native/nativeToolContracts.js +1 -1
- package/dist/contracts/sessionLifecycleInputs.js +4 -3
- package/dist/contracts/sessionStatusContract.js +3 -2
- package/dist/contracts/sessionToolContracts.js +3 -2
- package/dist/contracts/sessionToolSchemas.js +3 -2
- package/dist/contracts/toolOutputSchemaGroups.js +2 -2
- package/dist/contracts/toolOutputSchemaPrimitives.js +2 -5
- package/dist/domain/analysisErrorBase.js +5 -0
- package/dist/domain/analysisErrorPresentation.js +4 -2
- package/dist/domain/analysisSnapshot.js +3 -1
- package/dist/domain/analysisView/analysisView.js +1 -3
- package/dist/domain/android/androidPartialObservation.js +36 -0
- package/dist/domain/apple/dylibResolution.js +1 -1
- package/dist/domain/artifactComparison.js +4 -4
- package/dist/domain/artifactGraph.js +1 -1
- package/dist/domain/artifactIdentity.js +8 -8
- package/dist/domain/artifactInspection.js +8 -8
- package/dist/domain/artifactInventoryEvidence.js +5 -5
- package/dist/domain/browserCompleteness.js +3 -2
- package/dist/domain/browserScenarioCaptureValues.js +2 -2
- package/dist/domain/browserScenarioNormalization.js +3 -3
- package/dist/domain/browserScenarioValues.js +3 -2
- package/dist/domain/callPath.js +8 -10
- package/dist/domain/canonicalDigest.js +7 -1
- package/dist/domain/canonicalOrdering.js +1 -13
- package/dist/domain/changedBehavior.js +2 -3
- package/dist/domain/comparisonSemantics.js +0 -5
- package/dist/domain/digests.js +0 -3
- package/dist/domain/evidence.js +10 -5
- package/dist/domain/evidenceBundle.js +51 -33
- package/dist/domain/firmware/firmwareAnalysis.js +4 -3
- package/dist/domain/functionComparison.js +2 -1
- package/dist/domain/functionComparisonNormalization.js +4 -3
- package/dist/domain/functionComparisonResults.js +2 -2
- package/dist/domain/functionDossierEvidence.js +2 -1
- package/dist/domain/hopperValues.js +11 -15
- package/dist/domain/javascript/electronActiveObservation.js +4 -3
- package/dist/domain/javascript/electronStaticAnalysisBrowser.js +2 -2
- package/dist/domain/javascript/electronStaticAnalysisIpc.js +9 -1
- package/dist/domain/javascript/electronStaticAnalysisNative.js +5 -3
- package/dist/domain/javascript/electronStaticAnalysisValues.js +8 -4
- package/dist/domain/javascript/javascriptApplicationAnalysis.js +3 -1
- package/dist/domain/javascript/javascriptApplicationChangeGraph.js +12 -8
- package/dist/domain/javascript/javascriptApplicationEvidenceSchemas.js +4 -0
- package/dist/domain/javascript/javascriptApplicationGraph.js +15 -13
- package/dist/domain/javascript/javascriptApplicationVersionComparison.js +4 -4
- package/dist/domain/javascript/javascriptApplicationVersionComparisonSchemas.js +37 -22
- package/dist/domain/javascript/javascriptApplicationVersionItems.js +45 -34
- package/dist/domain/javascript/javascriptApplicationVersionKeys.js +7 -7
- package/dist/domain/javascript/javascriptAstFingerprint.js +2 -2
- package/dist/domain/javascript/javascriptAstValues.js +22 -0
- package/dist/domain/javascript/javascriptExportShapeComparison.js +3 -2
- package/dist/domain/javascript/javascriptExportShapeComparisonSchemas.js +31 -23
- package/dist/domain/javascript/javascriptExportShapeSelection.js +2 -2
- package/dist/domain/javascript/javascriptExportShapeVariants.js +3 -2
- package/dist/domain/javascript/javascriptFeatureSeed.js +5 -3
- package/dist/domain/javascript/javascriptFeatureTrace.js +7 -6
- package/dist/domain/javascript/javascriptFeatureTraceSchemas.js +17 -9
- package/dist/domain/javascript/javascriptFeatureTraversal.js +4 -4
- package/dist/domain/javascript/javascriptNativeHandoff.js +6 -6
- package/dist/domain/javascript/javascriptRuntimeObservation.js +8 -5
- package/dist/domain/javascript/javascriptRuntimeReconciliation.js +12 -6
- package/dist/domain/javascript/javascriptRuntimeReconciliationActive.js +9 -8
- package/dist/domain/javascript/javascriptRuntimeReconciliationCaptureParsing.js +212 -0
- package/dist/domain/javascript/javascriptRuntimeReconciliationGraph.js +5 -4
- package/dist/domain/javascript/javascriptRuntimeReconciliationInputValidation.js +28 -0
- package/dist/domain/javascript/javascriptRuntimeReconciliationMatching.js +5 -5
- package/dist/domain/javascript/javascriptRuntimeReconciliationParsing.js +12 -223
- package/dist/domain/javascript/javascriptRuntimeReconciliationResult.js +2 -2
- package/dist/domain/javascript/javascriptRuntimeReconciliationRuntime.js +15 -4
- package/dist/domain/javascript/javascriptRuntimeReconciliationSchemas.js +2 -2
- package/dist/domain/javascript/javascriptRuntimeStaticCandidates.js +7 -6
- package/dist/domain/javascript/javascriptSemanticAnalysis.js +200 -8
- package/dist/domain/javascript/javascriptSemanticCallResolution.js +9 -7
- package/dist/domain/javascript/javascriptSemanticChildProcesses.js +2 -2
- package/dist/domain/javascript/javascriptSemanticCoverage.js +20 -0
- package/dist/domain/javascript/javascriptSemanticDataEffectHelpers.js +7 -9
- package/dist/domain/javascript/javascriptSemanticDataEffects.js +4 -11
- package/dist/domain/javascript/javascriptSemanticFingerprints.js +2 -2
- package/dist/domain/javascript/javascriptSemanticGraph.js +142 -35
- package/dist/domain/javascript/javascriptSemanticGraphSchemas.js +19 -1
- package/dist/domain/javascript/javascriptSemanticIr.js +0 -4
- package/dist/domain/javascript/javascriptSemanticIterationSources.js +106 -0
- package/dist/domain/javascript/javascriptSemanticMemberMutations.js +497 -113
- package/dist/domain/javascript/javascriptSemanticMutationInitializers.js +190 -0
- package/dist/domain/javascript/javascriptSemanticMutationValues.js +41 -27
- package/dist/domain/javascript/javascriptSemanticObjects.js +2 -6
- package/dist/domain/javascript/javascriptSemanticPrimitives.js +7 -2
- package/dist/domain/javascript/javascriptSemanticProjection.js +20 -14
- package/dist/domain/javascript/javascriptSemanticPromises.js +15 -21
- package/dist/domain/javascript/javascriptSemanticPropertyPaths.js +23 -0
- package/dist/domain/javascript/javascriptSemanticProvenance.js +3 -3
- package/dist/domain/javascript/javascriptSemanticQuery.js +8 -2
- package/dist/domain/javascript/javascriptSemanticQueryIdentity.js +3 -2
- package/dist/domain/javascript/javascriptSemanticQuerySchemas.js +8 -9
- package/dist/domain/javascript/javascriptSemanticRequireOrigin.js +16 -10
- package/dist/domain/javascript/javascriptSemanticReturns.js +23 -27
- package/dist/domain/javascript/javascriptSemanticTraversal.js +6 -1
- package/dist/domain/javascript/javascriptSemanticValues.js +135 -24
- package/dist/domain/javascript/javascriptSourceMapPaths.js +11 -1
- package/dist/domain/javascript/javascriptSourceParser.js +34 -9
- package/dist/domain/javascript/javascriptStaticAnalysisBundler.js +5 -6
- package/dist/domain/javascript/javascriptStaticAnalysisHelpers.js +26 -15
- package/dist/domain/javascript/sourceToBundleComparison.js +7 -5
- package/dist/domain/javascript/sourceToBundleSignals.js +7 -7
- package/dist/domain/jsonSerialization.js +109 -55
- package/dist/domain/jsonShape.js +46 -19
- package/dist/domain/localPath.js +10 -4
- package/dist/domain/managed/managedApplicationGraph.js +10 -6
- package/dist/domain/managed/managedApplicationGraphNodes.js +82 -57
- package/dist/domain/managed/managedMemberComparisonMatch.js +6 -7
- package/dist/domain/native/nativeCallObservation.js +2 -4
- package/dist/domain/native/nativeValueFlow.js +5 -11
- package/dist/domain/native/objcSwiftMetadata.js +15 -17
- package/dist/domain/process/processCapture.js +11 -10
- package/dist/domain/process/processCaptureCoverage.js +8 -5
- package/dist/domain/process/processCaptureExample.js +43 -0
- package/dist/domain/process/processCaptureValidation.js +4 -3
- package/dist/domain/process/processComparison.js +0 -23
- package/dist/domain/process/processScenario.js +3 -3
- package/dist/domain/process/processTraceEvaluation.js +4 -4
- package/dist/domain/process/processTraceSpecification.js +1 -3
- package/dist/domain/providerCleanupError.js +6 -2
- package/dist/domain/reconstructionCoverage.js +2 -1
- package/dist/domain/reconstructionUnknowns.js +4 -3
- package/dist/domain/reconstructionVerification.js +3 -2
- package/dist/domain/referenceSourceGraph.js +7 -7
- package/dist/domain/referenceSourceImportParsing.js +34 -45
- package/dist/domain/residualUnknown.js +3 -2
- package/dist/domain/staticRuntimeCorrelation.js +2 -1
- package/dist/domain/swiftSymbolClassification.js +6 -1
- package/dist/domain/symbolAnalysis.js +17 -2
- package/dist/domain/unicodeCodePointOrder.js +6 -0
- package/dist/domain/webBundleAnalyzerInspection.js +9 -1
- package/dist/domain/webCaptureDiff.js +71 -29
- package/dist/domain/webCaptureDiffSchemas.js +2 -8
- package/dist/domain/webInventory.js +3 -2
- package/dist/domain/webMcpDiscovery.js +4 -3
- package/dist/domain/webScriptExport.js +1 -1
- package/dist/dotnet/ManagedMemberInstructionDecoder.js +1 -2
- package/dist/dotnet/ManagedStaticProvider.js +10 -7
- package/dist/dotnet/ManagedStaticProviderMetadata.js +1 -4
- package/dist/filesystem/RegularFile.js +41 -0
- package/dist/generatedPackageMetadata.js +1 -1
- package/dist/ghidra/GhidraClient.js +14 -4
- package/dist/ghidra/GhidraInstallation.js +111 -10
- package/dist/ghidra/GhidraLauncher.js +43 -19
- package/dist/hopper/HopperCleanup.js +1 -1
- package/dist/ida/IdaOperationRunner.js +2 -0
- package/dist/ida/IdaSessionClient.js +4 -2
- package/dist/inspector/JavaScriptRuntimeScope.js +9 -5
- package/dist/inspector/V8InspectorCaptureProjection.js +46 -13
- package/dist/inspector/V8InspectorProvider.js +60 -8
- package/dist/main/shutdown.js +76 -32
- package/dist/main/transport.js +1 -1
- package/dist/native/AppleObjcDispatchFacets.js +3 -3
- package/dist/native/AppleObjcProperties.js +17 -7
- package/dist/native/LldbCallTracer.js +241 -75
- package/dist/native/NativeMacOSProvider.js +10 -5
- package/dist/native/NativeMacOSProviderMetadata.js +1 -2
- package/dist/process/ProcessOwnershipObservation.js +9 -13
- package/dist/process/capture/FilesystemSnapshot.js +88 -18
- package/dist/process/capture/ProcessCaptureLifecycle.js +13 -27
- package/dist/process/capture/ProcessFilesystemEffects.js +19 -4
- package/dist/process/capture/ProcessHarness.js +8 -21
- package/dist/server/analysisAdmission.js +8 -0
- package/dist/server/createServer.js +22 -23
- package/dist/server/registerApplicationTools/compareExportShapes.js +2 -1
- package/dist/server/registerApplicationTools/helpers.js +3 -2
- package/dist/server/registerArtifactTools.js +2 -2
- package/dist/server/registerCloseLifecycleTool.js +6 -4
- package/dist/server/registerEnhancedTools.js +78 -73
- package/dist/server/registerEvidenceTools.js +54 -46
- package/dist/server/registerManagedTools.js +7 -4
- package/dist/server/registerOfficialTools.js +31 -25
- package/dist/server/registerSessionTools.js +9 -3
- package/native/windows/build/manifest.json +1 -1
- package/package.json +6 -3
- package/skills/reverse-engineer-anything/SKILL.md +5 -5
- package/skills/reverse-engineer-anything/references/native-and-artifacts.md +9 -0
- package/dist/artifacts/inventory/policy.js +0 -2
- package/dist/domain/managed/managedApplicationGraphNodeCoverage.js +0 -6
- package/dist/server/registerNativeTools.js +0 -6
|
@@ -6,6 +6,10 @@ import { AnalysisError } from "../domain/analysisErrorBase.js";
|
|
|
6
6
|
import { BrowserObservationError } from "../domain/browserObservationError.js";
|
|
7
7
|
import { withPlaywrightExecutionBoundary } from "./PlaywrightExecutionBoundary.js";
|
|
8
8
|
const OPERATION = "capture_browser_scenario";
|
|
9
|
+
const throwIfScenarioCancelled = (signal) => {
|
|
10
|
+
if (signal?.aborted === true)
|
|
11
|
+
throw new BrowserObservationError(OPERATION, "cancelled");
|
|
12
|
+
};
|
|
9
13
|
/** Owns one browser connection and optional private profile through cleanup retries. */
|
|
10
14
|
export class PlaywrightScenarioBrowserCleanupOwner {
|
|
11
15
|
resources;
|
|
@@ -22,9 +26,10 @@ export class PlaywrightScenarioBrowserCleanupOwner {
|
|
|
22
26
|
const cleanup = this.#closePromise ?? this.#closeResources(finishEvents);
|
|
23
27
|
if (this.#closePromise === undefined) {
|
|
24
28
|
this.#closePromise = cleanup;
|
|
25
|
-
void cleanup.
|
|
29
|
+
void cleanup.then(() => this.resources.onSettled?.(this.#browserClosed), () => {
|
|
26
30
|
if (this.#closePromise === cleanup)
|
|
27
31
|
this.#closePromise = undefined;
|
|
32
|
+
this.resources.onSettled?.(this.#browserClosed);
|
|
28
33
|
});
|
|
29
34
|
}
|
|
30
35
|
return this.#awaitCleanup(cleanup, signal);
|
|
@@ -86,6 +91,79 @@ export class PlaywrightScenarioBrowserCleanupOwner {
|
|
|
86
91
|
throw new AggregateError(failures, "Browser session cleanup failed");
|
|
87
92
|
}
|
|
88
93
|
}
|
|
94
|
+
const attachedScenarioAdmissions = new Map();
|
|
95
|
+
const releaseAttachedScenario = (key, admission) => {
|
|
96
|
+
const waiter = admission.waiters.shift();
|
|
97
|
+
if (waiter === undefined) {
|
|
98
|
+
admission.active = false;
|
|
99
|
+
if (admission.cleanupOwner === undefined &&
|
|
100
|
+
attachedScenarioAdmissions.get(key) === admission)
|
|
101
|
+
attachedScenarioAdmissions.delete(key);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (waiter.onAbort !== undefined)
|
|
105
|
+
waiter.signal?.removeEventListener("abort", waiter.onAbort);
|
|
106
|
+
if (waiter.signal?.aborted === true) {
|
|
107
|
+
waiter.reject(new BrowserObservationError(OPERATION, "cancelled"));
|
|
108
|
+
releaseAttachedScenario(key, admission);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
waiter.resolve(createAttachedScenarioRelease(key, admission));
|
|
112
|
+
};
|
|
113
|
+
const createAttachedScenarioRelease = (key, admission) => {
|
|
114
|
+
let released = false;
|
|
115
|
+
return () => {
|
|
116
|
+
if (released)
|
|
117
|
+
return;
|
|
118
|
+
released = true;
|
|
119
|
+
releaseAttachedScenario(key, admission);
|
|
120
|
+
};
|
|
121
|
+
};
|
|
122
|
+
const acquireAttachedScenario = (scenario, signal) => {
|
|
123
|
+
if (signal?.aborted === true)
|
|
124
|
+
return Promise.reject(new BrowserObservationError(OPERATION, "cancelled"));
|
|
125
|
+
const key = JSON.stringify([scenario.cdp_endpoint, scenario.target_id]);
|
|
126
|
+
const admission = attachedScenarioAdmissions.get(key) ??
|
|
127
|
+
{
|
|
128
|
+
active: false,
|
|
129
|
+
waiters: [],
|
|
130
|
+
cleanupOwner: undefined,
|
|
131
|
+
};
|
|
132
|
+
attachedScenarioAdmissions.set(key, admission);
|
|
133
|
+
return new Promise((resolve, reject) => {
|
|
134
|
+
const grant = (release) => resolve({ admission, release });
|
|
135
|
+
if (!admission.active) {
|
|
136
|
+
admission.active = true;
|
|
137
|
+
grant(createAttachedScenarioRelease(key, admission));
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
const waiter = {
|
|
141
|
+
signal,
|
|
142
|
+
resolve: (release) => grant(release),
|
|
143
|
+
reject,
|
|
144
|
+
onAbort: undefined,
|
|
145
|
+
};
|
|
146
|
+
admission.waiters.push(waiter);
|
|
147
|
+
if (signal !== undefined) {
|
|
148
|
+
const onAbort = () => {
|
|
149
|
+
const index = admission.waiters.indexOf(waiter);
|
|
150
|
+
if (index < 0)
|
|
151
|
+
return;
|
|
152
|
+
admission.waiters.splice(index, 1);
|
|
153
|
+
signal.removeEventListener("abort", onAbort);
|
|
154
|
+
reject(new BrowserObservationError(OPERATION, "cancelled"));
|
|
155
|
+
if (!admission.active && admission.waiters.length === 0)
|
|
156
|
+
releaseAttachedScenario(key, admission);
|
|
157
|
+
};
|
|
158
|
+
waiter.onAbort = onAbort;
|
|
159
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
160
|
+
if (signal.aborted) {
|
|
161
|
+
onAbort();
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
};
|
|
89
167
|
const allowedBrowserEnvironment = (environment) => {
|
|
90
168
|
const allowed = [
|
|
91
169
|
"DBUS_SESSION_BUS_ADDRESS",
|
|
@@ -106,12 +184,14 @@ const allowedBrowserEnvironment = (environment) => {
|
|
|
106
184
|
.map((name) => [name, environment[name]])
|
|
107
185
|
.filter((entry) => entry[1] !== undefined));
|
|
108
186
|
};
|
|
109
|
-
const findConnectedPage = async (browser, targetId) => {
|
|
187
|
+
const findConnectedPage = async (browser, targetId, signal) => {
|
|
110
188
|
for (const context of browser.contexts())
|
|
111
189
|
for (const page of context.pages()) {
|
|
112
190
|
const session = await context.newCDPSession(page);
|
|
113
191
|
try {
|
|
192
|
+
throwIfScenarioCancelled(signal);
|
|
114
193
|
const { targetInfo } = await session.send("Target.getTargetInfo");
|
|
194
|
+
throwIfScenarioCancelled(signal);
|
|
115
195
|
if (targetInfo.targetId !== targetId)
|
|
116
196
|
continue;
|
|
117
197
|
return { context, page };
|
|
@@ -122,33 +202,33 @@ const findConnectedPage = async (browser, targetId) => {
|
|
|
122
202
|
}
|
|
123
203
|
throw new BrowserObservationError(OPERATION, "target_not_found");
|
|
124
204
|
};
|
|
125
|
-
const configureAttachedEnvironment = async (context, page,
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
height: scenario.environment.viewport.height,
|
|
129
|
-
});
|
|
205
|
+
const configureAttachedEnvironment = async (context, page, environment, signal) => {
|
|
206
|
+
// setViewportSize also resizes the external browser window. The scenario's
|
|
207
|
+
// CDP metrics override below supplies the viewport and expires on disconnect.
|
|
130
208
|
await page.emulateMedia({
|
|
131
|
-
colorScheme:
|
|
132
|
-
reducedMotion:
|
|
209
|
+
colorScheme: environment.color_scheme,
|
|
210
|
+
reducedMotion: environment.reduced_motion,
|
|
133
211
|
});
|
|
212
|
+
throwIfScenarioCancelled(signal);
|
|
134
213
|
const session = await context.newCDPSession(page);
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
214
|
+
throwIfScenarioCancelled(signal);
|
|
215
|
+
// Chromium resets these overrides when the CDP session detaches. Keep it on
|
|
216
|
+
// the scenario transport until cleanup disconnects the attached browser.
|
|
217
|
+
await session.send("Emulation.setDeviceMetricsOverride", {
|
|
218
|
+
width: environment.viewport.width,
|
|
219
|
+
height: environment.viewport.height,
|
|
220
|
+
deviceScaleFactor: environment.viewport.device_scale_factor,
|
|
221
|
+
mobile: false,
|
|
222
|
+
dontSetVisibleSize: true,
|
|
223
|
+
});
|
|
224
|
+
throwIfScenarioCancelled(signal);
|
|
225
|
+
await session.send("Emulation.setLocaleOverride", {
|
|
226
|
+
locale: environment.locale,
|
|
227
|
+
});
|
|
228
|
+
throwIfScenarioCancelled(signal);
|
|
229
|
+
await session.send("Emulation.setTimezoneOverride", {
|
|
230
|
+
timezoneId: environment.timezone,
|
|
231
|
+
});
|
|
152
232
|
};
|
|
153
233
|
/** Preserve an operation failure while reporting any incomplete cleanup. */
|
|
154
234
|
export const failBrowserScenarioOperation = async (cleanup, primaryFailure, fallbackCleanupResources = ["browser_transport"]) => {
|
|
@@ -174,28 +254,51 @@ export const failBrowserScenarioOperation = async (cleanup, primaryFailure, fall
|
|
|
174
254
|
}
|
|
175
255
|
throw primaryFailure;
|
|
176
256
|
};
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
257
|
+
const openAttachedScenarioBrowser = async (browserRequest, environment, launcher, signal) => {
|
|
258
|
+
const lease = await acquireAttachedScenario(browserRequest, signal);
|
|
259
|
+
let cleanupOwner;
|
|
260
|
+
try {
|
|
261
|
+
const priorOwner = lease.admission.cleanupOwner;
|
|
262
|
+
if (priorOwner !== undefined)
|
|
263
|
+
await priorOwner.close();
|
|
264
|
+
throwIfScenarioCancelled(signal);
|
|
265
|
+
const browser = await launcher.connectOverCDP(browserRequest.cdp_endpoint);
|
|
181
266
|
const cleanup = new PlaywrightScenarioBrowserCleanupOwner({
|
|
182
267
|
closeBrowser: () => browser.close(),
|
|
268
|
+
onSettled: (browserClosed) => {
|
|
269
|
+
if (browserClosed && lease.admission.cleanupOwner === cleanup)
|
|
270
|
+
lease.admission.cleanupOwner = undefined;
|
|
271
|
+
lease.release();
|
|
272
|
+
},
|
|
183
273
|
removeProfile: undefined,
|
|
184
274
|
});
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
275
|
+
cleanupOwner = cleanup;
|
|
276
|
+
lease.admission.cleanupOwner = cleanup;
|
|
277
|
+
throwIfScenarioCancelled(signal);
|
|
278
|
+
const target = await withPlaywrightExecutionBoundary(() => findConnectedPage(browser, browserRequest.target_id, signal), undefined, signal);
|
|
279
|
+
throwIfScenarioCancelled(signal);
|
|
280
|
+
await withPlaywrightExecutionBoundary(() => configureAttachedEnvironment(target.context, target.page, environment, signal), undefined, signal);
|
|
281
|
+
return {
|
|
282
|
+
...target,
|
|
283
|
+
browser,
|
|
284
|
+
profilePath: undefined,
|
|
285
|
+
cleanup,
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
catch (cause) {
|
|
289
|
+
if (cleanupOwner === undefined) {
|
|
290
|
+
lease.release();
|
|
291
|
+
throw cause;
|
|
197
292
|
}
|
|
293
|
+
const cleanup = cleanupOwner;
|
|
294
|
+
return failBrowserScenarioOperation(() => cleanup.close(), cause);
|
|
198
295
|
}
|
|
296
|
+
};
|
|
297
|
+
/** Launch or attach using the caller-selected environment and browser engine. */
|
|
298
|
+
export const openPlaywrightScenarioBrowser = async (scenario, environment, options = {}) => {
|
|
299
|
+
const launcher = options.launcher ?? chromium;
|
|
300
|
+
if (scenario.browser.mode === "connect")
|
|
301
|
+
return openAttachedScenarioBrowser(scenario.browser, scenario.environment, launcher, options.signal);
|
|
199
302
|
const profilePath = await mkdtemp(join(tmpdir(), "rea-browser-scenario-"));
|
|
200
303
|
let context;
|
|
201
304
|
try {
|
|
@@ -86,7 +86,9 @@ export class PlaywrightScenarioSession {
|
|
|
86
86
|
if (secrets === undefined)
|
|
87
87
|
throw new BrowserObservationError(OPERATION, "secret_unavailable");
|
|
88
88
|
const startedAt = Date.now();
|
|
89
|
-
const opening = openPlaywrightScenarioBrowser(scenario, environment
|
|
89
|
+
const opening = openPlaywrightScenarioBrowser(scenario, environment, {
|
|
90
|
+
signal: options.signal,
|
|
91
|
+
});
|
|
90
92
|
let opened;
|
|
91
93
|
let events;
|
|
92
94
|
try {
|
|
@@ -203,13 +205,3 @@ export class PlaywrightScenarioSession {
|
|
|
203
205
|
return this.secrets.redact(error instanceof Error ? error.message : "browser action failed");
|
|
204
206
|
}
|
|
205
207
|
}
|
|
206
|
-
/** Production Playwright/CDP session factory. */
|
|
207
|
-
export class PlaywrightScenarioSessionFactory {
|
|
208
|
-
environment;
|
|
209
|
-
constructor(environment) {
|
|
210
|
-
this.environment = environment;
|
|
211
|
-
}
|
|
212
|
-
open(scenario, options = {}) {
|
|
213
|
-
return PlaywrightScenarioSession.open(scenario, this.environment, options);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
@@ -106,6 +106,12 @@ class SourceMapEncodingError extends Error {
|
|
|
106
106
|
this.name = "SourceMapEncodingError";
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
|
+
class SourceMapRedirectLocationError extends Error {
|
|
110
|
+
constructor(url, location) {
|
|
111
|
+
super(`Source-map redirect from ${JSON.stringify(url)} supplied an invalid Location URL: ${JSON.stringify(location)}.`);
|
|
112
|
+
this.name = "SourceMapRedirectLocationError";
|
|
113
|
+
}
|
|
114
|
+
}
|
|
109
115
|
const fetchOne = async (request, input, signal, host, budget) => {
|
|
110
116
|
if (!approvedUrl(request.fetchUrl, input.allowed_origins))
|
|
111
117
|
return emptySourceMapItem(request, "policy_filtered", "Declared source-map URL is outside the approved exact origins.");
|
|
@@ -131,13 +137,25 @@ const fetchOne = async (request, input, signal, host, budget) => {
|
|
|
131
137
|
throw cause;
|
|
132
138
|
if (cause instanceof SourceMapEncodingError)
|
|
133
139
|
return emptySourceMapItem(request, "invalid", cause.message);
|
|
134
|
-
return emptySourceMapItem(request, "fetch_failed", cause instanceof
|
|
140
|
+
return emptySourceMapItem(request, "fetch_failed", cause instanceof SourceMapRedirectLocationError ||
|
|
141
|
+
cause instanceof SourceMapSizeLimitError ||
|
|
142
|
+
cause instanceof SourceMapDeadlineError
|
|
135
143
|
? cause.message
|
|
136
|
-
:
|
|
137
|
-
? cause.message
|
|
138
|
-
: "Source-map fetch or validation failed.");
|
|
144
|
+
: "Source-map fetch or validation failed.");
|
|
139
145
|
}
|
|
140
146
|
};
|
|
147
|
+
/**
|
|
148
|
+
* Fetch redirect statuses per WHATWG Fetch (redirect status list:
|
|
149
|
+
* 301, 302, 303, 307, 308). Single owner for redirect decisions.
|
|
150
|
+
* 300/304/305/306 carry `Location` without being redirects — following
|
|
151
|
+
* them would replace the observed failure with an unrelated map.
|
|
152
|
+
* See https://fetch.spec.whatwg.org/#redirect-status
|
|
153
|
+
*/
|
|
154
|
+
export const isFetchRedirectStatus = (status) => status === 301 ||
|
|
155
|
+
status === 302 ||
|
|
156
|
+
status === 303 ||
|
|
157
|
+
status === 307 ||
|
|
158
|
+
status === 308;
|
|
141
159
|
const fetchFollowingApprovedRedirects = async (initialUrl, allowedOrigins, signal, host) => {
|
|
142
160
|
let current = initialUrl;
|
|
143
161
|
const visited = new Set();
|
|
@@ -163,13 +181,21 @@ const fetchFollowingApprovedRedirects = async (initialUrl, allowedOrigins, signa
|
|
|
163
181
|
await response.body?.cancel(signal.reason).catch(() => undefined);
|
|
164
182
|
throw signal.reason;
|
|
165
183
|
}
|
|
166
|
-
|
|
184
|
+
// `Location` is a redirect target only for Fetch redirect statuses.
|
|
185
|
+
// Other 3xx responses retain their own HTTP failure (strict identity:
|
|
186
|
+
// never replace the observed failure with an unrelated map).
|
|
187
|
+
if (!isFetchRedirectStatus(response.status))
|
|
167
188
|
return { response, fetchedUrl: current };
|
|
168
189
|
const location = response.headers.get("location");
|
|
169
190
|
if (location === null)
|
|
170
191
|
return { response, fetchedUrl: current };
|
|
171
192
|
await response.body?.cancel();
|
|
172
|
-
|
|
193
|
+
try {
|
|
194
|
+
current = new URL(location, current).href;
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
throw new SourceMapRedirectLocationError(current, location);
|
|
198
|
+
}
|
|
173
199
|
}
|
|
174
200
|
};
|
|
175
201
|
const readBoundedText = async (response, budget, maxBytes, signal) => {
|
|
@@ -14,9 +14,9 @@ const indexResponses = (events) => {
|
|
|
14
14
|
requests: new Map(),
|
|
15
15
|
};
|
|
16
16
|
for (const event of events) {
|
|
17
|
-
if (event.kind === "request"
|
|
17
|
+
if (event.kind === "request")
|
|
18
18
|
index.requests.set(event.transaction_id, (index.requests.get(event.transaction_id) ?? 0) + 1);
|
|
19
|
-
if (event.kind === "response"
|
|
19
|
+
if (event.kind === "response")
|
|
20
20
|
append(index.responses, event.transaction_id, event);
|
|
21
21
|
if (event.kind === "network-content" && event.phase === "response")
|
|
22
22
|
append(index.contents, event.source_event_sequence, event);
|
|
@@ -25,33 +25,29 @@ const indexResponses = (events) => {
|
|
|
25
25
|
};
|
|
26
26
|
const projectRequest = (request, index) => {
|
|
27
27
|
const id = request.transaction_id;
|
|
28
|
-
const matches =
|
|
28
|
+
const matches = index.responses.get(id) ?? [];
|
|
29
29
|
const response = matches.length === 1 ? matches[0] : undefined;
|
|
30
30
|
const bodies = response === undefined ? [] : (index.contents.get(response.sequence) ?? []);
|
|
31
31
|
const body = bodies.length === 1 ? bodies[0]?.body : undefined;
|
|
32
|
-
const ambiguous =
|
|
33
|
-
matches.length > 1 ||
|
|
34
|
-
bodies.length > 1;
|
|
32
|
+
const ambiguous = index.requests.get(id) !== 1 || matches.length > 1 || bodies.length > 1;
|
|
35
33
|
return {
|
|
36
34
|
source: {
|
|
37
35
|
kind: "scenario-response",
|
|
38
|
-
transaction_id: id
|
|
36
|
+
transaction_id: id,
|
|
39
37
|
request_sequence: request.sequence,
|
|
40
38
|
response_sequence: ambiguous ? null : (response?.sequence ?? null),
|
|
41
39
|
status: ambiguous ? null : (response?.status ?? null),
|
|
42
40
|
},
|
|
43
41
|
url: request.url.url,
|
|
44
|
-
content: projectBody(body,
|
|
42
|
+
content: projectBody(body, ambiguous),
|
|
45
43
|
};
|
|
46
44
|
};
|
|
47
45
|
const unavailable = (reason, message) => ({ state: "unavailable", reason, message });
|
|
48
|
-
const projectBody = (body,
|
|
46
|
+
const projectBody = (body, ambiguous) => {
|
|
49
47
|
if (ambiguous)
|
|
50
48
|
return unavailable("ambiguous-transaction", "The capture does not identify one request, response, and content record for this transaction.");
|
|
51
49
|
if (body === undefined)
|
|
52
|
-
return unavailable(
|
|
53
|
-
? "transaction-identity-unavailable"
|
|
54
|
-
: "response-content-not-retained", "No selected, completed script response bytes were retained for this request.");
|
|
50
|
+
return unavailable("response-content-not-retained", "No selected, completed script response bytes were retained for this request.");
|
|
55
51
|
if (body.state === "unavailable")
|
|
56
52
|
return unavailable(body.reason, body.message);
|
|
57
53
|
if (body.state !== "captured")
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { registerCoreBinaryCommands } from "./coreBinaryCommands.js";
|
|
2
2
|
import { registerCoreNativeCommands } from "./coreNativeCommands.js";
|
|
3
3
|
/** Register core binary and native deep-analysis CLI commands. */
|
|
4
|
-
export const registerCoreAnalysisCommands = (cli, logger, runDirectAnalysis
|
|
5
|
-
registerCoreBinaryCommands(cli, logger, runDirectAnalysis
|
|
4
|
+
export const registerCoreAnalysisCommands = (cli, logger, runDirectAnalysis) => {
|
|
5
|
+
registerCoreBinaryCommands(cli, logger, runDirectAnalysis);
|
|
6
6
|
registerCoreNativeCommands(cli, logger, runDirectAnalysis);
|
|
7
7
|
};
|
|
@@ -7,9 +7,10 @@ import { logCliCommand } from "../cliLogging.js";
|
|
|
7
7
|
import { directAnalysisOptions, formatSelectionOption, providerSelectionOption, } from "./options.js";
|
|
8
8
|
import { runCliJavaScriptApplicationAnalysis } from "./javascriptApplicationAnalysis.js";
|
|
9
9
|
import { withCommandCancellation } from "./commandCancellation.js";
|
|
10
|
+
import { javascriptApplicationOptions } from "../cliObservationOptions.js";
|
|
10
11
|
/** Register provider-neutral binary overview and procedure CLI commands. */
|
|
11
|
-
export const registerCoreBinaryCommands = (cli, logger, runDirectAnalysis
|
|
12
|
-
registerOverviewCommands(cli, logger, runDirectAnalysis
|
|
12
|
+
export const registerCoreBinaryCommands = (cli, logger, runDirectAnalysis) => {
|
|
13
|
+
registerOverviewCommands(cli, logger, runDirectAnalysis);
|
|
13
14
|
registerDecompileCommand(cli, logger, runDirectAnalysis);
|
|
14
15
|
registerFunctionCommand(cli, logger, runDirectAnalysis);
|
|
15
16
|
registerInstructionsCommand(cli, logger, runDirectAnalysis);
|
|
@@ -17,7 +18,7 @@ export const registerCoreBinaryCommands = (cli, logger, runDirectAnalysis, resul
|
|
|
17
18
|
registerXrefsCommand(cli, logger, runDirectAnalysis);
|
|
18
19
|
registerTraceCommand(cli, logger, runDirectAnalysis);
|
|
19
20
|
};
|
|
20
|
-
const registerOverviewCommands = (cli, logger, runDirectAnalysis
|
|
21
|
+
const registerOverviewCommands = (cli, logger, runDirectAnalysis) => {
|
|
21
22
|
const overviewOptions = z.object({
|
|
22
23
|
snapshot: z
|
|
23
24
|
.string()
|
|
@@ -32,16 +33,19 @@ const registerOverviewCommands = (cli, logger, runDirectAnalysis, resultOutput)
|
|
|
32
33
|
args: z.object({
|
|
33
34
|
path: z.string().describe("App, program, or analysis database path"),
|
|
34
35
|
}),
|
|
35
|
-
options: overviewOptions
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
options: overviewOptions.extend({
|
|
37
|
+
integrityPolicy: javascriptApplicationOptions.shape.integrityPolicy,
|
|
38
|
+
}),
|
|
39
|
+
alias: { integrityPolicy: "integrity-policy" },
|
|
40
|
+
run: async ({ args, options }) => {
|
|
40
41
|
// Route JavaScript targets exactly like analyze-javascript-application,
|
|
41
42
|
// including typed cancellation; cancellation wraps logging so its exit
|
|
42
43
|
// code is not replaced by the logged failure status.
|
|
43
44
|
if (await routesToJavaScriptAnalysis(args.path, options))
|
|
44
|
-
return withCommandCancellation((signal) => logCliCommand(logger, "analyze", () => runCliJavaScriptApplicationAnalysis({
|
|
45
|
+
return withCommandCancellation((signal) => logCliCommand(logger, "analyze", () => runCliJavaScriptApplicationAnalysis({
|
|
46
|
+
input_path: resolve(args.path),
|
|
47
|
+
integrity_policy: options.integrityPolicy,
|
|
48
|
+
}, signal)));
|
|
45
49
|
return logCliCommand(logger, "analyze", () => runDirectAnalysis(args.path, "binary_overview", {}, directAnalysisOptions(logger, options.snapshot, options.provider, options["target-format"])));
|
|
46
50
|
},
|
|
47
51
|
});
|
|
@@ -14,10 +14,10 @@ import { electronPageInspectionOptions, javascriptApplicationOptions, } from "..
|
|
|
14
14
|
import { runCliJavaScriptApplicationAnalysis } from "./javascriptApplicationAnalysis.js";
|
|
15
15
|
import { withCommandCancellation } from "./commandCancellation.js";
|
|
16
16
|
/** Register CLI equivalents of the Electron MCP tools. */
|
|
17
|
-
export const registerElectronCommands = (cli, logger, environment
|
|
17
|
+
export const registerElectronCommands = (cli, logger, environment) => {
|
|
18
18
|
registerElectronObservationCommands(cli, logger);
|
|
19
19
|
registerElectronActiveCommand(cli, logger, environment);
|
|
20
|
-
registerJavaScriptApplicationCommand(cli, logger
|
|
20
|
+
registerJavaScriptApplicationCommand(cli, logger);
|
|
21
21
|
registerJavaScriptRuntimeReconciliationCommand(cli, logger);
|
|
22
22
|
};
|
|
23
23
|
const registerElectronActiveCommand = (cli, logger, environment) => {
|
|
@@ -107,20 +107,19 @@ const registerElectronPageInspection = (cli, logger) => {
|
|
|
107
107
|
}),
|
|
108
108
|
});
|
|
109
109
|
};
|
|
110
|
-
const registerJavaScriptApplicationCommand = (cli, logger
|
|
110
|
+
const registerJavaScriptApplicationCommand = (cli, logger) => {
|
|
111
111
|
cli.command(CLI_COMMANDS.analyzeJavaScriptApplication, {
|
|
112
112
|
description: "Statically reconstruct a local JavaScript/Electron application",
|
|
113
113
|
args: z.object({
|
|
114
114
|
path: z.string().describe("ASAR or extracted application path"),
|
|
115
115
|
}),
|
|
116
116
|
options: javascriptApplicationOptions,
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
:
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
}, signal))),
|
|
117
|
+
alias: { integrityPolicy: "integrity-policy" },
|
|
118
|
+
run: ({ args, options }) => withCommandCancellation((signal) => logCliCommand(logger, CLI_COMMANDS.analyzeJavaScriptApplication, () => runCliJavaScriptApplicationAnalysis({
|
|
119
|
+
input_path: args.path,
|
|
120
|
+
format: options.artifactFormat,
|
|
121
|
+
integrity_policy: options.integrityPolicy,
|
|
122
|
+
}, signal))),
|
|
124
123
|
});
|
|
125
124
|
};
|
|
126
125
|
const electronObservationContext = async () => {
|
|
@@ -2,8 +2,7 @@ import { analyzeJavaScriptApplication } from "../application/javascript/JavaScri
|
|
|
2
2
|
import { createProgressReporter } from "../application/ProgressReporter.js";
|
|
3
3
|
import { projectAnalysisError } from "../domain/analysisErrorProjection.js";
|
|
4
4
|
/** Execute the shared one-shot CLI boundary for static JavaScript analysis. */
|
|
5
|
-
export const runCliJavaScriptApplicationAnalysis = async (input,
|
|
6
|
-
const started = performance.now();
|
|
5
|
+
export const runCliJavaScriptApplicationAnalysis = async (input, signal) => {
|
|
7
6
|
const progress = createProgressReporter(async (update) => {
|
|
8
7
|
process.stderr.write(`${JSON.stringify({ rea_progress: update })}\n`);
|
|
9
8
|
}, { minimumIntervalMs: 0 });
|
|
@@ -11,16 +10,7 @@ export const runCliJavaScriptApplicationAnalysis = async (input, output, signal)
|
|
|
11
10
|
progress,
|
|
12
11
|
...(signal === undefined ? {} : { signal }),
|
|
13
12
|
});
|
|
14
|
-
|
|
15
|
-
if (output !== undefined &&
|
|
16
|
-
(await output.output.write(value, {
|
|
17
|
-
command: output.command,
|
|
18
|
-
format: output.format,
|
|
19
|
-
duration: `${Math.round(performance.now() - started)}ms`,
|
|
20
|
-
})))
|
|
21
|
-
// Keep failures visible to command logging after the stream has handled stdout.
|
|
22
|
-
return result.ok ? undefined : value;
|
|
23
|
-
return value;
|
|
13
|
+
return result.ok ? result.value : cliError(result.error);
|
|
24
14
|
};
|
|
25
15
|
const cliError = (error) => ({
|
|
26
16
|
error: "JavaScript application analysis failed",
|
package/dist/cli/jsonOutput.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { bufferedJsonParts, jsonParts } from "../domain/jsonSerialization.js";
|
|
2
2
|
/** Write ordinary JSON without constructing a document-sized string. */
|
|
3
3
|
export const writeJsonOutput = async (value, destination, format = "json") => {
|
|
4
|
-
for (const part of bufferedJsonParts(
|
|
4
|
+
for (const part of bufferedJsonParts(jsonOutputParts(value, format)))
|
|
5
5
|
await writePart(destination, part);
|
|
6
6
|
};
|
|
7
7
|
const writePart = (destination, part) => new Promise((resolve, reject) => {
|
|
@@ -25,7 +25,8 @@ const writePart = (destination, part) => new Promise((resolve, reject) => {
|
|
|
25
25
|
reject(cause);
|
|
26
26
|
}
|
|
27
27
|
});
|
|
28
|
-
|
|
28
|
+
/** The exact formatted document, including its final newline. */
|
|
29
|
+
export function* jsonOutputParts(value, format) {
|
|
29
30
|
if (format === "jsonl" && Array.isArray(value)) {
|
|
30
31
|
for (const item of value) {
|
|
31
32
|
yield* jsonParts(item);
|