rea-agents 2.3.0 → 2.5.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 +80 -18
- package/bridge/ghidra/ReaGhidraBridge.java +48 -1
- package/bridge/hopper_bridge.py +259 -24
- package/dist/application/AnalysisClientCleanup.js +14 -0
- package/dist/application/ApplicationWorkflowEvidenceResolver.js +31 -13
- package/dist/application/ArtifactExtraction.js +5 -1
- package/dist/application/ArtifactGraphConstruction.js +3 -15
- package/dist/application/ArtifactInventory/classify.js +5 -1
- package/dist/application/ArtifactInventory/reader.js +2 -0
- package/dist/application/BinarySession.js +15 -4
- package/dist/application/BinarySessionStatus.js +32 -1
- package/dist/application/BrowserEvidence.js +14 -0
- package/dist/application/BrowserScenarioCapturePort.js +1 -0
- package/dist/application/BrowserScenarioCaptureService.js +53 -0
- package/dist/application/BrowserScenarioEvidence.js +40 -0
- package/dist/application/CallPathTracing.js +160 -0
- package/dist/application/CapabilityInventory.js +79 -15
- package/dist/application/CompositeProvider.js +10 -1
- package/dist/application/DirectAnalysis.js +7 -2
- package/dist/application/EnhancedLiteralTracing.js +118 -0
- package/dist/application/EnhancedTools.js +35 -121
- package/dist/application/JavaScriptApplicationWorkflowEvidence.js +13 -0
- package/dist/application/JavaScriptApplicationWorkflowService.js +27 -1
- package/dist/application/JavaScriptRuntimeObservationEvidence.js +34 -0
- package/dist/application/JavaScriptRuntimeObservationPort.js +1 -0
- package/dist/application/JavaScriptRuntimeObservationService.js +46 -0
- package/dist/application/JavaScriptSemanticGraphAsyncProjection.js +147 -0
- package/dist/application/JavaScriptSemanticGraphBuilder.js +34 -6
- package/dist/application/JavaScriptSemanticGraphChildProcessProjection.js +156 -0
- package/dist/application/JavaScriptSemanticGraphConstruction.js +2 -2
- package/dist/application/JavaScriptSemanticGraphDataProjection.js +203 -0
- package/dist/application/JavaScriptSemanticGraphFingerprintProjection.js +25 -0
- package/dist/application/JavaScriptSemanticGraphFlowProjection.js +129 -8
- package/dist/application/JavaScriptSemanticGraphObjectProjection.js +81 -0
- package/dist/application/JavaScriptSemanticGraphProjection.js +14 -7
- package/dist/application/JavaScriptSemanticGraphResourceProjection.js +59 -0
- package/dist/application/JavaScriptSemanticGraphValueProjection.js +77 -0
- package/dist/application/ProcessCaptureEnvironment.js +26 -0
- package/dist/application/ProcessCaptureLifecycle.js +1 -0
- package/dist/application/ProcessCheckpoints.js +5 -0
- package/dist/application/ProcessHarness.js +45 -34
- package/dist/application/ProcessNormalization.js +6 -0
- package/dist/application/ProcessReactiveCoordinator.js +10 -3
- package/dist/application/ProcessReactiveEffects.js +15 -1
- package/dist/application/ProcessReactiveHarness.js +100 -0
- package/dist/application/ProcessReactiveObservations.js +101 -16
- package/dist/application/ProjectPermissionStore.js +1 -0
- package/dist/application/ReconstructionObligationAuthority.js +72 -0
- package/dist/application/ReconstructionObligationCandidates.js +265 -0
- package/dist/application/ReconstructionObligationLedgerDiagnostics.js +47 -0
- package/dist/application/ReconstructionObligationLedgerEvaluation.js +263 -0
- package/dist/application/ReconstructionObligationLedgerProjection.js +86 -0
- package/dist/application/ReconstructionObligationLedgerService.js +72 -0
- package/dist/application/ReconstructionObligationOriginalCases.js +33 -0
- package/dist/application/ReconstructionObligationPolicies.js +132 -0
- package/dist/application/ReconstructionReadinessService.js +48 -0
- package/dist/artifacts/ArtifactProvider.js +87 -22
- package/dist/browser/BrowserScenarioSecrets.js +53 -0
- package/dist/browser/BrowserScenarioSessionPort.js +1 -0
- package/dist/browser/CdpBrowserProvider.js +2 -2
- package/dist/browser/CdpCaptureDocuments.js +57 -0
- package/dist/browser/CdpCaptureStorage.js +71 -29
- package/dist/browser/CdpCaptureStorageFingerprints.js +328 -0
- package/dist/browser/CdpEndpoint.js +8 -6
- package/dist/browser/CdpPageCapture.js +2 -0
- package/dist/browser/JavaScriptRuntimeScope.js +38 -0
- package/dist/browser/PlaywrightBrowserScenarioProvider.js +253 -0
- package/dist/browser/PlaywrightExecutionBoundary.js +42 -0
- package/dist/browser/PlaywrightScenarioActions.js +62 -0
- package/dist/browser/PlaywrightScenarioArtifacts.js +238 -0
- package/dist/browser/PlaywrightScenarioBrowser.js +144 -0
- package/dist/browser/PlaywrightScenarioEvents.js +301 -0
- package/dist/browser/PlaywrightScenarioSession.js +300 -0
- package/dist/browser/V8InspectorCaptureProjection.js +110 -0
- package/dist/browser/V8InspectorEndpoint.js +72 -0
- package/dist/browser/V8InspectorProvider.js +267 -0
- package/dist/catalogIdentity.js +8 -0
- package/dist/cli/artifactCommands.js +39 -0
- package/dist/cli/coreAnalysisCommands.js +37 -0
- package/dist/cli.js +4 -0
- package/dist/cliApplicationCommands.js +30 -2
- package/dist/cliBrowserAdvancedCommands.js +17 -5
- package/dist/cliBrowserCommands.js +1 -0
- package/dist/cliBrowserScenarioCommands.js +43 -0
- package/dist/cliCommandNames.js +8 -0
- package/dist/cliJavaScriptRuntimeCommands.js +164 -0
- package/dist/cliObservationOptions.js +4 -0
- package/dist/cliPolicyCommands.js +1 -0
- package/dist/config/environment.js +12 -0
- package/dist/config/parseConfig.js +88 -17
- package/dist/contracts/analysisSearchContract.js +14 -0
- package/dist/contracts/applicationToolContracts.js +86 -2
- package/dist/contracts/applicationWorkflowInputContracts.js +18 -0
- package/dist/contracts/artifactToolContracts.js +22 -0
- package/dist/contracts/browserProviderToolContracts.js +7 -0
- package/dist/contracts/browserScenarioToolContracts.js +81 -0
- package/dist/contracts/browserToolContracts.js +88 -98
- package/dist/contracts/enhancedInputs.js +25 -6
- package/dist/contracts/functionInstructionContract.js +8 -0
- package/dist/contracts/hopperMemoryContracts.js +22 -0
- package/dist/contracts/javascriptApplicationWorkflowExamples.js +42 -0
- package/dist/contracts/javascriptRuntimeObservationToolContracts.js +58 -0
- package/dist/contracts/reconstructionReadinessExample.js +436 -0
- package/dist/contracts/toolContractExamples.js +5 -0
- package/dist/contracts/toolContractTypes.js +1 -0
- package/dist/contracts/toolContracts.js +13 -21
- package/dist/contracts/toolEffects.js +21 -0
- package/dist/contracts/toolOutputSchemaGroups.js +70 -20
- package/dist/contracts/toolOutputSchemaPrimitives.js +40 -0
- package/dist/domain/analysisErrorProjection.js +8 -0
- package/dist/domain/analysisSnapshot.js +2 -0
- package/dist/domain/artifactGraph.js +2 -0
- package/dist/domain/artifactInspection.js +347 -0
- package/dist/domain/binaryTarget.js +3 -6
- package/dist/domain/browserCaptureComparison.js +82 -0
- package/dist/domain/browserObservation.js +8 -1
- package/dist/domain/browserObservationErrors.js +1 -0
- package/dist/domain/browserObservationSchemas.js +26 -0
- package/dist/domain/browserScenario.js +165 -0
- package/dist/domain/browserScenarioCapture.js +57 -0
- package/dist/domain/browserScenarioCaptureValues.js +204 -0
- package/dist/domain/browserScenarioDiff.js +324 -0
- package/dist/domain/browserScenarioDiffValues.js +157 -0
- package/dist/domain/browserScenarioNormalization.js +45 -0
- package/dist/domain/browserScenarioValues.js +372 -0
- package/dist/domain/evidence.js +2 -0
- package/dist/domain/hopperValues.js +10 -0
- package/dist/domain/javascriptRuntimeObservation.js +170 -0
- package/dist/domain/javascriptRuntimeReconciliationParsing.js +120 -2
- package/dist/domain/javascriptRuntimeReconciliationResult.js +3 -3
- package/dist/domain/javascriptRuntimeReconciliationRuntime.js +2 -2
- package/dist/domain/javascriptRuntimeReconciliationSchemas.js +1 -1
- package/dist/domain/javascriptSemanticAnalysis.js +5 -4
- package/dist/domain/javascriptSemanticAsyncEffects.js +253 -0
- package/dist/domain/javascriptSemanticChildProcesses.js +237 -0
- package/dist/domain/javascriptSemanticDataEffectHelpers.js +125 -0
- package/dist/domain/javascriptSemanticDataEffects.js +284 -0
- package/dist/domain/javascriptSemanticDerivedAnalysis.js +41 -0
- package/dist/domain/javascriptSemanticFingerprints.js +174 -0
- package/dist/domain/javascriptSemanticIr.js +21 -1
- package/dist/domain/javascriptSemanticObjects.js +115 -0
- package/dist/domain/javascriptSemanticPromises.js +290 -0
- package/dist/domain/javascriptSemanticResources.js +136 -0
- package/dist/domain/javascriptStaticAnalysis.js +4 -3
- package/dist/domain/javascriptStaticAnalysisBundler.js +38 -0
- package/dist/domain/javascriptStaticAnalysisCalls.js +23 -1
- package/dist/domain/javascriptStaticAnalysisHelpers.js +8 -0
- package/dist/domain/processCapture.js +71 -1
- package/dist/domain/processCaptureReactiveValidation.js +175 -0
- package/dist/domain/processCaptureValidation.js +2 -0
- package/dist/domain/processObservation.js +15 -6
- package/dist/domain/processReactiveRuntime.js +21 -10
- package/dist/domain/processReactiveScenario.js +1 -0
- package/dist/domain/processReactiveTransition.js +17 -10
- package/dist/domain/processScenario.js +21 -0
- package/dist/domain/providerCleanupError.js +11 -0
- package/dist/domain/reconstructionObligationLedgerSchemas.js +278 -0
- package/dist/domain/reconstructionReadiness.js +121 -0
- package/dist/domain/reconstructionReadinessFindingHelpers.js +17 -0
- package/dist/domain/reconstructionReadinessIntegrityFindings.js +118 -0
- package/dist/domain/reconstructionReadinessJourneyFindings.js +193 -0
- package/dist/domain/reconstructionReadinessSchemas.js +240 -0
- package/dist/domain/sourceToBundleComparison.js +335 -0
- package/dist/domain/sourceToBundleComparisonSchemas.js +133 -0
- package/dist/domain/sourceToBundleSignals.js +202 -0
- package/dist/domain/webCaptureDiff.js +141 -27
- package/dist/domain/webScreenshot.js +1 -1
- package/dist/domain/zipPackageFormat.js +20 -0
- package/dist/generatedPackageMetadata.js +1 -1
- package/dist/ghidra/GhidraDefaults.js +1 -1
- package/dist/ghidra/GhidraFunctionValues.js +13 -1
- package/dist/ghidra/GhidraProviderCapabilities.js +7 -0
- package/dist/hopper/HopperCleanup.js +158 -0
- package/dist/hopper/HopperClient.js +69 -99
- package/dist/hopper/HopperProvider.js +20 -1
- package/dist/hopper/HopperRequestQueue.js +187 -0
- package/dist/hopper/HopperResponseStream.js +46 -0
- package/dist/hopper/protocol.js +1 -0
- package/dist/main/transport.js +24 -24
- package/dist/main.js +6 -0
- package/dist/mcpDoctor.js +25 -2
- package/dist/native/NativeMacOSProvider.js +1 -0
- package/dist/process/ProcessCommandIdentity.js +19 -0
- package/dist/process/ProcessOwnership.js +11 -8
- package/dist/server/DynamicToolAvailability.js +70 -0
- package/dist/server/createServer.js +46 -1
- package/dist/server/lifecycleProgress.js +10 -0
- package/dist/server/permissionFailure.js +12 -0
- package/dist/server/registerApplicationTools/compareSourceToBundle.js +35 -0
- package/dist/server/registerApplicationTools/helpers.js +11 -7
- package/dist/server/registerApplicationTools/obligationLedger.js +27 -0
- package/dist/server/registerApplicationTools/readiness.js +55 -0
- package/dist/server/registerApplicationTools.js +6 -0
- package/dist/server/registerArtifactTools.js +9 -1
- package/dist/server/registerBrowserScenarioTool.js +25 -0
- package/dist/server/registerBrowserTools.js +2 -2
- package/dist/server/registerCloseLifecycleTool.js +57 -0
- package/dist/server/registerEnhancedTools.js +16 -5
- package/dist/server/registerEvidenceResources.js +4 -0
- package/dist/server/registerEvidenceTools.js +9 -2
- package/dist/server/registerJavaScriptRuntimeObservationTools.js +37 -0
- package/dist/server/registerReconstructionObligationLedgerResource.js +39 -0
- package/dist/server/registerReconstructionReadinessResource.js +39 -0
- package/dist/server/registerSessionStatusTool.js +11 -8
- package/dist/server/registerSessionTools.js +11 -57
- package/dist/server/sessionAvailabilityPolicy.js +10 -8
- package/package.json +12 -6
- package/skills/reverse-engineer-anything/SKILL.md +4 -3
- package/skills/reverse-engineer-anything/references/native-and-artifacts.md +2 -2
|
@@ -2,21 +2,22 @@ import { randomBytes, randomUUID } from "node:crypto";
|
|
|
2
2
|
import { access } from "node:fs/promises";
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
5
|
-
import { HopperCancelledError, HopperProcessError, HopperProtocolError, HopperStartError, hopperStartupFailure, HopperTimeoutError, } from "../domain/errors.js";
|
|
5
|
+
import { AnalysisCapabilityUnavailableError, HopperCancelledError, HopperProcessError, HopperProtocolError, HopperRemoteError, HopperStartError, hopperStartupFailure, HopperTimeoutError, } from "../domain/errors.js";
|
|
6
6
|
import { err, ok } from "../domain/result.js";
|
|
7
7
|
import { silentLogger } from "../logger.js";
|
|
8
|
-
import { PendingOperations } from "../process/PendingOperations.js";
|
|
9
8
|
import { PrivateRuntimeRoot } from "../process/PrivateRuntimeRoot.js";
|
|
10
9
|
import { ProviderStartupDeadline } from "../process/ProviderDeadline.js";
|
|
11
10
|
import { ProviderRunLineage } from "../process/ProviderRunLineage.js";
|
|
12
11
|
import { ProviderProcessSupervisor, } from "../process/ProviderProcess.js";
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
12
|
+
import { cleanupHopperSession } from "./HopperCleanup.js";
|
|
13
|
+
import { parseHopperServerInfo, } from "./HopperSessionValues.js";
|
|
15
14
|
import { connectHopperSocketOnce } from "./HopperSocketConnection.js";
|
|
16
15
|
import { hopperLauncherFailureDiagnostic } from "./HopperProcessDiagnostic.js";
|
|
17
|
-
import {
|
|
18
|
-
|
|
16
|
+
import { HopperRequestQueue, } from "./HopperRequestQueue.js";
|
|
17
|
+
import { HopperResponseStream } from "./HopperResponseStream.js";
|
|
18
|
+
import { responseResult } from "./protocol.js";
|
|
19
19
|
const SHUTDOWN_TIMEOUT_MS = 30_000;
|
|
20
|
+
const MAX_QUEUED_REQUESTS = 64;
|
|
20
21
|
const SESSION_ROOT = process.platform === "darwin" ? "/tmp" : tmpdir();
|
|
21
22
|
/** Safe launcher telemetry; stderr content is intentionally never exposed. */
|
|
22
23
|
/**
|
|
@@ -29,7 +30,8 @@ const SESSION_ROOT = process.platform === "darwin" ? "/tmp" : tmpdir();
|
|
|
29
30
|
*/
|
|
30
31
|
export class HopperClient {
|
|
31
32
|
#options;
|
|
32
|
-
#
|
|
33
|
+
#requests;
|
|
34
|
+
#responses;
|
|
33
35
|
#logger;
|
|
34
36
|
#socket;
|
|
35
37
|
#launch;
|
|
@@ -38,7 +40,6 @@ export class HopperClient {
|
|
|
38
40
|
#token;
|
|
39
41
|
#lineage = new ProviderRunLineage();
|
|
40
42
|
#nextId = 1;
|
|
41
|
-
#buffer = "";
|
|
42
43
|
#closing = false;
|
|
43
44
|
#launcherExitCode;
|
|
44
45
|
#launcherFailureDiagnostic;
|
|
@@ -46,7 +47,7 @@ export class HopperClient {
|
|
|
46
47
|
#startPromise;
|
|
47
48
|
#closePromise;
|
|
48
49
|
#onSocketData = (chunk) => {
|
|
49
|
-
this.#
|
|
50
|
+
this.#responses.push(chunk);
|
|
50
51
|
};
|
|
51
52
|
#onSocketError = () => {
|
|
52
53
|
this.#failAll(new HopperProcessError(null));
|
|
@@ -62,11 +63,33 @@ export class HopperClient {
|
|
|
62
63
|
requestTimeoutMs: options.requestTimeoutMs ?? 30_000,
|
|
63
64
|
startupTimeoutMs: options.startupTimeoutMs ?? 120_000,
|
|
64
65
|
};
|
|
66
|
+
this.#requests = new HopperRequestQueue(MAX_QUEUED_REQUESTS, ({ id, method, params }, failed) => {
|
|
67
|
+
const socket = this.#socket;
|
|
68
|
+
const token = this.#token;
|
|
69
|
+
if (socket === undefined || socket.destroyed || token === undefined) {
|
|
70
|
+
failed();
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
socket.write(`${JSON.stringify({ id, token, method, params })}\n`, (cause) => {
|
|
74
|
+
if (cause !== undefined && cause !== null)
|
|
75
|
+
failed();
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
this.#responses = new HopperResponseStream({
|
|
79
|
+
accept: (response) => this.#requests.accept(response.id, responseResult(response)),
|
|
80
|
+
hasQueued: (id) => this.#requests.hasQueued(id),
|
|
81
|
+
nextRequestId: () => this.#nextId,
|
|
82
|
+
abort: (message, cause) => this.#abortProtocol(message, cause),
|
|
83
|
+
});
|
|
65
84
|
}
|
|
66
85
|
/** Latest token-verified launcher lineage for the active run. */
|
|
67
86
|
runtimeLineage() {
|
|
68
87
|
return this.#lineage.snapshot();
|
|
69
88
|
}
|
|
89
|
+
/** Observe a request that still occupies Hopper after caller timeout/cancel. */
|
|
90
|
+
requestActivity() {
|
|
91
|
+
return this.#requests.activity();
|
|
92
|
+
}
|
|
70
93
|
/** Launch the bridge once and complete its authenticated health handshake. */
|
|
71
94
|
start(signal) {
|
|
72
95
|
if (this.#closePromise !== undefined) {
|
|
@@ -186,20 +209,29 @@ export class HopperClient {
|
|
|
186
209
|
const started = await this.start(options.signal);
|
|
187
210
|
if (!started.ok)
|
|
188
211
|
return started;
|
|
189
|
-
|
|
212
|
+
const result = await this.#request(name, arguments_, options);
|
|
213
|
+
return !result.ok &&
|
|
214
|
+
result.error instanceof HopperRemoteError &&
|
|
215
|
+
result.error.diagnosticType === "capability_unavailable"
|
|
216
|
+
? err(new AnalysisCapabilityUnavailableError("hopper", name, result.error.safeMessage))
|
|
217
|
+
: result;
|
|
190
218
|
}
|
|
191
219
|
/** Stop the bridge, settle outstanding requests, and remove session artifacts. */
|
|
192
220
|
close() {
|
|
221
|
+
return this.closeWithOutcome().then(() => undefined);
|
|
222
|
+
}
|
|
223
|
+
/** Stop the bridge and report whether every owned resource was verified clean. */
|
|
224
|
+
closeWithOutcome(options = {}) {
|
|
193
225
|
const starting = this.#startPromise;
|
|
194
226
|
const controller = this.#startupController;
|
|
195
227
|
controller?.abort();
|
|
196
|
-
this.#closePromise ??= Promise.resolve().then(() => this.#close(starting, controller));
|
|
228
|
+
this.#closePromise ??= Promise.resolve().then(() => this.#close(starting, controller, options));
|
|
197
229
|
return this.#closePromise;
|
|
198
230
|
}
|
|
199
|
-
async #close(starting, controller) {
|
|
231
|
+
async #close(starting, controller, options) {
|
|
200
232
|
try {
|
|
201
233
|
await starting?.catch(() => undefined);
|
|
202
|
-
await this.#cleanup();
|
|
234
|
+
return await this.#cleanup(options);
|
|
203
235
|
}
|
|
204
236
|
finally {
|
|
205
237
|
if (this.#startPromise === starting)
|
|
@@ -210,63 +242,39 @@ export class HopperClient {
|
|
|
210
242
|
this.#closePromise = undefined;
|
|
211
243
|
}
|
|
212
244
|
}
|
|
213
|
-
async #cleanup() {
|
|
245
|
+
async #cleanup(options = {}) {
|
|
214
246
|
this.#closing = true;
|
|
215
247
|
try {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
!isHopperShutdownAcknowledgement(shutdown.value))
|
|
236
|
-
this.#logger.warn({ status: shutdown.ok ? "invalid-acknowledgement" : "failed" }, "Hopper document shutdown was not confirmed");
|
|
237
|
-
}
|
|
238
|
-
this.#failAll(new HopperProcessError(null));
|
|
239
|
-
if (socket !== undefined)
|
|
240
|
-
this.#detachSocket(socket);
|
|
241
|
-
socket?.destroy();
|
|
248
|
+
return await cleanupHopperSession({
|
|
249
|
+
socket: this.#socket,
|
|
250
|
+
launch: this.#launch,
|
|
251
|
+
processSupervisor: this.#process,
|
|
252
|
+
runtimeRoot: this.#runtimeRoot,
|
|
253
|
+
activeRequest: this.#requests.activity(),
|
|
254
|
+
progress: options.progress,
|
|
255
|
+
logger: this.#logger,
|
|
256
|
+
onDiagnostic: this.#options.onDiagnostic,
|
|
257
|
+
request: (method) => this.#request(method, {}, { timeoutMs: SHUTDOWN_TIMEOUT_MS }),
|
|
258
|
+
releaseTransport: (socket) => {
|
|
259
|
+
this.#failAll(new HopperProcessError(null));
|
|
260
|
+
if (socket !== undefined)
|
|
261
|
+
this.#detachSocket(socket);
|
|
262
|
+
socket?.destroy();
|
|
263
|
+
},
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
finally {
|
|
242
267
|
this.#socket = undefined;
|
|
243
|
-
if (this.#process !== undefined) {
|
|
244
|
-
const stopped = await this.#process.stop(cleanupResult === undefined ? {} : { cleanupResult });
|
|
245
|
-
const diagnostic = createOwnedHopperShutdownDiagnostic(this.#process.launch, stopped, cleanupResult);
|
|
246
|
-
this.#options.onDiagnostic?.(diagnostic);
|
|
247
|
-
this.#logger.info(diagnostic, "Owned Hopper launcher shutdown completed");
|
|
248
|
-
if (stopped.status === "incomplete")
|
|
249
|
-
this.#logger.warn({ reason: stopped.reason }, "Owned launcher cleanup failed closed");
|
|
250
|
-
}
|
|
251
268
|
this.#process = undefined;
|
|
252
269
|
this.#launch = undefined;
|
|
253
|
-
const runtimeRoot = this.#runtimeRoot;
|
|
254
270
|
this.#runtimeRoot = undefined;
|
|
255
|
-
await runtimeRoot?.close();
|
|
256
271
|
this.#token = undefined;
|
|
257
|
-
this.#
|
|
272
|
+
this.#responses.reset();
|
|
258
273
|
this.#launcherExitCode = undefined;
|
|
259
274
|
this.#launcherFailureDiagnostic = undefined;
|
|
260
|
-
}
|
|
261
|
-
finally {
|
|
262
275
|
this.#closing = false;
|
|
263
276
|
}
|
|
264
277
|
}
|
|
265
|
-
async #fallbackDocumentShutdown() {
|
|
266
|
-
const fallback = await this.#request("shutdown_document", {}, { timeoutMs: SHUTDOWN_TIMEOUT_MS }).catch(() => err(new HopperProcessError(null)));
|
|
267
|
-
if (!fallback.ok || !isHopperShutdownAcknowledgement(fallback.value))
|
|
268
|
-
this.#logger.warn({ status: fallback.ok ? "invalid-acknowledgement" : "failed" }, "Hopper document shutdown fallback was not confirmed");
|
|
269
|
-
}
|
|
270
278
|
async #connect(socketPath, deadline) {
|
|
271
279
|
while (deadline.remainingMs() > 0) {
|
|
272
280
|
if (deadline.signal.aborted)
|
|
@@ -306,17 +314,11 @@ export class HopperClient {
|
|
|
306
314
|
const id = this.#nextId++;
|
|
307
315
|
const startedAt = performance.now();
|
|
308
316
|
const timeoutMs = options.timeoutMs ?? this.#options.requestTimeoutMs;
|
|
309
|
-
const
|
|
317
|
+
const result = await this.#requests.run(id, method, params, {
|
|
310
318
|
timeoutMs,
|
|
311
319
|
...(options.signal === undefined ? {} : { signal: options.signal }),
|
|
312
|
-
|
|
313
|
-
cancelledValue: () => err(new HopperCancelledError()),
|
|
320
|
+
...(options.progress !== undefined ? { progress: options.progress } : {}),
|
|
314
321
|
});
|
|
315
|
-
socket.write(`${JSON.stringify({ id, token, method, params })}\n`, (cause) => {
|
|
316
|
-
if (cause !== undefined && cause !== null)
|
|
317
|
-
this.#pending.settle(id, err(new HopperProcessError(null)));
|
|
318
|
-
});
|
|
319
|
-
const result = await response;
|
|
320
322
|
this.#logger[result.ok ? "debug" : "warn"]({
|
|
321
323
|
method,
|
|
322
324
|
durationMs: Math.round((performance.now() - startedAt) * 100) / 100,
|
|
@@ -364,44 +366,12 @@ export class HopperClient {
|
|
|
364
366
|
if (launch.ownsProcessLifetime && !this.#closing)
|
|
365
367
|
this.#failAll(new HopperProcessError(event.code, this.#launcherFailureDiagnostic));
|
|
366
368
|
}
|
|
367
|
-
#onData(chunk) {
|
|
368
|
-
this.#buffer += chunk;
|
|
369
|
-
let newline = this.#buffer.indexOf("\n");
|
|
370
|
-
while (newline >= 0) {
|
|
371
|
-
const line = this.#buffer.slice(0, newline).trim();
|
|
372
|
-
this.#buffer = this.#buffer.slice(newline + 1);
|
|
373
|
-
if (Buffer.byteLength(line) > MAX_LINE_BYTES) {
|
|
374
|
-
this.#abortProtocol("Hopper response exceeded the maximum line size");
|
|
375
|
-
return;
|
|
376
|
-
}
|
|
377
|
-
if (line.length > 0)
|
|
378
|
-
this.#onLine(line);
|
|
379
|
-
newline = this.#buffer.indexOf("\n");
|
|
380
|
-
}
|
|
381
|
-
if (Buffer.byteLength(this.#buffer) > MAX_LINE_BYTES) {
|
|
382
|
-
this.#abortProtocol("Hopper response exceeded the maximum line size");
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
#onLine(line) {
|
|
386
|
-
const parsed = parseResponseLine(line);
|
|
387
|
-
if (!parsed.ok) {
|
|
388
|
-
this.#abortProtocol(parsed.error.message, parsed.error);
|
|
389
|
-
return;
|
|
390
|
-
}
|
|
391
|
-
if (!this.#pending.has(parsed.value.id)) {
|
|
392
|
-
if (parsed.value.id >= this.#nextId) {
|
|
393
|
-
this.#abortProtocol("Hopper returned an unknown response id");
|
|
394
|
-
}
|
|
395
|
-
return;
|
|
396
|
-
}
|
|
397
|
-
this.#pending.settle(parsed.value.id, responseResult(parsed.value));
|
|
398
|
-
}
|
|
399
369
|
#abortProtocol(message, cause) {
|
|
400
370
|
this.#failAll(new HopperProtocolError(message, { cause }));
|
|
401
371
|
this.#socket?.destroy();
|
|
402
372
|
}
|
|
403
373
|
#failAll(error) {
|
|
404
|
-
this.#
|
|
374
|
+
this.#requests.failAll(error);
|
|
405
375
|
}
|
|
406
376
|
}
|
|
407
377
|
const isAborted = (signal) => signal?.aborted === true;
|
|
@@ -47,7 +47,7 @@ const CAPABILITIES = Object.freeze(HOPPER_PROVIDER_TOOL_CONTRACTS.map((contract)
|
|
|
47
47
|
}),
|
|
48
48
|
limits: Object.freeze({
|
|
49
49
|
maxResults: null,
|
|
50
|
-
maxPayloadBytes: null,
|
|
50
|
+
maxPayloadBytes: contract.name === "read_bytes" ? 4_096 : null,
|
|
51
51
|
timeoutMs: null,
|
|
52
52
|
}),
|
|
53
53
|
limitations: Object.freeze([
|
|
@@ -200,6 +200,25 @@ export class HopperProvider {
|
|
|
200
200
|
? []
|
|
201
201
|
: [{ provider: executionProvider, observation }];
|
|
202
202
|
},
|
|
203
|
+
requestActivitySnapshots: () => {
|
|
204
|
+
const activity = client.requestActivity();
|
|
205
|
+
return [
|
|
206
|
+
{
|
|
207
|
+
provider: executionProvider,
|
|
208
|
+
active: activity === null
|
|
209
|
+
? null
|
|
210
|
+
: {
|
|
211
|
+
requestId: activity.requestId,
|
|
212
|
+
operation: activity.operation,
|
|
213
|
+
elapsedMs: activity.elapsedMs,
|
|
214
|
+
timeoutMs: activity.timeoutMs,
|
|
215
|
+
callerState: activity.callerState,
|
|
216
|
+
},
|
|
217
|
+
queuedRequests: activity?.queuedRequests ?? 0,
|
|
218
|
+
},
|
|
219
|
+
];
|
|
220
|
+
},
|
|
221
|
+
closeWithOutcome: (options) => client.closeWithOutcome(options),
|
|
203
222
|
close: () => client.close(),
|
|
204
223
|
};
|
|
205
224
|
}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { performance } from "node:perf_hooks";
|
|
2
|
+
import { HopperCancelledError, HopperProcessError, HopperProtocolError, HopperTimeoutError, } from "../domain/errors.js";
|
|
3
|
+
import { err } from "../domain/result.js";
|
|
4
|
+
/** Bounded FIFO that keeps the wire serialized until Hopper actually replies. */
|
|
5
|
+
export class HopperRequestQueue {
|
|
6
|
+
maximum;
|
|
7
|
+
send;
|
|
8
|
+
#queue = [];
|
|
9
|
+
#active;
|
|
10
|
+
constructor(maximum, send) {
|
|
11
|
+
this.maximum = maximum;
|
|
12
|
+
this.send = send;
|
|
13
|
+
}
|
|
14
|
+
/** Queue one request, counting queue wait against its caller deadline. */
|
|
15
|
+
run(id, method, params, options) {
|
|
16
|
+
if (options.signal?.aborted === true)
|
|
17
|
+
return Promise.resolve(err(new HopperCancelledError()));
|
|
18
|
+
if (options.timeoutMs <= 0)
|
|
19
|
+
return Promise.resolve(err(new HopperTimeoutError(options.timeoutMs)));
|
|
20
|
+
if (this.#size() >= this.maximum)
|
|
21
|
+
return Promise.resolve(err(new HopperProtocolError(`Hopper serial request queue reached its ${String(this.maximum)}-request limit`)));
|
|
22
|
+
return new Promise((resolve) => {
|
|
23
|
+
let entry;
|
|
24
|
+
const onAbort = options.signal === undefined ? undefined : () => this.#cancel(entry);
|
|
25
|
+
const timer = setTimeout(() => this.#timeout(entry), options.timeoutMs);
|
|
26
|
+
entry = {
|
|
27
|
+
id,
|
|
28
|
+
method,
|
|
29
|
+
params,
|
|
30
|
+
signal: options.signal,
|
|
31
|
+
timeoutMs: options.timeoutMs,
|
|
32
|
+
deadline: performance.now() + options.timeoutMs,
|
|
33
|
+
progress: options.progress,
|
|
34
|
+
resolve,
|
|
35
|
+
timer,
|
|
36
|
+
onAbort,
|
|
37
|
+
callerState: "waiting",
|
|
38
|
+
callerSettled: false,
|
|
39
|
+
startedAt: undefined,
|
|
40
|
+
heartbeat: undefined,
|
|
41
|
+
};
|
|
42
|
+
this.#queue.push(entry);
|
|
43
|
+
if (onAbort !== undefined)
|
|
44
|
+
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
45
|
+
if (this.#active !== undefined || this.#queue.length > 1)
|
|
46
|
+
this.#report(entry, `${method} queued behind ${String(this.#size() - 1)} Hopper request(s)`);
|
|
47
|
+
this.#drain();
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
/** Settle the active wire request. False identifies an unexpected response id. */
|
|
51
|
+
accept(id, result) {
|
|
52
|
+
const entry = this.#active;
|
|
53
|
+
if (entry === undefined || entry.id !== id)
|
|
54
|
+
return false;
|
|
55
|
+
this.#releaseWire(entry);
|
|
56
|
+
if (!entry.callerSettled)
|
|
57
|
+
this.#settleCaller(entry, result, "waiting");
|
|
58
|
+
this.#active = undefined;
|
|
59
|
+
this.#drain();
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
/** Fail the active wire request and every request still waiting in the FIFO. */
|
|
63
|
+
failAll(error) {
|
|
64
|
+
const active = this.#active;
|
|
65
|
+
this.#active = undefined;
|
|
66
|
+
if (active !== undefined) {
|
|
67
|
+
this.#releaseWire(active);
|
|
68
|
+
if (!active.callerSettled)
|
|
69
|
+
this.#settleCaller(active, err(error), "waiting");
|
|
70
|
+
}
|
|
71
|
+
for (const entry of this.#queue.splice(0))
|
|
72
|
+
this.#settleCaller(entry, err(error), "waiting");
|
|
73
|
+
}
|
|
74
|
+
/** Snapshot the one request still occupying Hopper's serial Python thread. */
|
|
75
|
+
activity() {
|
|
76
|
+
const active = this.#active;
|
|
77
|
+
if (active === undefined || active.startedAt === undefined)
|
|
78
|
+
return null;
|
|
79
|
+
return {
|
|
80
|
+
requestId: active.id,
|
|
81
|
+
operation: active.method,
|
|
82
|
+
elapsedMs: Math.max(0, Math.round(performance.now() - active.startedAt)),
|
|
83
|
+
timeoutMs: active.timeoutMs,
|
|
84
|
+
callerState: active.callerState,
|
|
85
|
+
queuedRequests: this.#queue.length,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
/** Return whether an id belongs to a request that has not crossed the wire. */
|
|
89
|
+
hasQueued(id) {
|
|
90
|
+
return this.#queue.some((entry) => entry.id === id);
|
|
91
|
+
}
|
|
92
|
+
/** Number of caller requests waiting behind the active bridge operation. */
|
|
93
|
+
queuedCount() {
|
|
94
|
+
return this.#queue.length;
|
|
95
|
+
}
|
|
96
|
+
#size() {
|
|
97
|
+
return this.#queue.length + (this.#active === undefined ? 0 : 1);
|
|
98
|
+
}
|
|
99
|
+
#drain() {
|
|
100
|
+
if (this.#active !== undefined)
|
|
101
|
+
return;
|
|
102
|
+
const entry = this.#queue.shift();
|
|
103
|
+
if (entry === undefined)
|
|
104
|
+
return;
|
|
105
|
+
const remaining = entry.deadline - performance.now();
|
|
106
|
+
if (entry.signal?.aborted === true || remaining <= 0) {
|
|
107
|
+
this.#settleCaller(entry, entry.signal?.aborted === true
|
|
108
|
+
? err(new HopperCancelledError())
|
|
109
|
+
: err(new HopperTimeoutError(entry.timeoutMs)), entry.signal?.aborted === true ? "cancelled" : "timed_out");
|
|
110
|
+
this.#drain();
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
this.#active = entry;
|
|
114
|
+
entry.startedAt = performance.now();
|
|
115
|
+
this.#report(entry, `${entry.method} started on Hopper's serial bridge`);
|
|
116
|
+
entry.heartbeat = setInterval(() => {
|
|
117
|
+
if (entry.callerSettled || entry.startedAt === undefined)
|
|
118
|
+
return;
|
|
119
|
+
const elapsed = Math.round(performance.now() - entry.startedAt);
|
|
120
|
+
this.#report(entry, `${entry.method} is still running in Hopper (${String(elapsed)} ms elapsed)`);
|
|
121
|
+
}, 1_000);
|
|
122
|
+
try {
|
|
123
|
+
this.send({ id: entry.id, method: entry.method, params: entry.params }, () => this.accept(entry.id, err(new HopperProcessError(null))));
|
|
124
|
+
}
|
|
125
|
+
catch (cause) {
|
|
126
|
+
this.accept(entry.id, err(new HopperProtocolError("Hopper socket write failed", { cause })));
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
#timeout(entry) {
|
|
130
|
+
if (entry.callerSettled)
|
|
131
|
+
return;
|
|
132
|
+
if (this.#active === entry) {
|
|
133
|
+
this.#settleCaller(entry, err(new HopperTimeoutError(entry.timeoutMs)), "timed_out");
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const index = this.#queue.indexOf(entry);
|
|
137
|
+
if (index < 0)
|
|
138
|
+
return;
|
|
139
|
+
this.#queue.splice(index, 1);
|
|
140
|
+
this.#settleCaller(entry, err(new HopperTimeoutError(entry.timeoutMs)), "timed_out");
|
|
141
|
+
}
|
|
142
|
+
#cancel(entry) {
|
|
143
|
+
if (entry.callerSettled)
|
|
144
|
+
return;
|
|
145
|
+
if (this.#active === entry) {
|
|
146
|
+
this.#settleCaller(entry, err(new HopperCancelledError()), "cancelled");
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
const index = this.#queue.indexOf(entry);
|
|
150
|
+
if (index < 0)
|
|
151
|
+
return;
|
|
152
|
+
this.#queue.splice(index, 1);
|
|
153
|
+
this.#settleCaller(entry, err(new HopperCancelledError()), "cancelled");
|
|
154
|
+
}
|
|
155
|
+
#settleCaller(entry, result, callerState) {
|
|
156
|
+
if (entry.callerSettled)
|
|
157
|
+
return;
|
|
158
|
+
entry.callerSettled = true;
|
|
159
|
+
entry.callerState = callerState;
|
|
160
|
+
if (this.#active === entry && entry.heartbeat !== undefined) {
|
|
161
|
+
clearInterval(entry.heartbeat);
|
|
162
|
+
entry.heartbeat = undefined;
|
|
163
|
+
}
|
|
164
|
+
clearTimeout(entry.timer);
|
|
165
|
+
if (entry.signal !== undefined && entry.onAbort !== undefined)
|
|
166
|
+
entry.signal.removeEventListener("abort", entry.onAbort);
|
|
167
|
+
entry.resolve(result);
|
|
168
|
+
}
|
|
169
|
+
#releaseWire(entry) {
|
|
170
|
+
if (entry.heartbeat !== undefined)
|
|
171
|
+
clearInterval(entry.heartbeat);
|
|
172
|
+
entry.heartbeat = undefined;
|
|
173
|
+
clearTimeout(entry.timer);
|
|
174
|
+
if (entry.signal !== undefined && entry.onAbort !== undefined)
|
|
175
|
+
entry.signal.removeEventListener("abort", entry.onAbort);
|
|
176
|
+
}
|
|
177
|
+
#report(entry, message) {
|
|
178
|
+
void entry.progress
|
|
179
|
+
?.report({
|
|
180
|
+
phase: "hopper_request",
|
|
181
|
+
completed: 0,
|
|
182
|
+
total: 1,
|
|
183
|
+
message,
|
|
184
|
+
})
|
|
185
|
+
.catch(() => undefined);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { parseResponseLine } from "./protocol.js";
|
|
2
|
+
const MAX_LINE_BYTES = 10 * 1024 * 1024;
|
|
3
|
+
/** Incrementally validates bounded Hopper NDJSON response frames. */
|
|
4
|
+
export class HopperResponseStream {
|
|
5
|
+
options;
|
|
6
|
+
#buffer = "";
|
|
7
|
+
constructor(options) {
|
|
8
|
+
this.options = options;
|
|
9
|
+
}
|
|
10
|
+
push(chunk) {
|
|
11
|
+
this.#buffer += chunk;
|
|
12
|
+
let newline = this.#buffer.indexOf("\n");
|
|
13
|
+
while (newline >= 0) {
|
|
14
|
+
const line = this.#buffer.slice(0, newline).trim();
|
|
15
|
+
this.#buffer = this.#buffer.slice(newline + 1);
|
|
16
|
+
if (Buffer.byteLength(line) > MAX_LINE_BYTES) {
|
|
17
|
+
this.options.abort("Hopper response exceeded the maximum line size");
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
if (line.length > 0 && !this.#acceptLine(line))
|
|
21
|
+
return;
|
|
22
|
+
newline = this.#buffer.indexOf("\n");
|
|
23
|
+
}
|
|
24
|
+
if (Buffer.byteLength(this.#buffer) > MAX_LINE_BYTES) {
|
|
25
|
+
this.options.abort("Hopper response exceeded the maximum line size");
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
reset() {
|
|
29
|
+
this.#buffer = "";
|
|
30
|
+
}
|
|
31
|
+
#acceptLine(line) {
|
|
32
|
+
const parsed = parseResponseLine(line);
|
|
33
|
+
if (!parsed.ok) {
|
|
34
|
+
this.options.abort(parsed.error.message, parsed.error);
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
if (this.options.accept(parsed.value))
|
|
38
|
+
return true;
|
|
39
|
+
if (parsed.value.id >= this.options.nextRequestId() ||
|
|
40
|
+
this.options.hasQueued(parsed.value.id)) {
|
|
41
|
+
this.options.abort("Hopper returned an unknown response id");
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
}
|
package/dist/hopper/protocol.js
CHANGED
package/dist/main/transport.js
CHANGED
|
@@ -14,35 +14,14 @@ export const startMcpTransport = async (dependencies, session, serverContext) =>
|
|
|
14
14
|
analysisSnapshotFilePolicy: serverContext.runtimeState.snapshotPolicy,
|
|
15
15
|
permissionAuthority: serverContext.permissionAuthority,
|
|
16
16
|
browserObservation: serverContext.browserObservation,
|
|
17
|
+
browserScenarioCapture: serverContext.browserScenarioCapture,
|
|
17
18
|
electronObservation: serverContext.electronObservation,
|
|
19
|
+
javascriptRuntimeObservation: serverContext.javascriptRuntimeObservation,
|
|
18
20
|
artifactIntegrityContinueEnabled: () => serverContext.runtimeState.currentConfig
|
|
19
21
|
.artifactIntegrityContinueEnabled,
|
|
20
22
|
javascriptReplayPolicy: serverContext.runtimeState.javascriptReplayPolicy,
|
|
21
23
|
managedRuntimePolicy: serverContext.runtimeState.managedRuntimePolicy,
|
|
22
|
-
availabilityPolicy: () => (
|
|
23
|
-
processCaptureEnabled: serverContext.runtimeState.currentConfig.processExecutionPolicy
|
|
24
|
-
.enabled,
|
|
25
|
-
evidenceFileRoots: serverContext.runtimeState.currentConfig.evidenceFilePolicy
|
|
26
|
-
.roots.length,
|
|
27
|
-
investigationInputRoots: serverContext.runtimeState.currentConfig.investigationInputRoots
|
|
28
|
-
.length,
|
|
29
|
-
browserObservationEnabled: serverContext.runtimeState.currentConfig
|
|
30
|
-
.browserObservationEnabled &&
|
|
31
|
-
serverContext.runtimeState.currentConfig.browserCdpEndpoints
|
|
32
|
-
.length > 0 &&
|
|
33
|
-
serverContext.runtimeState.currentConfig.browserAllowedOrigins
|
|
34
|
-
.length > 0,
|
|
35
|
-
electronObservationEnabled: serverContext.runtimeState.currentConfig
|
|
36
|
-
.electronObservationEnabled &&
|
|
37
|
-
serverContext.runtimeState.currentConfig.electronCdpEndpoints
|
|
38
|
-
.length > 0 &&
|
|
39
|
-
serverContext.runtimeState.currentConfig.electronFileRoots
|
|
40
|
-
.length > 0,
|
|
41
|
-
javascriptReplayEnabled: serverContext.runtimeState.currentConfig.javascriptReplayPolicy
|
|
42
|
-
.enabled,
|
|
43
|
-
managedRuntimeEnabled: serverContext.runtimeState.currentConfig.managedRuntimePolicy
|
|
44
|
-
.enabled,
|
|
45
|
-
}),
|
|
24
|
+
availabilityPolicy: () => runtimeAvailability(serverContext.runtimeState),
|
|
46
25
|
});
|
|
47
26
|
liveServers.add(server);
|
|
48
27
|
return server;
|
|
@@ -61,3 +40,24 @@ export const startMcpTransport = async (dependencies, session, serverContext) =>
|
|
|
61
40
|
}
|
|
62
41
|
return { ok: true, handle, liveServers };
|
|
63
42
|
};
|
|
43
|
+
const runtimeAvailability = (state) => ({
|
|
44
|
+
processCaptureEnabled: state.currentConfig.processExecutionPolicy.enabled,
|
|
45
|
+
evidenceFileRoots: state.currentConfig.evidenceFilePolicy.roots.length,
|
|
46
|
+
investigationInputRoots: state.currentConfig.investigationInputRoots.length,
|
|
47
|
+
browserObservationEnabled: state.currentConfig.browserObservationEnabled &&
|
|
48
|
+
state.currentConfig.browserCdpEndpoints.length > 0 &&
|
|
49
|
+
state.currentConfig.browserAllowedOrigins.length > 0,
|
|
50
|
+
browserScenarioEnabled: state.currentConfig.browserScenarioPolicy.enabled &&
|
|
51
|
+
state.currentConfig.browserScenarioPolicy.allowedOrigins.length > 0 &&
|
|
52
|
+
(state.currentConfig.browserScenarioPolicy.executableRoots.length > 0 ||
|
|
53
|
+
state.currentConfig.browserScenarioPolicy.cdpEndpoints.length > 0),
|
|
54
|
+
electronObservationEnabled: state.currentConfig.electronObservationEnabled &&
|
|
55
|
+
state.currentConfig.electronCdpEndpoints.length > 0 &&
|
|
56
|
+
state.currentConfig.electronFileRoots.length > 0,
|
|
57
|
+
v8InspectorObservationEnabled: state.currentConfig.v8InspectorObservationEnabled &&
|
|
58
|
+
state.currentConfig.v8InspectorEndpoints.length > 0 &&
|
|
59
|
+
(state.currentConfig.v8InspectorFileRoots.length > 0 ||
|
|
60
|
+
state.currentConfig.v8InspectorAllowedOrigins.length > 0),
|
|
61
|
+
javascriptReplayEnabled: state.currentConfig.javascriptReplayPolicy.enabled,
|
|
62
|
+
managedRuntimeEnabled: state.currentConfig.managedRuntimePolicy.enabled,
|
|
63
|
+
});
|
package/dist/main.js
CHANGED
|
@@ -9,6 +9,8 @@ import { projectAnalysisError } from "./domain/errors.js";
|
|
|
9
9
|
import { loadConfiguredPermissionAuthority } from "./application/PermissionConfiguration.js";
|
|
10
10
|
import { CdpBrowserProvider } from "./browser/CdpBrowserProvider.js";
|
|
11
11
|
import { CdpElectronProvider } from "./browser/CdpElectronProvider.js";
|
|
12
|
+
import { V8InspectorProvider } from "./browser/V8InspectorProvider.js";
|
|
13
|
+
import { PlaywrightBrowserScenarioProvider } from "./browser/PlaywrightBrowserScenarioProvider.js";
|
|
12
14
|
import { SERVER_START_FAILED } from "./main/messages.js";
|
|
13
15
|
import { createRuntimeState } from "./main/state.js";
|
|
14
16
|
import { openInitialTarget } from "./main/startup.js";
|
|
@@ -59,7 +61,9 @@ export const run = async (dependencies = runtimeDependencies()) => {
|
|
|
59
61
|
}
|
|
60
62
|
const session = createBinarySession(config.value, logger);
|
|
61
63
|
const browserObservation = new CdpBrowserProvider();
|
|
64
|
+
const browserScenarioCapture = new PlaywrightBrowserScenarioProvider();
|
|
62
65
|
const electronObservation = new CdpElectronProvider();
|
|
66
|
+
const javascriptRuntimeObservation = new V8InspectorProvider();
|
|
63
67
|
const opened = await openInitialTarget(session, config.value, serverLogger, dependencies.writeStderr);
|
|
64
68
|
if (!opened.ok)
|
|
65
69
|
return opened.exitCode;
|
|
@@ -68,7 +72,9 @@ export const run = async (dependencies = runtimeDependencies()) => {
|
|
|
68
72
|
logger,
|
|
69
73
|
serverLogger,
|
|
70
74
|
browserObservation,
|
|
75
|
+
browserScenarioCapture,
|
|
71
76
|
electronObservation,
|
|
77
|
+
javascriptRuntimeObservation,
|
|
72
78
|
permissionAuthority: permissionAuthority.value,
|
|
73
79
|
runtimeState,
|
|
74
80
|
});
|