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
|
@@ -75,6 +75,7 @@ const runAnalysis = async (dependencies, path, tool, arguments_, options) => {
|
|
|
75
75
|
const prepared = await prepareSnapshot({
|
|
76
76
|
path,
|
|
77
77
|
snapshotPath,
|
|
78
|
+
signal,
|
|
78
79
|
...(options.formatHint === undefined
|
|
79
80
|
? {}
|
|
80
81
|
: { formatHint: options.formatHint }),
|
|
@@ -144,7 +145,7 @@ const runAnalysis = async (dependencies, path, tool, arguments_, options) => {
|
|
|
144
145
|
if (evidence !== undefined) {
|
|
145
146
|
const recorded = session.recordEvidence(evidence);
|
|
146
147
|
if (!recorded.ok)
|
|
147
|
-
return cliError(recorded.error);
|
|
148
|
+
return cliError(recorded.error.retainPartialObservation(evidence));
|
|
148
149
|
if (isWorkflowEvidenceTool(tool)) {
|
|
149
150
|
const unknowns = recordWorkflowUnknowns({
|
|
150
151
|
name: tool,
|
|
@@ -153,7 +154,7 @@ const runAnalysis = async (dependencies, path, tool, arguments_, options) => {
|
|
|
153
154
|
recordUnknown: (unknown) => session.recordUnknown(unknown),
|
|
154
155
|
});
|
|
155
156
|
if (!unknowns.ok)
|
|
156
|
-
return cliError(unknowns.error);
|
|
157
|
+
return cliError(unknowns.error.retainPartialObservation(evidence));
|
|
157
158
|
}
|
|
158
159
|
}
|
|
159
160
|
if (isWorkflowEvidenceTool(tool) &&
|
|
@@ -165,7 +166,7 @@ const runAnalysis = async (dependencies, path, tool, arguments_, options) => {
|
|
|
165
166
|
if (workflowRecord !== undefined) {
|
|
166
167
|
const recorded = session.recordWorkflowSnapshot(workflowRecord);
|
|
167
168
|
if (!recorded.ok)
|
|
168
|
-
return cliError(recorded.error);
|
|
169
|
+
return cliError(recorded.error.retainPartialObservation(evidence));
|
|
169
170
|
}
|
|
170
171
|
}
|
|
171
172
|
if (tool !== "trace_native_ui_action" &&
|
|
@@ -173,10 +174,10 @@ const runAnalysis = async (dependencies, path, tool, arguments_, options) => {
|
|
|
173
174
|
evidence !== undefined) {
|
|
174
175
|
const snapshot = session.exportAnalysisSnapshot();
|
|
175
176
|
if (!snapshot.ok)
|
|
176
|
-
return cliError(snapshot.error);
|
|
177
|
+
return cliError(snapshot.error.retainPartialObservation(evidence));
|
|
177
178
|
const written = await writeAnalysisSnapshot(snapshot.value, snapshotPath, true);
|
|
178
179
|
if (!written.ok)
|
|
179
|
-
return cliError(written.error);
|
|
180
|
+
return cliError(written.error.retainPartialObservation(evidence));
|
|
180
181
|
}
|
|
181
182
|
return output;
|
|
182
183
|
}, directAnalysisCleanupFailure);
|
|
@@ -266,7 +267,12 @@ const prepareSnapshot = async (options) => {
|
|
|
266
267
|
const loaded = await readAnalysisSnapshot(snapshotPath);
|
|
267
268
|
if (!loaded.ok)
|
|
268
269
|
return loaded;
|
|
269
|
-
const target = await parseBinaryTarget(path,
|
|
270
|
+
const target = await parseBinaryTarget(path, {
|
|
271
|
+
signal: options.signal,
|
|
272
|
+
...(options.formatHint === undefined
|
|
273
|
+
? {}
|
|
274
|
+
: { formatHint: options.formatHint }),
|
|
275
|
+
});
|
|
270
276
|
if (!target.ok)
|
|
271
277
|
return target;
|
|
272
278
|
if (!snapshotMatchesTarget(loaded.value.target, target.value))
|
|
@@ -39,7 +39,6 @@ export const directAnalysisCleanupFailure = (output, error) => {
|
|
|
39
39
|
"execution_failure" in primary.data.details
|
|
40
40
|
? (primary.data.details.execution_failure ?? primary.data.code)
|
|
41
41
|
: primary.data.code,
|
|
42
|
-
primary_error: projection,
|
|
43
42
|
cleanup_error: cleanup,
|
|
44
43
|
},
|
|
45
44
|
};
|
|
@@ -2,7 +2,8 @@ import { projectAnalysisError } from "../domain/analysisErrorProjection.js";
|
|
|
2
2
|
import { jsonObjectSchema } from "../domain/jsonValue.js";
|
|
3
3
|
import { createServerIdentity } from "../serverIdentity.js";
|
|
4
4
|
import { silentLogger } from "../logger.js";
|
|
5
|
-
|
|
5
|
+
/** Read target-free provider status and operation availability. */
|
|
6
|
+
export const runSessionStatus = async (dependencies, logger = silentLogger) => {
|
|
6
7
|
const config = dependencies.readConfiguration();
|
|
7
8
|
if (!config.ok)
|
|
8
9
|
return { error: projectAnalysisError(config.error) };
|
|
@@ -19,7 +20,3 @@ const runSessionStatus = async (dependencies, logger = silentLogger) => {
|
|
|
19
20
|
await session.close();
|
|
20
21
|
}
|
|
21
22
|
};
|
|
22
|
-
/** List binary-session provider candidates and auxiliary operation availability. */
|
|
23
|
-
export const runProviderStatus = (dependencies, logger = silentLogger) => runSessionStatus(dependencies, logger);
|
|
24
|
-
/** List binary-session operation descriptors; this is not the full MCP catalog. */
|
|
25
|
-
export const runCapabilityStatus = (dependencies, logger = silentLogger) => runSessionStatus(dependencies, logger);
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { constants } from "node:fs";
|
|
2
|
-
import { access,
|
|
2
|
+
import { access, readdir } from "node:fs/promises";
|
|
3
3
|
import { homeDirectoryFromEnvironment } from "../config/homeDirectory.js";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { analysisErrorRemediationAction } from "../domain/analysisErrorPresentation.js";
|
|
6
|
+
import { BinaryTargetError } from "../domain/configurationErrors.js";
|
|
6
7
|
import { parseBinaryTarget } from "./BinaryTargetResolver.js";
|
|
7
8
|
import { execFileOutput } from "../process/ExecFileOutput.js";
|
|
8
9
|
import { installedCaskAppdir, probeHomebrew } from "./homebrew.js";
|
|
9
10
|
import { linuxHopperBinarySupported, linuxSharedLibrariesAvailable, readLinuxDistribution, } from "./LinuxHopper.js";
|
|
10
|
-
import {
|
|
11
|
+
import { claudeCodeSkillsDirectory, readInstalledSkillIdentity, } from "./SetupSkill.js";
|
|
11
12
|
import { CATALOG_IDENTITY } from "../catalogIdentity.js";
|
|
12
13
|
import { PRODUCT_IDENTITY, SDK_IDENTITY } from "../identity.js";
|
|
13
14
|
import { readClientRegistrationStatuses, } from "./ClientRegistrationStatus.js";
|
|
@@ -21,8 +22,9 @@ export const DOCTOR_PROVIDER_IDS = ["hopper", "ghidra", "ida"];
|
|
|
21
22
|
* or an agent consuming the structured result.
|
|
22
23
|
*/
|
|
23
24
|
export const runDoctor = async (target, host = systemDoctorHost(), requestedScope) => {
|
|
25
|
+
const scope = normalizeDoctorScope(requestedScope, target);
|
|
24
26
|
const { checks: diagnosticChecks, hopperPath, providerInspections, } = await collectDoctorDiagnostics(target, host);
|
|
25
|
-
const identity = await collectDoctorIdentity(host);
|
|
27
|
+
const identity = await collectDoctorIdentity(host, scope);
|
|
26
28
|
const checks = [...diagnosticChecks, ...identity.checks];
|
|
27
29
|
const providers = {
|
|
28
30
|
hopperAvailable: hopperPath !== undefined &&
|
|
@@ -33,7 +35,6 @@ export const runDoctor = async (target, host = systemDoctorHost(), requestedScop
|
|
|
33
35
|
providerInspections,
|
|
34
36
|
};
|
|
35
37
|
const environmentHealthy = doctorHealthy(checks, providers);
|
|
36
|
-
const scope = normalizeDoctorScope(requestedScope, target);
|
|
37
38
|
const scoped = scopeDoctorChecks({
|
|
38
39
|
checks,
|
|
39
40
|
registrations: identity.value.registrations,
|
|
@@ -53,11 +54,14 @@ export const runDoctor = async (target, host = systemDoctorHost(), requestedScop
|
|
|
53
54
|
identity: identity.value,
|
|
54
55
|
};
|
|
55
56
|
};
|
|
56
|
-
const collectDoctorIdentity = async (host) => {
|
|
57
|
+
const collectDoctorIdentity = async (host, scope) => {
|
|
57
58
|
const installationPaths = (await host.installationPaths?.()) ?? [];
|
|
58
|
-
const installedSkillIdentity = await host.installedSkillIdentity?.();
|
|
59
|
-
const skillAligned = skillIdentityAligned(installedSkillIdentity);
|
|
60
59
|
const registrations = (await host.clientRegistrations?.()) ?? [];
|
|
60
|
+
const skillClientIds = scope.mode === "audit-wide"
|
|
61
|
+
? registrations.map(({ client }) => client)
|
|
62
|
+
: scope.clients;
|
|
63
|
+
const installedSkillIdentity = await host.installedSkillIdentity?.(skillClientIds);
|
|
64
|
+
const skillAligned = skillIdentityAligned(installedSkillIdentity);
|
|
61
65
|
return {
|
|
62
66
|
checks: [
|
|
63
67
|
...(skillAligned ? [] : [skillIdentityCheck(installedSkillIdentity)]),
|
|
@@ -81,7 +85,6 @@ const collectDoctorIdentity = async (host) => {
|
|
|
81
85
|
skill: {
|
|
82
86
|
installed_version: installedSkillIdentity?.version ?? null,
|
|
83
87
|
installed_tool_count: installedSkillIdentity?.toolCount ?? null,
|
|
84
|
-
installed_catalog_digest: installedSkillIdentity?.catalogDigest ?? null,
|
|
85
88
|
state: installedSkillIdentity === undefined
|
|
86
89
|
? "missing"
|
|
87
90
|
: skillAligned
|
|
@@ -137,10 +140,16 @@ export const systemDoctorHost = (options = {}) => {
|
|
|
137
140
|
macosVersion: () => readMacosVersion(hostExecFileOutput, commandEnvironment),
|
|
138
141
|
linuxDistribution: readLinuxDistribution,
|
|
139
142
|
async validTarget(path) {
|
|
140
|
-
return (await parseBinaryTarget(path,
|
|
143
|
+
return (await parseBinaryTarget(path, {
|
|
144
|
+
cwd: process.cwd(),
|
|
145
|
+
hostArchitecture: architecture,
|
|
146
|
+
})).ok;
|
|
141
147
|
},
|
|
142
148
|
async inspectTarget(path) {
|
|
143
|
-
const result = await parseBinaryTarget(path,
|
|
149
|
+
const result = await parseBinaryTarget(path, {
|
|
150
|
+
cwd: process.cwd(),
|
|
151
|
+
hostArchitecture: architecture,
|
|
152
|
+
});
|
|
144
153
|
if (result.ok)
|
|
145
154
|
return {
|
|
146
155
|
name: "target",
|
|
@@ -149,18 +158,19 @@ export const systemDoctorHost = (options = {}) => {
|
|
|
149
158
|
detail: path,
|
|
150
159
|
};
|
|
151
160
|
const error = result.error;
|
|
161
|
+
const targetError = error instanceof BinaryTargetError ? error : undefined;
|
|
152
162
|
return {
|
|
153
163
|
name: "target",
|
|
154
164
|
ok: false,
|
|
155
|
-
classification:
|
|
165
|
+
classification: targetError?.constraint === "directory_requires_file"
|
|
156
166
|
? "unsupported_target"
|
|
157
167
|
: "config_drift",
|
|
158
168
|
detail: path,
|
|
159
169
|
details: {
|
|
160
|
-
reason: error.
|
|
161
|
-
...(
|
|
170
|
+
reason: targetError?.reason ?? error.message,
|
|
171
|
+
...(targetError?.constraint === undefined
|
|
162
172
|
? {}
|
|
163
|
-
: { constraint:
|
|
173
|
+
: { constraint: targetError.constraint }),
|
|
164
174
|
},
|
|
165
175
|
remediation: analysisErrorRemediationAction(error),
|
|
166
176
|
};
|
|
@@ -218,7 +228,7 @@ export const systemDoctorHost = (options = {}) => {
|
|
|
218
228
|
return [];
|
|
219
229
|
}
|
|
220
230
|
},
|
|
221
|
-
installedSkillIdentity: () =>
|
|
231
|
+
installedSkillIdentity: (clientIds) => readInstalledSkillIdentity(homeDirectory, clientIds, claudeCodeSkillsDirectory(homeDirectory, environment)),
|
|
222
232
|
clientRegistrations: () => readClientRegistrationStatuses(homeDirectory, undefined, {
|
|
223
233
|
platform,
|
|
224
234
|
environment,
|
|
@@ -272,25 +282,6 @@ const manualHopperPaths = async (home) => {
|
|
|
272
282
|
}
|
|
273
283
|
return paths;
|
|
274
284
|
};
|
|
275
|
-
const readInstalledSkill = (home) => readFile(join(home, ".agents/skills", PRODUCT_IDENTITY.skillName, "SKILL.md"), "utf8");
|
|
276
|
-
const installedSkillIdentity = async (home) => {
|
|
277
|
-
try {
|
|
278
|
-
const content = await readInstalledSkill(home);
|
|
279
|
-
const countText = /^\s{2}tool_count:\s*(\d+)\s*$/mu.exec(content)?.[1];
|
|
280
|
-
return {
|
|
281
|
-
canonical: !(await canonicalSkillNeedsInstall(home)),
|
|
282
|
-
version: /^\s{2}version:\s*"([^"]+)"\s*$/mu.exec(content)?.[1] ?? null,
|
|
283
|
-
toolCount: countText === undefined ? null : Number.parseInt(countText, 10),
|
|
284
|
-
catalogDigest: /^\s{2}catalog_digest:\s*"([a-f0-9]{64})"\s*$/mu.exec(content)?.[1] ??
|
|
285
|
-
null,
|
|
286
|
-
};
|
|
287
|
-
}
|
|
288
|
-
catch (cause) {
|
|
289
|
-
// best-effort cleanup: optional skill probing; failure means unknown.
|
|
290
|
-
void cause;
|
|
291
|
-
return undefined;
|
|
292
|
-
}
|
|
293
|
-
};
|
|
294
285
|
const uniqueLines = (value) => [
|
|
295
286
|
...new Set(value
|
|
296
287
|
.split(/\r?\n/u)
|
|
@@ -65,7 +65,7 @@ const hostCheck = async (host) => {
|
|
|
65
65
|
? `${host.platform} ${host.architecture}`
|
|
66
66
|
: `${linuxDistribution.id} ${linuxDistribution.versionId ?? "unknown"}`);
|
|
67
67
|
return check("host", supported, detail, {
|
|
68
|
-
remediation: "REA supports macOS 12+, Ubuntu 24.04+, Fedora 41+, 64-bit Arch Linux, CachyOS, and the experimental Windows x64 Ghidra P0 boundary.",
|
|
68
|
+
remediation: "REA supports macOS 12+, Ubuntu 24.04+, Fedora 41+, Nobara 44+, 64-bit Arch Linux, CachyOS, and the experimental Windows x64 Ghidra P0 boundary.",
|
|
69
69
|
classification: "unsupported_host",
|
|
70
70
|
});
|
|
71
71
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { describeEvidenceBundleFailure, describeValidationFailure, parseEvidenceBundle, } from "../domain/evidenceBundle.js";
|
|
2
2
|
import { EvidenceFileError, EvidenceIntegrityError, } from "../domain/evidenceErrors.js";
|
|
3
3
|
import { err, ok } from "../domain/result.js";
|
|
4
|
-
import { AnalysisCancelledError } from "../domain/analysisErrorCore.js";
|
|
4
|
+
import { AnalysisCancelledError, } from "../domain/analysisErrorCore.js";
|
|
5
5
|
import { parseProcessCapture } from "../domain/process/processCaptureParsing.js";
|
|
6
6
|
import { bufferedJsonParts, canonicalJsonParts, } from "../domain/jsonSerialization.js";
|
|
7
7
|
import { readJsonFile, writeTextParts } from "./JsonFiles.js";
|
|
@@ -13,17 +13,17 @@ export const workflowAnalysisProfile = (upstream, operation) => createAnalysisPr
|
|
|
13
13
|
: {}),
|
|
14
14
|
});
|
|
15
15
|
/** Provider identity for deterministic artifact inventories. */
|
|
16
|
-
export const ARTIFACT_GRAPH_PROVIDER = {
|
|
16
|
+
export const ARTIFACT_GRAPH_PROVIDER = Object.freeze({
|
|
17
17
|
id: "rea-artifact-graph",
|
|
18
18
|
name: "REA safe artifact graph provider",
|
|
19
19
|
version: "1",
|
|
20
|
-
};
|
|
20
|
+
});
|
|
21
21
|
/** Provider identity for execution-free managed PE/CLI analysis. */
|
|
22
|
-
export const MANAGED_STATIC_PROVIDER = {
|
|
22
|
+
export const MANAGED_STATIC_PROVIDER = Object.freeze({
|
|
23
23
|
id: "rea-dotnet-static",
|
|
24
24
|
name: "REA managed static analysis provider",
|
|
25
25
|
version: "1",
|
|
26
|
-
};
|
|
26
|
+
});
|
|
27
27
|
/** Provider identity for deterministic managed-code comparison workflows. */
|
|
28
28
|
export const MANAGED_WORKFLOW_PROVIDER = {
|
|
29
29
|
id: "rea-dotnet-workflows",
|
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
import { link, lstat, mkdtemp, open,
|
|
1
|
+
import { link, lstat, mkdtemp, open, realpath, rename, rm, } from "node:fs/promises";
|
|
2
2
|
import { basename, dirname, resolve } from "node:path";
|
|
3
3
|
import { EvidenceFileError } from "../domain/evidenceErrors.js";
|
|
4
|
-
import { AnalysisCancelledError } from "../domain/analysisErrorCore.js";
|
|
4
|
+
import { AnalysisCancelledError, AnalysisResourceConstraintError, } from "../domain/analysisErrorCore.js";
|
|
5
5
|
import { err, ok } from "../domain/result.js";
|
|
6
|
+
import { parseUtf8Json } from "./Utf8JsonInput.js";
|
|
7
|
+
import { readRegularFile } from "./RegularFileRead.js";
|
|
8
|
+
import { NonRegularFileReadError } from "../filesystem/RegularFile.js";
|
|
6
9
|
/** Read JSON data from a regular file at the caller-supplied path. */
|
|
7
10
|
export const readJsonFile = async (path) => {
|
|
8
11
|
const requestedPath = resolve(path);
|
|
9
12
|
try {
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
if (!
|
|
13
|
-
return err(new EvidenceFileError("read", "not-file", { path: requestedPath }));
|
|
14
|
-
const encoded = await readFile(canonicalPath);
|
|
15
|
-
let decoded;
|
|
16
|
-
try {
|
|
17
|
-
decoded = JSON.parse(new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(encoded));
|
|
18
|
-
}
|
|
19
|
-
catch (cause) {
|
|
13
|
+
const encoded = await readRegularFile(requestedPath);
|
|
14
|
+
const decoded = parseUtf8Json(encoded, "read_evidence_file", requestedPath);
|
|
15
|
+
if (!decoded.ok) {
|
|
20
16
|
return err(new EvidenceFileError("read", "invalid-json", {
|
|
21
|
-
cause,
|
|
17
|
+
cause: decoded.cause,
|
|
22
18
|
path: requestedPath,
|
|
23
19
|
}));
|
|
24
20
|
}
|
|
25
|
-
return ok(decoded);
|
|
21
|
+
return ok(decoded.value);
|
|
26
22
|
}
|
|
27
23
|
catch (cause) {
|
|
28
|
-
|
|
24
|
+
if (cause instanceof AnalysisResourceConstraintError)
|
|
25
|
+
return err(cause);
|
|
26
|
+
return err(new EvidenceFileError("read", cause instanceof NonRegularFileReadError
|
|
27
|
+
? "not-file"
|
|
28
|
+
: missingOrIo(cause), {
|
|
29
29
|
cause,
|
|
30
30
|
path: requestedPath,
|
|
31
31
|
}));
|
|
@@ -63,7 +63,8 @@ export const parseLinuxDistribution = (text) => {
|
|
|
63
63
|
(id === "arch" ||
|
|
64
64
|
id === "cachyos" ||
|
|
65
65
|
(id === "ubuntu" && versionAtLeast(versionId, 24)) ||
|
|
66
|
-
(id === "fedora" && versionAtLeast(versionId, 41))
|
|
66
|
+
(id === "fedora" && versionAtLeast(versionId, 41)) ||
|
|
67
|
+
(id === "nobara" && versionAtLeast(versionId, 44)));
|
|
67
68
|
const identity = {
|
|
68
69
|
id,
|
|
69
70
|
...(versionId === undefined ? {} : { versionId }),
|
|
@@ -2,6 +2,7 @@ import { createHash } from "node:crypto";
|
|
|
2
2
|
import canonicalize from "canonicalize";
|
|
3
3
|
import { parseEvidenceBundle, } from "../domain/evidenceBundle.js";
|
|
4
4
|
import { parseProcessCapture } from "../domain/process/processCaptureParsing.js";
|
|
5
|
+
import { resolveJavaScriptSemanticEvidence } from "../domain/javascript/javascriptSemanticGraph.js";
|
|
5
6
|
import { parseApplicationGraphEvidence } from "./javascript/JavaScriptApplicationEvidenceGraph.js";
|
|
6
7
|
import { applicationObligationPolicy, semanticObligationPolicy, } from "./ReconstructionObligationPolicies.js";
|
|
7
8
|
/** Derive conservative candidates from graph, process, and reviewed inputs. */
|
|
@@ -29,7 +30,12 @@ const deriveApplicationCandidates = (evidence, records, candidates, limitations)
|
|
|
29
30
|
].includes(evidence.operation))
|
|
30
31
|
return;
|
|
31
32
|
try {
|
|
32
|
-
const
|
|
33
|
+
const parsed = parseApplicationGraphEvidence(evidence);
|
|
34
|
+
if (!parsed.ok) {
|
|
35
|
+
limitations.add(`Application Evidence ${evidence.evidence_id} could not generate candidates because it failed graph validation.`);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const source = parsed.value;
|
|
33
39
|
for (const node of source.graph.nodes) {
|
|
34
40
|
const candidatePolicy = applicationObligationPolicy(node.kind);
|
|
35
41
|
if (candidatePolicy === undefined) {
|
|
@@ -54,6 +60,7 @@ const deriveApplicationCandidates = (evidence, records, candidates, limitations)
|
|
|
54
60
|
const candidatePolicy = semanticObligationPolicy(node.kind);
|
|
55
61
|
if (candidatePolicy === undefined)
|
|
56
62
|
continue;
|
|
63
|
+
const evidenceContext = resolveJavaScriptSemanticEvidence(source.semanticGraph, node.evidence);
|
|
57
64
|
addCandidate(candidates, generatedCandidate({
|
|
58
65
|
key: `semantic:${node.node_id}:${candidatePolicy.family}`,
|
|
59
66
|
title: node.label ?? `${node.kind} semantic boundary`,
|
|
@@ -63,7 +70,7 @@ const deriveApplicationCandidates = (evidence, records, candidates, limitations)
|
|
|
63
70
|
semanticNodeId: node.node_id,
|
|
64
71
|
location: `semantic-graph:${source.semanticGraph.graph_id}/nodes/${node.node_id}`,
|
|
65
72
|
authorityReferences: [
|
|
66
|
-
graphReference(evidence, records,
|
|
73
|
+
graphReference(evidence, records, evidenceContext, `${source.semanticGraph.graph_id}/node/${node.node_id}`),
|
|
67
74
|
],
|
|
68
75
|
}));
|
|
69
76
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import canonicalize from "canonicalize";
|
|
3
|
+
import { canonicalJson } from "../domain/comparisonSemantics.js";
|
|
4
|
+
import { compareUnicodeCodePoints } from "../domain/unicodeCodePointOrder.js";
|
|
3
5
|
export const obligationLedgerCoverage = (incomplete) => ({
|
|
4
6
|
status: incomplete ? "partial" : "complete",
|
|
5
7
|
});
|
|
@@ -64,7 +66,7 @@ export const obligationLedgerStatus = (obligations) => {
|
|
|
64
66
|
return "unknown";
|
|
65
67
|
return requiredOpen.length === 0 ? "ready" : "open";
|
|
66
68
|
};
|
|
67
|
-
export const obligationEdgeOrder = (left, right) =>
|
|
69
|
+
export const obligationEdgeOrder = (left, right) => compareUnicodeCodePoints(canonicalJson(left), canonicalJson(right));
|
|
68
70
|
export const digestObligationLedgerValue = (value) => {
|
|
69
71
|
const encoded = canonicalize(value);
|
|
70
72
|
if (encoded === undefined)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { openRegularFile } from "../filesystem/RegularFile.js";
|
|
2
|
+
/** Admit one regular-file handle, retain it through the consumer, and always close it. */
|
|
3
|
+
export const withRegularFile = async (path, read, signal) => {
|
|
4
|
+
const handle = await openRegularFile(path, { symlinks: "follow", signal });
|
|
5
|
+
try {
|
|
6
|
+
const stats = await handle.stat();
|
|
7
|
+
signal?.throwIfAborted();
|
|
8
|
+
const value = await read(handle, stats);
|
|
9
|
+
signal?.throwIfAborted();
|
|
10
|
+
return value;
|
|
11
|
+
}
|
|
12
|
+
finally {
|
|
13
|
+
await handle.close();
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
/** Admit a regular file without waiting for a pipe, then read its verified handle. */
|
|
17
|
+
export const readRegularFile = (path, signal) => withRegularFile(path, (handle) => handle.readFile({ signal }), signal);
|
|
@@ -34,18 +34,27 @@ export const runSetup = async (options, host = systemSetupHost(), confirm) => {
|
|
|
34
34
|
: (options.clientIds ??
|
|
35
35
|
options.readinessScope?.clients ??
|
|
36
36
|
discovery.defaultClientIds);
|
|
37
|
+
let skillNeedsInstall = await host.skillNeedsInstall(selectedClientIds);
|
|
37
38
|
let skillSelected = options.installSkill === true ||
|
|
38
39
|
(options.installSkill !== false && selectedClientIds.length > 0);
|
|
39
|
-
let installSkill = skillSelected &&
|
|
40
|
+
let installSkill = skillSelected && skillNeedsInstall;
|
|
40
41
|
let planDiscovery = discovery;
|
|
41
42
|
if (interactiveSelection) {
|
|
42
|
-
const
|
|
43
|
+
const selectionSkillClientIds = [
|
|
44
|
+
...new Set([
|
|
45
|
+
...discovery.defaultClientIds,
|
|
46
|
+
...discovery.detectedClientIds,
|
|
47
|
+
]),
|
|
48
|
+
];
|
|
49
|
+
const selectionSkillNeedsInstall = await host.skillNeedsInstall(selectionSkillClientIds);
|
|
50
|
+
const offerSkillAction = options.installSkill !== false && selectionSkillNeedsInstall;
|
|
43
51
|
const selectionActions = await planSetupActions({
|
|
44
52
|
discovery,
|
|
45
53
|
host,
|
|
46
54
|
providerEnvironment,
|
|
47
55
|
command: host.registrationCommand,
|
|
48
56
|
clientIds: [],
|
|
57
|
+
skillClientIds: selectionSkillClientIds,
|
|
49
58
|
installSkill: offerSkillAction,
|
|
50
59
|
});
|
|
51
60
|
const decision = await confirm(selectionActions.plannedActions, {
|
|
@@ -67,6 +76,7 @@ export const runSetup = async (options, host = systemSetupHost(), confirm) => {
|
|
|
67
76
|
selectedClientIds = [...selectedActionIds]
|
|
68
77
|
.filter((id) => id.startsWith("configure_client:"))
|
|
69
78
|
.map((id) => id.slice("configure_client:".length));
|
|
79
|
+
skillNeedsInstall = await host.skillNeedsInstall(selectedClientIds);
|
|
70
80
|
const proposedInstallAction = selectionActions.plannedActions.some(({ id }) => id === "install_hopper");
|
|
71
81
|
planDiscovery = {
|
|
72
82
|
...discovery,
|
|
@@ -78,7 +88,7 @@ export const runSetup = async (options, host = systemSetupHost(), confirm) => {
|
|
|
78
88
|
(selectedActionIds.has("install_skill") &&
|
|
79
89
|
selectedClientIds.length === 0) ||
|
|
80
90
|
(options.installSkill !== false && selectedClientIds.length > 0);
|
|
81
|
-
installSkill = skillSelected &&
|
|
91
|
+
installSkill = skillSelected && skillNeedsInstall;
|
|
82
92
|
}
|
|
83
93
|
const planned = await planSetupActions({
|
|
84
94
|
discovery: planDiscovery,
|
|
@@ -86,6 +96,7 @@ export const runSetup = async (options, host = systemSetupHost(), confirm) => {
|
|
|
86
96
|
providerEnvironment,
|
|
87
97
|
command: host.registrationCommand,
|
|
88
98
|
clientIds: selectedClientIds,
|
|
99
|
+
skillClientIds: selectedClientIds,
|
|
89
100
|
installSkill,
|
|
90
101
|
});
|
|
91
102
|
plannedActions = planned.plannedActions;
|
|
@@ -177,8 +188,8 @@ export const runSetup = async (options, host = systemSetupHost(), confirm) => {
|
|
|
177
188
|
if (clientFailure !== undefined)
|
|
178
189
|
return fail(clientFailure);
|
|
179
190
|
if (planSelection.installSkill &&
|
|
180
|
-
!(await installSkillAction(host, options, appliedActions)))
|
|
181
|
-
return fail("REA analysis skill could not be installed or verified. Check permissions for
|
|
191
|
+
!(await installSkillAction(host, options, appliedActions, selectedClientIds)))
|
|
192
|
+
return fail("REA analysis skill could not be installed or verified. Check permissions for its planned skill directories, then rerun setup.");
|
|
182
193
|
const doctor = summarizeDoctor(await host.doctor(readinessScope));
|
|
183
194
|
const remediation = combineRemediation(finalSetupRemediation(host.platform, appliedActions.includes("installed_hopper"), doctor.healthy, hopperPath), manualRemediation);
|
|
184
195
|
return {
|
|
@@ -236,14 +247,14 @@ const installHopperAction = async (input) => {
|
|
|
236
247
|
selectedClients: await filterClientsNeedingConfigure(input.host, input.selectedClients, providerEnvironment, input.host.registrationCommand),
|
|
237
248
|
};
|
|
238
249
|
};
|
|
239
|
-
const installSkillAction = async (host, options, appliedActions) => {
|
|
250
|
+
const installSkillAction = async (host, options, appliedActions, skillClientIds) => {
|
|
240
251
|
const label = "REA reverse-engineering skill";
|
|
241
252
|
emitProgress(options, {
|
|
242
253
|
actionId: "install_skill",
|
|
243
254
|
label,
|
|
244
255
|
state: "started",
|
|
245
256
|
});
|
|
246
|
-
const skill = await host.installSkill();
|
|
257
|
+
const skill = await host.installSkill(skillClientIds);
|
|
247
258
|
if (skill === "failed") {
|
|
248
259
|
emitProgress(options, {
|
|
249
260
|
actionId: "install_skill",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { clientRegistrationEntry, clientConfigurationValuesEqual,
|
|
1
|
+
import { clientRegistrationEntry, clientConfigurationValuesEqual, clientServerListedDisabled, clientServerPath, legacyClientServerPath, OMP_DISABLED_SERVERS_KEY, parseClientConfiguration, serializeClientConfiguration, withClientServers, } from "./ClientConfigurationDocument.js";
|
|
2
2
|
import { constants as fsConstants } from "node:fs";
|
|
3
3
|
import { copyFile, mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
4
4
|
import { dirname } from "node:path";
|
|
@@ -7,9 +7,8 @@ import { PRODUCT_IDENTITY } from "../identity.js";
|
|
|
7
7
|
import { npxRegistrationCommand } from "./ClientRegistrationIdentity.js";
|
|
8
8
|
import { MCP_STARTUP_POLICY } from "../mcpStartupPolicy.js";
|
|
9
9
|
import { resolveClientConfigTransactionPath } from "./ClientConfigPath.js";
|
|
10
|
-
const defaultCommand = () => npxRegistrationCommand();
|
|
11
10
|
/** Configure one supported client's native stdio MCP registration shape. */
|
|
12
|
-
export const configureClientConfiguration = (client, environment = {}, command =
|
|
11
|
+
export const configureClientConfiguration = (client, environment = {}, command = npxRegistrationCommand()) => {
|
|
13
12
|
if (client.format === undefined || client.format === "unsupported")
|
|
14
13
|
return Promise.resolve({ status: "failed", reason: "readback" });
|
|
15
14
|
return configureClientDocument(client, environment, command, client.format);
|
|
@@ -45,12 +44,25 @@ const configureClientDocument = async (client, environment, command, format) =>
|
|
|
45
44
|
// A native OpenCode V2 entry replaces REA's legacy V1 entry, which would
|
|
46
45
|
// otherwise conflict with it.
|
|
47
46
|
const legacyPath = legacyClientServerPath(parsed, PRODUCT_IDENTITY.mcpServerKey);
|
|
48
|
-
const
|
|
47
|
+
const registered = withClientServers(parsed, { ...parsed.servers, [PRODUCT_IDENTITY.mcpServerKey]: desired }, PRODUCT_IDENTITY.mcpServerKey);
|
|
48
|
+
// OMP's denylist would hide the registration; keep every other listed name.
|
|
49
|
+
const ompDisabled = parsed.dialect === "omp"
|
|
50
|
+
? parsed.document[OMP_DISABLED_SERVERS_KEY]
|
|
51
|
+
: undefined;
|
|
52
|
+
const enableOmp = Array.isArray(ompDisabled) &&
|
|
53
|
+
ompDisabled.includes(PRODUCT_IDENTITY.mcpServerKey);
|
|
54
|
+
const document = enableOmp && Array.isArray(ompDisabled)
|
|
55
|
+
? {
|
|
56
|
+
...registered,
|
|
57
|
+
[OMP_DISABLED_SERVERS_KEY]: ompDisabled.filter((name) => name !== PRODUCT_IDENTITY.mcpServerKey),
|
|
58
|
+
}
|
|
59
|
+
: registered;
|
|
49
60
|
try {
|
|
50
61
|
await mkdir(dirname(client.configPath), { recursive: true });
|
|
51
62
|
await writeFileAtomic(transactionPath, serializeClientConfiguration(document, format, original, [
|
|
52
63
|
clientServerPath(parsed, PRODUCT_IDENTITY.mcpServerKey),
|
|
53
64
|
...(legacyPath === undefined ? [] : [legacyPath]),
|
|
65
|
+
...(enableOmp ? [[OMP_DISABLED_SERVERS_KEY]] : []),
|
|
54
66
|
]), {
|
|
55
67
|
encoding: "utf8",
|
|
56
68
|
mode: 0o600,
|
|
@@ -155,11 +167,10 @@ const restoreConfig = async (path, original) => {
|
|
|
155
167
|
void cause;
|
|
156
168
|
}
|
|
157
169
|
};
|
|
158
|
-
/** Whether REA's entry matches, no legacy entry remains, and
|
|
170
|
+
/** Whether REA's entry matches, no legacy entry remains, and no client disable list suppresses it. */
|
|
159
171
|
const registrationCurrent = (parsed, desired) => clientConfigurationValuesEqual(parsed.servers[PRODUCT_IDENTITY.mcpServerKey], desired) &&
|
|
160
172
|
!Object.hasOwn(parsed.legacyServers, PRODUCT_IDENTITY.mcpServerKey) &&
|
|
161
|
-
!(parsed.
|
|
162
|
-
grokServerListedDisabled(parsed.document, PRODUCT_IDENTITY.mcpServerKey));
|
|
173
|
+
!clientServerListedDisabled(parsed, PRODUCT_IDENTITY.mcpServerKey);
|
|
163
174
|
const clientConfigurationDesired = (client, providerEnvironment, command, format) => {
|
|
164
175
|
const environment = Object.fromEntries(Object.entries(providerEnvironment).sort(([left], [right]) => left.localeCompare(right)));
|
|
165
176
|
const registration = clientRegistrationEntry(format ?? "json", command.length === 0 ? [PRODUCT_IDENTITY.cliBinary, "mcp"] : command, environment);
|
|
@@ -7,7 +7,7 @@ import { runDoctor, systemDoctorHost } from "./Doctor.js";
|
|
|
7
7
|
import { installLinuxHopper, readLinuxDistribution, systemLinuxHopperInstallHost, } from "./LinuxHopper.js";
|
|
8
8
|
import { installMacHopper, systemMacHopperInstallHost } from "./MacHopper.js";
|
|
9
9
|
import { supportedClients } from "./SupportedClients.js";
|
|
10
|
-
import { canonicalSkillNeedsInstall, installCanonicalSkill, } from "./SetupSkill.js";
|
|
10
|
+
import { claudeCodeSkillsDirectory as resolveClaudeCodeSkillsDirectory, canonicalSkillNeedsInstall, installCanonicalSkill, } from "./SetupSkill.js";
|
|
11
11
|
import { clientConfigurationAligned, configureClientConfiguration, inspectClientConfiguration, } from "./SetupClientConfiguration.js";
|
|
12
12
|
import { setupInstallFailure } from "./SetupInstallFailure.js";
|
|
13
13
|
import { providerRegistrationEnvironment } from "./SetupRegistrationEnvironment.js";
|
|
@@ -40,16 +40,18 @@ export const hostRemediation = async (host, installHopper) => {
|
|
|
40
40
|
}
|
|
41
41
|
if ((await host.linuxDistribution())?.supported === true)
|
|
42
42
|
return undefined;
|
|
43
|
-
return "Automated Hopper setup supports Ubuntu 24.04+, Fedora 41+, 64-bit Arch Linux, and CachyOS; configure an existing supported provider instead.";
|
|
43
|
+
return "Automated Hopper setup supports Ubuntu 24.04+, Fedora 41+, Nobara 44+, 64-bit Arch Linux, and CachyOS; configure an existing supported provider instead.";
|
|
44
44
|
};
|
|
45
45
|
/** Production setup effects for Hopper, agent configuration, and the canonical skill directory. */
|
|
46
46
|
export const systemSetupHost = (selectedDoctorHost = undefined, environment = process.env) => {
|
|
47
47
|
const doctorHost = selectedDoctorHost ?? systemDoctorHost({ environment });
|
|
48
48
|
const platform = doctorHost.platform;
|
|
49
49
|
const { homeDirectory } = doctorHost;
|
|
50
|
+
const claudeSkillsDirectory = resolveClaudeCodeSkillsDirectory(homeDirectory, environment);
|
|
50
51
|
return {
|
|
51
52
|
platform,
|
|
52
53
|
homeDirectory,
|
|
54
|
+
claudeCodeSkillsDirectory: claudeSkillsDirectory,
|
|
53
55
|
registrationCommand: setupRegistrationCommand(platform, environment.npm_command === "exec"),
|
|
54
56
|
nodeVersion: process.versions.node,
|
|
55
57
|
macosVersion: () => doctorHost.macosVersion(),
|
|
@@ -86,8 +88,8 @@ export const systemSetupHost = (selectedDoctorHost = undefined, environment = pr
|
|
|
86
88
|
? Promise.resolve(false)
|
|
87
89
|
: clientConfigurationAligned(client, providerEnvironment, command).then((aligned) => !aligned),
|
|
88
90
|
inspectClientConfiguration: inspectClientConfiguration,
|
|
89
|
-
skillNeedsInstall: () => canonicalSkillNeedsInstall(homeDirectory),
|
|
90
|
-
installSkill: () => installCanonicalSkill(homeDirectory),
|
|
91
|
+
skillNeedsInstall: (clientIds) => canonicalSkillNeedsInstall(homeDirectory, clientIds, claudeSkillsDirectory),
|
|
92
|
+
installSkill: (clientIds) => installCanonicalSkill(homeDirectory, clientIds, claudeSkillsDirectory),
|
|
91
93
|
doctor: (scope) => runDoctor(undefined, doctorHost, scope),
|
|
92
94
|
};
|
|
93
95
|
};
|