rea-agents 1.6.0 → 2.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 +157 -66
- package/bridge/ghidra/ReaGhidraBridge.java +2075 -0
- package/bridge/hopper_bridge.py +13 -3
- package/dist/application/AbortablePromise.js +25 -0
- package/dist/application/AnalysisProvider.js +3 -0
- package/dist/application/AnalysisProviderEvaluation.js +60 -0
- package/dist/application/AnalysisProviderRegistry.js +228 -0
- package/dist/application/AnalysisSnapshotCache.js +41 -21
- package/dist/application/AnalysisSnapshotFiles.js +5 -6
- package/dist/application/BinarySession.js +218 -101
- package/dist/application/CapabilityInventory.js +18 -0
- package/dist/application/CompositeProvider.js +20 -8
- package/dist/application/CrossVersionInvestigation.js +10 -6
- package/dist/application/DirectAnalysis.js +49 -35
- package/dist/application/Doctor.js +110 -8
- package/dist/application/ElectronBoundaryAnalysis.js +96 -0
- package/dist/application/ElectronBoundaryGraph.js +9 -0
- package/dist/application/ElectronBoundaryGraphContext.js +62 -0
- package/dist/application/ElectronBoundaryGraphIpc.js +242 -0
- package/dist/application/ElectronBoundaryGraphNative.js +86 -0
- package/dist/application/ElectronBoundaryGraphWindows.js +199 -0
- package/dist/application/EnhancedTools.js +39 -14
- package/dist/application/InvestigationProviders.js +41 -0
- package/dist/application/JavaScriptApplicationEvidence.js +26 -0
- package/dist/application/JavaScriptApplicationEvidenceGraph.js +89 -0
- package/dist/application/JavaScriptApplicationService.js +74 -0
- package/dist/application/JavaScriptApplicationWorkflowEvidence.js +29 -0
- package/dist/application/JavaScriptApplicationWorkflowService.js +90 -0
- package/dist/application/JavaScriptArtifactAnalysis.js +305 -0
- package/dist/application/JavaScriptArtifactAnalysisTypes.js +1 -0
- package/dist/application/JavaScriptArtifactFiles.js +231 -0
- package/dist/application/JavaScriptArtifactGraphAccumulator.js +54 -0
- package/dist/application/JavaScriptArtifactGraphBuilder.js +144 -0
- package/dist/application/JavaScriptArtifactGraphContext.js +205 -0
- package/dist/application/JavaScriptArtifactGraphDocuments.js +108 -0
- package/dist/application/JavaScriptArtifactGraphEvidence.js +99 -0
- package/dist/application/JavaScriptArtifactGraphFindings.js +271 -0
- package/dist/application/JavaScriptArtifactGraphStructure.js +409 -0
- package/dist/application/JavaScriptArtifactReconstruction.js +77 -0
- package/dist/application/JavaScriptArtifactReconstructionInput.js +18 -0
- package/dist/application/JavaScriptReplayPlanning.js +201 -0
- package/dist/application/JavaScriptReplayService.js +266 -0
- package/dist/application/JavaScriptRuntimeReconciliationEvidence.js +25 -0
- package/dist/application/JavaScriptRuntimeReconciliationService.js +27 -0
- package/dist/application/MacHopper.js +20 -4
- package/dist/application/ManagedApplicationGraphService.js +55 -0
- package/dist/application/ManagedMemberComparisonService.js +122 -0
- package/dist/application/ManagedNativeVerificationService.js +39 -0
- package/dist/application/ManagedReconstructionService.js +58 -0
- package/dist/application/ManagedRuntimeCorrelationService.js +103 -0
- package/dist/application/PermissionAuthority.js +1 -1
- package/dist/application/ProcessCaptureLifecycle.js +1 -1
- package/dist/application/ProcessHarness.js +1 -1
- package/dist/application/ProcessSampling.js +16 -12
- package/dist/application/ProjectPermissionStore.js +1 -0
- package/dist/application/SessionProviderRouter.js +219 -0
- package/dist/application/Setup.js +84 -60
- package/dist/application/SetupClients.js +1 -1
- package/dist/application/SetupPlan.js +9 -2
- package/dist/application/SupportedClients.js +40 -16
- package/dist/application/Upgrade.js +1 -1
- package/dist/application/runtime.js +11 -6
- package/dist/artifacts/AsarArtifactReader.js +23 -3
- package/dist/browser/CdpBrowserProvider.js +4 -2
- package/dist/browser/CdpCaptureEvents.js +49 -0
- package/dist/browser/CdpElectronInspection.js +106 -162
- package/dist/browser/CdpElectronProvider.js +9 -3
- package/dist/browser/CdpElectronScriptEvents.js +69 -0
- package/dist/browser/CdpElectronScripts.js +94 -0
- package/dist/browser/CdpElectronWorkers.js +56 -0
- package/dist/browser/CdpEndpoint.js +14 -1
- package/dist/browser/CdpPageCapture.js +8 -4
- package/dist/catalogIdentity.js +6 -42
- package/dist/cli.js +446 -34
- package/dist/cliApplicationCommands.js +62 -0
- package/dist/cliBrowserAdvancedCommands.js +5 -4
- package/dist/cliBrowserCommands.js +5 -4
- package/dist/cliCommandNames.js +56 -0
- package/dist/cliElectronCommands.js +106 -3
- package/dist/cliEvidenceCommands.js +4 -3
- package/dist/cliInvestigationCommands.js +2 -1
- package/dist/cliJsonInput.js +54 -0
- package/dist/cliPolicyCommands.js +2 -1
- package/dist/cliProcessCommands.js +3 -2
- package/dist/config.js +101 -2
- package/dist/contracts/applicationToolContracts.js +91 -0
- package/dist/contracts/artifactToolContracts.js +5 -9
- package/dist/contracts/browserToolContracts.js +14 -62
- package/dist/contracts/electronToolContracts.js +45 -19
- package/dist/contracts/enhancedInputs.js +2 -2
- package/dist/contracts/errorSchemas.js +1 -0
- package/dist/contracts/investigationExamples.js +0 -6
- package/dist/contracts/javascriptApplicationWorkflowExamples.js +46 -0
- package/dist/contracts/javascriptRuntimeReconciliationExample.js +208 -0
- package/dist/contracts/managedToolContracts.js +153 -0
- package/dist/contracts/managedWorkflowExamples.js +346 -0
- package/dist/contracts/managedWorkflowToolContracts.js +203 -0
- package/dist/contracts/nativeToolContracts.js +2 -6
- package/dist/contracts/promptContracts.js +18 -2
- package/dist/contracts/providerSelection.js +28 -0
- package/dist/contracts/sessionLifecycleInputs.js +2 -0
- package/dist/contracts/toolContractExamples.js +10 -25
- package/dist/contracts/toolContracts.js +69 -65
- package/dist/contracts/toolEffects.js +160 -0
- package/dist/contracts/toolOutputSchemas.js +152 -42
- package/dist/doctorRuntime.js +47 -0
- package/dist/domain/analysisProfile.js +78 -0
- package/dist/domain/analysisSnapshot.js +92 -46
- package/dist/domain/artifactComparison.js +3 -4
- package/dist/domain/artifactGraph.js +1 -0
- package/dist/domain/binaryTarget.js +4 -29
- package/dist/domain/browserObservation.js +3 -0
- package/dist/domain/bundleComparison.js +4 -4
- package/dist/domain/electronObservation.js +13 -0
- package/dist/domain/electronStaticAnalysis.js +9 -0
- package/dist/domain/electronStaticAnalysisBrowser.js +194 -0
- package/dist/domain/electronStaticAnalysisIpc.js +171 -0
- package/dist/domain/electronStaticAnalysisNative.js +164 -0
- package/dist/domain/electronStaticAnalysisTypes.js +1 -0
- package/dist/domain/electronStaticAnalysisValues.js +103 -0
- package/dist/domain/errors.js +148 -7
- package/dist/domain/evidence.js +44 -5
- package/dist/domain/evidenceBundle.js +9 -7
- package/dist/domain/functionComparison.js +9 -3
- package/dist/domain/functionComparisonNormalization.js +37 -0
- package/dist/domain/functionComparisonSchemas.js +3 -8
- package/dist/domain/functionDossierEvidence.js +4 -1
- package/dist/domain/hopperValues.js +66 -9
- package/dist/domain/inputIssueProjection.js +52 -0
- package/dist/domain/investigationWorkspace.js +2 -1
- package/dist/domain/javascriptApplicationAnalysis.js +155 -0
- package/dist/domain/javascriptApplicationChangeGraph.js +231 -0
- package/dist/domain/javascriptApplicationEvidenceSchemas.js +379 -0
- package/dist/domain/javascriptApplicationGraph.js +282 -0
- package/dist/domain/javascriptApplicationGraphSchemas.js +139 -0
- package/dist/domain/javascriptApplicationVersionComparison.js +116 -0
- package/dist/domain/javascriptApplicationVersionComparisonSchemas.js +139 -0
- package/dist/domain/javascriptApplicationVersionItems.js +221 -0
- package/dist/domain/javascriptApplicationVersionKeys.js +170 -0
- package/dist/domain/javascriptAstFingerprint.js +143 -0
- package/dist/domain/javascriptFeatureSeed.js +140 -0
- package/dist/domain/javascriptFeatureTrace.js +232 -0
- package/dist/domain/javascriptFeatureTraceSchemas.js +136 -0
- package/dist/domain/javascriptFeatureTraversal.js +88 -0
- package/dist/domain/javascriptNativeHandoff.js +85 -0
- package/dist/domain/javascriptReplay.js +361 -0
- package/dist/domain/javascriptRuntimeLoadState.js +106 -0
- package/dist/domain/javascriptRuntimeReconciliation.js +42 -0
- package/dist/domain/javascriptRuntimeReconciliationGraph.js +169 -0
- package/dist/domain/javascriptRuntimeReconciliationMatching.js +247 -0
- package/dist/domain/javascriptRuntimeReconciliationParsing.js +160 -0
- package/dist/domain/javascriptRuntimeReconciliationResult.js +119 -0
- package/dist/domain/javascriptRuntimeReconciliationRuntime.js +316 -0
- package/dist/domain/javascriptRuntimeReconciliationSchemas.js +245 -0
- package/dist/domain/javascriptRuntimeStaticCandidates.js +191 -0
- package/dist/domain/javascriptStaticAnalysis.js +346 -0
- package/dist/domain/javascriptStaticAnalysisFindings.js +39 -0
- package/dist/domain/javascriptStaticAnalysisHelpers.js +274 -0
- package/dist/domain/javascriptStaticAnalysisState.js +23 -0
- package/dist/domain/javascriptStaticAnalysisTypes.js +1 -0
- package/dist/domain/managedApplicationGraph.js +556 -0
- package/dist/domain/managedArtifact.js +444 -0
- package/dist/domain/managedMemberComparison.js +565 -0
- package/dist/domain/managedNativeVerification.js +408 -0
- package/dist/domain/managedReconstruction.js +183 -0
- package/dist/domain/managedRuntimeCorrelation.js +175 -0
- package/dist/domain/reconstructionVerificationSchemas.js +1 -3
- package/dist/dotnet/ManagedArtifactInspector.js +318 -0
- package/dist/dotnet/ManagedMemberInspector.js +887 -0
- package/dist/dotnet/ManagedMetadataHeaps.js +131 -0
- package/dist/dotnet/ManagedMetadataInventory.js +368 -0
- package/dist/dotnet/ManagedMetadataLayout.js +322 -0
- package/dist/dotnet/ManagedNativeBoundaryInspector.js +391 -0
- package/dist/dotnet/ManagedPeReader.js +157 -0
- package/dist/dotnet/ManagedReaderFailure.js +10 -0
- package/dist/dotnet/ManagedStaticProvider.js +203 -0
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraAnalysisProfile.js +37 -0
- package/dist/ghidra/GhidraClient.js +400 -0
- package/dist/ghidra/GhidraClientTypes.js +1 -0
- package/dist/ghidra/GhidraDefaults.js +20 -0
- package/dist/ghidra/GhidraDiagnostics.js +43 -0
- package/dist/ghidra/GhidraDoctor.js +59 -0
- package/dist/ghidra/GhidraFunctionValues.js +264 -0
- package/dist/ghidra/GhidraInstallation.js +239 -0
- package/dist/ghidra/GhidraInventoryValues.js +217 -0
- package/dist/ghidra/GhidraLauncher.js +139 -0
- package/dist/ghidra/GhidraProvider.js +366 -0
- package/dist/ghidra/GhidraRequestQueue.js +98 -0
- package/dist/ghidra/GhidraResponseBuffer.js +31 -0
- package/dist/ghidra/GhidraResponseRouter.js +24 -0
- package/dist/ghidra/GhidraSessionError.js +39 -0
- package/dist/ghidra/GhidraSessionValues.js +62 -0
- package/dist/ghidra/GhidraSocketConnection.js +46 -0
- package/dist/ghidra/protocol.js +69 -0
- package/dist/hopper/BridgeLauncher.js +19 -54
- package/dist/hopper/HopperAnalysisProfile.js +106 -0
- package/dist/hopper/HopperClient.js +154 -162
- package/dist/hopper/HopperProvider.js +99 -7
- package/dist/hopper/HopperSessionValues.js +27 -0
- package/dist/hopper/HopperSocketConnection.js +31 -0
- package/dist/main.js +14 -0
- package/dist/native/NativeMacOSProvider.js +3 -1
- package/dist/process/PendingOperations.js +59 -0
- package/dist/process/PrivateRuntimeRoot.js +33 -0
- package/dist/process/ProviderDeadline.js +95 -0
- package/dist/process/ProviderProcess.js +275 -0
- package/dist/replay/JavaScriptReplayWorker.js +286 -0
- package/dist/replay/LinuxJavaScriptReplayRunner.js +434 -0
- package/dist/replay/LinuxRuntimeClosure.js +46 -0
- package/dist/replay/LinuxSeccompPolicy.js +40 -0
- package/dist/replay/ReplayWorkerProtocol.js +55 -0
- package/dist/replay/SystemJavaScriptReplayHost.js +182 -0
- package/dist/server/createServer.js +53 -0
- package/dist/server/promptCompletion.js +9 -3
- package/dist/server/registerApplicationTools.js +115 -0
- package/dist/server/registerArtifactComparisonTool.js +16 -9
- package/dist/server/registerBrowserTools.js +33 -8
- package/dist/server/registerBundleComparisonTool.js +17 -20
- package/dist/server/registerElectronTools.js +45 -3
- package/dist/server/registerEnhancedTools.js +67 -19
- package/dist/server/registerEvidenceTools.js +5 -1
- package/dist/server/registerFunctionComparisonTool.js +14 -7
- package/dist/server/registerInvestigationTools.js +21 -17
- package/dist/server/registerManagedTools.js +6 -0
- package/dist/server/registerManagedWorkflowTools.js +277 -0
- package/dist/server/registerOfficialTools.js +11 -8
- package/dist/server/registerProcessComparisonTool.js +25 -47
- package/dist/server/registerSessionStatusTool.js +7 -7
- package/dist/server/registerSessionTools.js +57 -87
- package/dist/server/sessionEvidence.js +14 -19
- package/dist/server/toolInputValidation.js +77 -0
- package/dist/server/toolRegistrationOptions.js +79 -2
- package/dist/server/toolResult.js +25 -17
- package/package.json +17 -7
- package/scripts/rea.mjs +36 -2
- package/skills/rea-analysis/SKILL.md +59 -3
- /package/dist/{application → process}/ProcessOwnership.js +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { access, copyFile, mkdir, readFile, rm, writeFile, } from "node:fs/promises";
|
|
2
|
+
import { constants as fsConstants } from "node:fs";
|
|
2
3
|
import { homedir } from "node:os";
|
|
3
4
|
import { dirname, resolve } from "node:path";
|
|
4
5
|
import { z } from "zod";
|
|
@@ -7,7 +8,7 @@ import { parse as parseToml, stringify as stringifyToml } from "smol-toml";
|
|
|
7
8
|
import { PRODUCT_IDENTITY } from "../identity.js";
|
|
8
9
|
import { supportsNodeVersion } from "../domain/runtimeVersion.js";
|
|
9
10
|
import { resolveClientConfigTransactionPath } from "./ClientConfigPath.js";
|
|
10
|
-
import { runDoctor, systemDoctorHost } from "./Doctor.js";
|
|
11
|
+
import { runDoctor, systemDoctorHost, } from "./Doctor.js";
|
|
11
12
|
import { installLinuxHopper, readLinuxDistribution, } from "./LinuxHopper.js";
|
|
12
13
|
import { installMacHopper } from "./MacHopper.js";
|
|
13
14
|
import { configureDetectedClients } from "./SetupClients.js";
|
|
@@ -36,12 +37,14 @@ export const runSetup = async (options, host = systemSetupHost(), confirm) => {
|
|
|
36
37
|
doctor: await host.doctor(),
|
|
37
38
|
remediation,
|
|
38
39
|
});
|
|
39
|
-
const unsupported = await hostRemediation(host);
|
|
40
|
+
const unsupported = await hostRemediation(host, options.installHopper);
|
|
40
41
|
if (unsupported !== undefined)
|
|
41
42
|
return fail(unsupported);
|
|
42
43
|
let hopperPath = await host.hopperPath();
|
|
43
|
-
|
|
44
|
-
const
|
|
44
|
+
let providerEnvironment = await initialProviderEnvironment(host, hopperPath);
|
|
45
|
+
const discovery = await discoverSetupActions(host, providerEnvironment, options.installHopper);
|
|
46
|
+
const { installHopper, installSkill } = discovery;
|
|
47
|
+
let { detectedClients } = discovery;
|
|
45
48
|
plannedActions = discovery.plannedActions;
|
|
46
49
|
let approved = options.approved || plannedActions.length === 0;
|
|
47
50
|
let interactiveApproval = false;
|
|
@@ -59,7 +62,7 @@ export const runSetup = async (options, host = systemSetupHost(), confirm) => {
|
|
|
59
62
|
remediation: "Review the setup plan, then rerun interactively or with --yes.",
|
|
60
63
|
};
|
|
61
64
|
if (installHopper && (interactiveApproval || options.installHopper)) {
|
|
62
|
-
const installed = await host.installHopper();
|
|
65
|
+
const installed = await host.installHopper(options.installHopper);
|
|
63
66
|
if (installed.status === "failed")
|
|
64
67
|
return {
|
|
65
68
|
status: "needs_human",
|
|
@@ -71,12 +74,17 @@ export const runSetup = async (options, host = systemSetupHost(), confirm) => {
|
|
|
71
74
|
remediation: installed.remediation,
|
|
72
75
|
};
|
|
73
76
|
hopperPath = installed.launcherPath;
|
|
77
|
+
providerEnvironment = {
|
|
78
|
+
...providerEnvironment,
|
|
79
|
+
HOPPER_LAUNCHER_PATH: installed.launcherPath,
|
|
80
|
+
};
|
|
74
81
|
appliedActions.push("installed_hopper");
|
|
82
|
+
detectedClients = await filterClientsNeedingConfigure(host, detectedClients, providerEnvironment, registrationCommand());
|
|
75
83
|
}
|
|
76
84
|
const clientFailure = await configureDetectedClients({
|
|
77
85
|
host,
|
|
78
86
|
detectedClients,
|
|
79
|
-
|
|
87
|
+
providerEnvironment,
|
|
80
88
|
command: registrationCommand(),
|
|
81
89
|
clients,
|
|
82
90
|
appliedActions,
|
|
@@ -101,12 +109,14 @@ export const runSetup = async (options, host = systemSetupHost(), confirm) => {
|
|
|
101
109
|
...(remediation === undefined ? {} : { remediation }),
|
|
102
110
|
};
|
|
103
111
|
};
|
|
104
|
-
const discoverSetupActions = async (host,
|
|
112
|
+
const discoverSetupActions = async (host, providerEnvironment, forceHopperInstall) => {
|
|
105
113
|
const initialDoctor = await host.doctor();
|
|
106
114
|
const linuxHopperRepairNeeded = initialDoctor.checks.some(({ name, ok, detail }) => !ok &&
|
|
107
115
|
(name === "hopper-demo-runtime" ||
|
|
108
116
|
(name === "hopper-version" && detail === "/opt/hopper/bin/Hopper")));
|
|
109
|
-
const installHopper =
|
|
117
|
+
const installHopper = forceHopperInstall ||
|
|
118
|
+
Object.keys(providerEnvironment).length === 0 ||
|
|
119
|
+
linuxHopperRepairNeeded;
|
|
110
120
|
const [detectedClients, installSkill] = await Promise.all([
|
|
111
121
|
host.detectedClients(),
|
|
112
122
|
host.skillNeedsInstall(),
|
|
@@ -114,8 +124,8 @@ const discoverSetupActions = async (host, hopperPath) => {
|
|
|
114
124
|
const command = registrationCommand();
|
|
115
125
|
const clients = installHopper
|
|
116
126
|
? detectedClients
|
|
117
|
-
: await filterClientsNeedingConfigure(host, detectedClients,
|
|
118
|
-
const plannedActions = setupPlan(host.platform, installHopper, installSkill, clients);
|
|
127
|
+
: await filterClientsNeedingConfigure(host, detectedClients, providerEnvironment, command);
|
|
128
|
+
const plannedActions = setupPlan(host.platform, installHopper, installSkill, clients, providerEnvironment);
|
|
119
129
|
return {
|
|
120
130
|
installHopper,
|
|
121
131
|
installSkill,
|
|
@@ -123,10 +133,14 @@ const discoverSetupActions = async (host, hopperPath) => {
|
|
|
123
133
|
plannedActions,
|
|
124
134
|
};
|
|
125
135
|
};
|
|
126
|
-
const filterClientsNeedingConfigure = async (host, detectedClients,
|
|
127
|
-
const needs = await Promise.all(detectedClients.map((client) => host.clientNeedsConfigure(client,
|
|
136
|
+
const filterClientsNeedingConfigure = async (host, detectedClients, providerEnvironment, command) => {
|
|
137
|
+
const needs = await Promise.all(detectedClients.map((client) => host.clientNeedsConfigure(client, providerEnvironment, command)));
|
|
128
138
|
return detectedClients.filter((_, index) => needs[index]);
|
|
129
139
|
};
|
|
140
|
+
const initialProviderEnvironment = async (host, hopperPath) => ({
|
|
141
|
+
...(await host.providerEnvironment?.()),
|
|
142
|
+
...(hopperPath === undefined ? {} : { HOPPER_LAUNCHER_PATH: hopperPath }),
|
|
143
|
+
});
|
|
130
144
|
const finalSetupRemediation = (platform, installedHopper, healthy, hopperPath) => {
|
|
131
145
|
if (platform === "darwin" && installedHopper)
|
|
132
146
|
return "Open Hopper, choose its demo mode or activate a license, then rerun rea doctor --json.";
|
|
@@ -136,7 +150,7 @@ const finalSetupRemediation = (platform, installedHopper, healthy, hopperPath) =
|
|
|
136
150
|
? "Hopper is optional for non-Hopper providers. Rerun with --yes --install-hopper for deep native analysis."
|
|
137
151
|
: "Run rea doctor and apply each reported remediation.";
|
|
138
152
|
};
|
|
139
|
-
const hostRemediation = async (host) => {
|
|
153
|
+
const hostRemediation = async (host, forceHopperInstall) => {
|
|
140
154
|
if (host.platform !== "darwin" && host.platform !== "linux")
|
|
141
155
|
return "REA supports Hopper on macOS and selected 64-bit Linux distributions.";
|
|
142
156
|
if (!supportsNodeVersion(host.nodeVersion))
|
|
@@ -147,34 +161,47 @@ const hostRemediation = async (host) => {
|
|
|
147
161
|
? "Upgrade to macOS 12 or newer."
|
|
148
162
|
: undefined;
|
|
149
163
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
164
|
+
if ((await host.linuxDistribution())?.supported === true)
|
|
165
|
+
return undefined;
|
|
166
|
+
const providerEnvironment = await host.providerEnvironment?.();
|
|
167
|
+
if (!forceHopperInstall &&
|
|
168
|
+
providerEnvironment !== undefined &&
|
|
169
|
+
Object.keys(providerEnvironment).length > 0)
|
|
170
|
+
return undefined;
|
|
171
|
+
return "Automated Hopper setup supports Ubuntu 24.04+, Fedora 41+, and 64-bit Arch Linux; configure an existing supported provider instead.";
|
|
153
172
|
};
|
|
154
173
|
/** Production setup effects for Hopper, agent configuration, and the canonical skill directory. */
|
|
155
|
-
const systemSetupHost = () => {
|
|
156
|
-
const doctorHost = systemDoctorHost();
|
|
174
|
+
export const systemSetupHost = (doctorHost = systemDoctorHost()) => {
|
|
157
175
|
return {
|
|
158
176
|
platform: process.platform,
|
|
159
177
|
nodeVersion: process.versions.node,
|
|
160
178
|
macosVersion: () => doctorHost.macosVersion(),
|
|
161
179
|
linuxDistribution: readLinuxDistribution,
|
|
162
180
|
hopperPath: async () => (await runDoctor(undefined, doctorHost)).hopperPath,
|
|
163
|
-
|
|
181
|
+
providerEnvironment: async () => {
|
|
182
|
+
const diagnosis = await runDoctor(undefined, doctorHost);
|
|
183
|
+
return {
|
|
184
|
+
...providerRegistrationEnvironment(diagnosis.providerInspections ?? []),
|
|
185
|
+
...(diagnosis.hopperPath === undefined
|
|
186
|
+
? {}
|
|
187
|
+
: { HOPPER_LAUNCHER_PATH: diagnosis.hopperPath }),
|
|
188
|
+
};
|
|
189
|
+
},
|
|
190
|
+
installHopper: async (replaceExisting) => {
|
|
164
191
|
const result = process.platform === "linux"
|
|
165
192
|
? await installLinuxHopper()
|
|
166
|
-
: await installMacHopper();
|
|
193
|
+
: await installMacHopper({ replaceExisting });
|
|
167
194
|
if (result.status === "installed")
|
|
168
195
|
return result;
|
|
169
196
|
return setupInstallFailure(result.reason);
|
|
170
197
|
},
|
|
171
198
|
detectedClients: () => detectClients(homedir()),
|
|
172
|
-
configureClient: (client,
|
|
199
|
+
configureClient: (client, providerEnvironment, command) => client.format === "unsupported"
|
|
173
200
|
? Promise.resolve({ status: "skipped" })
|
|
174
201
|
: client.format === "toml"
|
|
175
|
-
? configureTomlClient(client,
|
|
176
|
-
: configureJsonClient(client,
|
|
177
|
-
clientNeedsConfigure: (client,
|
|
202
|
+
? configureTomlClient(client, providerEnvironment, command)
|
|
203
|
+
: configureJsonClient(client, providerEnvironment, command),
|
|
204
|
+
clientNeedsConfigure: (client, providerEnvironment, command) => clientConfigurationAligned(client, providerEnvironment, command).then((aligned) => !aligned),
|
|
178
205
|
skillNeedsInstall: () => canonicalSkillNeedsInstall(homedir()),
|
|
179
206
|
installSkill: () => installCanonicalSkill(homedir()),
|
|
180
207
|
doctor: () => runDoctor(undefined, doctorHost),
|
|
@@ -189,7 +216,7 @@ export const detectClients = async (home) => {
|
|
|
189
216
|
return detected;
|
|
190
217
|
};
|
|
191
218
|
/** Back up, atomically update, and semantically read back one JSON MCP configuration. */
|
|
192
|
-
export const configureJsonClient = async (client,
|
|
219
|
+
export const configureJsonClient = async (client, environment = {}, command = [
|
|
193
220
|
"npx",
|
|
194
221
|
"-y",
|
|
195
222
|
PRODUCT_IDENTITY.packageName,
|
|
@@ -215,25 +242,15 @@ export const configureJsonClient = async (client, hopperPath, command = [
|
|
|
215
242
|
catch {
|
|
216
243
|
return { status: "failed", reason: "readback" };
|
|
217
244
|
}
|
|
218
|
-
const desired =
|
|
219
|
-
command: command[0] ?? PRODUCT_IDENTITY.cliBinary,
|
|
220
|
-
args: command.slice(1),
|
|
221
|
-
...(hopperPath === undefined
|
|
222
|
-
? {}
|
|
223
|
-
: { env: { HOPPER_LAUNCHER_PATH: hopperPath } }),
|
|
224
|
-
};
|
|
245
|
+
const desired = clientConfigurationDesired(normalizeProviderEnvironment(environment), command);
|
|
225
246
|
if (JSON.stringify(servers[PRODUCT_IDENTITY.mcpServerKey]) ===
|
|
226
247
|
JSON.stringify(desired))
|
|
227
248
|
return { status: "unchanged" };
|
|
228
249
|
let backupPath;
|
|
229
250
|
if (original !== undefined) {
|
|
230
251
|
backupPath = `${client.configPath}.rea.backup`;
|
|
231
|
-
|
|
232
|
-
await copyFile(transactionPath, backupPath);
|
|
233
|
-
}
|
|
234
|
-
catch {
|
|
252
|
+
if (!(await preserveConfigBackup(transactionPath, backupPath)))
|
|
235
253
|
return { status: "failed", reason: "backup" };
|
|
236
|
-
}
|
|
237
254
|
}
|
|
238
255
|
document.mcpServers = {
|
|
239
256
|
...servers,
|
|
@@ -268,7 +285,7 @@ export const configureJsonClient = async (client, hopperPath, command = [
|
|
|
268
285
|
};
|
|
269
286
|
};
|
|
270
287
|
/** Back up, atomically update, and semantically read back Codex TOML configuration. */
|
|
271
|
-
export const configureTomlClient = async (client,
|
|
288
|
+
export const configureTomlClient = async (client, environment = {}, command = [
|
|
272
289
|
"npx",
|
|
273
290
|
"-y",
|
|
274
291
|
PRODUCT_IDENTITY.packageName,
|
|
@@ -294,24 +311,14 @@ export const configureTomlClient = async (client, hopperPath, command = [
|
|
|
294
311
|
catch {
|
|
295
312
|
return { status: "failed", reason: "readback" };
|
|
296
313
|
}
|
|
297
|
-
const desired =
|
|
298
|
-
command: command[0] ?? PRODUCT_IDENTITY.cliBinary,
|
|
299
|
-
args: command.slice(1),
|
|
300
|
-
...(hopperPath === undefined
|
|
301
|
-
? {}
|
|
302
|
-
: { env: { HOPPER_LAUNCHER_PATH: hopperPath } }),
|
|
303
|
-
};
|
|
314
|
+
const desired = clientConfigurationDesired(normalizeProviderEnvironment(environment), command);
|
|
304
315
|
if (JSON.stringify(servers[PRODUCT_IDENTITY.mcpServerKey]) ===
|
|
305
316
|
JSON.stringify(desired))
|
|
306
317
|
return { status: "unchanged" };
|
|
307
318
|
const backupPath = original === undefined ? undefined : `${client.configPath}.rea.backup`;
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
await copyFile(transactionPath, backupPath);
|
|
311
|
-
}
|
|
312
|
-
catch {
|
|
319
|
+
if (backupPath !== undefined &&
|
|
320
|
+
!(await preserveConfigBackup(transactionPath, backupPath)))
|
|
313
321
|
return { status: "failed", reason: "backup" };
|
|
314
|
-
}
|
|
315
322
|
document.mcp_servers = {
|
|
316
323
|
...servers,
|
|
317
324
|
[PRODUCT_IDENTITY.mcpServerKey]: desired,
|
|
@@ -345,6 +352,15 @@ const exists = async (path) => {
|
|
|
345
352
|
return false;
|
|
346
353
|
}
|
|
347
354
|
};
|
|
355
|
+
const preserveConfigBackup = async (source, destination) => {
|
|
356
|
+
try {
|
|
357
|
+
await copyFile(source, destination, fsConstants.COPYFILE_EXCL);
|
|
358
|
+
return true;
|
|
359
|
+
}
|
|
360
|
+
catch (cause) {
|
|
361
|
+
return cause instanceof Error && "code" in cause && cause.code === "EEXIST";
|
|
362
|
+
}
|
|
363
|
+
};
|
|
348
364
|
const objectSchema = z.record(z.string(), z.unknown());
|
|
349
365
|
const parseOptionalObject = (value) => value === undefined ? {} : objectSchema.parse(value);
|
|
350
366
|
const parseObject = (text) => objectSchema.parse(JSON.parse(text));
|
|
@@ -360,15 +376,16 @@ const restoreConfig = async (path, original) => {
|
|
|
360
376
|
// The backup remains available for the remediation reported by setup.
|
|
361
377
|
}
|
|
362
378
|
};
|
|
363
|
-
const clientConfigurationDesired = (
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
|
|
379
|
+
const clientConfigurationDesired = (providerEnvironment, command) => {
|
|
380
|
+
const environment = Object.fromEntries(Object.entries(providerEnvironment).sort(([left], [right]) => left.localeCompare(right)));
|
|
381
|
+
return {
|
|
382
|
+
command: command[0] ?? PRODUCT_IDENTITY.cliBinary,
|
|
383
|
+
args: command.slice(1),
|
|
384
|
+
...(Object.keys(environment).length === 0 ? {} : { env: environment }),
|
|
385
|
+
};
|
|
386
|
+
};
|
|
387
|
+
const clientConfigurationAligned = async (client, providerEnvironment, command) => {
|
|
388
|
+
const desired = clientConfigurationDesired(providerEnvironment, command);
|
|
372
389
|
try {
|
|
373
390
|
const original = await readFile(client.configPath, "utf8");
|
|
374
391
|
if (client.format === "toml") {
|
|
@@ -386,3 +403,10 @@ const clientConfigurationAligned = async (client, hopperPath, command) => {
|
|
|
386
403
|
return false;
|
|
387
404
|
}
|
|
388
405
|
};
|
|
406
|
+
const normalizeProviderEnvironment = (environment) => typeof environment === "string"
|
|
407
|
+
? { HOPPER_LAUNCHER_PATH: environment }
|
|
408
|
+
: environment;
|
|
409
|
+
const providerRegistrationEnvironment = (inspections) => Object.fromEntries(inspections
|
|
410
|
+
.filter(({ available }) => available)
|
|
411
|
+
.flatMap(({ registrationEnvironment }) => Object.entries(registrationEnvironment))
|
|
412
|
+
.sort(([left], [right]) => left.localeCompare(right)));
|
|
@@ -11,7 +11,7 @@ const failedConfigurationMessage = (reason) => {
|
|
|
11
11
|
export const configureDetectedClients = async (options) => {
|
|
12
12
|
let failure;
|
|
13
13
|
for (const client of options.detectedClients) {
|
|
14
|
-
const result = await options.host.configureClient(client, options.
|
|
14
|
+
const result = await options.host.configureClient(client, options.providerEnvironment, options.command);
|
|
15
15
|
options.clients[client.name] = result;
|
|
16
16
|
if (result.status === "failed")
|
|
17
17
|
failure ??= failedConfigurationMessage(result.reason);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Build the complete setup mutation plan before approval. */
|
|
2
|
-
export const setupPlan = (platform, installHopper, installSkill, clients) => [
|
|
2
|
+
export const setupPlan = (platform, installHopper, installSkill, clients, providerEnvironment) => [
|
|
3
3
|
...(installHopper
|
|
4
4
|
? [
|
|
5
5
|
{
|
|
@@ -19,7 +19,7 @@ export const setupPlan = (platform, installHopper, installSkill, clients) => [
|
|
|
19
19
|
.map((client) => ({
|
|
20
20
|
kind: "configure_client",
|
|
21
21
|
target: client.configPath,
|
|
22
|
-
detail:
|
|
22
|
+
detail: clientConfigurationDetail(client.name, providerEnvironment),
|
|
23
23
|
external: false,
|
|
24
24
|
})),
|
|
25
25
|
...(installSkill
|
|
@@ -33,3 +33,10 @@ export const setupPlan = (platform, installHopper, installSkill, clients) => [
|
|
|
33
33
|
]
|
|
34
34
|
: []),
|
|
35
35
|
];
|
|
36
|
+
const clientConfigurationDetail = (client, environment) => {
|
|
37
|
+
const entries = Object.entries(environment)
|
|
38
|
+
.sort(([left], [right]) => left.localeCompare(right))
|
|
39
|
+
.map(([name, value]) => `${name}=${value}`);
|
|
40
|
+
const suffix = entries.length === 0 ? "" : ` Environment: ${entries.join(", ")}.`;
|
|
41
|
+
return `Add the REA MCP registration for ${client}; preserve unrelated configuration.${suffix}`;
|
|
42
|
+
};
|
|
@@ -1,41 +1,65 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
|
-
/**
|
|
3
|
-
export const
|
|
2
|
+
/** Stable product metadata used to derive setup discovery and documentation. */
|
|
3
|
+
export const SUPPORTED_CLIENT_DEFINITIONS = [
|
|
4
4
|
{
|
|
5
5
|
name: "claude_code",
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
displayName: "Claude Code",
|
|
7
|
+
configPath: [".claude.json"],
|
|
8
|
+
markerPath: [".claude"],
|
|
9
|
+
format: "json",
|
|
8
10
|
},
|
|
9
11
|
{
|
|
10
12
|
name: "claude_desktop",
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
displayName: "Claude Desktop",
|
|
14
|
+
configPath: [
|
|
15
|
+
"Library",
|
|
16
|
+
"Application Support",
|
|
17
|
+
"Claude",
|
|
18
|
+
"claude_desktop_config.json",
|
|
19
|
+
],
|
|
20
|
+
markerPath: ["Library", "Application Support", "Claude"],
|
|
21
|
+
format: "json",
|
|
13
22
|
},
|
|
14
23
|
{
|
|
15
24
|
name: "codex",
|
|
16
|
-
|
|
17
|
-
|
|
25
|
+
displayName: "Codex",
|
|
26
|
+
configPath: [".codex", "config.toml"],
|
|
27
|
+
markerPath: [".codex"],
|
|
18
28
|
format: "toml",
|
|
19
29
|
},
|
|
20
30
|
{
|
|
21
31
|
name: "cursor",
|
|
22
|
-
|
|
23
|
-
|
|
32
|
+
displayName: "Cursor",
|
|
33
|
+
configPath: [".cursor", "mcp.json"],
|
|
34
|
+
markerPath: [".cursor"],
|
|
35
|
+
format: "json",
|
|
24
36
|
},
|
|
25
37
|
{
|
|
26
38
|
name: "gemini_cli",
|
|
27
|
-
|
|
28
|
-
|
|
39
|
+
displayName: "Gemini CLI",
|
|
40
|
+
configPath: [".gemini", "settings.json"],
|
|
41
|
+
markerPath: [".gemini"],
|
|
42
|
+
format: "json",
|
|
29
43
|
},
|
|
30
44
|
{
|
|
31
45
|
name: "windsurf",
|
|
32
|
-
|
|
33
|
-
|
|
46
|
+
displayName: "Windsurf",
|
|
47
|
+
configPath: [".codeium", "windsurf", "mcp_config.json"],
|
|
48
|
+
markerPath: [".codeium", "windsurf"],
|
|
49
|
+
format: "json",
|
|
34
50
|
},
|
|
35
51
|
{
|
|
36
52
|
name: "devin",
|
|
37
|
-
|
|
38
|
-
|
|
53
|
+
displayName: "Devin",
|
|
54
|
+
configPath: [".devin"],
|
|
55
|
+
markerPath: [".devin"],
|
|
39
56
|
format: "unsupported",
|
|
40
57
|
},
|
|
41
58
|
];
|
|
59
|
+
/** Describe every client location that setup, doctor, or uninstall may inspect. */
|
|
60
|
+
export const supportedClients = (home) => SUPPORTED_CLIENT_DEFINITIONS.map((definition) => ({
|
|
61
|
+
name: definition.name,
|
|
62
|
+
configPath: join(home, ...definition.configPath),
|
|
63
|
+
markerPath: join(home, ...definition.markerPath),
|
|
64
|
+
format: definition.format,
|
|
65
|
+
}));
|
|
@@ -112,7 +112,7 @@ const inferUnixGlobalPrefix = (packageRoot) => {
|
|
|
112
112
|
};
|
|
113
113
|
const runCommand = (command, arguments_, output) => new Promise((resolveResult) => {
|
|
114
114
|
const child = spawn(command, [...arguments_], {
|
|
115
|
-
stdio: output === "human" ? "inherit" : ["inherit",
|
|
115
|
+
stdio: output === "human" ? "inherit" : ["inherit", "ignore", "inherit"],
|
|
116
116
|
});
|
|
117
117
|
child.once("error", () => resolveResult(false));
|
|
118
118
|
child.once("exit", (code) => resolveResult(code === 0));
|
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
import { BinarySession } from "./BinarySession.js";
|
|
2
2
|
import { HopperProvider } from "../hopper/HopperProvider.js";
|
|
3
|
+
import { GhidraProvider } from "../ghidra/GhidraProvider.js";
|
|
3
4
|
import { NativeMacOSProvider } from "../native/NativeMacOSProvider.js";
|
|
4
5
|
import { ArtifactProvider } from "../artifacts/ArtifactProvider.js";
|
|
5
|
-
import {
|
|
6
|
+
import { ManagedStaticProvider } from "../dotnet/ManagedStaticProvider.js";
|
|
6
7
|
import { silentLogger } from "../logger.js";
|
|
8
|
+
import { AnalysisProviderRegistry } from "./AnalysisProviderRegistry.js";
|
|
9
|
+
import { SessionProviderRouter } from "./SessionProviderRouter.js";
|
|
7
10
|
/**
|
|
8
11
|
* Compose the target-switching runtime shared directly by CLI and MCP adapters.
|
|
9
|
-
* This is the sole production wiring point
|
|
10
|
-
*
|
|
12
|
+
* This is the sole production wiring point, so both adapters share identical
|
|
13
|
+
* provider selection, profile, lifecycle, and Evidence semantics.
|
|
11
14
|
*/
|
|
12
15
|
export const createBinarySession = (config, logger = silentLogger) => {
|
|
13
|
-
|
|
16
|
+
const hopper = new HopperProvider(config, logger);
|
|
17
|
+
const ghidra = new GhidraProvider(config, logger);
|
|
18
|
+
return new BinarySession(SessionProviderRouter.selectable(new AnalysisProviderRegistry([hopper, ghidra], config.analysisProvider), [
|
|
14
19
|
new ArtifactProvider(config.artifactNativeMountEnabled, config.artifactIntegrityContinueEnabled),
|
|
15
20
|
new NativeMacOSProvider(),
|
|
16
|
-
new
|
|
17
|
-
])
|
|
21
|
+
new ManagedStaticProvider(),
|
|
22
|
+
]));
|
|
18
23
|
};
|
|
@@ -15,13 +15,25 @@ export class AsarArtifactReader {
|
|
|
15
15
|
this.path = path;
|
|
16
16
|
}
|
|
17
17
|
async *entries(signal) {
|
|
18
|
-
|
|
18
|
+
let paths;
|
|
19
|
+
try {
|
|
20
|
+
paths = listPackage(this.path, { isPack: false }).sort((left, right) => left.localeCompare(right, "en"));
|
|
21
|
+
}
|
|
22
|
+
catch (cause) {
|
|
23
|
+
throw asarFailure(this.path, "inventory", cause);
|
|
24
|
+
}
|
|
19
25
|
for (const listed of paths) {
|
|
20
26
|
abortIfNeeded(signal);
|
|
21
27
|
const path = listed.replace(/^\/+|\/+$/gu, "");
|
|
22
28
|
if (path.length === 0)
|
|
23
29
|
continue;
|
|
24
|
-
|
|
30
|
+
let metadata;
|
|
31
|
+
try {
|
|
32
|
+
metadata = statFile(this.path, path, false);
|
|
33
|
+
}
|
|
34
|
+
catch (cause) {
|
|
35
|
+
throw asarFailure(this.path, `stat ${path}`, cause);
|
|
36
|
+
}
|
|
25
37
|
const kind = "files" in metadata
|
|
26
38
|
? "directory"
|
|
27
39
|
: "link" in metadata
|
|
@@ -54,7 +66,12 @@ export class AsarArtifactReader {
|
|
|
54
66
|
abortIfNeeded(signal);
|
|
55
67
|
if (entry.kind !== "file")
|
|
56
68
|
return Promise.reject(new ArtifactReaderFailure("format", "ASAR entry is not a regular file"));
|
|
57
|
-
|
|
69
|
+
try {
|
|
70
|
+
return Promise.resolve(Readable.from(extractFile(this.path, entry.adapterKey, false)));
|
|
71
|
+
}
|
|
72
|
+
catch (cause) {
|
|
73
|
+
return Promise.reject(asarFailure(this.path, `read ${entry.path}`, cause));
|
|
74
|
+
}
|
|
58
75
|
}
|
|
59
76
|
close() {
|
|
60
77
|
return Promise.resolve();
|
|
@@ -67,3 +84,6 @@ const abortIfNeeded = (signal) => {
|
|
|
67
84
|
if (signal?.aborted === true)
|
|
68
85
|
throw new ArtifactReaderFailure("cancelled", "ASAR operation cancelled");
|
|
69
86
|
};
|
|
87
|
+
const asarFailure = (path, operation, cause) => cause instanceof ArtifactReaderFailure
|
|
88
|
+
? cause
|
|
89
|
+
: new ArtifactReaderFailure("format", `Malformed or unreadable ASAR during ${operation}: ${path}`, { cause });
|
|
@@ -15,11 +15,13 @@ import { observeCdpSession } from "./CdpObservationSession.js";
|
|
|
15
15
|
import { discoverWebMcp } from "./CdpWebMcpDiscovery.js";
|
|
16
16
|
import { captureCdpScreenshot } from "./CdpScreenshot.js";
|
|
17
17
|
import { comparePngScreenshots } from "./PngVisualDiff.js";
|
|
18
|
-
|
|
18
|
+
/** Public identity committed by passive browser observations. */
|
|
19
|
+
export const CDP_BROWSER_PROVIDER_IDENTITY = Object.freeze({
|
|
19
20
|
id: "rea-cdp-browser",
|
|
20
21
|
name: "REA Chrome DevTools Protocol observation provider",
|
|
21
22
|
version: "2",
|
|
22
|
-
};
|
|
23
|
+
});
|
|
24
|
+
const IDENTITY = CDP_BROWSER_PROVIDER_IDENTITY;
|
|
23
25
|
const CLEANUP_DOMAINS = ["Network", "Debugger", "Runtime", "Page"];
|
|
24
26
|
/** Passive, origin-scoped browser observation through a user-owned CDP endpoint. */
|
|
25
27
|
export class CdpBrowserProvider {
|
|
@@ -8,6 +8,7 @@ export class CdpCaptureEvents {
|
|
|
8
8
|
input;
|
|
9
9
|
allowedOrigins;
|
|
10
10
|
scripts = new Map();
|
|
11
|
+
executionContextFrames = new Map();
|
|
11
12
|
network = new Map();
|
|
12
13
|
allowedWebSockets = new Set();
|
|
13
14
|
console = [];
|
|
@@ -36,6 +37,7 @@ export class CdpCaptureEvents {
|
|
|
36
37
|
this.originViolation = false;
|
|
37
38
|
this.navigationDuringCapture = false;
|
|
38
39
|
this.scripts.clear();
|
|
40
|
+
this.executionContextFrames.clear();
|
|
39
41
|
this.network.clear();
|
|
40
42
|
this.allowedWebSockets.clear();
|
|
41
43
|
this.console.length = 0;
|
|
@@ -62,6 +64,15 @@ export class CdpCaptureEvents {
|
|
|
62
64
|
if (params === undefined)
|
|
63
65
|
return;
|
|
64
66
|
switch (event.method) {
|
|
67
|
+
case "Runtime.executionContextCreated":
|
|
68
|
+
this.#executionContext(params);
|
|
69
|
+
break;
|
|
70
|
+
case "Runtime.executionContextDestroyed":
|
|
71
|
+
this.#destroyExecutionContext(params);
|
|
72
|
+
break;
|
|
73
|
+
case "Runtime.executionContextsCleared":
|
|
74
|
+
this.executionContextFrames.clear();
|
|
75
|
+
break;
|
|
65
76
|
case "Debugger.scriptParsed":
|
|
66
77
|
this.#script(params);
|
|
67
78
|
break;
|
|
@@ -91,6 +102,37 @@ export class CdpCaptureEvents {
|
|
|
91
102
|
break;
|
|
92
103
|
}
|
|
93
104
|
}
|
|
105
|
+
/** Resolve a transient execution context to one already authorized frame. */
|
|
106
|
+
frameForScript(script, allowedFrameIds) {
|
|
107
|
+
if (script.executionContextKey === null)
|
|
108
|
+
return null;
|
|
109
|
+
const frameId = this.executionContextFrames.get(script.executionContextKey);
|
|
110
|
+
return frameId !== undefined && allowedFrameIds.has(frameId)
|
|
111
|
+
? frameId
|
|
112
|
+
: null;
|
|
113
|
+
}
|
|
114
|
+
#executionContext(params) {
|
|
115
|
+
const context = recordValue(params.context);
|
|
116
|
+
const identifier = numberValue(context?.id);
|
|
117
|
+
const frameId = stringValue(recordValue(context?.auxData)?.frameId);
|
|
118
|
+
if (identifier === undefined ||
|
|
119
|
+
!Number.isSafeInteger(identifier) ||
|
|
120
|
+
frameId === undefined ||
|
|
121
|
+
frameId.length > 256)
|
|
122
|
+
return;
|
|
123
|
+
const key = String(identifier);
|
|
124
|
+
if (this.executionContextFrames.size >= this.input.limits.max_scripts &&
|
|
125
|
+
!this.executionContextFrames.has(key)) {
|
|
126
|
+
this.completeness.truncate("scripts");
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
this.executionContextFrames.set(key, frameId);
|
|
130
|
+
}
|
|
131
|
+
#destroyExecutionContext(params) {
|
|
132
|
+
const key = executionContextKey(params.executionContextId);
|
|
133
|
+
if (key !== null)
|
|
134
|
+
this.executionContextFrames.delete(key);
|
|
135
|
+
}
|
|
94
136
|
#script(params) {
|
|
95
137
|
const scriptId = stringValue(params.scriptId);
|
|
96
138
|
const rawUrl = stringValue(params.url) ?? "";
|
|
@@ -120,6 +162,7 @@ export class CdpCaptureEvents {
|
|
|
120
162
|
language: boundedText(params.scriptLanguage, 100),
|
|
121
163
|
sourceMapUrl: sourceMap.sanitized,
|
|
122
164
|
sourceMapRawUrl: sourceMap.raw,
|
|
165
|
+
executionContextKey: executionContextKey(params.executionContextId),
|
|
123
166
|
});
|
|
124
167
|
}
|
|
125
168
|
#sourceMap(value, scriptUrl) {
|
|
@@ -501,6 +544,12 @@ const integerOrNull = (value) => {
|
|
|
501
544
|
const number = numberValue(value);
|
|
502
545
|
return number === undefined ? null : Math.max(0, Math.trunc(number));
|
|
503
546
|
};
|
|
547
|
+
const executionContextKey = (value) => {
|
|
548
|
+
const identifier = numberValue(value);
|
|
549
|
+
return identifier !== undefined && Number.isSafeInteger(identifier)
|
|
550
|
+
? String(identifier)
|
|
551
|
+
: null;
|
|
552
|
+
};
|
|
504
553
|
const isJsonContentType = (headers) => {
|
|
505
554
|
if (headers === undefined)
|
|
506
555
|
return false;
|