rea-agents 2.4.0 → 3.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 +91 -19
- package/bridge/ghidra/ReaGhidraBridge.java +524 -4
- package/bridge/hopper_bridge.py +313 -28
- package/dist/application/AnalysisClientCleanup.js +14 -0
- package/dist/application/AnalysisContextQueries.js +130 -0
- package/dist/application/AnalysisSnapshotCache.js +4 -2
- package/dist/application/ApplicationWorkflowEvidenceResolver.js +31 -13
- package/dist/application/ArtifactInventory/scanCanonical.js +1 -1
- package/dist/application/BinarySession.js +20 -8
- package/dist/application/BinarySessionComposition.js +21 -0
- package/dist/application/BinarySessionRecords.js +79 -9
- package/dist/application/BinarySessionStatus.js +31 -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 +84 -14
- package/dist/application/ClientRegistrationStatus.js +4 -1
- package/dist/application/CompositeProvider.js +10 -1
- package/dist/application/DirectAnalysis.js +13 -4
- package/dist/application/EnhancedLiteralTracing.js +118 -0
- package/dist/application/EnhancedTools.js +71 -127
- package/dist/application/EvidenceLedger.js +45 -16
- package/dist/application/JavaScriptApplicationWorkflowEvidence.js +13 -0
- package/dist/application/JavaScriptApplicationWorkflowService.js +27 -1
- package/dist/application/JavaScriptArtifactAnalysis.js +13 -4
- 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/LazyAnalysisProvider.js +77 -0
- package/dist/application/LoopbackReplay.js +1 -1
- package/dist/application/NativeApiInspection.js +80 -0
- package/dist/application/ProcessReactiveEffects.js +6 -0
- package/dist/application/ProcessReactiveHarness.js +16 -1
- 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/application/SessionProviderRouter.js +6 -6
- package/dist/application/SetupClientConfiguration.js +4 -2
- package/dist/application/runtime.js +26 -9
- 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 +259 -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 +11 -3
- package/dist/cli/artifactCommands.js +44 -3
- package/dist/cli/coreAnalysisCommands.js +78 -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 +9 -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 +29 -2
- 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 +35 -6
- package/dist/contracts/functionInstructionContract.js +8 -0
- package/dist/contracts/functionWorkflowToolContracts.js +30 -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/promptContracts.js +14 -15
- package/dist/contracts/reconstructionReadinessExample.js +436 -0
- package/dist/contracts/toolContractExamples.js +8 -0
- package/dist/contracts/toolContractTypes.js +1 -0
- package/dist/contracts/toolContracts.js +34 -25
- package/dist/contracts/toolEffects.js +25 -0
- package/dist/contracts/toolOutputSchemaGroups.js +120 -30
- package/dist/contracts/toolOutputSchemaPrimitives.js +37 -0
- package/dist/domain/analysisErrorPresentation.js +8 -2
- package/dist/domain/analysisErrorProjection.js +9 -0
- package/dist/domain/artifactInspection.js +347 -0
- 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/bytecodeProvider.js +179 -0
- package/dist/domain/conformancePackage.js +169 -0
- package/dist/domain/conformanceReplay.js +104 -0
- package/dist/domain/conformanceTrustGate.js +193 -0
- package/dist/domain/customProtocolCapture.js +137 -0
- package/dist/domain/eventProcessTree.js +214 -0
- package/dist/domain/evidenceBundle.js +47 -0
- package/dist/domain/hopperStartupFailure.js +1 -1
- package/dist/domain/hopperValues.js +14 -1
- package/dist/domain/inputIssueProjection.js +7 -1
- 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 +13 -16
- 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/javascriptSourceParser.js +15 -0
- package/dist/domain/javascriptStaticAnalysis.js +12 -15
- package/dist/domain/javascriptStaticAnalysisBundler.js +38 -0
- package/dist/domain/javascriptStaticAnalysisCalls.js +23 -1
- package/dist/domain/javascriptStaticAnalysisHelpers.js +8 -0
- package/dist/domain/mobileApplicationInvestigation.js +159 -0
- package/dist/domain/nativeApiBoundary.js +130 -0
- package/dist/domain/objcSwiftMetadata.js +150 -0
- package/dist/domain/packageAnalysis.js +123 -0
- package/dist/domain/peInspection.js +196 -0
- package/dist/domain/processCapture.js +8 -2
- package/dist/domain/processReactiveScenario.js +1 -0
- package/dist/domain/processReactiveTransition.js +9 -4
- package/dist/domain/protocolCapture.js +243 -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/dotnet/ManagedStaticProvider.js +34 -5
- package/dist/generatedMcpToolCatalog.js +37 -0
- package/dist/generatedPackageMetadata.js +4 -4
- package/dist/ghidra/GhidraDefaults.js +1 -1
- package/dist/ghidra/GhidraFunctionValues.js +40 -2
- package/dist/ghidra/GhidraProviderCapabilities.js +47 -38
- package/dist/hopper/HopperCleanup.js +158 -0
- package/dist/hopper/HopperClient.js +93 -99
- package/dist/hopper/HopperProvider.js +61 -30
- package/dist/hopper/HopperRequestQueue.js +215 -0
- package/dist/hopper/HopperResponseStream.js +46 -0
- package/dist/hopper/protocol.js +63 -20
- package/dist/main/transport.js +24 -27
- package/dist/main.js +14 -6
- package/dist/mcpDoctor.js +27 -4
- package/dist/mcpStartupPolicy.js +14 -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/LazyToolCatalog.js +134 -0
- package/dist/server/createServer.js +92 -154
- package/dist/server/hydrateServerTools.js +191 -0
- 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 +28 -7
- package/dist/server/registerEvidenceResources.js +54 -101
- package/dist/server/registerEvidenceTools.js +9 -2
- package/dist/server/registerInvestigationTools.js +1 -2
- package/dist/server/registerJavaScriptApplicationGraphResource.js +0 -4
- package/dist/server/registerJavaScriptRuntimeObservationTools.js +37 -0
- package/dist/server/registerReconstructionObligationLedgerResource.js +32 -0
- package/dist/server/registerReconstructionReadinessResource.js +32 -0
- package/dist/server/registerSessionRecordTools.js +82 -12
- package/dist/server/registerSessionStatusTool.js +11 -8
- package/dist/server/registerSessionTools.js +32 -58
- package/dist/server/sessionAvailabilityPolicy.js +10 -8
- package/dist/server/toolRegistrationOptions.js +21 -6
- package/dist/server/toolResult.js +12 -0
- package/package.json +28 -11
- package/scripts/package-runner-bootstrap.mjs +72 -0
- package/scripts/rea.mjs +11 -1
- package/skills/reverse-engineer-anything/SKILL.md +10 -3
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import { javascriptRuntimeObservationSchema, javascriptRuntimeTargetListSchema, } from "../domain/javascriptRuntimeObservation.js";
|
|
2
|
+
import { AnalysisError, BrowserObservationError, ProviderAdapterError, } from "../domain/errors.js";
|
|
3
|
+
import { err, ok } from "../domain/result.js";
|
|
4
|
+
import { boundedText, numberValue, recordValue, stringValue, delayWithCancellation, } from "./CdpCaptureValues.js";
|
|
5
|
+
import { CdpConnection } from "./CdpConnection.js";
|
|
6
|
+
import { authorizeRuntimeLocation, canonicalRuntimeRoots, } from "./JavaScriptRuntimeScope.js";
|
|
7
|
+
import { createInspectorExclusionCounts, describeInspectorTargetLimitations, finalizeInspectorCapture, } from "./V8InspectorCaptureProjection.js";
|
|
8
|
+
import { discoverV8Inspector, } from "./V8InspectorEndpoint.js";
|
|
9
|
+
/** Public identity committed by passive V8 Inspector observations. */
|
|
10
|
+
export const V8_INSPECTOR_PROVIDER_IDENTITY = Object.freeze({
|
|
11
|
+
id: "rea-v8-inspector",
|
|
12
|
+
name: "REA passive Node/Electron V8 Inspector provider",
|
|
13
|
+
version: "1",
|
|
14
|
+
});
|
|
15
|
+
/** Attach-only provider; sends only Runtime.enable and Debugger.enable. */
|
|
16
|
+
export class V8InspectorProvider {
|
|
17
|
+
identity() {
|
|
18
|
+
return V8_INSPECTOR_PROVIDER_IDENTITY;
|
|
19
|
+
}
|
|
20
|
+
async listTargets(input, options = {}) {
|
|
21
|
+
try {
|
|
22
|
+
const roots = await canonicalRuntimeRoots(input.allowed_file_roots);
|
|
23
|
+
const discovery = await discoverV8Inspector(input.inspector_endpoint, "list_javascript_runtime_targets", options.signal);
|
|
24
|
+
const allowed = [];
|
|
25
|
+
const excluded = createInspectorExclusionCounts();
|
|
26
|
+
for (const target of discovery.targets) {
|
|
27
|
+
const decision = await authorizeRuntimeLocation(target.url, roots, input.allowed_origins);
|
|
28
|
+
if (!decision.allowed) {
|
|
29
|
+
excluded[decision.reason] += 1;
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
if (decision.location.kind === "builtin") {
|
|
33
|
+
excluded.unsupported_location += 1;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
allowed.push({ ...target, location: decision.location });
|
|
37
|
+
}
|
|
38
|
+
allowed.sort((left, right) => left.id < right.id ? -1 : left.id > right.id ? 1 : 0);
|
|
39
|
+
const items = allowed
|
|
40
|
+
.slice(input.offset, input.offset + input.limit)
|
|
41
|
+
.map(projectTarget);
|
|
42
|
+
const nextOffset = input.offset + items.length;
|
|
43
|
+
return ok(javascriptRuntimeTargetListSchema.parse({
|
|
44
|
+
schema_version: 1,
|
|
45
|
+
runtime: discovery.runtime,
|
|
46
|
+
targets: {
|
|
47
|
+
items,
|
|
48
|
+
offset: input.offset,
|
|
49
|
+
limit: input.limit,
|
|
50
|
+
total: allowed.length,
|
|
51
|
+
next_offset: nextOffset < allowed.length ? nextOffset : null,
|
|
52
|
+
has_more: nextOffset < allowed.length,
|
|
53
|
+
},
|
|
54
|
+
excluded: { ...excluded, unconnectable: 0 },
|
|
55
|
+
limitations: describeInspectorTargetLimitations(),
|
|
56
|
+
}));
|
|
57
|
+
}
|
|
58
|
+
catch (cause) {
|
|
59
|
+
return err(providerError(cause, "list_javascript_runtime_targets"));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async observe(input, options = {}) {
|
|
63
|
+
let connection;
|
|
64
|
+
try {
|
|
65
|
+
const roots = await canonicalRuntimeRoots(input.allowed_file_roots);
|
|
66
|
+
const discovery = await discoverV8Inspector(input.inspector_endpoint, "observe_javascript_runtime", options.signal);
|
|
67
|
+
const target = await authorizedTarget(discovery.targets, input, roots);
|
|
68
|
+
assertRuntimeKind(target, input.runtime_kind);
|
|
69
|
+
connection = await CdpConnection.connect(target.webSocketUrl, "observe_javascript_runtime", options.signal);
|
|
70
|
+
const state = emptyCaptureState();
|
|
71
|
+
const removeListener = connection.onEvent((event) => ingestEvent(event, input, state));
|
|
72
|
+
try {
|
|
73
|
+
await connection.send("Runtime.enable", {}, undefined, options.signal);
|
|
74
|
+
await connection.send("Debugger.enable", {}, undefined, options.signal);
|
|
75
|
+
await waitForCapture(connection, input.observation_ms, options.signal);
|
|
76
|
+
}
|
|
77
|
+
finally {
|
|
78
|
+
removeListener();
|
|
79
|
+
}
|
|
80
|
+
const result = await finalizeInspectorCapture({
|
|
81
|
+
input,
|
|
82
|
+
runtime: discovery.runtime,
|
|
83
|
+
target,
|
|
84
|
+
roots,
|
|
85
|
+
state,
|
|
86
|
+
});
|
|
87
|
+
return ok(javascriptRuntimeObservationSchema.parse(result));
|
|
88
|
+
}
|
|
89
|
+
catch (cause) {
|
|
90
|
+
return err(providerError(cause, "observe_javascript_runtime"));
|
|
91
|
+
}
|
|
92
|
+
finally {
|
|
93
|
+
await connection?.close();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
const projectTarget = (target) => ({
|
|
98
|
+
target_id: target.id,
|
|
99
|
+
protocol_type: target.type,
|
|
100
|
+
attached: target.attached,
|
|
101
|
+
location: target.location,
|
|
102
|
+
});
|
|
103
|
+
const authorizedTarget = async (targets, input, roots) => {
|
|
104
|
+
const target = targets.find(({ id }) => id === input.target_id);
|
|
105
|
+
if (target === undefined)
|
|
106
|
+
throw new BrowserObservationError("observe_javascript_runtime", "target_not_found");
|
|
107
|
+
const decision = await authorizeRuntimeLocation(target.url, roots, input.allowed_origins);
|
|
108
|
+
if (target.attached ||
|
|
109
|
+
!decision.allowed ||
|
|
110
|
+
decision.location.kind === "builtin")
|
|
111
|
+
throw new BrowserObservationError("observe_javascript_runtime", "target_not_allowed");
|
|
112
|
+
return { ...target, location: decision.location };
|
|
113
|
+
};
|
|
114
|
+
const assertRuntimeKind = (target, kind) => {
|
|
115
|
+
const accepted = kind === "electron-preload" || kind === "electron-renderer"
|
|
116
|
+
? target.type === "page"
|
|
117
|
+
: target.type === "node";
|
|
118
|
+
if (!accepted)
|
|
119
|
+
throw new BrowserObservationError("observe_javascript_runtime", "target_not_allowed");
|
|
120
|
+
};
|
|
121
|
+
const emptyCaptureState = () => ({
|
|
122
|
+
scripts: [],
|
|
123
|
+
contexts: new Map(),
|
|
124
|
+
eventsObserved: 0,
|
|
125
|
+
eventsRetained: 0,
|
|
126
|
+
eventsDropped: 0,
|
|
127
|
+
metadataBytes: 0,
|
|
128
|
+
scriptsObserved: 0,
|
|
129
|
+
invalidScripts: 0,
|
|
130
|
+
truncated: false,
|
|
131
|
+
truncationReasons: new Set(),
|
|
132
|
+
});
|
|
133
|
+
const ingestEvent = (event, input, state) => {
|
|
134
|
+
if (event.method !== "Debugger.scriptParsed" &&
|
|
135
|
+
event.method !== "Debugger.scriptFailedToParse" &&
|
|
136
|
+
event.method !== "Runtime.executionContextCreated" &&
|
|
137
|
+
event.method !== "Runtime.executionContextDestroyed" &&
|
|
138
|
+
event.method !== "Runtime.executionContextsCleared")
|
|
139
|
+
return;
|
|
140
|
+
state.eventsObserved += 1;
|
|
141
|
+
if (state.eventsObserved > input.limits.max_events) {
|
|
142
|
+
drop(state, "max_events");
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
if (event.method === "Debugger.scriptParsed") {
|
|
146
|
+
ingestScript(event, input, state);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
if (event.method === "Debugger.scriptFailedToParse") {
|
|
150
|
+
state.invalidScripts += 1;
|
|
151
|
+
retainEvent(state, 0, input);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
ingestContext(event, input, state);
|
|
155
|
+
};
|
|
156
|
+
const ingestScript = (event, input, state) => {
|
|
157
|
+
state.scriptsObserved += 1;
|
|
158
|
+
const value = recordValue(event.params);
|
|
159
|
+
const rawUrl = stringValue(value?.url);
|
|
160
|
+
if (rawUrl === undefined ||
|
|
161
|
+
rawUrl === "" ||
|
|
162
|
+
Buffer.byteLength(rawUrl) > input.limits.max_location_bytes) {
|
|
163
|
+
state.invalidScripts += 1;
|
|
164
|
+
retainEvent(state, 0, input);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
if (state.scripts.length >= input.limits.max_scripts) {
|
|
168
|
+
drop(state, "max_scripts");
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
const draft = {
|
|
172
|
+
rawUrl,
|
|
173
|
+
executionContextKey: contextKey(value?.executionContextId),
|
|
174
|
+
cdpHash: boundedText(value?.hash, 512),
|
|
175
|
+
length: nonnegativeInteger(value?.length),
|
|
176
|
+
isModule: value?.isModule === true,
|
|
177
|
+
};
|
|
178
|
+
const bytes = metadataBytes(draft);
|
|
179
|
+
if (!retainEvent(state, bytes, input))
|
|
180
|
+
return;
|
|
181
|
+
state.scripts.push(draft);
|
|
182
|
+
};
|
|
183
|
+
const ingestContext = (event, input, state) => {
|
|
184
|
+
if (event.method === "Runtime.executionContextsCleared") {
|
|
185
|
+
for (const context of state.contexts.values())
|
|
186
|
+
context.state = "cleared";
|
|
187
|
+
retainEvent(state, 0, input);
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
const parameters = recordValue(event.params);
|
|
191
|
+
const runtimeContext = event.method === "Runtime.executionContextCreated"
|
|
192
|
+
? recordValue(parameters?.context)
|
|
193
|
+
: parameters;
|
|
194
|
+
const key = contextKey(event.method === "Runtime.executionContextCreated"
|
|
195
|
+
? runtimeContext?.id
|
|
196
|
+
: runtimeContext?.executionContextId);
|
|
197
|
+
if (key === null) {
|
|
198
|
+
retainEvent(state, 0, input);
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
if (state.contexts.size >= input.limits.max_execution_contexts &&
|
|
202
|
+
!state.contexts.has(key)) {
|
|
203
|
+
drop(state, "max_execution_contexts");
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
const origin = event.method === "Runtime.executionContextCreated"
|
|
207
|
+
? boundedText(runtimeContext?.origin, 4_096)
|
|
208
|
+
: null;
|
|
209
|
+
const draft = {
|
|
210
|
+
contextKey: key,
|
|
211
|
+
state: event.method === "Runtime.executionContextCreated"
|
|
212
|
+
? "created"
|
|
213
|
+
: "destroyed",
|
|
214
|
+
origin: origin !== null && input.allowed_origins.includes(origin) ? origin : null,
|
|
215
|
+
};
|
|
216
|
+
const bytes = metadataBytes(draft);
|
|
217
|
+
if (!retainEvent(state, bytes, input))
|
|
218
|
+
return;
|
|
219
|
+
state.contexts.set(key, draft);
|
|
220
|
+
};
|
|
221
|
+
const retainEvent = (state, bytes, input) => {
|
|
222
|
+
if (state.metadataBytes + bytes > input.limits.max_total_metadata_bytes) {
|
|
223
|
+
drop(state, "max_total_metadata_bytes");
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
state.metadataBytes += bytes;
|
|
227
|
+
state.eventsRetained += 1;
|
|
228
|
+
return true;
|
|
229
|
+
};
|
|
230
|
+
const drop = (state, reason) => {
|
|
231
|
+
state.eventsDropped += 1;
|
|
232
|
+
state.truncated = true;
|
|
233
|
+
state.truncationReasons.add(reason);
|
|
234
|
+
};
|
|
235
|
+
const waitForCapture = async (connection, observationMs, signal) => {
|
|
236
|
+
let removeDisconnect = () => undefined;
|
|
237
|
+
const disconnected = new Promise((_resolve, reject) => {
|
|
238
|
+
removeDisconnect = connection.onDisconnect(() => reject(new BrowserObservationError("observe_javascript_runtime", "disconnected")));
|
|
239
|
+
});
|
|
240
|
+
try {
|
|
241
|
+
await Promise.race([
|
|
242
|
+
delayWithCancellation(observationMs, "observe_javascript_runtime", signal),
|
|
243
|
+
disconnected,
|
|
244
|
+
]);
|
|
245
|
+
}
|
|
246
|
+
finally {
|
|
247
|
+
removeDisconnect();
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
const metadataBytes = (value) => Buffer.byteLength(JSON.stringify(value));
|
|
251
|
+
const nonnegativeInteger = (value) => {
|
|
252
|
+
const parsed = numberValue(value);
|
|
253
|
+
return parsed === undefined ? 0 : Math.max(0, Math.trunc(parsed));
|
|
254
|
+
};
|
|
255
|
+
const contextKey = (value) => {
|
|
256
|
+
const identifier = numberValue(value);
|
|
257
|
+
return identifier !== undefined && Number.isSafeInteger(identifier)
|
|
258
|
+
? String(identifier)
|
|
259
|
+
: null;
|
|
260
|
+
};
|
|
261
|
+
const providerError = (cause, operation) => {
|
|
262
|
+
if (cause instanceof AnalysisError)
|
|
263
|
+
return cause;
|
|
264
|
+
return new ProviderAdapterError(V8_INSPECTOR_PROVIDER_IDENTITY.id, operation, {
|
|
265
|
+
cause,
|
|
266
|
+
});
|
|
267
|
+
};
|
package/dist/catalogIdentity.js
CHANGED
|
@@ -29,7 +29,7 @@ const promptCatalog = PROMPT_CONTRACTS.map((contract) => ({
|
|
|
29
29
|
/** Canonical fixed resources exposed by every target-free MCP session. */
|
|
30
30
|
export const MCP_RESOURCE_CATALOG = [
|
|
31
31
|
{ name: "server-identity", uri: "rea://server/identity" },
|
|
32
|
-
{ name: "
|
|
32
|
+
{ name: "analysis-snapshot", uri: "rea://snapshot/current" },
|
|
33
33
|
];
|
|
34
34
|
/** Canonical resource templates exposed by every target-free MCP session. */
|
|
35
35
|
export const MCP_RESOURCE_TEMPLATE_CATALOG = [
|
|
@@ -40,8 +40,8 @@ export const MCP_RESOURCE_TEMPLATE_CATALOG = [
|
|
|
40
40
|
},
|
|
41
41
|
{ name: "residual-unknown", uri_template: "rea://unknown/{unknownId}" },
|
|
42
42
|
{
|
|
43
|
-
name: "
|
|
44
|
-
uri_template: "rea://
|
|
43
|
+
name: "evidence-bundle",
|
|
44
|
+
uri_template: "rea://evidence-bundle/{bundleDigest}",
|
|
45
45
|
},
|
|
46
46
|
{
|
|
47
47
|
name: "artifact-page",
|
|
@@ -59,6 +59,14 @@ export const MCP_RESOURCE_TEMPLATE_CATALOG = [
|
|
|
59
59
|
name: "reconstruction-coverage-revision",
|
|
60
60
|
uri_template: "rea://reconstruction-coverage/{workspaceId}/revision/{revision}",
|
|
61
61
|
},
|
|
62
|
+
{
|
|
63
|
+
name: "reconstruction-obligation-ledger-page",
|
|
64
|
+
uri_template: "rea://evidence/{evidenceId}/reconstruction-obligation-ledger",
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
name: "reconstruction-readiness-report",
|
|
68
|
+
uri_template: "rea://evidence/{evidenceId}/reconstruction-readiness-report",
|
|
69
|
+
},
|
|
62
70
|
{
|
|
63
71
|
name: "javascript-application-graph-page",
|
|
64
72
|
uri_template: "rea://evidence/{evidenceId}/application-graph/{collection}/offset/{offset}/limit/{limit}",
|
|
@@ -3,6 +3,11 @@ import { runProviderAnalysis } from "../application/DirectAnalysis.js";
|
|
|
3
3
|
import { logCliCommand } from "../cliLogging.js";
|
|
4
4
|
import { CLI_COMMANDS } from "../cliCommandNames.js";
|
|
5
5
|
export const registerArtifactCommands = (cli, logger) => {
|
|
6
|
+
registerInventoryCommand(cli, logger);
|
|
7
|
+
registerInspectionCommand(cli, logger);
|
|
8
|
+
registerExtractionCommand(cli, logger);
|
|
9
|
+
};
|
|
10
|
+
const registerInventoryCommand = (cli, logger) => {
|
|
6
11
|
cli.command(CLI_COMMANDS.inventoryArtifact, {
|
|
7
12
|
description: "Build a bounded deterministic artifact graph",
|
|
8
13
|
args: z.object({
|
|
@@ -61,22 +66,58 @@ export const registerArtifactCommands = (cli, logger) => {
|
|
|
61
66
|
native_mount_approved: options.nativeMountApproved,
|
|
62
67
|
}, logger)),
|
|
63
68
|
});
|
|
69
|
+
};
|
|
70
|
+
const registerExtractionCommand = (cli, logger) => {
|
|
64
71
|
cli.command(CLI_COMMANDS.extractArtifact, {
|
|
65
72
|
description: "Extract explicitly selected artifact occurrences safely",
|
|
66
73
|
args: z.object({
|
|
67
74
|
path: z.string().describe("Application or package path"),
|
|
68
75
|
outputRoot: z.string().describe("Absent absolute output root"),
|
|
76
|
+
}),
|
|
77
|
+
options: z.object({
|
|
69
78
|
occurrenceIds: z
|
|
70
79
|
.array(z.string().regex(/^occ_[a-f0-9]{64}$/u))
|
|
71
80
|
.min(1)
|
|
72
81
|
.max(500)
|
|
73
82
|
.describe("Exact artifact occurrence IDs selected for extraction"),
|
|
74
83
|
}),
|
|
75
|
-
alias: {
|
|
76
|
-
run: ({ args }) => logCliCommand(logger, "extract-artifact", () => runProviderAnalysis(args.path, "extract_artifact", {
|
|
84
|
+
alias: { occurrenceIds: "occurrence-ids" },
|
|
85
|
+
run: ({ args, options }) => logCliCommand(logger, "extract-artifact", () => runProviderAnalysis(args.path, "extract_artifact", {
|
|
77
86
|
approved: true,
|
|
78
87
|
output_root: args.outputRoot,
|
|
79
|
-
occurrence_ids:
|
|
88
|
+
occurrence_ids: options.occurrenceIds,
|
|
89
|
+
}, logger)),
|
|
90
|
+
});
|
|
91
|
+
};
|
|
92
|
+
const registerInspectionCommand = (cli, logger) => {
|
|
93
|
+
cli.command(CLI_COMMANDS.inspectArtifact, {
|
|
94
|
+
description: "Inspect one artifact with bounded observations and explicit next probes",
|
|
95
|
+
args: z.object({
|
|
96
|
+
path: z.string().describe("Application or package path"),
|
|
97
|
+
}),
|
|
98
|
+
options: z.object({
|
|
99
|
+
maxObservations: z
|
|
100
|
+
.number()
|
|
101
|
+
.int()
|
|
102
|
+
.min(1)
|
|
103
|
+
.max(500)
|
|
104
|
+
.default(100)
|
|
105
|
+
.describe("Maximum retained observations"),
|
|
106
|
+
maxRelationships: z
|
|
107
|
+
.number()
|
|
108
|
+
.int()
|
|
109
|
+
.min(1)
|
|
110
|
+
.max(500)
|
|
111
|
+
.default(100)
|
|
112
|
+
.describe("Maximum retained derived relationships"),
|
|
113
|
+
}),
|
|
114
|
+
alias: {
|
|
115
|
+
maxObservations: "max-observations",
|
|
116
|
+
maxRelationships: "max-relationships",
|
|
117
|
+
},
|
|
118
|
+
run: ({ args, options }) => logCliCommand(logger, "inspect-artifact", () => runProviderAnalysis(args.path, "inspect_artifact", {
|
|
119
|
+
max_observations: options.maxObservations,
|
|
120
|
+
max_relationships: options.maxRelationships,
|
|
80
121
|
}, logger)),
|
|
81
122
|
});
|
|
82
123
|
};
|
|
@@ -9,6 +9,8 @@ import { runCliJavaScriptApplicationAnalysis } from "./javascriptApplicationAnal
|
|
|
9
9
|
export const registerCoreAnalysisCommands = (cli, logger) => {
|
|
10
10
|
registerCoreCommands(cli, logger);
|
|
11
11
|
registerFunctionCommand(cli, logger);
|
|
12
|
+
registerNativeApiCommand(cli, logger);
|
|
13
|
+
registerInstructionsCommand(cli, logger);
|
|
12
14
|
registerSearchCommand(cli, logger);
|
|
13
15
|
registerXrefsCommand(cli, logger);
|
|
14
16
|
registerTraceCommand(cli, logger);
|
|
@@ -212,6 +214,82 @@ const registerFunctionCommand = (cli, logger) => {
|
|
|
212
214
|
}, directAnalysisOptions(logger, options.snapshot, options.provider))),
|
|
213
215
|
});
|
|
214
216
|
};
|
|
217
|
+
const registerNativeApiCommand = (cli, logger) => {
|
|
218
|
+
cli.command(CLI_COMMANDS.inspectNativeApi, {
|
|
219
|
+
description: "Reconstruct one native function API boundary with evidence",
|
|
220
|
+
args: z.object({
|
|
221
|
+
path: z.string().describe("App or program path"),
|
|
222
|
+
address: z.string().describe("Procedure name or address"),
|
|
223
|
+
}),
|
|
224
|
+
options: z.object({
|
|
225
|
+
maxPseudocodeChars: z
|
|
226
|
+
.number()
|
|
227
|
+
.int()
|
|
228
|
+
.min(1)
|
|
229
|
+
.max(100_000)
|
|
230
|
+
.default(20_000)
|
|
231
|
+
.describe("Maximum pseudocode characters to inspect"),
|
|
232
|
+
maxInstructions: z
|
|
233
|
+
.number()
|
|
234
|
+
.int()
|
|
235
|
+
.min(1)
|
|
236
|
+
.max(5_000)
|
|
237
|
+
.default(500)
|
|
238
|
+
.describe("Maximum assembly instructions to inspect"),
|
|
239
|
+
snapshot: z
|
|
240
|
+
.string()
|
|
241
|
+
.min(1)
|
|
242
|
+
.optional()
|
|
243
|
+
.describe("Load and update a local analysis snapshot"),
|
|
244
|
+
provider: providerSelectionOption,
|
|
245
|
+
}),
|
|
246
|
+
alias: {
|
|
247
|
+
maxPseudocodeChars: "max-pseudocode-chars",
|
|
248
|
+
maxInstructions: "max-instructions",
|
|
249
|
+
},
|
|
250
|
+
run: ({ args, options }) => logCliCommand(logger, "inspect-native-api", () => runDirectAnalysis(args.path, "inspect_native_api", {
|
|
251
|
+
procedure: args.address,
|
|
252
|
+
max_pseudocode_chars: options.maxPseudocodeChars,
|
|
253
|
+
max_instructions: options.maxInstructions,
|
|
254
|
+
}, directAnalysisOptions(logger, options.snapshot, options.provider))),
|
|
255
|
+
});
|
|
256
|
+
};
|
|
257
|
+
const registerInstructionsCommand = (cli, logger) => {
|
|
258
|
+
cli.command(CLI_COMMANDS.instructions, {
|
|
259
|
+
description: "Read one bounded raw-instruction window without decompiling",
|
|
260
|
+
args: z.object({
|
|
261
|
+
path: z.string().describe("App or program path"),
|
|
262
|
+
address: z.string().describe("Procedure name or address"),
|
|
263
|
+
}),
|
|
264
|
+
options: z.object({
|
|
265
|
+
offset: z
|
|
266
|
+
.number()
|
|
267
|
+
.int()
|
|
268
|
+
.min(0)
|
|
269
|
+
.max(100_000)
|
|
270
|
+
.default(0)
|
|
271
|
+
.describe("Zero-based instruction offset"),
|
|
272
|
+
limit: z
|
|
273
|
+
.number()
|
|
274
|
+
.int()
|
|
275
|
+
.min(1)
|
|
276
|
+
.max(500)
|
|
277
|
+
.default(64)
|
|
278
|
+
.describe("Maximum raw instructions to return"),
|
|
279
|
+
snapshot: z
|
|
280
|
+
.string()
|
|
281
|
+
.min(1)
|
|
282
|
+
.optional()
|
|
283
|
+
.describe("Load and update a local analysis snapshot"),
|
|
284
|
+
provider: providerSelectionOption,
|
|
285
|
+
}),
|
|
286
|
+
run: ({ args, options }) => logCliCommand(logger, CLI_COMMANDS.instructions, () => runDirectAnalysis(args.path, "read_function_instructions", {
|
|
287
|
+
procedure: args.address,
|
|
288
|
+
offset: options.offset,
|
|
289
|
+
limit: options.limit,
|
|
290
|
+
}, directAnalysisOptions(logger, options.snapshot, options.provider))),
|
|
291
|
+
});
|
|
292
|
+
};
|
|
215
293
|
const registerSearchCommand = (cli, logger) => {
|
|
216
294
|
cli.command(CLI_COMMANDS.search, {
|
|
217
295
|
description: "Search bounded analyzed strings or procedure names",
|
package/dist/cli.js
CHANGED
|
@@ -13,7 +13,9 @@ import { registerProcessCommands } from "./cliProcessCommands.js";
|
|
|
13
13
|
import { registerPolicyCommands } from "./cliPolicyCommands.js";
|
|
14
14
|
import { registerBrowserCommands } from "./cliBrowserCommands.js";
|
|
15
15
|
import { registerAdvancedBrowserCommands } from "./cliBrowserAdvancedCommands.js";
|
|
16
|
+
import { registerBrowserScenarioCommands } from "./cliBrowserScenarioCommands.js";
|
|
16
17
|
import { registerElectronCommands } from "./cliElectronCommands.js";
|
|
18
|
+
import { registerJavaScriptRuntimeObservationCommands } from "./cliJavaScriptRuntimeCommands.js";
|
|
17
19
|
import { registerApplicationCommands } from "./cliApplicationCommands.js";
|
|
18
20
|
/**
|
|
19
21
|
* Build the one-shot Incur CLI without starting Hopper at import time.
|
|
@@ -52,7 +54,9 @@ export const createCli = () => {
|
|
|
52
54
|
registerPolicyCommands(cli, logger);
|
|
53
55
|
registerBrowserCommands(cli, logger);
|
|
54
56
|
registerAdvancedBrowserCommands(cli, logger);
|
|
57
|
+
registerBrowserScenarioCommands(cli, logger);
|
|
55
58
|
registerElectronCommands(cli, logger);
|
|
59
|
+
registerJavaScriptRuntimeObservationCommands(cli, logger);
|
|
56
60
|
registerApplicationCommands(cli, logger);
|
|
57
61
|
return cli;
|
|
58
62
|
};
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { Cli, z } from "incur";
|
|
2
|
-
import { compareApplicationVersionsEvidenceValidated, compareJavaScriptExportShapesEvidenceValidated, traceApplicationFeatureEvidenceValidated, } from "./application/JavaScriptApplicationWorkflowService.js";
|
|
2
|
+
import { compareApplicationVersionsEvidenceValidated, compareJavaScriptExportShapesEvidenceValidated, compareSourceToBundleEvidenceValidated, traceApplicationFeatureEvidenceValidated, } from "./application/JavaScriptApplicationWorkflowService.js";
|
|
3
3
|
import { traceJavaScriptSemanticsEvidenceValidated } from "./application/JavaScriptSemanticTraceService.js";
|
|
4
|
-
import { resolveCompareApplicationVersionsRequest, resolveCompareJavaScriptExportShapesRequest, resolveTraceApplicationFeatureRequest, resolveTraceJavaScriptSemanticsRequest, } from "./application/ApplicationWorkflowEvidenceResolver.js";
|
|
4
|
+
import { resolveCompareApplicationVersionsRequest, resolveCompareJavaScriptExportShapesRequest, resolveCompareSourceToBundleRequest, resolveTraceApplicationFeatureRequest, resolveTraceJavaScriptSemanticsRequest, } from "./application/ApplicationWorkflowEvidenceResolver.js";
|
|
5
5
|
import { readEvidenceBundle } from "./application/EvidenceBundleFiles.js";
|
|
6
6
|
import { runControlledReplay } from "./application/JavaScriptReplayService.js";
|
|
7
7
|
import { executeNodeCharacterization, prepareNodeCharacterization, } from "./application/NodeRuntimeCharacterizationService.js";
|
|
8
8
|
import { commitReconstructionCoverage, queryReconstructionCoverage, reconstructionCoverageCommitInputSchema, reconstructionCoverageQueryInputSchema, } from "./application/ReconstructionCoverageService.js";
|
|
9
|
+
import { buildReconstructionObligationLedgerEvidenceValidated, resolveReconstructionObligationLedgerRequest, } from "./application/ReconstructionObligationLedgerService.js";
|
|
10
|
+
import { evaluateReconstructionReadinessValidated, resolveReconstructionReadinessRequest, } from "./application/ReconstructionReadinessService.js";
|
|
9
11
|
import { authorizeFileReadWithDeferredWrite, authorizeRootPermission, } from "./application/DeferredFileAuthorization.js";
|
|
10
12
|
import { loadConfiguredPermissionAuthority } from "./application/PermissionConfiguration.js";
|
|
11
13
|
import { CLI_COMMANDS } from "./cliCommandNames.js";
|
|
@@ -41,6 +43,14 @@ export const registerApplicationCommands = (cli, logger) => {
|
|
|
41
43
|
resolveInput: resolveCompareApplicationVersionsRequest,
|
|
42
44
|
workflow: compareApplicationVersionsEvidenceValidated,
|
|
43
45
|
});
|
|
46
|
+
registerJsonCommand({
|
|
47
|
+
cli,
|
|
48
|
+
logger,
|
|
49
|
+
name: CLI_COMMANDS.compareSourceToBundle,
|
|
50
|
+
description: "Compare committed historical source with authenticated application Evidence",
|
|
51
|
+
resolveInput: resolveCompareSourceToBundleRequest,
|
|
52
|
+
workflow: compareSourceToBundleEvidenceValidated,
|
|
53
|
+
});
|
|
44
54
|
registerJsonCommand({
|
|
45
55
|
cli,
|
|
46
56
|
logger,
|
|
@@ -87,8 +97,26 @@ export const registerApplicationCommands = (cli, logger) => {
|
|
|
87
97
|
description: "Execute one separately approved exact Node/JavaScript characterization",
|
|
88
98
|
workflow: (config, authority, input) => executeNodeCharacterization(replayDependencies(config, authority), input),
|
|
89
99
|
});
|
|
100
|
+
registerObligationLedgerCommand(cli, logger);
|
|
101
|
+
registerReadinessCommand(cli, logger);
|
|
90
102
|
registerCoverageCommands(cli, logger);
|
|
91
103
|
};
|
|
104
|
+
const registerObligationLedgerCommand = (cli, logger) => registerJsonCommand({
|
|
105
|
+
cli,
|
|
106
|
+
logger,
|
|
107
|
+
name: CLI_COMMANDS.buildReconstructionObligationLedger,
|
|
108
|
+
description: "Generate a deterministic Evidence-backed reconstruction obligation ledger page",
|
|
109
|
+
resolveInput: resolveReconstructionObligationLedgerRequest,
|
|
110
|
+
workflow: buildReconstructionObligationLedgerEvidenceValidated,
|
|
111
|
+
});
|
|
112
|
+
const registerReadinessCommand = (cli, logger) => registerJsonCommand({
|
|
113
|
+
cli,
|
|
114
|
+
logger,
|
|
115
|
+
name: CLI_COMMANDS.evaluateReconstructionReadiness,
|
|
116
|
+
description: "Evaluate a complete Evidence-backed reconstruction readiness journey",
|
|
117
|
+
resolveInput: resolveReconstructionReadinessRequest,
|
|
118
|
+
workflow: evaluateReconstructionReadinessValidated,
|
|
119
|
+
});
|
|
92
120
|
const registerAuthorizedJsonCommand = ({ cli, logger, name, description, workflow, }) => {
|
|
93
121
|
cli.command(name, {
|
|
94
122
|
description,
|
|
@@ -5,7 +5,7 @@ import { CdpBrowserProvider } from "./browser/CdpBrowserProvider.js";
|
|
|
5
5
|
import { logCliCommand } from "./cliLogging.js";
|
|
6
6
|
import { parseConfig } from "./config.js";
|
|
7
7
|
import { AnalysisInputError, projectAnalysisError } from "./domain/errors.js";
|
|
8
|
-
import {
|
|
8
|
+
import { browserCaptureComparisonInputSchema } from "./domain/browserCaptureComparison.js";
|
|
9
9
|
import { discoverWebMcpToolsInputSchema } from "./domain/webMcpDiscovery.js";
|
|
10
10
|
import { captureWebScreenshotInputSchema, compareWebScreenshotsInputSchema, } from "./domain/webScreenshot.js";
|
|
11
11
|
import { CLI_COMMANDS } from "./cliCommandNames.js";
|
|
@@ -92,7 +92,7 @@ const registerWebMcp = (cli, logger) => {
|
|
|
92
92
|
};
|
|
93
93
|
const registerCaptureDiff = (cli, logger) => {
|
|
94
94
|
cli.command(CLI_COMMANDS.compareWebCaptures, {
|
|
95
|
-
description: "Compare two normalized
|
|
95
|
+
description: "Compare two normalized passive captures or recorded browser scenarios",
|
|
96
96
|
args: z.object({
|
|
97
97
|
beforeJson: z.string().describe("Earlier normalized web capture JSON"),
|
|
98
98
|
afterJson: z.string().describe("Later normalized web capture JSON"),
|
|
@@ -105,15 +105,27 @@ const registerCaptureDiff = (cli, logger) => {
|
|
|
105
105
|
.max(20_000)
|
|
106
106
|
.default(2_000)
|
|
107
107
|
.describe("Maximum normalized changes to return"),
|
|
108
|
+
normalizationJson: z
|
|
109
|
+
.string()
|
|
110
|
+
.default('{"rules":[]}')
|
|
111
|
+
.describe("Recorded literal normalization policy for browser scenarios"),
|
|
108
112
|
}),
|
|
109
113
|
run: ({ args, options }) => logCliCommand(logger, "compare-web-captures", async () => {
|
|
110
114
|
const before = parseJson(args.beforeJson);
|
|
111
115
|
const after = parseJson(args.afterJson);
|
|
112
|
-
const
|
|
113
|
-
before,
|
|
114
|
-
after,
|
|
116
|
+
const scenarioComparison = browserCaptureComparisonInputSchema.safeParse({
|
|
117
|
+
before_scenario: before,
|
|
118
|
+
after_scenario: after,
|
|
119
|
+
normalization: parseJson(options.normalizationJson),
|
|
115
120
|
max_changes: options.maxChanges,
|
|
116
121
|
});
|
|
122
|
+
const parsed = scenarioComparison.success
|
|
123
|
+
? scenarioComparison
|
|
124
|
+
: browserCaptureComparisonInputSchema.safeParse({
|
|
125
|
+
before,
|
|
126
|
+
after,
|
|
127
|
+
max_changes: options.maxChanges,
|
|
128
|
+
});
|
|
117
129
|
if (!parsed.success)
|
|
118
130
|
return inputError("compare_web_captures");
|
|
119
131
|
const result = await compareWebCaptureEvidence(new CdpBrowserProvider(), parsed.data);
|
|
@@ -93,6 +93,7 @@ const registerPageInspection = (cli, logger) => {
|
|
|
93
93
|
websocket_shape_approved: options.websocketShapeApproved,
|
|
94
94
|
include_script_sources: options.includeScriptSources,
|
|
95
95
|
include_storage_keys: options.includeStorageKeys,
|
|
96
|
+
include_storage_fingerprints: options.includeStorageFingerprints,
|
|
96
97
|
limits: {
|
|
97
98
|
max_frames: options.maxFrames,
|
|
98
99
|
max_dom_nodes: options.maxDomNodes,
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Cli } from "incur";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { captureBrowserScenario } from "./application/BrowserScenarioCaptureService.js";
|
|
4
|
+
import { loadConfiguredPermissionAuthority } from "./application/PermissionConfiguration.js";
|
|
5
|
+
import { PlaywrightBrowserScenarioProvider } from "./browser/PlaywrightBrowserScenarioProvider.js";
|
|
6
|
+
import { CLI_COMMANDS } from "./cliCommandNames.js";
|
|
7
|
+
import { parseCliJsonInput } from "./cliJsonInput.js";
|
|
8
|
+
import { logCliCommand } from "./cliLogging.js";
|
|
9
|
+
import { parseConfig } from "./config.js";
|
|
10
|
+
import { AnalysisInputError, projectAnalysisError } from "./domain/errors.js";
|
|
11
|
+
import { browserScenarioSchema } from "./domain/browserScenario.js";
|
|
12
|
+
const OPERATION = "capture_browser_scenario";
|
|
13
|
+
/** Register the one-shot controlled browser scenario command. */
|
|
14
|
+
export const registerBrowserScenarioCommands = (cli, logger) => {
|
|
15
|
+
cli.command(CLI_COMMANDS.captureBrowserScenario, {
|
|
16
|
+
description: "Run one approved, bounded Playwright browser scenario and return Evidence",
|
|
17
|
+
args: z.object({
|
|
18
|
+
inputJson: z
|
|
19
|
+
.string()
|
|
20
|
+
.describe("Inline browser scenario JSON or JSON file path"),
|
|
21
|
+
}),
|
|
22
|
+
run: ({ args }) => logCliCommand(logger, CLI_COMMANDS.captureBrowserScenario, async () => {
|
|
23
|
+
const input = await parseCliJsonInput(args.inputJson, OPERATION);
|
|
24
|
+
if (!input.ok)
|
|
25
|
+
return input.error;
|
|
26
|
+
const scenario = browserScenarioSchema.safeParse(input.value);
|
|
27
|
+
if (!scenario.success)
|
|
28
|
+
return cliError(new AnalysisInputError(OPERATION));
|
|
29
|
+
const config = parseConfig(process.env);
|
|
30
|
+
if (!config.ok)
|
|
31
|
+
return cliError(config.error);
|
|
32
|
+
const authority = await loadConfiguredPermissionAuthority(config.value);
|
|
33
|
+
if (!authority.ok)
|
|
34
|
+
return cliError(authority.error);
|
|
35
|
+
const result = await captureBrowserScenario(new PlaywrightBrowserScenarioProvider(), authority.value, scenario.data);
|
|
36
|
+
return result.ok ? result.value : cliError(result.error);
|
|
37
|
+
}),
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
const cliError = (error) => ({
|
|
41
|
+
error: "Browser scenario capture failed",
|
|
42
|
+
...projectAnalysisError(error),
|
|
43
|
+
});
|