rea-agents 6.2.0 → 6.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -20
- package/bridge/hopper_bridge.py +2 -0
- package/dist/android/JadxProvider.js +8 -2
- package/dist/android/JadxSession.js +51 -9
- package/dist/application/BinaryTargetResolver.js +63 -17
- package/dist/application/BrowserScenarioEvidence.js +2 -2
- package/dist/application/ClientConfigurationDocument.js +28 -0
- package/dist/application/ClientRegistrationStatus.js +19 -6
- package/dist/application/DirectAnalysis.js +12 -6
- package/dist/application/DirectAnalysisCleanup.js +0 -1
- package/dist/application/DirectAnalysisStatus.js +2 -5
- package/dist/application/Doctor.js +25 -34
- package/dist/application/DoctorDiagnostics.js +1 -1
- package/dist/application/EvidenceBundleFiles.js +1 -1
- package/dist/application/InvestigationProviders.js +4 -4
- package/dist/application/JsonFiles.js +15 -15
- package/dist/application/LinuxHopper.js +2 -1
- package/dist/application/ReconstructionObligationCandidates.js +9 -2
- package/dist/application/ReconstructionObligationLedgerProjection.js +3 -1
- package/dist/application/RegularFileRead.js +17 -0
- package/dist/application/Setup.js +18 -7
- package/dist/application/SetupClientConfiguration.js +18 -7
- package/dist/application/SetupHost.js +6 -4
- package/dist/application/SetupPlan.js +19 -15
- package/dist/application/SetupSkill.js +57 -8
- package/dist/application/SupportedClients.js +43 -0
- package/dist/application/Uninstall.js +18 -2
- package/dist/application/UpdateMaintenance.js +6 -2
- package/dist/application/Utf8JsonInput.js +64 -0
- package/dist/application/WebScriptExportService.js +13 -6
- package/dist/application/android/AndroidAnalysisService.js +1 -1
- package/dist/application/binary/AnalysisSnapshotCache.js +5 -4
- package/dist/application/binary/BinarySession.js +16 -0
- package/dist/application/binary/BinarySessionOpen.js +9 -1
- package/dist/application/javascript/ElectronActiveEvidence.js +2 -2
- package/dist/application/javascript/ElectronBoundaryAnalysis.js +2 -2
- package/dist/application/javascript/ElectronBoundaryGraphNative.js +5 -1
- package/dist/application/javascript/JavaScriptApplicationEvidence.js +1 -0
- package/dist/application/javascript/JavaScriptApplicationEvidenceGraph.js +107 -46
- package/dist/application/javascript/JavaScriptApplicationService.js +1 -0
- package/dist/application/javascript/JavaScriptApplicationWorkflowService.js +59 -45
- package/dist/application/javascript/JavaScriptArtifactAnalysis.js +0 -6
- package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +8 -18
- package/dist/application/javascript/JavaScriptArtifactGraphFindings.js +34 -26
- package/dist/application/javascript/JavaScriptArtifactPathResolution.js +44 -12
- package/dist/application/javascript/JavaScriptArtifactReconstruction.js +6 -3
- package/dist/application/javascript/JavaScriptArtifactReconstructionInput.js +1 -0
- package/dist/application/javascript/JavaScriptJsonModules.js +2 -2
- package/dist/application/javascript/JavaScriptModuleRelationships.js +5 -17
- package/dist/application/javascript/JavaScriptRuntimeReconciliationService.js +11 -27
- package/dist/application/javascript/JavaScriptSemanticGraphAsyncProjection.js +2 -2
- package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +8 -6
- package/dist/application/javascript/JavaScriptSemanticGraphChildProcessProjection.js +1 -1
- package/dist/application/javascript/JavaScriptSemanticGraphConstruction.js +7 -5
- package/dist/application/javascript/JavaScriptSemanticGraphDataProjection.js +1 -1
- package/dist/application/javascript/JavaScriptSemanticGraphEvidence.js +1 -1
- package/dist/application/javascript/JavaScriptSemanticGraphFingerprintProjection.js +2 -2
- package/dist/application/javascript/JavaScriptSemanticGraphFlowProjection.js +2 -2
- package/dist/application/javascript/JavaScriptSemanticGraphObjectProjection.js +1 -1
- package/dist/application/javascript/JavaScriptSemanticGraphProjection.js +4 -4
- package/dist/application/javascript/JavaScriptSemanticGraphResourceProjection.js +1 -1
- package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +10 -7
- package/dist/application/javascript/JavaScriptSemanticTraceService.js +15 -10
- package/dist/application/native/NativeCallRoutes.js +2 -4
- package/dist/artifacts/ArtifactProvider.js +14 -16
- package/dist/artifacts/ArtifactProviderMetadata.js +1 -4
- package/dist/artifacts/AsarArtifactReader.js +81 -17
- package/dist/artifacts/DirectoryArtifactReader.js +2 -2
- package/dist/artifacts/NativeDmgArtifactReader.js +152 -67
- package/dist/artifacts/NativeDmgOwnership.js +109 -0
- package/dist/artifacts/apple/KeyedArchiveReader.js +54 -46
- package/dist/artifacts/apple/MachoLoadCommandReader.js +36 -6
- package/dist/artifacts/extraction/ArtifactExtraction.js +29 -11
- package/dist/artifacts/inventory/ArtifactGraphConstruction.js +7 -8
- package/dist/artifacts/inventory/classify.js +33 -14
- package/dist/artifacts/inventory/hashStableRootArtifact.js +37 -0
- package/dist/artifacts/inventory/scanCanonical.js +28 -22
- package/dist/artifacts/inventory/scanReader.js +7 -11
- package/dist/artifacts/javascript/JavaScriptArtifactFiles.js +65 -27
- package/dist/browser/CdpBrowserProvider.js +4 -3
- package/dist/browser/CdpCaptureStorageFingerprints.js +3 -3
- package/dist/browser/CdpElectronInspection.js +2 -2
- package/dist/browser/CdpElectronProvider.js +4 -3
- package/dist/browser/CdpElectronScripts.js +2 -2
- package/dist/browser/CdpWebMcpDiscovery.js +16 -13
- package/dist/browser/PlaywrightBrowserScenarioProvider.js +6 -6
- package/dist/browser/PlaywrightScenarioBrowser.js +145 -42
- package/dist/browser/PlaywrightScenarioSession.js +3 -11
- package/dist/browser/WebSourceMapFetcher.js +32 -6
- package/dist/browser/assets/ScenarioScriptCapture.js +8 -12
- package/dist/cli/coreAnalysisCommands.js +2 -2
- package/dist/cli/coreBinaryCommands.js +13 -9
- package/dist/cli/electronCommands.js +9 -10
- package/dist/cli/javascriptApplicationAnalysis.js +2 -12
- package/dist/cli/jsonOutput.js +3 -2
- package/dist/cli/streamedJsonOutput.js +83 -4
- package/dist/cli/utilityCommands.js +2 -4
- package/dist/cli.js +5 -2
- package/dist/cliJsonFile.js +179 -0
- package/dist/cliJsonInput.js +47 -34
- package/dist/cliObservationOptions.js +4 -0
- package/dist/composition/auxiliaryAnalysisProviders.js +5 -4
- package/dist/composition/browserScenario.js +2 -2
- package/dist/composition/directAnalysis.js +2 -3
- package/dist/contracts/artifactComparisonExample.js +5 -5
- package/dist/contracts/errorSchemas.js +3 -1
- package/dist/contracts/functionComparisonExample.js +8 -0
- package/dist/contracts/inputSchemaPresentation.js +94 -3
- package/dist/contracts/javascript/electronToolContracts.js +2 -1
- package/dist/contracts/javascript/javascriptApplicationWorkflowExamples.js +3 -2
- package/dist/contracts/javascript/javascriptExportShapeComparisonExample.js +6 -3
- package/dist/contracts/javascript/javascriptRuntimeReconciliationExample.js +8 -7
- package/dist/contracts/managed/managedToolContracts.js +3 -2
- package/dist/contracts/mobileApplicationGraphExamples.js +5 -5
- package/dist/contracts/native/nativeToolContracts.js +1 -1
- package/dist/contracts/sessionLifecycleInputs.js +4 -3
- package/dist/contracts/sessionStatusContract.js +3 -2
- package/dist/contracts/sessionToolContracts.js +3 -2
- package/dist/contracts/sessionToolSchemas.js +3 -2
- package/dist/contracts/toolOutputSchemaGroups.js +2 -2
- package/dist/contracts/toolOutputSchemaPrimitives.js +2 -5
- package/dist/domain/analysisErrorBase.js +5 -0
- package/dist/domain/analysisErrorPresentation.js +4 -2
- package/dist/domain/analysisSnapshot.js +3 -1
- package/dist/domain/analysisView/analysisView.js +1 -3
- package/dist/domain/android/androidPartialObservation.js +36 -0
- package/dist/domain/apple/dylibResolution.js +1 -1
- package/dist/domain/artifactComparison.js +4 -4
- package/dist/domain/artifactGraph.js +1 -1
- package/dist/domain/artifactIdentity.js +8 -8
- package/dist/domain/artifactInspection.js +8 -8
- package/dist/domain/artifactInventoryEvidence.js +5 -5
- package/dist/domain/browserCompleteness.js +3 -2
- package/dist/domain/browserScenarioCaptureValues.js +2 -2
- package/dist/domain/browserScenarioNormalization.js +3 -3
- package/dist/domain/browserScenarioValues.js +3 -2
- package/dist/domain/callPath.js +8 -10
- package/dist/domain/canonicalDigest.js +7 -1
- package/dist/domain/canonicalOrdering.js +1 -13
- package/dist/domain/changedBehavior.js +2 -3
- package/dist/domain/comparisonSemantics.js +0 -5
- package/dist/domain/digests.js +0 -3
- package/dist/domain/evidence.js +10 -5
- package/dist/domain/evidenceBundle.js +51 -33
- package/dist/domain/firmware/firmwareAnalysis.js +4 -3
- package/dist/domain/functionComparison.js +2 -1
- package/dist/domain/functionComparisonNormalization.js +4 -3
- package/dist/domain/functionComparisonResults.js +2 -2
- package/dist/domain/functionDossierEvidence.js +2 -1
- package/dist/domain/hopperValues.js +11 -15
- package/dist/domain/javascript/electronActiveObservation.js +4 -3
- package/dist/domain/javascript/electronStaticAnalysisBrowser.js +2 -2
- package/dist/domain/javascript/electronStaticAnalysisIpc.js +9 -1
- package/dist/domain/javascript/electronStaticAnalysisNative.js +5 -3
- package/dist/domain/javascript/electronStaticAnalysisValues.js +8 -4
- package/dist/domain/javascript/javascriptApplicationAnalysis.js +3 -1
- package/dist/domain/javascript/javascriptApplicationChangeGraph.js +12 -8
- package/dist/domain/javascript/javascriptApplicationEvidenceSchemas.js +4 -0
- package/dist/domain/javascript/javascriptApplicationGraph.js +15 -13
- package/dist/domain/javascript/javascriptApplicationVersionComparison.js +4 -4
- package/dist/domain/javascript/javascriptApplicationVersionComparisonSchemas.js +37 -22
- package/dist/domain/javascript/javascriptApplicationVersionItems.js +45 -34
- package/dist/domain/javascript/javascriptApplicationVersionKeys.js +7 -7
- package/dist/domain/javascript/javascriptAstFingerprint.js +2 -2
- package/dist/domain/javascript/javascriptAstValues.js +22 -0
- package/dist/domain/javascript/javascriptExportShapeComparison.js +3 -2
- package/dist/domain/javascript/javascriptExportShapeComparisonSchemas.js +31 -23
- package/dist/domain/javascript/javascriptExportShapeSelection.js +2 -2
- package/dist/domain/javascript/javascriptExportShapeVariants.js +3 -2
- package/dist/domain/javascript/javascriptFeatureSeed.js +5 -3
- package/dist/domain/javascript/javascriptFeatureTrace.js +7 -6
- package/dist/domain/javascript/javascriptFeatureTraceSchemas.js +17 -9
- package/dist/domain/javascript/javascriptFeatureTraversal.js +4 -4
- package/dist/domain/javascript/javascriptNativeHandoff.js +6 -6
- package/dist/domain/javascript/javascriptRuntimeObservation.js +8 -5
- package/dist/domain/javascript/javascriptRuntimeReconciliation.js +12 -6
- package/dist/domain/javascript/javascriptRuntimeReconciliationActive.js +9 -8
- package/dist/domain/javascript/javascriptRuntimeReconciliationCaptureParsing.js +212 -0
- package/dist/domain/javascript/javascriptRuntimeReconciliationGraph.js +5 -4
- package/dist/domain/javascript/javascriptRuntimeReconciliationInputValidation.js +28 -0
- package/dist/domain/javascript/javascriptRuntimeReconciliationMatching.js +5 -5
- package/dist/domain/javascript/javascriptRuntimeReconciliationParsing.js +12 -223
- package/dist/domain/javascript/javascriptRuntimeReconciliationResult.js +2 -2
- package/dist/domain/javascript/javascriptRuntimeReconciliationRuntime.js +15 -4
- package/dist/domain/javascript/javascriptRuntimeReconciliationSchemas.js +2 -2
- package/dist/domain/javascript/javascriptRuntimeStaticCandidates.js +7 -6
- package/dist/domain/javascript/javascriptSemanticAnalysis.js +200 -8
- package/dist/domain/javascript/javascriptSemanticCallResolution.js +9 -7
- package/dist/domain/javascript/javascriptSemanticChildProcesses.js +2 -2
- package/dist/domain/javascript/javascriptSemanticCoverage.js +20 -0
- package/dist/domain/javascript/javascriptSemanticDataEffectHelpers.js +7 -9
- package/dist/domain/javascript/javascriptSemanticDataEffects.js +4 -11
- package/dist/domain/javascript/javascriptSemanticFingerprints.js +2 -2
- package/dist/domain/javascript/javascriptSemanticGraph.js +142 -35
- package/dist/domain/javascript/javascriptSemanticGraphSchemas.js +19 -1
- package/dist/domain/javascript/javascriptSemanticIr.js +0 -4
- package/dist/domain/javascript/javascriptSemanticIterationSources.js +106 -0
- package/dist/domain/javascript/javascriptSemanticMemberMutations.js +497 -113
- package/dist/domain/javascript/javascriptSemanticMutationInitializers.js +190 -0
- package/dist/domain/javascript/javascriptSemanticMutationValues.js +41 -27
- package/dist/domain/javascript/javascriptSemanticObjects.js +2 -6
- package/dist/domain/javascript/javascriptSemanticPrimitives.js +7 -2
- package/dist/domain/javascript/javascriptSemanticProjection.js +20 -14
- package/dist/domain/javascript/javascriptSemanticPromises.js +15 -21
- package/dist/domain/javascript/javascriptSemanticPropertyPaths.js +23 -0
- package/dist/domain/javascript/javascriptSemanticProvenance.js +3 -3
- package/dist/domain/javascript/javascriptSemanticQuery.js +8 -2
- package/dist/domain/javascript/javascriptSemanticQueryIdentity.js +3 -2
- package/dist/domain/javascript/javascriptSemanticQuerySchemas.js +8 -9
- package/dist/domain/javascript/javascriptSemanticRequireOrigin.js +16 -10
- package/dist/domain/javascript/javascriptSemanticReturns.js +23 -27
- package/dist/domain/javascript/javascriptSemanticTraversal.js +6 -1
- package/dist/domain/javascript/javascriptSemanticValues.js +135 -24
- package/dist/domain/javascript/javascriptSourceMapPaths.js +11 -1
- package/dist/domain/javascript/javascriptSourceParser.js +34 -9
- package/dist/domain/javascript/javascriptStaticAnalysisBundler.js +5 -6
- package/dist/domain/javascript/javascriptStaticAnalysisHelpers.js +26 -15
- package/dist/domain/javascript/sourceToBundleComparison.js +7 -5
- package/dist/domain/javascript/sourceToBundleSignals.js +7 -7
- package/dist/domain/jsonSerialization.js +109 -55
- package/dist/domain/jsonShape.js +46 -19
- package/dist/domain/localPath.js +10 -4
- package/dist/domain/managed/managedApplicationGraph.js +10 -6
- package/dist/domain/managed/managedApplicationGraphNodes.js +82 -57
- package/dist/domain/managed/managedMemberComparisonMatch.js +6 -7
- package/dist/domain/native/nativeCallObservation.js +2 -4
- package/dist/domain/native/nativeValueFlow.js +5 -11
- package/dist/domain/native/objcSwiftMetadata.js +15 -17
- package/dist/domain/process/processCapture.js +11 -10
- package/dist/domain/process/processCaptureCoverage.js +8 -5
- package/dist/domain/process/processCaptureExample.js +43 -0
- package/dist/domain/process/processCaptureValidation.js +4 -3
- package/dist/domain/process/processComparison.js +0 -23
- package/dist/domain/process/processScenario.js +3 -3
- package/dist/domain/process/processTraceEvaluation.js +4 -4
- package/dist/domain/process/processTraceSpecification.js +1 -3
- package/dist/domain/providerCleanupError.js +6 -2
- package/dist/domain/reconstructionCoverage.js +2 -1
- package/dist/domain/reconstructionUnknowns.js +4 -3
- package/dist/domain/reconstructionVerification.js +3 -2
- package/dist/domain/referenceSourceGraph.js +7 -7
- package/dist/domain/referenceSourceImportParsing.js +34 -45
- package/dist/domain/residualUnknown.js +3 -2
- package/dist/domain/staticRuntimeCorrelation.js +2 -1
- package/dist/domain/swiftSymbolClassification.js +6 -1
- package/dist/domain/symbolAnalysis.js +17 -2
- package/dist/domain/unicodeCodePointOrder.js +6 -0
- package/dist/domain/webBundleAnalyzerInspection.js +9 -1
- package/dist/domain/webCaptureDiff.js +71 -29
- package/dist/domain/webCaptureDiffSchemas.js +2 -8
- package/dist/domain/webInventory.js +3 -2
- package/dist/domain/webMcpDiscovery.js +4 -3
- package/dist/domain/webScriptExport.js +1 -1
- package/dist/dotnet/ManagedMemberInstructionDecoder.js +1 -2
- package/dist/dotnet/ManagedStaticProvider.js +10 -7
- package/dist/dotnet/ManagedStaticProviderMetadata.js +1 -4
- package/dist/filesystem/RegularFile.js +41 -0
- package/dist/generatedPackageMetadata.js +1 -1
- package/dist/ghidra/GhidraClient.js +14 -4
- package/dist/ghidra/GhidraInstallation.js +111 -10
- package/dist/ghidra/GhidraLauncher.js +43 -19
- package/dist/hopper/HopperCleanup.js +1 -1
- package/dist/ida/IdaOperationRunner.js +2 -0
- package/dist/ida/IdaSessionClient.js +4 -2
- package/dist/inspector/JavaScriptRuntimeScope.js +9 -5
- package/dist/inspector/V8InspectorCaptureProjection.js +46 -13
- package/dist/inspector/V8InspectorProvider.js +60 -8
- package/dist/main/shutdown.js +76 -32
- package/dist/main/transport.js +1 -1
- package/dist/native/AppleObjcDispatchFacets.js +3 -3
- package/dist/native/AppleObjcProperties.js +17 -7
- package/dist/native/LldbCallTracer.js +241 -75
- package/dist/native/NativeMacOSProvider.js +10 -5
- package/dist/native/NativeMacOSProviderMetadata.js +1 -2
- package/dist/process/ProcessOwnershipObservation.js +9 -13
- package/dist/process/capture/FilesystemSnapshot.js +88 -18
- package/dist/process/capture/ProcessCaptureLifecycle.js +13 -27
- package/dist/process/capture/ProcessFilesystemEffects.js +19 -4
- package/dist/process/capture/ProcessHarness.js +8 -21
- package/dist/server/analysisAdmission.js +8 -0
- package/dist/server/createServer.js +22 -23
- package/dist/server/registerApplicationTools/compareExportShapes.js +2 -1
- package/dist/server/registerApplicationTools/helpers.js +3 -2
- package/dist/server/registerArtifactTools.js +2 -2
- package/dist/server/registerCloseLifecycleTool.js +6 -4
- package/dist/server/registerEnhancedTools.js +78 -73
- package/dist/server/registerEvidenceTools.js +54 -46
- package/dist/server/registerManagedTools.js +7 -4
- package/dist/server/registerOfficialTools.js +31 -25
- package/dist/server/registerSessionTools.js +9 -3
- package/native/windows/build/manifest.json +1 -1
- package/package.json +6 -3
- package/skills/reverse-engineer-anything/SKILL.md +5 -5
- package/skills/reverse-engineer-anything/references/native-and-artifacts.md +9 -0
- package/dist/artifacts/inventory/policy.js +0 -2
- package/dist/domain/managed/managedApplicationGraphNodeCoverage.js +0 -6
- package/dist/server/registerNativeTools.js +0 -6
|
@@ -7,7 +7,7 @@ import { STRICT_INTEGRITY_POLICY, } from "./types.js";
|
|
|
7
7
|
import { hashReadable } from "../ArtifactHash.js";
|
|
8
8
|
const UNAVAILABLE_UNPACKED_LIMITATION = "ASAR unpacked companion bytes were unavailable; no content hash or child artifact was produced.";
|
|
9
9
|
const emptyScan = () => ({ nodes: new Map(), occurrences: [], pendingContradictions: [] });
|
|
10
|
-
export const scanReader = async (reader, signal, integrity = STRICT_INTEGRITY_POLICY) => {
|
|
10
|
+
export const scanReader = async (reader, ownedReaders, signal, integrity = STRICT_INTEGRITY_POLICY) => {
|
|
11
11
|
const { nodes, occurrences, pendingContradictions } = emptyScan();
|
|
12
12
|
if (reader === undefined)
|
|
13
13
|
return { nodes, occurrences, pendingContradictions };
|
|
@@ -21,6 +21,7 @@ export const scanReader = async (reader, signal, integrity = STRICT_INTEGRITY_PO
|
|
|
21
21
|
occurrenceByPath: new Map(),
|
|
22
22
|
registry: new ArtifactPathRegistry(),
|
|
23
23
|
expandedContainerIds: new Set(),
|
|
24
|
+
ownedReaders,
|
|
24
25
|
};
|
|
25
26
|
await visitArtifactEntries(context, reader, "");
|
|
26
27
|
// Archive directories may appear after their children. Resolve containment
|
|
@@ -36,7 +37,6 @@ const visitArtifactEntries = async (context, currentReader, prefix) => {
|
|
|
36
37
|
reader: currentReader,
|
|
37
38
|
prefix,
|
|
38
39
|
iterator: currentReader.entries(context.signal)[Symbol.asyncIterator](),
|
|
39
|
-
owned: false,
|
|
40
40
|
},
|
|
41
41
|
];
|
|
42
42
|
try {
|
|
@@ -47,8 +47,6 @@ const visitArtifactEntries = async (context, currentReader, prefix) => {
|
|
|
47
47
|
const next = await frame.iterator.next();
|
|
48
48
|
if (next.done) {
|
|
49
49
|
stack.pop();
|
|
50
|
-
if (frame.owned)
|
|
51
|
-
await frame.reader.close();
|
|
52
50
|
continue;
|
|
53
51
|
}
|
|
54
52
|
const entry = next.value;
|
|
@@ -81,26 +79,24 @@ const visitArtifactEntries = async (context, currentReader, prefix) => {
|
|
|
81
79
|
}
|
|
82
80
|
context.occurrences.push(occurrence);
|
|
83
81
|
context.occurrenceByPath.set(logicalPath, occurrence);
|
|
84
|
-
if (expandableAsar && digested
|
|
82
|
+
if (expandableAsar && digested !== undefined && !digested.mismatched) {
|
|
85
83
|
const nested = new AsarArtifactReader(entry.adapterKey);
|
|
84
|
+
context.ownedReaders.push(nested);
|
|
85
|
+
await nested.prepareContainer(digested.node.sha256, context.signal);
|
|
86
86
|
// Only traversed containers can own members, not opaque ASAR-named files.
|
|
87
87
|
context.expandedContainerIds.add(occurrence.occurrence_id);
|
|
88
88
|
stack.push({
|
|
89
89
|
reader: nested,
|
|
90
90
|
prefix: logicalPath,
|
|
91
91
|
iterator: nested.entries(context.signal)[Symbol.asyncIterator](),
|
|
92
|
-
owned: true,
|
|
93
92
|
});
|
|
94
93
|
}
|
|
95
94
|
}
|
|
96
95
|
}
|
|
97
96
|
finally {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
.map(async ({ reader, iterator }) => {
|
|
97
|
+
// Readers remain owned by the inventory until its complete observation is built.
|
|
98
|
+
for (const { iterator } of stack)
|
|
101
99
|
await iterator.return?.();
|
|
102
|
-
await reader.close();
|
|
103
|
-
}));
|
|
104
100
|
}
|
|
105
101
|
};
|
|
106
102
|
const digestArtifactEntry = async (context, currentReader, entry, logicalPath) => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { isAbsolute } from "node:path";
|
|
3
|
-
import {
|
|
3
|
+
import { compareUnicodeCodePoints } from "../../domain/unicodeCodePointOrder.js";
|
|
4
4
|
import { AsarArtifactReader } from "../AsarArtifactReader.js";
|
|
5
5
|
import { ArtifactPathRegistry, normalizeArtifactPath, } from "../ArtifactPaths.js";
|
|
6
6
|
import { ArtifactReaderFailure, } from "../ArtifactReader.js";
|
|
@@ -12,7 +12,7 @@ export const readJavaScriptArtifactFiles = async (reader, snapshot, signal) => {
|
|
|
12
12
|
const root = snapshot.nodes.find(({ artifact_id }) => artifact_id === snapshot.manifest.root_artifact_id);
|
|
13
13
|
if (root === undefined)
|
|
14
14
|
throw new ArtifactReaderFailure("integrity", "Root artifact node is missing");
|
|
15
|
-
await verifyEntryBytes(reader.openContainer(signal), { path: ".", sha256: root.sha256, bytes: root.size }, signal);
|
|
15
|
+
await verifyEntryBytes(await reader.openContainer(signal), { path: ".", sha256: root.sha256, bytes: root.size }, signal);
|
|
16
16
|
}
|
|
17
17
|
const inventory = expectedInventory(snapshot);
|
|
18
18
|
const expected = inventory.files;
|
|
@@ -27,11 +27,11 @@ export const readJavaScriptArtifactFiles = async (reader, snapshot, signal) => {
|
|
|
27
27
|
invalidUtf8: 0,
|
|
28
28
|
};
|
|
29
29
|
await visitReader(reader, "", snapshot.manifest.root_sha256, context);
|
|
30
|
-
const files = context.files.sort((left, right) =>
|
|
30
|
+
const files = context.files.sort((left, right) => compareUnicodeCodePoints(left.path, right.path));
|
|
31
31
|
assertExpectedFilesWereVisited(expected, files);
|
|
32
32
|
return {
|
|
33
33
|
files,
|
|
34
|
-
containers: context.containers.sort((left, right) =>
|
|
34
|
+
containers: context.containers.sort((left, right) => compareUnicodeCodePoints(left.path, right.path)),
|
|
35
35
|
text_bytes_read: context.textBytes,
|
|
36
36
|
invalid_utf8_files: context.invalidUtf8,
|
|
37
37
|
};
|
|
@@ -43,9 +43,10 @@ const visitReader = async (reader, prefix, containerSha256, context) => {
|
|
|
43
43
|
prefix,
|
|
44
44
|
containerSha256,
|
|
45
45
|
iterator: reader.entries(context.signal)[Symbol.asyncIterator](),
|
|
46
|
-
owned: false,
|
|
47
46
|
},
|
|
48
47
|
];
|
|
48
|
+
const ownedReaders = [];
|
|
49
|
+
let failure;
|
|
49
50
|
try {
|
|
50
51
|
while (stack.length > 0) {
|
|
51
52
|
const frame = stack.at(-1);
|
|
@@ -54,8 +55,6 @@ const visitReader = async (reader, prefix, containerSha256, context) => {
|
|
|
54
55
|
const next = await frame.iterator.next();
|
|
55
56
|
if (next.done) {
|
|
56
57
|
stack.pop();
|
|
57
|
-
if (frame.owned)
|
|
58
|
-
await frame.reader.close();
|
|
59
58
|
continue;
|
|
60
59
|
}
|
|
61
60
|
const entry = next.value;
|
|
@@ -64,17 +63,32 @@ const visitReader = async (reader, prefix, containerSha256, context) => {
|
|
|
64
63
|
const nestedAsar = isFilesystemAsar(entry, path);
|
|
65
64
|
context.registry.add(path, nestedAsar ? "directory" : entry.kind);
|
|
66
65
|
if (nestedAsar) {
|
|
67
|
-
const
|
|
66
|
+
const container = context.expectedContainers.get(path);
|
|
67
|
+
// Inventory deliberately does not expand unverified or unavailable
|
|
68
|
+
// nested archives. Keep the same boundary here when reconstruction
|
|
69
|
+
// reads the active entries again.
|
|
70
|
+
if (container === undefined)
|
|
71
|
+
throw new ArtifactReaderFailure("integrity", `Nested ASAR was not present in inventory: ${path}`);
|
|
72
|
+
if (container.hash_status === "mismatched")
|
|
73
|
+
continue;
|
|
74
|
+
if (container.hash_status === "unavailable")
|
|
75
|
+
throw new ArtifactReaderFailure("unavailable", `Nested ASAR bytes were unavailable during inventory: ${path}`);
|
|
76
|
+
if (container.hash_status !== "verified")
|
|
77
|
+
throw new ArtifactReaderFailure("integrity", `Nested ASAR was not integrity-verified: ${path}`);
|
|
78
|
+
const inventory = container.inventory;
|
|
79
|
+
if (inventory === null)
|
|
80
|
+
throw new ArtifactReaderFailure("integrity", `Verified nested ASAR has no inventory node: ${path}`);
|
|
68
81
|
await verifyEntryBytes(await frame.reader.open(entry, context.signal), inventory, context.signal);
|
|
69
82
|
context.containers.push(inventory);
|
|
70
83
|
const nested = new AsarArtifactReader(entry.adapterKey);
|
|
84
|
+
ownedReaders.push(nested);
|
|
71
85
|
stack.push({
|
|
72
86
|
reader: nested,
|
|
73
87
|
prefix: path,
|
|
74
88
|
containerSha256: inventory.sha256,
|
|
75
89
|
iterator: nested.entries(context.signal)[Symbol.asyncIterator](),
|
|
76
|
-
owned: true,
|
|
77
90
|
});
|
|
91
|
+
await nested.prepareContainer(inventory.sha256, context.signal);
|
|
78
92
|
continue;
|
|
79
93
|
}
|
|
80
94
|
const expected = context.expected.get(path);
|
|
@@ -97,20 +111,31 @@ const visitReader = async (reader, prefix, containerSha256, context) => {
|
|
|
97
111
|
});
|
|
98
112
|
}
|
|
99
113
|
}
|
|
114
|
+
catch (cause) {
|
|
115
|
+
failure = { cause };
|
|
116
|
+
}
|
|
100
117
|
finally {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
118
|
+
for (const { iterator } of stack) {
|
|
119
|
+
try {
|
|
120
|
+
await iterator.return?.();
|
|
121
|
+
}
|
|
122
|
+
catch (cause) {
|
|
123
|
+
failure ??= { cause };
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
for (const owned of ownedReaders.reverse()) {
|
|
127
|
+
try {
|
|
128
|
+
await owned.close();
|
|
129
|
+
}
|
|
130
|
+
catch (cause) {
|
|
131
|
+
failure = {
|
|
132
|
+
cause: ArtifactReaderFailure.withCleanup(failure?.cause ?? cause, ArtifactReaderFailure.cleanupObservation(cause, `nested ASAR reader for ${prefix}`)),
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
107
136
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
const container = context.expectedContainers.get(path);
|
|
111
|
-
if (container === undefined)
|
|
112
|
-
throw new ArtifactReaderFailure("integrity", `Nested ASAR disappeared from inventory: ${path}`);
|
|
113
|
-
return container;
|
|
137
|
+
if (failure !== undefined)
|
|
138
|
+
throw failure.cause;
|
|
114
139
|
};
|
|
115
140
|
const readText = async (context, input) => {
|
|
116
141
|
if (input.expected.kind === "native-addon") {
|
|
@@ -155,8 +180,18 @@ const expectedInventory = (snapshot) => {
|
|
|
155
180
|
const files = new Map();
|
|
156
181
|
const containers = new Map();
|
|
157
182
|
for (const occurrence of snapshot.occurrences) {
|
|
158
|
-
if (occurrence.
|
|
183
|
+
if (occurrence.logical_path === ".")
|
|
159
184
|
continue;
|
|
185
|
+
const isNestedAsar = occurrence.entry_kind === "file" &&
|
|
186
|
+
occurrence.logical_path.toLowerCase().endsWith(".asar");
|
|
187
|
+
if (occurrence.artifact_id === null) {
|
|
188
|
+
if (isNestedAsar)
|
|
189
|
+
containers.set(occurrence.logical_path, {
|
|
190
|
+
hash_status: occurrence.hash_status,
|
|
191
|
+
inventory: null,
|
|
192
|
+
});
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
160
195
|
const node = nodes.get(occurrence.artifact_id);
|
|
161
196
|
if (node === undefined)
|
|
162
197
|
throw new ArtifactReaderFailure("integrity", `Artifact inventory node is missing: ${occurrence.logical_path}`);
|
|
@@ -165,12 +200,15 @@ const expectedInventory = (snapshot) => {
|
|
|
165
200
|
// node_modules/@zip.js remains a graph node and must never be opened.
|
|
166
201
|
if (occurrence.entry_kind !== "file")
|
|
167
202
|
continue;
|
|
168
|
-
if (
|
|
203
|
+
if (isNestedAsar)
|
|
169
204
|
containers.set(occurrence.logical_path, {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
205
|
+
hash_status: occurrence.hash_status,
|
|
206
|
+
inventory: {
|
|
207
|
+
path: occurrence.logical_path,
|
|
208
|
+
sha256: node.sha256,
|
|
209
|
+
bytes: node.size,
|
|
210
|
+
inventory_artifact_id: node.artifact_id,
|
|
211
|
+
},
|
|
174
212
|
});
|
|
175
213
|
const kind = relevantKind(occurrence.logical_path);
|
|
176
214
|
if (kind === undefined)
|
|
@@ -21,12 +21,11 @@ import { discoverWebMcp } from "./CdpWebMcpDiscovery.js";
|
|
|
21
21
|
import { captureCdpScreenshot } from "./CdpScreenshot.js";
|
|
22
22
|
import { comparePngScreenshots } from "./PngVisualDiff.js";
|
|
23
23
|
import { CDP_BROWSER_PROVIDER_IDENTITY } from "./providerIdentities.js";
|
|
24
|
-
const IDENTITY = CDP_BROWSER_PROVIDER_IDENTITY;
|
|
25
24
|
const CLEANUP_DOMAINS = ["Network", "Debugger", "Runtime", "Page"];
|
|
26
25
|
/** Passive browser observation through a selected user-owned CDP endpoint. */
|
|
27
26
|
export class CdpBrowserProvider {
|
|
28
27
|
identity() {
|
|
29
|
-
return
|
|
28
|
+
return CDP_BROWSER_PROVIDER_IDENTITY;
|
|
30
29
|
}
|
|
31
30
|
async listTargets(input, options = {}) {
|
|
32
31
|
try {
|
|
@@ -262,4 +261,6 @@ const providerError = (cause, operation) => cause instanceof BrowserObservationE
|
|
|
262
261
|
? new BrowserObservationError(operation, cause.reason, { cause })
|
|
263
262
|
: cause instanceof AnalysisError
|
|
264
263
|
? cause
|
|
265
|
-
: new ProviderAdapterError(
|
|
264
|
+
: new ProviderAdapterError(CDP_BROWSER_PROVIDER_IDENTITY.id, operation, {
|
|
265
|
+
cause,
|
|
266
|
+
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import canonicalize from "canonicalize";
|
|
3
|
-
import {
|
|
3
|
+
import { compareUnicodeCodePoints } from "../domain/unicodeCodePointOrder.js";
|
|
4
4
|
import { CdpConnection } from "./CdpConnection.js";
|
|
5
5
|
import { optionalCdpCommand } from "./CdpOptionalCommand.js";
|
|
6
6
|
import { recordValue, recordsValue, cdpStringValue, } from "./CdpCaptureValues.js";
|
|
@@ -16,7 +16,7 @@ export const captureStorageFingerprints = async ({ context, origin, cookieUrl, l
|
|
|
16
16
|
await addCookies(run, cookieUrl);
|
|
17
17
|
await addIndexedDb(run, origin, indexedDbNames);
|
|
18
18
|
await addCaches(run, caches);
|
|
19
|
-
state.items.sort((left, right) =>
|
|
19
|
+
state.items.sort((left, right) => compareUnicodeCodePoints(`${left.scope}:${left.identity_sha256}`, `${right.scope}:${right.identity_sha256}`));
|
|
20
20
|
const complete = state.complete && state.items.every(({ complete }) => complete);
|
|
21
21
|
return { items: state.items, complete };
|
|
22
22
|
};
|
|
@@ -282,7 +282,7 @@ const stableValue = (value) => {
|
|
|
282
282
|
return String(value);
|
|
283
283
|
return Object.fromEntries(Object.entries(record)
|
|
284
284
|
.filter(([key]) => key !== "objectId" && key !== "customPreview")
|
|
285
|
-
.sort(([left], [right]) =>
|
|
285
|
+
.sort(([left], [right]) => compareUnicodeCodePoints(left, right))
|
|
286
286
|
.map(([key, item]) => [key, stableValue(item)]));
|
|
287
287
|
};
|
|
288
288
|
const stableValueComplete = (value) => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { digestCanonicalValue } from "../domain/canonicalDigest.js";
|
|
2
2
|
import { BrowserObservationError } from "../domain/browserObservationError.js";
|
|
3
3
|
import { CdpCaptureCompleteness } from "./CdpCaptureCompleteness.js";
|
|
4
4
|
import { delayWithCancellation, numberValue, recordValue, recordsValue, requiredRecord, cdpStringValue, } from "./CdpCaptureValues.js";
|
|
@@ -176,7 +176,7 @@ const captureResources = async (context, completeness) => {
|
|
|
176
176
|
? null
|
|
177
177
|
: Math.max(0, numberValue(resource.contentSize) ?? 0),
|
|
178
178
|
};
|
|
179
|
-
const resourceKey = `electron_resource_${
|
|
179
|
+
const resourceKey = `electron_resource_${digestCanonicalValue(item, "CDP capture")}`;
|
|
180
180
|
if (seen.has(resourceKey))
|
|
181
181
|
continue;
|
|
182
182
|
seen.add(resourceKey);
|
|
@@ -9,11 +9,10 @@ import { closeCdpTargetSession, openCdpTargetSession, } from "./CdpTargetSession
|
|
|
9
9
|
import { inspectCdpElectronPage } from "./CdpElectronInspection.js";
|
|
10
10
|
import { authorizedElectronFile } from "./ElectronFileScope.js";
|
|
11
11
|
import { CDP_ELECTRON_PROVIDER_IDENTITY } from "./providerIdentities.js";
|
|
12
|
-
const IDENTITY = CDP_ELECTRON_PROVIDER_IDENTITY;
|
|
13
12
|
/** Passive Electron provider for local file pages exposed by loopback CDP. */
|
|
14
13
|
export class CdpElectronProvider {
|
|
15
14
|
identity() {
|
|
16
|
-
return
|
|
15
|
+
return CDP_ELECTRON_PROVIDER_IDENTITY;
|
|
17
16
|
}
|
|
18
17
|
async listTargets(input, options = {}) {
|
|
19
18
|
try {
|
|
@@ -106,4 +105,6 @@ const providerError = (cause, operation) => cause instanceof BrowserObservationE
|
|
|
106
105
|
? new BrowserObservationError(operation, cause.reason, { cause })
|
|
107
106
|
: cause instanceof AnalysisError
|
|
108
107
|
? cause
|
|
109
|
-
: new ProviderAdapterError(
|
|
108
|
+
: new ProviderAdapterError(CDP_ELECTRON_PROVIDER_IDENTITY.id, operation, {
|
|
109
|
+
cause,
|
|
110
|
+
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { digestCanonicalValue } from "../domain/canonicalDigest.js";
|
|
2
2
|
import { createWebTextArtifact } from "../domain/webContentArtifact.js";
|
|
3
3
|
import { CdpCaptureCompleteness } from "./CdpCaptureCompleteness.js";
|
|
4
4
|
import { requiredScriptSource } from "./CdpCaptureValues.js";
|
|
@@ -27,7 +27,7 @@ export const captureElectronScripts = async (input) => {
|
|
|
27
27
|
is_module: script.isModule,
|
|
28
28
|
language: script.language,
|
|
29
29
|
};
|
|
30
|
-
const scriptKey = `electron_script_${
|
|
30
|
+
const scriptKey = `electron_script_${digestCanonicalValue(identity, "CDP capture")}`;
|
|
31
31
|
if (seen.has(scriptKey))
|
|
32
32
|
continue;
|
|
33
33
|
seen.add(scriptKey);
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import {
|
|
2
|
+
import { jsonValueSchema } from "../domain/jsonValue.js";
|
|
3
|
+
import { digestCanonicalValue } from "../domain/canonicalDigest.js";
|
|
4
|
+
import { compositeKey } from "../domain/unicodeCodePointOrder.js";
|
|
3
5
|
import { CdpCaptureCompleteness } from "./CdpCaptureCompleteness.js";
|
|
4
6
|
import { BrowserObservationError } from "../domain/browserObservationError.js";
|
|
5
7
|
import { allowedSanitizedUrl, delayWithCancellation, numberValue, recordValue, recordsValue, cdpStringValue, } from "./CdpCaptureValues.js";
|
|
@@ -265,6 +267,10 @@ const normalizeTool = (value, input, frames, completeness) => {
|
|
|
265
267
|
}
|
|
266
268
|
const description = cdpStringValue(value.description) ?? "";
|
|
267
269
|
const annotations = recordValue(value.annotations);
|
|
270
|
+
const declaration = jsonValueSchema.safeParse(value.inputSchema);
|
|
271
|
+
if (!declaration.success)
|
|
272
|
+
completeness.exclude("webmcp_tools", "invalid_protocol_value");
|
|
273
|
+
const schema = declaration.success ? declaration.data : null;
|
|
268
274
|
return {
|
|
269
275
|
tool_key: toolKey(frame.url, frameId, name),
|
|
270
276
|
name,
|
|
@@ -275,7 +281,10 @@ const normalizeTool = (value, input, frames, completeness) => {
|
|
|
275
281
|
declaration_kind: numberValue(value.backendNodeId) === undefined
|
|
276
282
|
? "imperative"
|
|
277
283
|
: "declarative",
|
|
278
|
-
|
|
284
|
+
input_schema: schema,
|
|
285
|
+
input_schema_sha256: declaration.success
|
|
286
|
+
? digestCanonicalValue(schema)
|
|
287
|
+
: null,
|
|
279
288
|
annotations: {
|
|
280
289
|
read_only: booleanOrNull(annotations?.readOnly),
|
|
281
290
|
untrusted_content: booleanOrNull(annotations?.untrustedContent),
|
|
@@ -285,15 +294,6 @@ const normalizeTool = (value, input, frames, completeness) => {
|
|
|
285
294
|
trust: "page-declared-untrusted",
|
|
286
295
|
};
|
|
287
296
|
};
|
|
288
|
-
const schemaShape = (value) => {
|
|
289
|
-
if (recordValue(value) === undefined)
|
|
290
|
-
return null;
|
|
291
|
-
const encoded = JSON.stringify(value);
|
|
292
|
-
const shape = inferJsonShape(encoded);
|
|
293
|
-
if (shape === null)
|
|
294
|
-
throw new BrowserObservationError("inspect_web_page", "protocol_error");
|
|
295
|
-
return shape;
|
|
296
|
-
};
|
|
297
297
|
const registrationSource = (stack, allowedOrigins) => {
|
|
298
298
|
const frame = recordsValue(stack?.callFrames)[0];
|
|
299
299
|
const url = allowedSanitizedUrl(frame?.url, allowedOrigins);
|
|
@@ -327,8 +327,11 @@ const buildWebMcpResult = (options) => {
|
|
|
327
327
|
};
|
|
328
328
|
const toolKey = (frameUrl, frameId, name) =>
|
|
329
329
|
// Registrations without a known admitted frame are excluded above, so the
|
|
330
|
-
// frame ID here always distinguishes owners
|
|
331
|
-
|
|
330
|
+
// frame ID here always distinguishes owners. Composite tuple keeps a NUL
|
|
331
|
+
// inside one field from collapsing two registrations before hashing.
|
|
332
|
+
`webmcp_${createHash("sha256")
|
|
333
|
+
.update(compositeKey([frameUrl, frameId, name]))
|
|
334
|
+
.digest("hex")}`;
|
|
332
335
|
const booleanOrNull = (value) => typeof value === "boolean" ? value : null;
|
|
333
336
|
const integerOrNull = (value) => {
|
|
334
337
|
const number = numberValue(value);
|
|
@@ -135,11 +135,11 @@ const globalCompleteness = (scenario, session, steps) => {
|
|
|
135
135
|
missing.push("events");
|
|
136
136
|
return classifyBrowserScenarioCompleteness(missing, truncated);
|
|
137
137
|
};
|
|
138
|
-
const runScenario = async (
|
|
138
|
+
const runScenario = async (openSession, scenario, options) => {
|
|
139
139
|
if (options.signal?.aborted === true)
|
|
140
140
|
throw new BrowserObservationError(OPERATION, "cancelled");
|
|
141
141
|
const startedAt = Date.now();
|
|
142
|
-
const session = await
|
|
142
|
+
const session = await openSession(scenario, options.signal === undefined ? {} : { signal: options.signal });
|
|
143
143
|
const steps = [];
|
|
144
144
|
let operationOutcome = { ok: true };
|
|
145
145
|
try {
|
|
@@ -225,16 +225,16 @@ const runScenario = async (factory, scenario, options) => {
|
|
|
225
225
|
};
|
|
226
226
|
/** Controlled Playwright/CDP scenario driver with exact process ownership. */
|
|
227
227
|
export class PlaywrightBrowserScenarioProvider {
|
|
228
|
-
|
|
229
|
-
constructor(
|
|
230
|
-
this.
|
|
228
|
+
openSession;
|
|
229
|
+
constructor(openSession) {
|
|
230
|
+
this.openSession = openSession;
|
|
231
231
|
}
|
|
232
232
|
identity() {
|
|
233
233
|
return PLAYWRIGHT_BROWSER_SCENARIO_PROVIDER_IDENTITY;
|
|
234
234
|
}
|
|
235
235
|
async captureScenario(scenario, options = {}) {
|
|
236
236
|
try {
|
|
237
|
-
return ok(await runScenario(this.
|
|
237
|
+
return ok(await runScenario(this.openSession, scenario, options));
|
|
238
238
|
}
|
|
239
239
|
catch (cause) {
|
|
240
240
|
if (cause instanceof AnalysisError)
|