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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
|
-
import { PRODUCT_IDENTITY } from "../identity.js";
|
|
3
2
|
import { isOwnedClientRegistrationCommand } from "./ClientRegistrationIdentity.js";
|
|
4
3
|
import { linuxHopperInstallDisclosure, } from "./LinuxHopper.js";
|
|
4
|
+
import { skillDestinations } from "./SetupSkill.js";
|
|
5
5
|
import { macHopperInstallDisclosure } from "./MacHopper.js";
|
|
6
6
|
/** Discover supported clients and current registrations without mutation. */
|
|
7
7
|
export const discoverSetupState = async (input) => {
|
|
@@ -20,10 +20,9 @@ export const discoverSetupState = async (input) => {
|
|
|
20
20
|
input.proposeHopper &&
|
|
21
21
|
(Object.keys(input.providerEnvironment).length === 0 ||
|
|
22
22
|
linuxHopperRepairNeeded));
|
|
23
|
-
const [clients, detectedClients
|
|
23
|
+
const [clients, detectedClients] = await Promise.all([
|
|
24
24
|
input.host.supportedClients(),
|
|
25
25
|
input.host.detectedClients(),
|
|
26
|
-
input.host.skillNeedsInstall(),
|
|
27
26
|
]);
|
|
28
27
|
const detectedIds = new Set(detectedClients.map(({ name }) => name));
|
|
29
28
|
const registrations = initialDoctor.identity?.registrations ?? [];
|
|
@@ -56,7 +55,6 @@ export const discoverSetupState = async (input) => {
|
|
|
56
55
|
return {
|
|
57
56
|
initialDoctor,
|
|
58
57
|
installHopper,
|
|
59
|
-
skillNeedsInstall,
|
|
60
58
|
clients,
|
|
61
59
|
detectedClientIds: [...detectedIds],
|
|
62
60
|
defaultClientIds,
|
|
@@ -119,6 +117,8 @@ export const planSetupActions = async (input) => {
|
|
|
119
117
|
homeDirectory: input.host.homeDirectory,
|
|
120
118
|
installHopper: input.discovery.installHopper,
|
|
121
119
|
installSkill: input.installSkill,
|
|
120
|
+
skillClientIds: input.skillClientIds,
|
|
121
|
+
claudeCodeSkillsDirectory: input.host.claudeCodeSkillsDirectory,
|
|
122
122
|
clients: clientPlans,
|
|
123
123
|
providerEnvironment: input.providerEnvironment,
|
|
124
124
|
...(input.discovery.linuxPackageFamily === undefined
|
|
@@ -170,17 +170,21 @@ const setupPlan = (input) => [
|
|
|
170
170
|
...(backupPath === undefined ? {} : { backupPath }),
|
|
171
171
|
})),
|
|
172
172
|
...(input.installSkill
|
|
173
|
-
?
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
173
|
+
? skillDestinations(input.homeDirectory, input.skillClientIds, input.claudeCodeSkillsDirectory).map(({ client, path }) => ({
|
|
174
|
+
id: client === "claude_code"
|
|
175
|
+
? "install_skill:claude_code"
|
|
176
|
+
: "install_skill",
|
|
177
|
+
kind: "install_skill",
|
|
178
|
+
label: client === "claude_code"
|
|
179
|
+
? "REA skill for Claude Code"
|
|
180
|
+
: "REA reverse-engineering skill",
|
|
181
|
+
target: path,
|
|
182
|
+
detail: client === "claude_code"
|
|
183
|
+
? "Install or update the REA skill in Claude Code's personal skill directory."
|
|
184
|
+
: "Install or update the bundled REA reverse-engineering skill and on-demand references.",
|
|
185
|
+
external: false,
|
|
186
|
+
operation: "install",
|
|
187
|
+
}))
|
|
184
188
|
: []),
|
|
185
189
|
];
|
|
186
190
|
const linuxDisclosure = (family) => {
|
|
@@ -10,7 +10,33 @@ const SKILL_FILES = [
|
|
|
10
10
|
"references/runtime-observation.md",
|
|
11
11
|
"references/evidence-workflows.md",
|
|
12
12
|
];
|
|
13
|
-
|
|
13
|
+
/** Resolve Claude Code personal skills from the selected environment. */
|
|
14
|
+
export const claudeCodeSkillsDirectory = (home, environment = {}) => join(environment.CLAUDE_CONFIG_DIR ?? join(home, ".claude"), "skills");
|
|
15
|
+
/** Resolve the skill roots required by a client selection, or all owned roots. */
|
|
16
|
+
export const skillDestinations = (home, clientIds, claudeSkillsDirectory = claudeCodeSkillsDirectory(home)) => {
|
|
17
|
+
const includeClaude = clientIds === undefined || clientIds.includes("claude_code");
|
|
18
|
+
const includeShared = clientIds === undefined ||
|
|
19
|
+
clientIds.length === 0 ||
|
|
20
|
+
clientIds.some((clientId) => clientId !== "claude_code");
|
|
21
|
+
return [
|
|
22
|
+
...(includeShared
|
|
23
|
+
? [
|
|
24
|
+
{
|
|
25
|
+
client: "shared",
|
|
26
|
+
path: join(home, ".agents/skills", PRODUCT_IDENTITY.skillName),
|
|
27
|
+
},
|
|
28
|
+
]
|
|
29
|
+
: []),
|
|
30
|
+
...(includeClaude
|
|
31
|
+
? [
|
|
32
|
+
{
|
|
33
|
+
client: "claude_code",
|
|
34
|
+
path: join(claudeSkillsDirectory, PRODUCT_IDENTITY.skillName),
|
|
35
|
+
},
|
|
36
|
+
]
|
|
37
|
+
: []),
|
|
38
|
+
];
|
|
39
|
+
};
|
|
14
40
|
const readOptionalText = async (path) => {
|
|
15
41
|
try {
|
|
16
42
|
return await readFile(path, "utf8");
|
|
@@ -21,18 +47,18 @@ const readOptionalText = async (path) => {
|
|
|
21
47
|
throw cause;
|
|
22
48
|
}
|
|
23
49
|
};
|
|
24
|
-
const canonicalSkillFiles = async (home) => Promise.all(SKILL_FILES.map(async (relativePath) => {
|
|
25
|
-
const destination = join(
|
|
50
|
+
const canonicalSkillFiles = async (home, clientIds, claudeSkillsDirectory) => Promise.all(skillDestinations(home, clientIds, claudeSkillsDirectory).flatMap(({ path: root }) => SKILL_FILES.map(async (relativePath) => {
|
|
51
|
+
const destination = join(root, relativePath);
|
|
26
52
|
return {
|
|
27
53
|
destination,
|
|
28
54
|
content: await readFile(new URL(`../../skills/${PRODUCT_IDENTITY.skillName}/${relativePath}`, import.meta.url), "utf8"),
|
|
29
55
|
original: await readOptionalText(destination),
|
|
30
56
|
};
|
|
31
|
-
}));
|
|
57
|
+
})));
|
|
32
58
|
/** Report whether setup would change any file in the managed REA skill bundle. */
|
|
33
|
-
export const canonicalSkillNeedsInstall = async (home) => {
|
|
59
|
+
export const canonicalSkillNeedsInstall = async (home, clientIds = [], claudeSkillsDirectory) => {
|
|
34
60
|
try {
|
|
35
|
-
return (await canonicalSkillFiles(home)).some(({ content, original }) => original !== content);
|
|
61
|
+
return (await canonicalSkillFiles(home, clientIds, claudeSkillsDirectory)).some(({ content, original }) => original !== content);
|
|
36
62
|
}
|
|
37
63
|
catch (cause) {
|
|
38
64
|
// Unreadable skill state fails open to install so setup can repair it.
|
|
@@ -50,10 +76,10 @@ const restoreSkillFiles = async (changed) => {
|
|
|
50
76
|
}
|
|
51
77
|
};
|
|
52
78
|
/** Transactionally install or upgrade the canonical REA skill and references. */
|
|
53
|
-
export const installCanonicalSkill = async (home) => {
|
|
79
|
+
export const installCanonicalSkill = async (home, clientIds = [], claudeSkillsDirectory) => {
|
|
54
80
|
let changed = [];
|
|
55
81
|
try {
|
|
56
|
-
const canonical = await canonicalSkillFiles(home);
|
|
82
|
+
const canonical = await canonicalSkillFiles(home, clientIds, claudeSkillsDirectory);
|
|
57
83
|
changed = canonical.filter(({ content, original }) => original !== content);
|
|
58
84
|
if (changed.length === 0)
|
|
59
85
|
return "unchanged";
|
|
@@ -82,3 +108,26 @@ export const installCanonicalSkill = async (home) => {
|
|
|
82
108
|
return "failed";
|
|
83
109
|
}
|
|
84
110
|
};
|
|
111
|
+
/** Read installed skill metadata and compare every managed location. */
|
|
112
|
+
export const readInstalledSkillIdentity = async (home, clientIds, claudeSkillsDirectory) => {
|
|
113
|
+
const destinations = skillDestinations(home, clientIds, claudeSkillsDirectory);
|
|
114
|
+
let content;
|
|
115
|
+
for (const destination of destinations) {
|
|
116
|
+
try {
|
|
117
|
+
content = await readFile(join(destination.path, "SKILL.md"), "utf8");
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
// Another selected copy may provide metadata; canonical validation below
|
|
122
|
+
// still marks missing or unreadable copies as stale.
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (content === undefined)
|
|
126
|
+
return undefined;
|
|
127
|
+
const toolCount = /^\s{2}tool_count:\s*(\d+)\s*$/mu.exec(content)?.[1];
|
|
128
|
+
return {
|
|
129
|
+
canonical: !(await canonicalSkillNeedsInstall(home, clientIds, claudeSkillsDirectory)),
|
|
130
|
+
version: /^\s{2}version:\s*"([^"]+)"\s*$/mu.exec(content)?.[1] ?? null,
|
|
131
|
+
toolCount: toolCount === undefined ? null : Number.parseInt(toolCount, 10),
|
|
132
|
+
};
|
|
133
|
+
};
|
|
@@ -34,6 +34,38 @@ export const GROK_BOT_MANUAL_REGISTRATION_REMEDIATION = "Grok Bot keeps connecto
|
|
|
34
34
|
export const manualRegistrationRemediation = (clientName) => clientName === "grok_bot"
|
|
35
35
|
? GROK_BOT_MANUAL_REGISTRATION_REMEDIATION
|
|
36
36
|
: undefined;
|
|
37
|
+
const OMP_PROFILE_NAME = /^[a-z0-9][a-z0-9._-]{0,63}$/u;
|
|
38
|
+
/**
|
|
39
|
+
* OMP's active named profile. OMP_PROFILE wins over the legacy PI_PROFILE even
|
|
40
|
+
* when empty; empty and "default" select the default profile. OMP refuses to
|
|
41
|
+
* start with an invalid name, so one leaves the default location in place.
|
|
42
|
+
*/
|
|
43
|
+
const ompProfile = ({ env }) => {
|
|
44
|
+
const name = (env.OMP_PROFILE ?? env.PI_PROFILE)?.trim();
|
|
45
|
+
return name === undefined ||
|
|
46
|
+
name === "" ||
|
|
47
|
+
name === "default" ||
|
|
48
|
+
name.endsWith(".") ||
|
|
49
|
+
!OMP_PROFILE_NAME.test(name)
|
|
50
|
+
? undefined
|
|
51
|
+
: name;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* The OMP agent directory whose `mcp.json` holds user-scope MCP servers. OMP
|
|
55
|
+
* joins PI_CONFIG_DIR to the home directory, and a named profile ignores
|
|
56
|
+
* PI_CODING_AGENT_DIR. OMP resolves a relative agent directory against each
|
|
57
|
+
* process's working directory, so only an absolute override names one file.
|
|
58
|
+
*/
|
|
59
|
+
const ompAgentDirectory = (context) => {
|
|
60
|
+
const root = join(context.home, context.env.PI_CONFIG_DIR || ".omp");
|
|
61
|
+
const profile = ompProfile(context);
|
|
62
|
+
if (profile !== undefined)
|
|
63
|
+
return join(root, "profiles", profile, "agent");
|
|
64
|
+
const override = context.env.PI_CODING_AGENT_DIR;
|
|
65
|
+
return override !== undefined && override !== "" && isAbsolute(override)
|
|
66
|
+
? override
|
|
67
|
+
: join(root, "agent");
|
|
68
|
+
};
|
|
37
69
|
const copilotDirectory = ({ home, env }) => env.COPILOT_HOME ?? join(home, ".copilot");
|
|
38
70
|
const commandCodeDirectory = ({ home }) => join(home, ".commandcode");
|
|
39
71
|
const opencodeDirectory = ({ home, env }) => join(env.XDG_CONFIG_HOME ?? join(home, ".config"), "opencode");
|
|
@@ -157,6 +189,13 @@ export const SUPPORTED_CLIENT_DEFINITIONS = [
|
|
|
157
189
|
markerPath: grokDirectory,
|
|
158
190
|
format: "grok",
|
|
159
191
|
},
|
|
192
|
+
{
|
|
193
|
+
name: "omp",
|
|
194
|
+
displayName: "OMP",
|
|
195
|
+
configPath: (context) => join(ompAgentDirectory(context), "mcp.json"),
|
|
196
|
+
markerPath: ompAgentDirectory,
|
|
197
|
+
format: "omp",
|
|
198
|
+
},
|
|
160
199
|
{
|
|
161
200
|
name: "grok_bot",
|
|
162
201
|
displayName: "Grok Bot",
|
|
@@ -173,7 +212,11 @@ export const supportedClients = (home, platform = process.platform, env = {
|
|
|
173
212
|
CODEX_HOME: process.env.CODEX_HOME,
|
|
174
213
|
COPILOT_HOME: process.env.COPILOT_HOME,
|
|
175
214
|
GROK_HOME: process.env.GROK_HOME,
|
|
215
|
+
OMP_PROFILE: process.env.OMP_PROFILE,
|
|
176
216
|
OPENCODE_CONFIG: process.env.OPENCODE_CONFIG,
|
|
217
|
+
PI_CODING_AGENT_DIR: process.env.PI_CODING_AGENT_DIR,
|
|
218
|
+
PI_CONFIG_DIR: process.env.PI_CONFIG_DIR,
|
|
219
|
+
PI_PROFILE: process.env.PI_PROFILE,
|
|
177
220
|
SAND_DATA_ROOT: process.env.SAND_DATA_ROOT,
|
|
178
221
|
XDG_CONFIG_HOME: process.env.XDG_CONFIG_HOME,
|
|
179
222
|
}) => {
|
|
@@ -6,6 +6,7 @@ import { join } from "node:path";
|
|
|
6
6
|
import writeFileAtomic from "write-file-atomic";
|
|
7
7
|
import { z } from "zod";
|
|
8
8
|
import { PRODUCT_IDENTITY } from "../identity.js";
|
|
9
|
+
import { claudeCodeSkillsDirectory, skillDestinations } from "./SetupSkill.js";
|
|
9
10
|
import { isOwnedClientRegistrationCommand } from "./ClientRegistrationIdentity.js";
|
|
10
11
|
import { resolveClientConfigTransactionPath } from "./ClientConfigPath.js";
|
|
11
12
|
import { manualRegistrationRemediation, supportedClients, } from "./SupportedClients.js";
|
|
@@ -95,7 +96,7 @@ export const systemUninstallHost = (selectedHome = undefined, fileSystem = syste
|
|
|
95
96
|
: undefined;
|
|
96
97
|
},
|
|
97
98
|
removeClient: (client) => removeClient(client, fileSystem),
|
|
98
|
-
removeSkill: () => removeManagedSkills(home, fileSystem),
|
|
99
|
+
removeSkill: () => removeManagedSkills(home, fileSystem, environment),
|
|
99
100
|
purgeData: async () => [
|
|
100
101
|
await removeManagedPath(join(home, ".rea/cache"), "cache", fileSystem),
|
|
101
102
|
await removeManagedPath(join(home, ".rea/state"), "state", fileSystem),
|
|
@@ -224,7 +225,22 @@ const removeManagedPath = async (path, name, fileSystem) => {
|
|
|
224
225
|
: item(name, "failed", "This item could not be removed. Check file permissions, then rerun uninstall.");
|
|
225
226
|
}
|
|
226
227
|
};
|
|
227
|
-
const removeManagedSkills = async (home, fileSystem
|
|
228
|
+
const removeManagedSkills = async (home, fileSystem, environment) => {
|
|
229
|
+
const results = await Promise.all(skillDestinations(home, undefined, claudeCodeSkillsDirectory(home, environment)).map(({ client, path }) => removeManagedPath(path, client === "claude_code" ? "Claude Code skill" : "skill", fileSystem)));
|
|
230
|
+
const failed = results.find(({ status }) => status === "failed");
|
|
231
|
+
if (failed !== undefined)
|
|
232
|
+
return item("skill", "failed", results
|
|
233
|
+
.map(({ name, status, detail }) => `${name}: ${status} (${detail})`)
|
|
234
|
+
.join(" "));
|
|
235
|
+
const status = results.some(({ status: resultStatus }) => resultStatus === "removed")
|
|
236
|
+
? "removed"
|
|
237
|
+
: results.some(({ status: resultStatus }) => resultStatus === "retained")
|
|
238
|
+
? "retained"
|
|
239
|
+
: "skipped";
|
|
240
|
+
return item("skill", status, results
|
|
241
|
+
.map(({ name, status: resultStatus, detail }) => `${name}: ${resultStatus} (${detail})`)
|
|
242
|
+
.join(" "));
|
|
243
|
+
};
|
|
228
244
|
const item = (name, status, detail) => ({ name, status, detail });
|
|
229
245
|
const registrationSchema = z
|
|
230
246
|
.object({ command: z.string(), args: z.array(z.string()) })
|
|
@@ -4,7 +4,7 @@ import { z } from "zod";
|
|
|
4
4
|
import { PRODUCT_IDENTITY } from "../identity.js";
|
|
5
5
|
import { isOwnedClientRegistrationCommand } from "./ClientRegistrationIdentity.js";
|
|
6
6
|
import { readClientRegistrationStatuses } from "./ClientRegistrationStatus.js";
|
|
7
|
-
import { effectiveClientServer, parseClientConfiguration, } from "./ClientConfigurationDocument.js";
|
|
7
|
+
import { clientServerForcedEnabled, clientServerListedDisabled, effectiveClientServer, parseClientConfiguration, } from "./ClientConfigurationDocument.js";
|
|
8
8
|
import { supportedClients } from "./SupportedClients.js";
|
|
9
9
|
const setupPlanSchema = z.object({
|
|
10
10
|
status: z.literal("planned"),
|
|
@@ -41,7 +41,11 @@ export const existingMaintenanceScope = async (home, entryPoint, environment) =>
|
|
|
41
41
|
disabled: z.boolean().optional(),
|
|
42
42
|
})
|
|
43
43
|
.parse(effectiveClientServer(parsed, PRODUCT_IDENTITY.mcpServerKey));
|
|
44
|
-
|
|
44
|
+
// Root disable lists override enabled entries and OMP's force-on allowlist.
|
|
45
|
+
if ((enabled.enabled !== false ||
|
|
46
|
+
clientServerForcedEnabled(parsed, PRODUCT_IDENTITY.mcpServerKey)) &&
|
|
47
|
+
enabled.disabled !== true &&
|
|
48
|
+
!clientServerListedDisabled(parsed, PRODUCT_IDENTITY.mcpServerKey))
|
|
45
49
|
clients.push(client.name);
|
|
46
50
|
}
|
|
47
51
|
let skill = false;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { constants } from "node:buffer";
|
|
2
|
+
import { AnalysisResourceConstraintError } from "../domain/analysisErrorCore.js";
|
|
3
|
+
import { safeParseJson } from "../domain/safeJson.js";
|
|
4
|
+
/** Recovery that preserves complete, authenticated Evidence workflow inputs. */
|
|
5
|
+
export const JSON_INPUT_RESOURCE_REMEDIATION = "Provide a smaller valid JSON value. For Evidence workflows, re-analyze a smaller selection of the original target and use its complete Evidence; splitting JSON text or trimming Evidence fields does not produce valid workflow input.";
|
|
6
|
+
/** Decode JSON bytes without confusing a runtime string limit with malformed input. */
|
|
7
|
+
export const parseUtf8Json = (bytes, operation, path, boundary = "json-input") => {
|
|
8
|
+
const stringLimitFailure = (cause, decodedUnits) => new AnalysisResourceConstraintError(operation, "memory", "JSON input exceeds the runtime's maximum decoded string length", {
|
|
9
|
+
boundary,
|
|
10
|
+
input_path: path,
|
|
11
|
+
input_bytes: bytes.byteLength,
|
|
12
|
+
max_string_code_units: constants.MAX_STRING_LENGTH,
|
|
13
|
+
...(decodedUnits === undefined
|
|
14
|
+
? {}
|
|
15
|
+
: { decoded_string_code_units_at_least: decodedUnits }),
|
|
16
|
+
}, {
|
|
17
|
+
...(cause === undefined ? {} : { cause }),
|
|
18
|
+
remediationAction: JSON_INPUT_RESOURCE_REMEDIATION,
|
|
19
|
+
});
|
|
20
|
+
let text;
|
|
21
|
+
try {
|
|
22
|
+
const decoder = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true });
|
|
23
|
+
if (bytes.byteLength <= constants.MAX_STRING_LENGTH) {
|
|
24
|
+
text = decoder.decode(bytes);
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
// Node 22's UTF-8 fast path bounds encoded bytes before decoding. Decode
|
|
28
|
+
// large inputs in chunks so valid multibyte text is bounded by its actual
|
|
29
|
+
// UTF-16 length. Streaming also preserves characters spanning chunks.
|
|
30
|
+
const parts = [];
|
|
31
|
+
let decodedUnits = 0;
|
|
32
|
+
const append = (part) => {
|
|
33
|
+
decodedUnits += part.length;
|
|
34
|
+
if (decodedUnits > constants.MAX_STRING_LENGTH)
|
|
35
|
+
throw stringLimitFailure(undefined, decodedUnits);
|
|
36
|
+
parts.push(part);
|
|
37
|
+
};
|
|
38
|
+
const chunkBytes = 1024 * 1024;
|
|
39
|
+
for (let offset = 0; offset < bytes.byteLength; offset += chunkBytes)
|
|
40
|
+
append(decoder.decode(bytes.subarray(offset, offset + chunkBytes), {
|
|
41
|
+
stream: true,
|
|
42
|
+
}));
|
|
43
|
+
append(decoder.decode());
|
|
44
|
+
text = parts.join("");
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch (cause) {
|
|
48
|
+
if (cause instanceof AnalysisResourceConstraintError)
|
|
49
|
+
throw cause;
|
|
50
|
+
const code = typeof cause === "object" && cause !== null && "code" in cause
|
|
51
|
+
? cause.code
|
|
52
|
+
: undefined;
|
|
53
|
+
if (code === "ERR_STRING_TOO_LONG")
|
|
54
|
+
throw stringLimitFailure(cause);
|
|
55
|
+
if (code !== "ERR_ENCODING_INVALID_ENCODED_DATA")
|
|
56
|
+
throw cause;
|
|
57
|
+
return {
|
|
58
|
+
ok: false,
|
|
59
|
+
error: "JSON input is not valid UTF-8",
|
|
60
|
+
cause,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
return safeParseJson(text);
|
|
64
|
+
};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import { readFile } from "node:fs/promises";
|
|
3
2
|
import { isAbsolute } from "node:path";
|
|
4
3
|
import { z } from "zod";
|
|
5
4
|
import { ArtifactReaderFailure } from "../artifacts/ArtifactReader.js";
|
|
@@ -15,6 +14,8 @@ import { safeParseJson } from "../domain/safeJson.js";
|
|
|
15
14
|
import { exportWebScriptsInputSchema, } from "../domain/webScriptExport.js";
|
|
16
15
|
import { WebScriptExportError } from "../domain/webScriptExportError.js";
|
|
17
16
|
import { WEB_SCRIPT_EXPORT_PROVIDER as PROVIDER } from "./InvestigationProviders.js";
|
|
17
|
+
import { readRegularFile } from "./RegularFileRead.js";
|
|
18
|
+
import { NonRegularFileReadError } from "../filesystem/RegularFile.js";
|
|
18
19
|
const OPERATION = "export_web_scripts";
|
|
19
20
|
/** Export one local capture through the shared CLI/MCP application workflow. */
|
|
20
21
|
export const exportWebScripts = async (rawInput, options = {}) => {
|
|
@@ -97,20 +98,26 @@ export const exportWebScriptsValidated = async (input, options = {}) => {
|
|
|
97
98
|
*/
|
|
98
99
|
const readCapture = async (path, signal) => {
|
|
99
100
|
try {
|
|
100
|
-
return ok(await
|
|
101
|
+
return ok(await readRegularFile(path, signal));
|
|
101
102
|
}
|
|
102
103
|
catch (cause) {
|
|
103
104
|
const code = cause instanceof Error && "code" in cause ? String(cause.code) : "";
|
|
104
105
|
if (code === "EACCES" || code === "EPERM")
|
|
105
106
|
return err(new AnalysisAccessDeniedError(OPERATION, path, code, { cause }));
|
|
106
|
-
if (
|
|
107
|
+
if (cause instanceof NonRegularFileReadError ||
|
|
108
|
+
code === "ENOENT" ||
|
|
109
|
+
code === "ENOTDIR" ||
|
|
110
|
+
code === "EISDIR" ||
|
|
111
|
+
code === "ENXIO")
|
|
107
112
|
return err(new AnalysisInputError(OPERATION, { cause }, [
|
|
108
113
|
{
|
|
109
114
|
path: ["capture_path"],
|
|
110
115
|
reason: "invalid_value",
|
|
111
|
-
message: code
|
|
112
|
-
?
|
|
113
|
-
:
|
|
116
|
+
message: cause instanceof NonRegularFileReadError && code !== "EISDIR"
|
|
117
|
+
? cause.message
|
|
118
|
+
: code === "EISDIR"
|
|
119
|
+
? `Selected capture is a directory, not a file: ${path}`
|
|
120
|
+
: `Selected capture could not be read (${code}): ${path}`,
|
|
114
121
|
},
|
|
115
122
|
]));
|
|
116
123
|
throw cause;
|
|
@@ -17,7 +17,7 @@ export class AndroidAnalysisService {
|
|
|
17
17
|
const request = androidRequestSchema.safeParse({ operation, input });
|
|
18
18
|
if (!request.success)
|
|
19
19
|
return err(new AnalysisInputError(operation, { cause: request.error }));
|
|
20
|
-
const target = await parseBinaryTarget(request.data.input.path);
|
|
20
|
+
const target = await parseBinaryTarget(request.data.input.path, options?.signal === undefined ? {} : { signal: options.signal });
|
|
21
21
|
if (!target.ok)
|
|
22
22
|
return target;
|
|
23
23
|
const executed = await this.provider.execute(target.value, request.data, options);
|
|
@@ -4,6 +4,7 @@ import {} from "../../domain/analysisErrorBase.js";
|
|
|
4
4
|
import { err, ok } from "../../domain/result.js";
|
|
5
5
|
import { analysisQueryId, createAnalysisSnapshotEntry, createAnalysisSnapshotWorkflowEntry, snapshotBinding, snapshotMatchesProfile, snapshotMatchesTarget, snapshotTarget, parseAnalysisSnapshot, } from "../../domain/analysisSnapshot.js";
|
|
6
6
|
import { OFFICIAL_TOOL_CONTRACTS } from "../../contracts/officialToolContracts.js";
|
|
7
|
+
import { compareUnicodeCodePoints } from "../../domain/unicodeCodePointOrder.js";
|
|
7
8
|
const STATEFUL_OPERATIONS = new Set([
|
|
8
9
|
"health",
|
|
9
10
|
"current_address",
|
|
@@ -87,8 +88,8 @@ export class AnalysisSnapshotCache {
|
|
|
87
88
|
try {
|
|
88
89
|
const snapshotTargetIdentity = snapshotTarget(target);
|
|
89
90
|
const binding = snapshotBinding(profile);
|
|
90
|
-
const entries = [...this.#entries.values()].sort((left, right) => left.query_id
|
|
91
|
-
const workflows = [...this.#workflowEntries.values()].sort((left, right) => left.query_id
|
|
91
|
+
const entries = [...this.#entries.values()].sort((left, right) => compareUnicodeCodePoints(left.query_id, right.query_id));
|
|
92
|
+
const workflows = [...this.#workflowEntries.values()].sort((left, right) => compareUnicodeCodePoints(left.query_id, right.query_id));
|
|
92
93
|
// Parsing owns the returned JSON and metadata; pre-cloning the same
|
|
93
94
|
// payloads here only adds another full materialization.
|
|
94
95
|
return ok(parseAnalysisSnapshot({
|
|
@@ -126,13 +127,13 @@ export class AnalysisSnapshotCache {
|
|
|
126
127
|
/** Return canonical entries for persistence. */
|
|
127
128
|
entries() {
|
|
128
129
|
return [...this.#entries.values()]
|
|
129
|
-
.sort((left, right) => left.query_id
|
|
130
|
+
.sort((left, right) => compareUnicodeCodePoints(left.query_id, right.query_id))
|
|
130
131
|
.map((entry) => structuredClone(entry));
|
|
131
132
|
}
|
|
132
133
|
/** Return canonical composed-workflow entries for persistence. */
|
|
133
134
|
workflowEntries() {
|
|
134
135
|
return [...this.#workflowEntries.values()]
|
|
135
|
-
.sort((left, right) => left.query_id
|
|
136
|
+
.sort((left, right) => compareUnicodeCodePoints(left.query_id, right.query_id))
|
|
136
137
|
.map((entry) => structuredClone(entry));
|
|
137
138
|
}
|
|
138
139
|
/** Record one exact derived workflow result unless the shared cache is full. */
|
|
@@ -314,6 +314,22 @@ export class BinarySession extends BinarySessionRecords {
|
|
|
314
314
|
this.#calls.set(call, generation);
|
|
315
315
|
return call.finally(() => this.#calls.delete(call));
|
|
316
316
|
}
|
|
317
|
+
/** Admit one composed request until its result and session bookkeeping settle. */
|
|
318
|
+
withAdmittedAnalysis(operationName, signal, operation) {
|
|
319
|
+
const generation = this.#transitionGeneration;
|
|
320
|
+
const transition = this.#transition;
|
|
321
|
+
const call = (async () => {
|
|
322
|
+
const admission = await this.#waitForTransition(operationName, signal, transition);
|
|
323
|
+
if (!admission.ok)
|
|
324
|
+
return admission;
|
|
325
|
+
return ok(await operation({
|
|
326
|
+
execute: (name, arguments_, options) => this.#execute(name, arguments_, options, Promise.resolve()),
|
|
327
|
+
}));
|
|
328
|
+
})();
|
|
329
|
+
// Register synchronously before a lifecycle transition can snapshot calls.
|
|
330
|
+
this.#calls.set(call, generation);
|
|
331
|
+
return call.finally(() => this.#calls.delete(call));
|
|
332
|
+
}
|
|
317
333
|
async #execute(name, arguments_, options, transition) {
|
|
318
334
|
const transitioned = await this.#waitForTransition(name, options?.signal, transition);
|
|
319
335
|
if (!transitioned.ok)
|
|
@@ -8,7 +8,15 @@ import { SessionProviderRouter } from "./SessionProviderRouter.js";
|
|
|
8
8
|
/** Parse a target, resolve its provider route, and validate snapshot binding. */
|
|
9
9
|
export const resolveSessionOpen = async (input) => {
|
|
10
10
|
const { path, options } = input;
|
|
11
|
-
const parsed = await parseBinaryTarget(path,
|
|
11
|
+
const parsed = await parseBinaryTarget(path, {
|
|
12
|
+
...(options.targetKind === undefined
|
|
13
|
+
? {}
|
|
14
|
+
: { targetKind: options.targetKind }),
|
|
15
|
+
...(options.formatHint === undefined
|
|
16
|
+
? {}
|
|
17
|
+
: { formatHint: options.formatHint }),
|
|
18
|
+
...(options.signal === undefined ? {} : { signal: options.signal }),
|
|
19
|
+
});
|
|
12
20
|
if (!parsed.ok)
|
|
13
21
|
return parsed;
|
|
14
22
|
return resolveSessionTarget({ ...input, target: parsed.value });
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { digestCanonicalValue } from "../../domain/canonicalDigest.js";
|
|
2
2
|
import { createEvidence } from "../../domain/evidence.js";
|
|
3
3
|
import { jsonObjectSchema, jsonValueSchema } from "../../domain/jsonValue.js";
|
|
4
4
|
/** Commit the selected Electron experiment and its observed result. */
|
|
@@ -24,6 +24,6 @@ const parameters = (input) => {
|
|
|
24
24
|
const scenario = jsonObjectSchema.parse(input);
|
|
25
25
|
return {
|
|
26
26
|
...scenario,
|
|
27
|
-
scenario_sha256:
|
|
27
|
+
scenario_sha256: digestCanonicalValue(scenario, "Electron scenario"),
|
|
28
28
|
};
|
|
29
29
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { compareUnicodeCodePoints } from "../../domain/unicodeCodePointOrder.js";
|
|
2
2
|
import { resolveArtifactPathByContext } from "./JavaScriptArtifactPathResolution.js";
|
|
3
3
|
/** Flatten all per-file IPC facts into deterministic application records. */
|
|
4
4
|
export const collectElectronIpcRecords = (analysis) => analysis.files
|
|
@@ -7,7 +7,7 @@ export const collectElectronIpcRecords = (analysis) => analysis.files
|
|
|
7
7
|
file,
|
|
8
8
|
finding,
|
|
9
9
|
})))
|
|
10
|
-
.sort((left, right) =>
|
|
10
|
+
.sort((left, right) => compareUnicodeCodePoints(left.key, right.key));
|
|
11
11
|
/** Match only exact literal channels and retain ambiguous matches separately. */
|
|
12
12
|
export const classifyElectronIpcPairings = (records) => {
|
|
13
13
|
const handlers = records.filter(isMainHandler);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { javascriptAnalysisCoverage, resolveArtifactPath, } from "./JavaScriptArtifactGraphContext.js";
|
|
2
2
|
import { astObservationEvidence } from "./JavaScriptArtifactGraphEvidence.js";
|
|
3
|
+
import { compositeKey } from "../../domain/unicodeCodePointOrder.js";
|
|
3
4
|
import { addElectronInferenceEdge, electronFindingSourceNode, electronObservationIdentity, electronRangeKey, } from "./ElectronBoundaryGraphContext.js";
|
|
4
5
|
/** Project JavaScript-requested native addon binding and re-export surfaces. */
|
|
5
6
|
export const addElectronNativeBoundaries = (context) => {
|
|
@@ -21,7 +22,10 @@ const addNativeBinding = (input) => {
|
|
|
21
22
|
const addon = resolved === null ? undefined : context.fileNodes.get(resolved);
|
|
22
23
|
const binding = context.accumulator.addNode({
|
|
23
24
|
kind: "native-export",
|
|
24
|
-
identity: electronObservationIdentity(context, "javascript-requested-native-export",
|
|
25
|
+
identity: electronObservationIdentity(context, "javascript-requested-native-export",
|
|
26
|
+
// Members are a variable-length source-derived list: compositeKey keeps
|
|
27
|
+
// ["a\0b"] distinct from ["a", "b"] inside the digested identity.
|
|
28
|
+
`${file.path}:${value.specifier}:${value.binding_kind}:${compositeKey(value.members)}:${electronRangeKey(value.location)}`),
|
|
25
29
|
observations: [
|
|
26
30
|
{
|
|
27
31
|
label: value.members.join(", "),
|