rea-agents 2.0.0 → 2.2.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 +103 -38
- package/bridge/ghidra/ReaGhidraBridge.java +96 -11
- package/dist/application/AndroidApplicationService.js +17 -0
- package/dist/application/AppleApplicationService.js +17 -0
- package/dist/application/ArtifactExtraction.js +1 -1
- package/dist/application/ArtifactInventory/classify.js +42 -0
- package/dist/application/ArtifactInventory/hash.js +43 -0
- package/dist/application/ArtifactInventory/reader.js +41 -0
- package/dist/application/ArtifactInventory/scanCanonical.js +155 -0
- package/dist/application/ArtifactInventory/scanReader.js +124 -0
- package/dist/application/ArtifactInventory/types.js +10 -0
- package/dist/application/ArtifactInventory.js +9 -351
- package/dist/application/AuthorizedArtifactInventory.js +2 -2
- package/dist/application/BinarySession.js +47 -270
- package/dist/application/BinarySessionExecution.js +28 -0
- package/dist/application/BinarySessionOpen.js +39 -0
- package/dist/application/BinarySessionRecords.js +149 -0
- package/dist/application/BinarySessionStatus.js +75 -0
- package/dist/application/CapabilityInventory.js +24 -2
- package/dist/application/ClientRegistrationStatus.js +11 -4
- package/dist/application/CrossVersionInventory.js +8 -2
- package/dist/application/CrossVersionInvestigation.js +1 -23
- package/dist/application/CrossVersionInvestigationCollections.js +23 -0
- package/dist/application/DirectAnalysis.js +47 -44
- package/dist/application/Doctor.js +156 -238
- package/dist/application/DoctorDiagnostics.js +180 -0
- package/dist/application/ElectronBoundaryAnalysis.js +23 -7
- package/dist/application/ElectronBoundaryGraphWindows.js +32 -8
- package/dist/application/EnhancedToolPagination.js +22 -0
- package/dist/application/EnhancedToolTypes.js +4 -0
- package/dist/application/EnhancedTools.js +20 -37
- package/dist/application/InstrumentedJavaScriptReplayHost.js +36 -0
- package/dist/application/InventoryProjectionEvidence.js +41 -0
- package/dist/application/InvestigationProviders.js +12 -0
- package/dist/application/InvestigationWorkspaceStore.js +24 -10
- package/dist/application/JavaScriptArtifactAnalysis.js +45 -6
- package/dist/application/JavaScriptArtifactFiles.js +6 -2
- package/dist/application/JavaScriptArtifactGraphBuilder.js +23 -1
- package/dist/application/JavaScriptArtifactGraphBundlers.js +225 -0
- package/dist/application/JavaScriptArtifactGraphContext.js +37 -36
- package/dist/application/JavaScriptArtifactGraphDocuments.js +27 -4
- package/dist/application/JavaScriptArtifactGraphFindings.js +54 -8
- package/dist/application/JavaScriptArtifactGraphStructure.js +29 -101
- package/dist/application/JavaScriptArtifactPathResolution.js +269 -0
- package/dist/application/JavaScriptArtifactReconstruction.js +1 -1
- package/dist/application/JavaScriptJsonModules.js +39 -0
- package/dist/application/JavaScriptModuleRelationships.js +262 -0
- package/dist/application/JavaScriptReplayPermission.js +16 -0
- package/dist/application/JavaScriptReplayService.js +182 -156
- package/dist/application/LinuxHopper.js +10 -0
- package/dist/application/MacHopper.js +22 -11
- package/dist/application/NodeRuntimeCharacterizationService.js +196 -0
- package/dist/application/PermissionAuthority.js +106 -63
- package/dist/application/ProcessCaptureCapability.js +1 -1
- package/dist/application/ProcessCapturePermission.js +13 -0
- package/dist/application/ProcessCli.js +2 -12
- package/dist/application/ProcessHarness.js +1 -1
- package/dist/application/ProcessPairedExperiment.js +72 -0
- package/dist/application/ProjectPermissionStore.js +48 -9
- package/dist/application/RealHopperAssertions.js +76 -0
- package/dist/application/ReconstructionCoverageService.js +69 -0
- package/dist/application/ReconstructionCoverageWorkspaceStore.js +31 -0
- package/dist/application/RuntimeExecutableDiagnostics.js +172 -0
- package/dist/application/Setup.js +148 -260
- package/dist/application/SetupClientConfiguration.js +224 -0
- package/dist/application/SetupClients.js +24 -2
- package/dist/application/SetupPlan.js +124 -12
- package/dist/application/SetupSkill.js +54 -36
- package/dist/application/SupportedClients.js +1 -0
- package/dist/application/Uninstall.js +12 -3
- package/dist/application/Upgrade.js +16 -1
- package/dist/application/WindowsCapabilities.js +86 -0
- package/dist/artifacts/AsarArtifactReader.js +11 -0
- package/dist/browser/BrowserProcessStartup.js +88 -0
- package/dist/browser/CdpCaptureDocuments.js +12 -8
- package/dist/browser/CdpCaptureEventBodyShapes.js +75 -0
- package/dist/browser/CdpCaptureEventHandlers.js +336 -0
- package/dist/browser/CdpCaptureEventHelpers.js +71 -0
- package/dist/browser/CdpCaptureEventState.js +1 -0
- package/dist/browser/CdpCaptureEventTypes.js +1 -0
- package/dist/browser/CdpCaptureEvents.js +29 -496
- package/dist/browser/CdpObservationSession.js +51 -8
- package/dist/browser/CdpPageCapture.js +12 -133
- package/dist/browser/CdpPageCaptureScripts.js +97 -0
- package/dist/browser/CdpPageCaptureWorkers.js +46 -0
- package/dist/browser/CdpWebMcpDiscovery.js +38 -14
- package/dist/browser/PngVisualDiff.js +9 -2
- package/dist/catalogIdentity.js +4 -0
- package/dist/cli/artifactCommands.js +82 -0
- package/dist/cli/coreAnalysisCommands.js +232 -0
- package/dist/cli/managedCommands.js +397 -0
- package/dist/cli/managedProjectGraphCommand.js +24 -0
- package/dist/cli/options.js +9 -0
- package/dist/cli/setupCommands.js +113 -0
- package/dist/cli/types.js +1 -0
- package/dist/cli/utilityCommands.js +122 -0
- package/dist/cli.js +10 -768
- package/dist/cliApplicationCommands.js +118 -4
- package/dist/cliBrowserAdvancedCommands.js +73 -16
- package/dist/cliBrowserCommands.js +39 -115
- package/dist/cliCommandNames.js +4 -0
- package/dist/cliElectronCommands.js +33 -62
- package/dist/cliEvidenceCommands.js +13 -2
- package/dist/cliInvestigationCommands.js +53 -10
- package/dist/cliObservationOptions.js +137 -0
- package/dist/cliPolicyCommands.js +80 -46
- package/dist/cliSetup.js +306 -0
- package/dist/config/environment.js +107 -0
- package/dist/config/parseConfig.js +228 -0
- package/dist/config/parsers.js +68 -0
- package/dist/config/permissions.js +30 -0
- package/dist/config/types.js +1 -0
- package/dist/config.js +1 -375
- package/dist/contracts/applicationToolContracts.js +134 -0
- package/dist/contracts/electronToolContracts.js +51 -3
- package/dist/contracts/managedToolContracts.js +8 -3
- package/dist/contracts/managedWorkflowToolContracts.js +3 -3
- package/dist/contracts/providerSelection.js +2 -0
- package/dist/contracts/sessionStatusContract.js +26 -0
- package/dist/contracts/toolContractTypes.js +12 -1
- package/dist/contracts/toolContracts.js +5 -12
- package/dist/contracts/toolEffects.js +14 -0
- package/dist/contracts/toolOutputSchemaGroups.js +274 -0
- package/dist/contracts/toolOutputSchemaPrimitives.js +328 -0
- package/dist/contracts/toolOutputSchemas.js +2 -550
- package/dist/domain/analysisErrorPresentation.js +234 -0
- package/dist/domain/analysisErrorProjection.js +284 -0
- package/dist/domain/androidApplication.js +206 -0
- package/dist/domain/appleApplication.js +221 -0
- package/dist/domain/artifactComparison.js +34 -15
- package/dist/domain/binaryTarget.js +87 -37
- package/dist/domain/boundedCartesianProjection.js +15 -0
- package/dist/domain/browserObservation.js +1 -285
- package/dist/domain/browserObservationSchemas.js +286 -0
- package/dist/domain/electronStaticAnalysisBrowser.js +14 -2
- package/dist/domain/errors.js +4 -486
- package/dist/domain/functionComparison.js +4 -165
- package/dist/domain/functionComparisonDimensions.js +164 -0
- package/dist/domain/javascriptApplicationVersionItems.js +18 -6
- package/dist/domain/javascriptApplicationVersionKeys.js +8 -8
- package/dist/domain/javascriptExportInstrumentation.js +97 -0
- package/dist/domain/javascriptFeatureTraversal.js +19 -7
- package/dist/domain/javascriptRuntimeStaticCandidates.js +3 -1
- package/dist/domain/javascriptSemanticAnalysis.js +386 -0
- package/dist/domain/javascriptSemanticIr.js +30 -0
- package/dist/domain/javascriptSemanticProjection.js +366 -0
- package/dist/domain/javascriptSemanticState.js +40 -0
- package/dist/domain/javascriptSemanticTraversal.js +22 -0
- package/dist/domain/javascriptSemanticValues.js +352 -0
- package/dist/domain/javascriptStaticAnalysis.js +5 -221
- package/dist/domain/javascriptStaticAnalysisBundler.js +209 -0
- package/dist/domain/javascriptStaticAnalysisCalls.js +180 -0
- package/dist/domain/javascriptStaticAnalysisHelpers.js +71 -2
- package/dist/domain/knownPageCoverage.js +21 -0
- package/dist/domain/managedApplicationGraph.js +14 -364
- package/dist/domain/managedApplicationGraphCoverage.js +170 -0
- package/dist/domain/managedApplicationGraphNodeCoverage.js +6 -0
- package/dist/domain/managedApplicationGraphNodes.js +336 -0
- package/dist/domain/managedArtifact.js +16 -8
- package/dist/domain/managedMemberComparison.js +37 -391
- package/dist/domain/managedMemberComparisonCoverage.js +72 -0
- package/dist/domain/managedMemberComparisonMatch.js +356 -0
- package/dist/domain/managedNativeVerification.js +27 -389
- package/dist/domain/managedNativeVerificationMatch.js +272 -0
- package/dist/domain/managedNativeVerificationSchemas.js +141 -0
- package/dist/domain/managedReconstruction.js +82 -69
- package/dist/domain/managedRuntimeCorrelation.js +12 -3
- package/dist/domain/nodeRuntimeCharacterization.js +66 -0
- package/dist/domain/permissionPolicy.js +2 -0
- package/dist/domain/processComparison.js +19 -0
- package/dist/domain/processPairedExperiment.js +128 -0
- package/dist/domain/reconstructionCoverage.js +387 -0
- package/dist/domain/reconstructionCoverageEvaluation.js +212 -0
- package/dist/domain/reconstructionVerificationSchemas.js +8 -0
- package/dist/domain/replayMachine.js +316 -0
- package/dist/domain/replayMachineRuntime.js +215 -0
- package/dist/domain/runtimeCharacterization.js +85 -0
- package/dist/domain/runtimeIdentification.js +210 -0
- package/dist/domain/webBundleAnalyzer.js +3 -409
- package/dist/domain/webBundleAnalyzerAst.js +77 -0
- package/dist/domain/webBundleAnalyzerInspection.js +307 -0
- package/dist/domain/webBundleAnalyzerResult.js +120 -0
- package/dist/dotnet/ManagedArtifactInspector.js +50 -29
- package/dist/dotnet/ManagedMemberInspector.js +51 -785
- package/dist/dotnet/ManagedMemberInspectorCore.js +297 -0
- package/dist/dotnet/ManagedMemberInstructionDecoder.js +427 -0
- package/dist/dotnet/ManagedMemberRows.js +120 -0
- package/dist/dotnet/ManagedMetadataInventory.js +42 -306
- package/dist/dotnet/ManagedMetadataInventoryRows.js +292 -0
- package/dist/dotnet/ManagedMetadataLayout.js +48 -111
- package/dist/dotnet/ManagedMetadataRowSizes.js +54 -0
- package/dist/dotnet/ManagedMethodBodyReader.js +143 -0
- package/dist/dotnet/ManagedNativeBoundaryHelpers.js +311 -0
- package/dist/dotnet/ManagedNativeBoundaryInspector.js +102 -350
- package/dist/dotnet/ManagedPeReader.js +59 -28
- package/dist/evaluation/CodexAgentEval.js +132 -0
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraClient.js +76 -91
- package/dist/ghidra/GhidraClientStartup.js +29 -0
- package/dist/ghidra/GhidraClientWire.js +34 -0
- package/dist/ghidra/GhidraDefaults.js +1 -1
- package/dist/ghidra/GhidraDiagnostics.js +6 -1
- package/dist/ghidra/GhidraInstallation.js +20 -15
- package/dist/ghidra/GhidraLauncher.js +93 -29
- package/dist/ghidra/GhidraProvider.js +61 -161
- package/dist/ghidra/GhidraProviderCapabilities.js +173 -0
- package/dist/ghidra/GhidraSessionValues.js +2 -0
- package/dist/ghidra/GhidraSocketConnection.js +44 -7
- package/dist/ghidra/GhidraTargetSnapshot.js +30 -0
- package/dist/ghidra/GhidraTransport.js +71 -0
- package/dist/identity.js +4 -2
- package/dist/main/messages.js +5 -0
- package/dist/main/reload.js +49 -0
- package/dist/main/shutdown.js +25 -0
- package/dist/main/startup.js +14 -0
- package/dist/main/state.js +26 -0
- package/dist/main/transport.js +61 -0
- package/dist/main/types.js +1 -0
- package/dist/main.js +35 -146
- package/dist/process/PrivateRuntimeRoot.js +3 -2
- package/dist/process/ProcessOwnership.js +35 -0
- package/dist/process/ProviderProcess.js +2 -0
- package/dist/replay/JavaScriptReplayWorker.js +64 -50
- package/dist/replay/LinuxJavaScriptReplayRunner.js +173 -390
- package/dist/replay/LinuxJavaScriptReplaySandbox.js +140 -0
- package/dist/replay/ReplayOutcome.js +95 -0
- package/dist/replay/ReplayProcessLifecycle.js +71 -0
- package/dist/server/ProcessCaptureElicitation.js +157 -0
- package/dist/server/createServer.js +124 -56
- package/dist/server/javascriptApplicationResult.js +85 -0
- package/dist/server/registerApplicationTools/characterization.js +57 -0
- package/dist/server/registerApplicationTools/compareVersions.js +34 -0
- package/dist/server/registerApplicationTools/controlledReplay.js +38 -0
- package/dist/server/registerApplicationTools/coverage.js +84 -0
- package/dist/server/registerApplicationTools/helpers.js +42 -0
- package/dist/server/registerApplicationTools/traceFeature.js +26 -0
- package/dist/server/registerApplicationTools/types.js +1 -0
- package/dist/server/registerApplicationTools.js +10 -112
- package/dist/server/registerBrowserTools.js +59 -83
- package/dist/server/registerElectronTools.js +48 -49
- package/dist/server/registerEnhancedTools.js +34 -42
- package/dist/server/registerEvidenceResources.js +56 -0
- package/dist/server/registerInvestigationTools/helpers.js +74 -0
- package/dist/server/registerInvestigationTools/types.js +1 -0
- package/dist/server/registerInvestigationTools.js +83 -116
- package/dist/server/registerJavaScriptApplicationGraphResource.js +69 -0
- package/dist/server/registerManagedTools.js +18 -1
- package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +65 -0
- package/dist/server/registerManagedWorkflowTools/contract.js +8 -0
- package/dist/server/registerManagedWorkflowTools/evidence.js +43 -0
- package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +39 -0
- package/dist/server/registerManagedWorkflowTools/planManagedRuntimeCorrelation.js +39 -0
- package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +52 -0
- package/dist/server/registerManagedWorkflowTools/types.js +1 -0
- package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +75 -0
- package/dist/server/registerManagedWorkflowTools.js +10 -274
- package/dist/server/registerOfficialTools.js +73 -59
- package/dist/server/registerSessionRecordTools.js +137 -0
- package/dist/server/registerSessionStatusTool.js +97 -26
- package/dist/server/registerSessionTools.js +60 -164
- package/dist/server/sessionAvailabilityPolicy.js +10 -0
- package/dist/server/toolRegistrationOptions.js +101 -3
- package/dist/server/toolResult.js +15 -4
- package/package.json +11 -11
- package/skills/reverse-engineer-anything/SKILL.md +76 -0
- package/skills/reverse-engineer-anything/references/controlled-replay.md +12 -0
- package/skills/reverse-engineer-anything/references/evidence-workflows.md +33 -0
- package/skills/reverse-engineer-anything/references/javascript-applications.md +25 -0
- package/skills/reverse-engineer-anything/references/native-and-artifacts.md +36 -0
- package/skills/reverse-engineer-anything/references/runtime-observation.md +24 -0
- package/scripts/prepare-node-pty.mjs +0 -35
- package/scripts/rebuild-native.mjs +0 -22
- package/skills/rea-analysis/SKILL.md +0 -222
|
@@ -133,7 +133,13 @@ class TimelineCapture {
|
|
|
133
133
|
targetTerminated() {
|
|
134
134
|
if (this.#endReason !== undefined)
|
|
135
135
|
return;
|
|
136
|
-
this.#add(
|
|
136
|
+
this.#add({
|
|
137
|
+
type: "target_terminated",
|
|
138
|
+
params: {},
|
|
139
|
+
rawUrl: null,
|
|
140
|
+
requestId: null,
|
|
141
|
+
detail: "target_terminated",
|
|
142
|
+
});
|
|
137
143
|
this.end("target_terminated");
|
|
138
144
|
}
|
|
139
145
|
setFinalUrl(rawUrl) {
|
|
@@ -145,7 +151,13 @@ class TimelineCapture {
|
|
|
145
151
|
return;
|
|
146
152
|
const reason = safeDetail(params.reason);
|
|
147
153
|
this.#pendingReload = reason === "reload";
|
|
148
|
-
this.#add(
|
|
154
|
+
this.#add({
|
|
155
|
+
type: "navigation_requested",
|
|
156
|
+
params,
|
|
157
|
+
rawUrl: stringValue(params.url) ?? null,
|
|
158
|
+
requestId: null,
|
|
159
|
+
detail: reason,
|
|
160
|
+
});
|
|
149
161
|
}
|
|
150
162
|
#navigationCommitted(params) {
|
|
151
163
|
const frame = recordValue(params.frame);
|
|
@@ -153,7 +165,13 @@ class TimelineCapture {
|
|
|
153
165
|
return;
|
|
154
166
|
const rawUrl = stringValue(frame?.url);
|
|
155
167
|
const destination = scopedUrl(rawUrl, this.allowedOrigins);
|
|
156
|
-
this.#add(
|
|
168
|
+
this.#add({
|
|
169
|
+
type: this.#pendingReload ? "same_origin_reload" : "navigation_committed",
|
|
170
|
+
params: { ...params, frameId: frame?.id, loaderId: frame?.loaderId },
|
|
171
|
+
rawUrl: rawUrl ?? null,
|
|
172
|
+
requestId: null,
|
|
173
|
+
detail: safeDetail(frame?.transitionType),
|
|
174
|
+
});
|
|
157
175
|
this.#pendingReload = false;
|
|
158
176
|
if (destination.scope === "approved")
|
|
159
177
|
this.finalUrl = destination.url;
|
|
@@ -168,7 +186,13 @@ class TimelineCapture {
|
|
|
168
186
|
return;
|
|
169
187
|
const rawUrl = stringValue(params.url);
|
|
170
188
|
const destination = scopedUrl(rawUrl, this.allowedOrigins);
|
|
171
|
-
this.#add(
|
|
189
|
+
this.#add({
|
|
190
|
+
type: "same_document_navigation",
|
|
191
|
+
params,
|
|
192
|
+
rawUrl: rawUrl ?? null,
|
|
193
|
+
requestId: null,
|
|
194
|
+
detail: null,
|
|
195
|
+
});
|
|
172
196
|
if (destination.scope === "approved")
|
|
173
197
|
this.finalUrl = destination.url;
|
|
174
198
|
else {
|
|
@@ -184,7 +208,13 @@ class TimelineCapture {
|
|
|
184
208
|
const request = recordValue(params.request);
|
|
185
209
|
const rawUrl = stringValue(request?.url);
|
|
186
210
|
const destination = scopedUrl(rawUrl, this.allowedOrigins);
|
|
187
|
-
this.#add(
|
|
211
|
+
this.#add({
|
|
212
|
+
type: "redirect",
|
|
213
|
+
params,
|
|
214
|
+
rawUrl: rawUrl ?? null,
|
|
215
|
+
requestId: stringValue(params.requestId) ?? null,
|
|
216
|
+
detail: null,
|
|
217
|
+
});
|
|
188
218
|
if (destination.scope !== "approved") {
|
|
189
219
|
this.completeness.exclude("timeline", "out_of_target_scope");
|
|
190
220
|
this.end("target_left_scope");
|
|
@@ -194,14 +224,27 @@ class TimelineCapture {
|
|
|
194
224
|
const frame = stringValue(params.frameId);
|
|
195
225
|
if (frame !== undefined && frame !== this.mainFrameId)
|
|
196
226
|
return;
|
|
197
|
-
this.#add(
|
|
227
|
+
this.#add({
|
|
228
|
+
type: "load_failed",
|
|
229
|
+
params,
|
|
230
|
+
rawUrl: null,
|
|
231
|
+
requestId: stringValue(params.requestId) ?? null,
|
|
232
|
+
detail: safeNetworkError(params.errorText),
|
|
233
|
+
});
|
|
198
234
|
}
|
|
199
235
|
#lifecycle(params) {
|
|
200
236
|
if (stringValue(params.frameId) !== this.mainFrameId)
|
|
201
237
|
return;
|
|
202
|
-
this.#add(
|
|
238
|
+
this.#add({
|
|
239
|
+
type: "lifecycle",
|
|
240
|
+
params,
|
|
241
|
+
rawUrl: null,
|
|
242
|
+
requestId: null,
|
|
243
|
+
detail: safeDetail(params.name),
|
|
244
|
+
});
|
|
203
245
|
}
|
|
204
|
-
#add(
|
|
246
|
+
#add(options) {
|
|
247
|
+
const { type, params, rawUrl = null, requestId = null, detail = null, } = options;
|
|
205
248
|
const destination = rawUrl == null ? null : scopedUrl(rawUrl, this.allowedOrigins);
|
|
206
249
|
if (this.timeline.length >= this.maximum) {
|
|
207
250
|
this.completeness.drop("timeline_events");
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { BrowserObservationError, } from "../domain/errors.js";
|
|
2
|
-
import {
|
|
2
|
+
import { stableWebResources } from "../domain/webInventory.js";
|
|
3
3
|
import { CdpConnection } from "./CdpConnection.js";
|
|
4
4
|
import { CdpCaptureEvents } from "./CdpCaptureEvents.js";
|
|
5
5
|
import { captureStorage } from "./CdpCaptureStorage.js";
|
|
6
6
|
import { optionalCdpCommand } from "./CdpOptionalCommand.js";
|
|
7
7
|
import { captureAccessibility, captureDom, captureFrames, captureResources, mainFrameUrl, } from "./CdpCaptureDocuments.js";
|
|
8
|
-
import { allowedSanitizedUrl,
|
|
8
|
+
import { allowedSanitizedUrl, delayWithCancellation, isHttpUrl, } from "./CdpCaptureValues.js";
|
|
9
|
+
import { captureScripts } from "./CdpPageCaptureScripts.js";
|
|
10
|
+
import { captureWorkers } from "./CdpPageCaptureWorkers.js";
|
|
9
11
|
/** Capture and normalize one attached page without evaluating page JavaScript. */
|
|
10
12
|
export const capturePage = async (context) => {
|
|
11
13
|
const allowedOrigins = new Set(context.input.allowed_origins);
|
|
@@ -59,8 +61,14 @@ const captureAuthorizedPage = async (state) => {
|
|
|
59
61
|
const accessibility = await accessibilityForFrames(state, frames);
|
|
60
62
|
if (accessibility.total > accessibility.nodes.length)
|
|
61
63
|
state.events.completeness.truncate("accessibility");
|
|
62
|
-
const scripts = await captureScripts(
|
|
63
|
-
|
|
64
|
+
const scripts = await captureScripts({
|
|
65
|
+
context,
|
|
66
|
+
events: state.events,
|
|
67
|
+
rawResources: resourceCapture.items,
|
|
68
|
+
resources,
|
|
69
|
+
frameIds: new Set(frames.map((frame) => frame.frame_id)),
|
|
70
|
+
});
|
|
71
|
+
const workerCapture = await captureWorkers({ context, allowedOrigins, limitations, events: state.events }, new Set(frames.map((frame) => frame.frame_id)));
|
|
64
72
|
if (workerCapture.total > workerCapture.items.length)
|
|
65
73
|
state.events.completeness.truncate("workers");
|
|
66
74
|
const storageCapture = await captureStorage(context, frames[0]?.origin ?? new URL(attachedUrl).origin, limitations);
|
|
@@ -220,88 +228,6 @@ const accessibilityForFrames = async (state, frames) => {
|
|
|
220
228
|
events.completeness.truncate("accessibility");
|
|
221
229
|
return capture;
|
|
222
230
|
};
|
|
223
|
-
const captureScripts = async (context, events, rawResources, resources, frameIds) => {
|
|
224
|
-
let totalSourceBytes = 0;
|
|
225
|
-
const drafts = [];
|
|
226
|
-
for (const script of events.scripts.values()) {
|
|
227
|
-
let source = sourceExcluded("source capture was not approved");
|
|
228
|
-
if (context.input.include_script_sources) {
|
|
229
|
-
if (script.length > context.input.limits.max_script_source_bytes) {
|
|
230
|
-
source = sourceExcluded("declared script length exceeds per-script limit");
|
|
231
|
-
events.completeness.truncate("script_sources");
|
|
232
|
-
}
|
|
233
|
-
else if (totalSourceBytes + script.length >
|
|
234
|
-
context.input.limits.max_total_script_source_bytes) {
|
|
235
|
-
source = sourceExcluded("total script source limit reached");
|
|
236
|
-
events.completeness.truncate("script_sources");
|
|
237
|
-
}
|
|
238
|
-
else {
|
|
239
|
-
const result = requiredRecord(await context.connection.send("Debugger.getScriptSource", { scriptId: script.scriptId }, context.sessionId, context.signal));
|
|
240
|
-
const content = stringValue(result.scriptSource) ?? "";
|
|
241
|
-
const bytes = Buffer.byteLength(content);
|
|
242
|
-
if (bytes > context.input.limits.max_script_source_bytes ||
|
|
243
|
-
totalSourceBytes + bytes >
|
|
244
|
-
context.input.limits.max_total_script_source_bytes) {
|
|
245
|
-
source = sourceExcluded("actual source exceeds configured byte limits");
|
|
246
|
-
events.completeness.truncate("script_sources");
|
|
247
|
-
}
|
|
248
|
-
else {
|
|
249
|
-
source = sourceResult(content);
|
|
250
|
-
totalSourceBytes += bytes;
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
const inventoryScript = {
|
|
255
|
-
frame_id: events.frameForScript(script, frameIds),
|
|
256
|
-
url: script.url,
|
|
257
|
-
cdp_hash: script.hash,
|
|
258
|
-
length: script.length,
|
|
259
|
-
is_module: script.isModule,
|
|
260
|
-
language: script.language,
|
|
261
|
-
source_map_url: script.sourceMapUrl,
|
|
262
|
-
};
|
|
263
|
-
drafts.push({
|
|
264
|
-
item: {
|
|
265
|
-
...inventoryScript,
|
|
266
|
-
origin: script.origin,
|
|
267
|
-
resource_reconciliation: reconcileCapturedWebScript({ ...inventoryScript, rawUrl: script.rawUrl }, rawResources, resources),
|
|
268
|
-
source,
|
|
269
|
-
},
|
|
270
|
-
sourceMapRawUrl: script.sourceMapRawUrl,
|
|
271
|
-
});
|
|
272
|
-
}
|
|
273
|
-
if (!context.input.include_script_sources)
|
|
274
|
-
events.completeness.exclude("script_sources", "not_approved", events.scripts.size);
|
|
275
|
-
const keyed = drafts.map((draft) => ({
|
|
276
|
-
...draft,
|
|
277
|
-
base: stableWebScriptKey(draft.item),
|
|
278
|
-
}));
|
|
279
|
-
keyed.sort((left, right) => left.base.localeCompare(right.base) ||
|
|
280
|
-
sourceDigest(left.item.source).localeCompare(sourceDigest(right.item.source)) ||
|
|
281
|
-
(left.item.frame_id ?? "").localeCompare(right.item.frame_id ?? ""));
|
|
282
|
-
const totals = new Map();
|
|
283
|
-
for (const { base } of keyed)
|
|
284
|
-
totals.set(base, (totals.get(base) ?? 0) + 1);
|
|
285
|
-
const seen = new Map();
|
|
286
|
-
const sourceMapRequests = [];
|
|
287
|
-
const items = keyed.map(({ base, item, sourceMapRawUrl }) => {
|
|
288
|
-
const occurrence = (seen.get(base) ?? 0) + 1;
|
|
289
|
-
seen.set(base, occurrence);
|
|
290
|
-
const scriptKey = totals.get(base) === 1 ? base : `${base}_${String(occurrence)}`;
|
|
291
|
-
if (item.source_map_url !== null && sourceMapRawUrl !== null)
|
|
292
|
-
sourceMapRequests.push({
|
|
293
|
-
scriptKey,
|
|
294
|
-
declaredUrl: item.source_map_url,
|
|
295
|
-
fetchUrl: sourceMapRawUrl,
|
|
296
|
-
});
|
|
297
|
-
return { script_key: scriptKey, ...item };
|
|
298
|
-
});
|
|
299
|
-
return {
|
|
300
|
-
inventory: { total: events.scripts.size, items },
|
|
301
|
-
sourceMapRequests,
|
|
302
|
-
};
|
|
303
|
-
};
|
|
304
|
-
const sourceDigest = (source) => (source.included ? source.artifact.sha256 : source.reason);
|
|
305
231
|
const publicResource = ({ rawUrl: _rawUrl, ...resource }) => resource;
|
|
306
232
|
const deduplicatedAgentHints = (hints) => {
|
|
307
233
|
const seen = new Set();
|
|
@@ -313,53 +239,6 @@ const deduplicatedAgentHints = (hints) => {
|
|
|
313
239
|
return true;
|
|
314
240
|
});
|
|
315
241
|
};
|
|
316
|
-
const captureWorkers = async (state, frameIds) => {
|
|
317
|
-
const { context, allowedOrigins, limitations, events } = state;
|
|
318
|
-
const completeness = events.completeness;
|
|
319
|
-
const result = await optionalCdpCommand({ ...context, sessionId: undefined }, "Target.getTargets", {}, limitations);
|
|
320
|
-
const items = [];
|
|
321
|
-
let total = 0;
|
|
322
|
-
if (result === undefined)
|
|
323
|
-
completeness.unavailable("workers");
|
|
324
|
-
for (const target of recordsValue(recordValue(result)?.targetInfos)) {
|
|
325
|
-
const type = stringValue(target.type) ?? "";
|
|
326
|
-
const url = allowedSanitizedUrl(target.url, allowedOrigins);
|
|
327
|
-
const relatedToPage = stringValue(target.openerId) === context.target.id ||
|
|
328
|
-
(stringValue(target.parentFrameId) !== undefined &&
|
|
329
|
-
frameIds.has(stringValue(target.parentFrameId) ?? ""));
|
|
330
|
-
if (!type.includes("worker"))
|
|
331
|
-
continue;
|
|
332
|
-
if (!relatedToPage) {
|
|
333
|
-
completeness.exclude("workers", "out_of_target_scope");
|
|
334
|
-
continue;
|
|
335
|
-
}
|
|
336
|
-
if (url === undefined) {
|
|
337
|
-
const rawUrl = stringValue(target.url);
|
|
338
|
-
completeness.exclude("workers", rawUrl === undefined || rawUrl === ""
|
|
339
|
-
? "unattributed_origin"
|
|
340
|
-
: isHttpUrl(rawUrl)
|
|
341
|
-
? "disallowed_origin"
|
|
342
|
-
: "unsupported_url");
|
|
343
|
-
continue;
|
|
344
|
-
}
|
|
345
|
-
total += 1;
|
|
346
|
-
if (items.length >= context.input.limits.max_workers)
|
|
347
|
-
continue;
|
|
348
|
-
items.push({
|
|
349
|
-
target_id: (stringValue(target.targetId) ?? "").slice(0, 256),
|
|
350
|
-
type: type.slice(0, 100),
|
|
351
|
-
url: url.url,
|
|
352
|
-
origin: url.origin,
|
|
353
|
-
attached: target.attached === true,
|
|
354
|
-
opener_target_id: boundedText(target.openerId, 256) ?? null,
|
|
355
|
-
parent_frame_id: boundedText(target.parentFrameId, 256) ?? null,
|
|
356
|
-
});
|
|
357
|
-
}
|
|
358
|
-
return {
|
|
359
|
-
total,
|
|
360
|
-
items,
|
|
361
|
-
};
|
|
362
|
-
};
|
|
363
242
|
const normalizedTarget = (target, currentUrl, allowedOrigins) => {
|
|
364
243
|
const url = allowedSanitizedUrl(currentUrl, allowedOrigins);
|
|
365
244
|
return {
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { reconcileCapturedWebScript, stableWebScriptKey, } from "../domain/webInventory.js";
|
|
2
|
+
import { requiredRecord, sourceExcluded, sourceResult, stringValue, } from "./CdpCaptureValues.js";
|
|
3
|
+
export const captureScripts = async (options) => {
|
|
4
|
+
const { context, events, rawResources, resources, frameIds } = options;
|
|
5
|
+
const state = {
|
|
6
|
+
context,
|
|
7
|
+
events,
|
|
8
|
+
frameIds,
|
|
9
|
+
rawResources,
|
|
10
|
+
resources,
|
|
11
|
+
totalSourceBytes: 0,
|
|
12
|
+
};
|
|
13
|
+
const drafts = [];
|
|
14
|
+
for (const script of events.scripts.values())
|
|
15
|
+
drafts.push(await buildScriptDraft(script, state));
|
|
16
|
+
if (!context.input.include_script_sources)
|
|
17
|
+
events.completeness.exclude("script_sources", "not_approved", events.scripts.size);
|
|
18
|
+
return keyAndBuildInventory(drafts, events.scripts.size);
|
|
19
|
+
};
|
|
20
|
+
const buildScriptDraft = async (script, state) => {
|
|
21
|
+
let source = state
|
|
22
|
+
.context.input.include_script_sources
|
|
23
|
+
? await captureScriptSource(script, state)
|
|
24
|
+
: sourceExcluded("source capture was not approved");
|
|
25
|
+
const inventoryScript = {
|
|
26
|
+
frame_id: state.events.frameForScript(script, state.frameIds),
|
|
27
|
+
url: script.url,
|
|
28
|
+
cdp_hash: script.hash,
|
|
29
|
+
length: script.length,
|
|
30
|
+
is_module: script.isModule,
|
|
31
|
+
language: script.language,
|
|
32
|
+
source_map_url: script.sourceMapUrl,
|
|
33
|
+
};
|
|
34
|
+
return {
|
|
35
|
+
item: {
|
|
36
|
+
...inventoryScript,
|
|
37
|
+
origin: script.origin,
|
|
38
|
+
resource_reconciliation: reconcileCapturedWebScript({ ...inventoryScript, rawUrl: script.rawUrl }, state.rawResources, state.resources),
|
|
39
|
+
source,
|
|
40
|
+
},
|
|
41
|
+
sourceMapRawUrl: script.sourceMapRawUrl,
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
const captureScriptSource = async (script, state) => {
|
|
45
|
+
const { context, events } = state;
|
|
46
|
+
if (script.length > context.input.limits.max_script_source_bytes) {
|
|
47
|
+
events.completeness.truncate("script_sources");
|
|
48
|
+
return sourceExcluded("declared script length exceeds per-script limit");
|
|
49
|
+
}
|
|
50
|
+
if (state.totalSourceBytes + script.length >
|
|
51
|
+
context.input.limits.max_total_script_source_bytes) {
|
|
52
|
+
events.completeness.truncate("script_sources");
|
|
53
|
+
return sourceExcluded("total script source limit reached");
|
|
54
|
+
}
|
|
55
|
+
const result = requiredRecord(await context.connection.send("Debugger.getScriptSource", { scriptId: script.scriptId }, context.sessionId, context.signal));
|
|
56
|
+
const content = stringValue(result.scriptSource) ?? "";
|
|
57
|
+
const bytes = Buffer.byteLength(content);
|
|
58
|
+
if (bytes > context.input.limits.max_script_source_bytes ||
|
|
59
|
+
state.totalSourceBytes + bytes >
|
|
60
|
+
context.input.limits.max_total_script_source_bytes) {
|
|
61
|
+
events.completeness.truncate("script_sources");
|
|
62
|
+
return sourceExcluded("actual source exceeds configured byte limits");
|
|
63
|
+
}
|
|
64
|
+
state.totalSourceBytes += bytes;
|
|
65
|
+
return sourceResult(content);
|
|
66
|
+
};
|
|
67
|
+
const keyAndBuildInventory = (drafts, scriptCount) => {
|
|
68
|
+
const keyed = drafts.map((draft) => ({
|
|
69
|
+
...draft,
|
|
70
|
+
base: stableWebScriptKey(draft.item),
|
|
71
|
+
}));
|
|
72
|
+
keyed.sort((left, right) => left.base.localeCompare(right.base) ||
|
|
73
|
+
sourceDigest(left.item.source).localeCompare(sourceDigest(right.item.source)) ||
|
|
74
|
+
(left.item.frame_id ?? "").localeCompare(right.item.frame_id ?? ""));
|
|
75
|
+
const totals = new Map();
|
|
76
|
+
for (const { base } of keyed)
|
|
77
|
+
totals.set(base, (totals.get(base) ?? 0) + 1);
|
|
78
|
+
const seen = new Map();
|
|
79
|
+
const sourceMapRequests = [];
|
|
80
|
+
const items = keyed.map(({ base, item, sourceMapRawUrl }) => {
|
|
81
|
+
const occurrence = (seen.get(base) ?? 0) + 1;
|
|
82
|
+
seen.set(base, occurrence);
|
|
83
|
+
const scriptKey = totals.get(base) === 1 ? base : `${base}_${String(occurrence)}`;
|
|
84
|
+
if (item.source_map_url !== null && sourceMapRawUrl !== null)
|
|
85
|
+
sourceMapRequests.push({
|
|
86
|
+
scriptKey,
|
|
87
|
+
declaredUrl: item.source_map_url,
|
|
88
|
+
fetchUrl: sourceMapRawUrl,
|
|
89
|
+
});
|
|
90
|
+
return { script_key: scriptKey, ...item };
|
|
91
|
+
});
|
|
92
|
+
return {
|
|
93
|
+
inventory: { total: scriptCount, items },
|
|
94
|
+
sourceMapRequests,
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
const sourceDigest = (source) => (source.included ? source.artifact.sha256 : source.reason);
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { allowedSanitizedUrl, boundedText, isHttpUrl, recordValue, recordsValue, stringValue, } from "./CdpCaptureValues.js";
|
|
2
|
+
import { optionalCdpCommand } from "./CdpOptionalCommand.js";
|
|
3
|
+
export const captureWorkers = async (input, frameIds) => {
|
|
4
|
+
const { context, allowedOrigins, limitations, events } = input;
|
|
5
|
+
const completeness = events.completeness;
|
|
6
|
+
const result = await optionalCdpCommand({ ...context, sessionId: undefined }, "Target.getTargets", {}, limitations);
|
|
7
|
+
const items = [];
|
|
8
|
+
let total = 0;
|
|
9
|
+
if (result === undefined)
|
|
10
|
+
completeness.unavailable("workers");
|
|
11
|
+
for (const target of recordsValue(recordValue(result)?.targetInfos)) {
|
|
12
|
+
const type = stringValue(target.type) ?? "";
|
|
13
|
+
const url = allowedSanitizedUrl(target.url, allowedOrigins);
|
|
14
|
+
const relatedToPage = stringValue(target.openerId) === context.target.id ||
|
|
15
|
+
(stringValue(target.parentFrameId) !== undefined &&
|
|
16
|
+
frameIds.has(stringValue(target.parentFrameId) ?? ""));
|
|
17
|
+
if (!type.includes("worker"))
|
|
18
|
+
continue;
|
|
19
|
+
if (!relatedToPage) {
|
|
20
|
+
completeness.exclude("workers", "out_of_target_scope");
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
if (url === undefined) {
|
|
24
|
+
const rawUrl = stringValue(target.url);
|
|
25
|
+
completeness.exclude("workers", rawUrl === undefined || rawUrl === ""
|
|
26
|
+
? "unattributed_origin"
|
|
27
|
+
: isHttpUrl(rawUrl)
|
|
28
|
+
? "disallowed_origin"
|
|
29
|
+
: "unsupported_url");
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
total += 1;
|
|
33
|
+
if (items.length >= context.input.limits.max_workers)
|
|
34
|
+
continue;
|
|
35
|
+
items.push({
|
|
36
|
+
target_id: (stringValue(target.targetId) ?? "").slice(0, 256),
|
|
37
|
+
type: type.slice(0, 100),
|
|
38
|
+
url: url.url,
|
|
39
|
+
origin: url.origin,
|
|
40
|
+
attached: target.attached === true,
|
|
41
|
+
opener_target_id: boundedText(target.openerId, 256) ?? null,
|
|
42
|
+
parent_frame_id: boundedText(target.parentFrameId, 256) ?? null,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
return { total, items };
|
|
46
|
+
};
|
|
@@ -35,7 +35,13 @@ export const discoverWebMcp = async (context) => {
|
|
|
35
35
|
return;
|
|
36
36
|
if (ingestFrameScopeEvent(event, frameScope))
|
|
37
37
|
return;
|
|
38
|
-
ingestWebMcpEvent(
|
|
38
|
+
ingestWebMcpEvent({
|
|
39
|
+
event,
|
|
40
|
+
input: context.input,
|
|
41
|
+
frames: frameUrls,
|
|
42
|
+
tools,
|
|
43
|
+
completeness,
|
|
44
|
+
});
|
|
39
45
|
});
|
|
40
46
|
await context.progress?.report({
|
|
41
47
|
phase: "browser_observation",
|
|
@@ -53,7 +59,14 @@ export const discoverWebMcp = async (context) => {
|
|
|
53
59
|
// CDP sends the enable response before the required toolsAdded replay.
|
|
54
60
|
await delayWithCancellation(Math.max(context.input.observation_ms, 25), "discover_webmcp_tools", context.signal);
|
|
55
61
|
await assertStableAuthorizedFrame(context, initialUrl, origins);
|
|
56
|
-
return
|
|
62
|
+
return buildWebMcpResult({
|
|
63
|
+
context,
|
|
64
|
+
frameTree,
|
|
65
|
+
tools,
|
|
66
|
+
completeness,
|
|
67
|
+
limitations,
|
|
68
|
+
available,
|
|
69
|
+
});
|
|
57
70
|
}
|
|
58
71
|
finally {
|
|
59
72
|
removeListener();
|
|
@@ -70,18 +83,27 @@ const ingestFrameScopeEvent = (event, state) => {
|
|
|
70
83
|
const params = recordValue(event.params);
|
|
71
84
|
if (params === undefined)
|
|
72
85
|
return false;
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
86
|
+
switch (event.method) {
|
|
87
|
+
case "Page.frameDetached":
|
|
88
|
+
return handleFrameDetached(params, state);
|
|
89
|
+
case "Page.frameNavigated":
|
|
90
|
+
return handleFrameUpdate(recordValue(params.frame), state);
|
|
91
|
+
case "Page.navigatedWithinDocument":
|
|
92
|
+
return handleFrameUpdate(params, state);
|
|
93
|
+
default:
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
const handleFrameDetached = (params, state) => {
|
|
98
|
+
const frameId = stringValue(params.frameId);
|
|
99
|
+
if (frameId === undefined || frameId.length > 256) {
|
|
100
|
+
state.completeness.exclude("webmcp_tools", "invalid_protocol_value");
|
|
79
101
|
return true;
|
|
80
102
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
103
|
+
removeFrame(frameId, state.frames, state.tools);
|
|
104
|
+
return true;
|
|
105
|
+
};
|
|
106
|
+
const handleFrameUpdate = (frame, state) => {
|
|
85
107
|
const frameId = stringValue(frame?.id) ?? stringValue(frame?.frameId);
|
|
86
108
|
if (frameId === undefined || frameId.length > 256) {
|
|
87
109
|
state.completeness.exclude("webmcp_tools", "invalid_protocol_value");
|
|
@@ -128,7 +150,8 @@ const assertStableAuthorizedFrame = async (context, initialUrl, origins) => {
|
|
|
128
150
|
if (finalUrl !== initialUrl)
|
|
129
151
|
throw new BrowserObservationError("inspect_web_page", "target_changed");
|
|
130
152
|
};
|
|
131
|
-
const ingestWebMcpEvent = (
|
|
153
|
+
const ingestWebMcpEvent = (options) => {
|
|
154
|
+
const { event, input, frames, tools, completeness } = options;
|
|
132
155
|
const params = recordValue(event.params);
|
|
133
156
|
if (params === undefined)
|
|
134
157
|
return;
|
|
@@ -214,7 +237,8 @@ const registrationSource = (stack, allowedOrigins) => {
|
|
|
214
237
|
column: integerOrNull(frame.columnNumber),
|
|
215
238
|
};
|
|
216
239
|
};
|
|
217
|
-
const
|
|
240
|
+
const buildWebMcpResult = (options) => {
|
|
241
|
+
const { context, frameTree, tools, completeness, limitations, available } = options;
|
|
218
242
|
const targetUrl = mainFrameUrl(frameTree) ?? context.target.url;
|
|
219
243
|
const sanitized = allowedSanitizedUrl(targetUrl, new Set(context.input.allowed_origins));
|
|
220
244
|
return {
|
|
@@ -128,7 +128,13 @@ const unfilter = (raw, width, height, channels) => {
|
|
|
128
128
|
const upperLeft = row > 0 && column >= channels
|
|
129
129
|
? (decoded[outputOffset + column - rowBytes - channels] ?? 0)
|
|
130
130
|
: 0;
|
|
131
|
-
decoded[outputOffset + column] = applyFilter(
|
|
131
|
+
decoded[outputOffset + column] = applyFilter({
|
|
132
|
+
filter,
|
|
133
|
+
source,
|
|
134
|
+
left,
|
|
135
|
+
above,
|
|
136
|
+
upperLeft,
|
|
137
|
+
});
|
|
132
138
|
}
|
|
133
139
|
}
|
|
134
140
|
if (channels === 4)
|
|
@@ -142,7 +148,8 @@ const unfilter = (raw, width, height, channels) => {
|
|
|
142
148
|
}
|
|
143
149
|
return rgba;
|
|
144
150
|
};
|
|
145
|
-
const applyFilter = (
|
|
151
|
+
const applyFilter = (options) => {
|
|
152
|
+
const { filter, source, left, above, upperLeft } = options;
|
|
146
153
|
switch (filter) {
|
|
147
154
|
case 0:
|
|
148
155
|
return source;
|
package/dist/catalogIdentity.js
CHANGED
|
@@ -53,6 +53,10 @@ const resourceTemplateCatalog = [
|
|
|
53
53
|
name: "investigation-workspace-revision",
|
|
54
54
|
uri_template: "rea://workspace/{workspaceId}/revision/{revision}",
|
|
55
55
|
},
|
|
56
|
+
{
|
|
57
|
+
name: "reconstruction-coverage-revision",
|
|
58
|
+
uri_template: "rea://reconstruction-coverage/{workspaceId}/revision/{revision}",
|
|
59
|
+
},
|
|
56
60
|
];
|
|
57
61
|
const digest = (value) => {
|
|
58
62
|
const encoded = canonicalize(value);
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { z } from "incur";
|
|
2
|
+
import { runProviderAnalysis } from "../application/DirectAnalysis.js";
|
|
3
|
+
import { logCliCommand } from "../cliLogging.js";
|
|
4
|
+
import { CLI_COMMANDS } from "../cliCommandNames.js";
|
|
5
|
+
export const registerArtifactCommands = (cli, logger) => {
|
|
6
|
+
cli.command(CLI_COMMANDS.inventoryArtifact, {
|
|
7
|
+
description: "Build a bounded deterministic artifact graph",
|
|
8
|
+
args: z.object({
|
|
9
|
+
path: z.string().describe("Application or package path"),
|
|
10
|
+
}),
|
|
11
|
+
options: z.object({
|
|
12
|
+
offset: z
|
|
13
|
+
.number()
|
|
14
|
+
.int()
|
|
15
|
+
.min(0)
|
|
16
|
+
.default(0)
|
|
17
|
+
.describe("Zero-based offset for graph nodes, occurrences, and edges"),
|
|
18
|
+
limit: z
|
|
19
|
+
.number()
|
|
20
|
+
.int()
|
|
21
|
+
.min(1)
|
|
22
|
+
.max(500)
|
|
23
|
+
.default(100)
|
|
24
|
+
.describe("Maximum nodes, occurrences, and edges per result section"),
|
|
25
|
+
integrityPolicy: z
|
|
26
|
+
.enum(["fail", "record-and-continue"])
|
|
27
|
+
.default("fail")
|
|
28
|
+
.describe("Behavior when declared artifact integrity does not match"),
|
|
29
|
+
integrityContinueApproved: z
|
|
30
|
+
.boolean()
|
|
31
|
+
.default(false)
|
|
32
|
+
.describe("Approve continuing after recorded integrity mismatches"),
|
|
33
|
+
maxIntegrityMismatches: z
|
|
34
|
+
.number()
|
|
35
|
+
.int()
|
|
36
|
+
.min(1)
|
|
37
|
+
.max(100)
|
|
38
|
+
.default(10)
|
|
39
|
+
.describe("Maximum integrity mismatches to record before stopping"),
|
|
40
|
+
nativeMountApproved: z
|
|
41
|
+
.boolean()
|
|
42
|
+
.default(false)
|
|
43
|
+
.describe("Approve read-only native mounting when required"),
|
|
44
|
+
}),
|
|
45
|
+
alias: {
|
|
46
|
+
integrityPolicy: "integrity-policy",
|
|
47
|
+
integrityContinueApproved: "integrity-continue-approved",
|
|
48
|
+
maxIntegrityMismatches: "max-integrity-mismatches",
|
|
49
|
+
nativeMountApproved: "native-mount-approved",
|
|
50
|
+
},
|
|
51
|
+
run: ({ args, options }) => logCliCommand(logger, "inventory-artifact", () => runProviderAnalysis(args.path, "inventory_artifact", {
|
|
52
|
+
node_offset: options.offset,
|
|
53
|
+
node_limit: options.limit,
|
|
54
|
+
occurrence_offset: options.offset,
|
|
55
|
+
occurrence_limit: options.limit,
|
|
56
|
+
edge_offset: options.offset,
|
|
57
|
+
edge_limit: options.limit,
|
|
58
|
+
integrity_policy: options.integrityPolicy,
|
|
59
|
+
integrity_continue_approved: options.integrityContinueApproved,
|
|
60
|
+
max_integrity_mismatches: options.maxIntegrityMismatches,
|
|
61
|
+
native_mount_approved: options.nativeMountApproved,
|
|
62
|
+
}, logger)),
|
|
63
|
+
});
|
|
64
|
+
cli.command(CLI_COMMANDS.extractArtifact, {
|
|
65
|
+
description: "Extract explicitly selected artifact occurrences safely",
|
|
66
|
+
args: z.object({
|
|
67
|
+
path: z.string().describe("Application or package path"),
|
|
68
|
+
outputRoot: z.string().describe("Absent absolute output root"),
|
|
69
|
+
occurrenceIds: z
|
|
70
|
+
.array(z.string().regex(/^occ_[a-f0-9]{64}$/u))
|
|
71
|
+
.min(1)
|
|
72
|
+
.max(500)
|
|
73
|
+
.describe("Exact artifact occurrence IDs selected for extraction"),
|
|
74
|
+
}),
|
|
75
|
+
alias: { outputRoot: "output-root", occurrenceIds: "occurrence-ids" },
|
|
76
|
+
run: ({ args }) => logCliCommand(logger, "extract-artifact", () => runProviderAnalysis(args.path, "extract_artifact", {
|
|
77
|
+
approved: true,
|
|
78
|
+
output_root: args.outputRoot,
|
|
79
|
+
occurrence_ids: args.occurrenceIds,
|
|
80
|
+
}, logger)),
|
|
81
|
+
});
|
|
82
|
+
};
|