rea-agents 6.0.0 → 6.1.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 +23 -17
- package/bridge/android/ReaJadxBridge.java +14 -5
- package/bridge/ghidra/ReaGhidraBridge.java +173 -47
- package/bridge/hopper_bridge.py +310 -128
- package/bridge/mitmproxy/capture.py +0 -2
- package/bridge/native/rea_lldb_tracer.py +630 -94
- package/bridge/process/ProcessRunTokenReader.swift +39 -5
- package/bridge/pwntools/recorded_crash_impl.py +4 -0
- package/dist/android/JadxConfiguration.js +196 -33
- package/dist/android/JadxMcpTransport.js +4 -0
- package/dist/android/JadxProtocol.js +6 -0
- package/dist/android/JadxProvider.js +19 -2
- package/dist/android/JadxSession.js +23 -4
- package/dist/application/AnalysisContextQueries.js +8 -35
- package/dist/application/AnalysisDocument.js +32 -0
- package/dist/application/AppBundleExecutable.js +67 -21
- package/dist/application/CallPathTracing.js +19 -3
- package/dist/application/CapabilityInventory.js +6 -3
- package/dist/application/ClientConfigurationDocument.js +871 -6
- package/dist/application/ClientRegistrationIdentity.js +26 -5
- package/dist/application/ClientRegistrationStatus.js +29 -14
- package/dist/application/DirectAnalysis.js +27 -37
- package/dist/application/Doctor.js +4 -2
- package/dist/application/DoctorScope.js +25 -13
- package/dist/application/EnhancedLiteralTracing.js +22 -25
- package/dist/application/EnhancedTools.js +13 -11
- package/dist/application/EvidenceBundleFiles.js +23 -11
- package/dist/application/FunctionAnalysisEvidence.js +2 -3
- package/dist/application/InventoryProjectionEvidence.js +4 -3
- package/dist/application/InvestigationProviders.js +3 -2
- package/dist/application/JsonFiles.js +50 -28
- package/dist/application/ProcedureAddressResolution.js +11 -0
- package/dist/application/ReconstructionCoverageService.js +7 -4
- package/dist/application/ReconstructionObligationLedgerService.js +4 -3
- package/dist/application/Setup.js +13 -1
- package/dist/application/SetupClientConfiguration.js +10 -15
- package/dist/application/SetupHost.js +5 -2
- package/dist/application/SetupPlan.js +5 -3
- package/dist/application/SupportedClients.js +34 -1
- package/dist/application/Uninstall.js +4 -3
- package/dist/application/Update.js +18 -3
- package/dist/application/UpdateRuntime.js +46 -25
- package/dist/application/WebModuleTraceService.js +4 -2
- package/dist/application/WebNetworkCaptureService.js +4 -2
- package/dist/application/WebRuntimeService.js +5 -3
- package/dist/application/WebScriptExportService.js +2 -2
- package/dist/application/WebSourceLocationService.js +4 -2
- package/dist/application/WorkflowEvidence.js +82 -0
- package/dist/application/binary/AnalysisProviderEvaluation.js +21 -5
- package/dist/application/binary/AnalysisProviderRegistry.js +2 -0
- package/dist/application/binary/AnalysisSnapshotCache.js +3 -6
- package/dist/application/binary/BinarySession.js +95 -68
- package/dist/application/binary/BinarySessionOpen.js +3 -3
- package/dist/application/binary/BinarySessionRecords.js +25 -3
- package/dist/application/binary/BinarySessionStatus.js +17 -1
- package/dist/application/binary/CompositeProvider.js +13 -0
- package/dist/application/binary/LazyAnalysisProvider.js +3 -0
- package/dist/application/binaryDiagnostics/BinaryLayoutService.js +4 -2
- package/dist/application/binaryDiagnostics/RecordedCrashService.js +4 -2
- package/dist/application/evm/EvmInterfaceService.js +4 -2
- package/dist/application/investigation/EvidenceLedger.js +21 -7
- package/dist/application/investigation/InvestigationRecords.js +8 -0
- package/dist/application/javascript/JavaScriptAnalysisControl.js +34 -0
- package/dist/application/javascript/JavaScriptApplicationEvidence.js +24 -3
- package/dist/application/javascript/JavaScriptApplicationEvidenceGraph.js +19 -2
- package/dist/application/javascript/JavaScriptApplicationService.js +22 -15
- package/dist/application/javascript/JavaScriptApplicationWorkflowService.js +5 -5
- package/dist/application/javascript/JavaScriptArtifactAnalysis.js +5 -4
- package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +39 -7
- package/dist/application/javascript/JavaScriptArtifactPathResolution.js +6 -3
- package/dist/application/javascript/JavaScriptArtifactReconstruction.js +11 -3
- package/dist/application/javascript/JavaScriptModuleRelationships.js +37 -8
- package/dist/application/javascript/JavaScriptRecoveryService.js +4 -2
- package/dist/application/javascript/JavaScriptRuntimeObservationService.js +3 -1
- package/dist/application/javascript/JavaScriptRuntimeReconciliationService.js +3 -3
- package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +63 -61
- package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +23 -1
- package/dist/application/managed/ManagedApplicationGraphService.js +4 -3
- package/dist/application/managed/ManagedMemberComparisonService.js +7 -4
- package/dist/application/managed/ManagedNativeVerificationService.js +4 -3
- package/dist/application/managed/ManagedReconstructionService.js +4 -3
- package/dist/application/process/ProcessCli.js +14 -6
- package/dist/application/process/ProcessEvidence.js +4 -3
- package/dist/application/workflowInputError.js +18 -0
- package/dist/artifacts/ArtifactProvider.js +12 -2
- package/dist/artifacts/MachOSliceArtifactReader.js +98 -14
- package/dist/artifacts/NativeDmgArtifactReader.js +13 -6
- package/dist/artifacts/apple/AppleAssetCatalogAnalysis.js +22 -3
- package/dist/artifacts/apple/InterfaceBuilderAnalysis.js +176 -56
- package/dist/artifacts/apple/InterfaceBuilderDecodeBudget.js +195 -0
- package/dist/artifacts/apple/KeyedArchiveReader.js +36 -22
- package/dist/artifacts/apple/MachoLoadCommandReader.js +92 -31
- package/dist/artifacts/apple/NibArchive.js +81 -14
- package/dist/artifacts/apple/NibViewHierarchy.js +10 -3
- package/dist/artifacts/apple/PlistNumberLiterals.js +164 -0
- package/dist/artifacts/inventory/ArtifactGraphConstruction.js +13 -8
- package/dist/artifacts/inventory/scanCanonical.js +11 -14
- package/dist/artifacts/javascript/JavaScriptArtifactFiles.js +6 -2
- package/dist/browser/CdpCaptureCompleteness.js +2 -0
- package/dist/browser/CdpCaptureEventHandlers.js +76 -11
- package/dist/browser/CdpCaptureEventTypes.js +5 -1
- package/dist/browser/CdpCaptureEvents.js +25 -0
- package/dist/browser/CdpConnection.js +30 -11
- package/dist/browser/CdpOptionalCommand.js +2 -3
- package/dist/browser/CdpPageCapture.js +23 -1
- package/dist/browser/PlaywrightElectronActiveActions.js +32 -23
- package/dist/browser/PlaywrightElectronActiveProjection.js +141 -0
- package/dist/browser/PlaywrightElectronActiveProvider.js +123 -124
- package/dist/browser/WebSourceMapFetcher.js +426 -72
- package/dist/browser/assets/LocalWebScriptArtifacts.js +2 -2
- package/dist/browser/history/CaptureFailures.js +37 -1
- package/dist/browser/history/CaptureRelease.js +5 -0
- package/dist/browser/history/HarCaptureAdapter.js +3 -3
- package/dist/browser/history/HarJson.js +3 -2
- package/dist/browser/history/HistoricalCaptureDecoder.js +4 -2
- package/dist/cli/analysisSelector.js +23 -0
- package/dist/cli/applicationCommands.js +2 -3
- package/dist/cli/coreBinaryCommands.js +70 -12
- package/dist/cli/electronCommands.js +7 -6
- package/dist/cli/javascriptApplicationAnalysis.js +7 -3
- package/dist/cli/jsonOutput.js +4 -99
- package/dist/cli/nativeCallCommands.js +2 -3
- package/dist/cli/webRuntimeCommands.js +8 -8
- package/dist/cli.js +2 -1
- package/dist/cliCommandNames.js +0 -1
- package/dist/cliJsonInput.js +9 -4
- package/dist/config/environment.js +4 -0
- package/dist/config/ghidraStartupTimeout.js +17 -0
- package/dist/config/mcpResponseBudget.js +22 -0
- package/dist/config/parseConfig.js +2 -1
- package/dist/contracts/enhancedInputs.js +5 -3
- package/dist/contracts/enhancedToolContracts.js +3 -3
- package/dist/contracts/hopperMemoryContracts.js +2 -5
- package/dist/contracts/javascript/electronToolContracts.js +1 -1
- package/dist/contracts/managed/managedToolContracts.js +2 -4
- package/dist/contracts/native/nativeToolContracts.js +4 -2
- package/dist/contracts/officialToolContracts.js +14 -15
- package/dist/contracts/promptContracts.js +3 -3
- package/dist/contracts/sessionLifecycleInputs.js +3 -7
- package/dist/contracts/sessionStatusContract.js +2 -4
- package/dist/contracts/sessionToolContracts.js +4 -6
- package/dist/contracts/sessionToolSchemas.js +2 -5
- package/dist/contracts/toolContractExamples.js +0 -1
- package/dist/contracts/toolContractHelpers.js +4 -1
- package/dist/contracts/toolEffects.js +0 -1
- package/dist/contracts/toolOutputSchemaGroups.js +28 -27
- package/dist/contracts/toolOutputSchemaPrimitives.js +18 -0
- package/dist/contracts/toolSchemaMetadata.js +69 -10
- package/dist/contracts/webNetworkCaptureToolContracts.js +1 -1
- package/dist/domain/analysisErrorBase.js +8 -3
- package/dist/domain/analysisErrorCore.js +3 -1
- package/dist/domain/analysisErrorPresentation.js +72 -17
- package/dist/domain/analysisErrorProjection.js +106 -27
- package/dist/domain/android/androidAnalysis.js +2 -4
- package/dist/domain/android/androidApplication.js +17 -9
- package/dist/domain/apple/appleApplication.js +41 -14
- package/dist/domain/apple/dyldEnvironment.js +73 -0
- package/dist/domain/apple/dylibResolution.js +120 -9
- package/dist/domain/apple/dylibResolutionFindings.js +9 -7
- package/dist/domain/apple/interfaceBuilderGraph.js +25 -13
- package/dist/domain/apple/interfaceBuilderKeyedArchive.js +13 -3
- package/dist/domain/apple/keyedArchive.js +9 -1
- package/dist/domain/apple/machoContainer.js +54 -0
- package/dist/domain/apple/plistNumbers.js +76 -0
- package/dist/domain/artifactIdentity.js +29 -0
- package/dist/domain/artifactInventoryEvidence.js +19 -24
- package/dist/domain/bridgeCandidateProjection.js +71 -0
- package/dist/domain/browserCompleteness.js +1 -0
- package/dist/domain/browserObservationError.js +24 -5
- package/dist/domain/browserScenarioValues.js +2 -6
- package/dist/domain/bundleComparison.js +3 -2
- package/dist/domain/canonicalJsonDigestSteps.js +133 -0
- package/dist/domain/canonicalOrdering.js +9 -5
- package/dist/domain/changedBehavior.js +6 -6
- package/dist/domain/comparisonSourceEvidence.js +40 -0
- package/dist/domain/configurationErrors.js +1 -1
- package/dist/domain/evidence.js +64 -9
- package/dist/domain/evidenceBundle.js +42 -1
- package/dist/domain/evidenceErrors.js +12 -1
- package/dist/domain/explicitSensitiveFailure.js +17 -1
- package/dist/domain/firmware/firmwareAnalysis.js +6 -7
- package/dist/domain/hopperErrors.js +23 -2
- package/dist/domain/hopperValues.js +51 -8
- package/dist/domain/immutableJson.js +114 -0
- package/dist/domain/inputIssueProjection.js +3 -0
- package/dist/domain/javascript/electronActiveObservation.js +30 -4
- package/dist/domain/javascript/electronStaticAnalysisValues.js +6 -12
- package/dist/domain/javascript/javascriptApplicationAnalysis.js +71 -23
- package/dist/domain/javascript/javascriptApplicationGraph.js +13 -0
- package/dist/domain/javascript/javascriptAstValues.js +20 -0
- package/dist/domain/javascript/javascriptRecovery.js +3 -8
- package/dist/domain/javascript/javascriptSemanticAnalysis.js +97 -2
- package/dist/domain/javascript/javascriptSemanticCoverage.js +6 -5
- package/dist/domain/javascript/javascriptSemanticDataEffectHelpers.js +9 -17
- package/dist/domain/javascript/javascriptSemanticDataEffects.js +22 -5
- package/dist/domain/javascript/javascriptSemanticGraph.js +13 -0
- package/dist/domain/javascript/javascriptSemanticGraphSchemas.js +1 -0
- package/dist/domain/javascript/javascriptSemanticPrimitives.js +25 -17
- package/dist/domain/javascript/javascriptSemanticQuerySchemas.js +8 -4
- package/dist/domain/javascript/javascriptSemanticResourceLimits.js +77 -0
- package/dist/domain/javascript/javascriptSemanticValues.js +83 -11
- package/dist/domain/javascript/javascriptSourceParser.js +6 -2
- package/dist/domain/javascript/javascriptStaticAnalysis.js +22 -17
- package/dist/domain/javascript/javascriptStaticAnalysisBundler.js +5 -3
- package/dist/domain/javascript/javascriptStaticAnalysisCalls.js +14 -4
- package/dist/domain/javascript/javascriptStaticAnalysisFindings.js +66 -7
- package/dist/domain/javascript/javascriptStaticAnalysisHelpers.js +28 -16
- package/dist/domain/javascript/javascriptStaticAnalysisState.js +3 -2
- package/dist/domain/jsonSerialization.js +109 -0
- package/dist/domain/jsonValue.js +90 -6
- package/dist/domain/localPath.js +6 -0
- package/dist/domain/managed/managedApplicationGraph.js +10 -10
- package/dist/domain/managed/managedInspectionEvidence.js +16 -0
- package/dist/domain/managed/managedMemberComparisonMatch.js +5 -9
- package/dist/domain/managed/managedNativeVerification.js +3 -9
- package/dist/domain/native/fileOffsetPartialObservation.js +1 -0
- package/dist/domain/native/nativeCallObservation.js +33 -11
- package/dist/domain/native/nativeCallPartialObservation.js +33 -0
- package/dist/domain/process/processCapture.js +8 -4
- package/dist/domain/process/processComparison.js +38 -4
- package/dist/domain/process/processScenario.js +11 -10
- package/dist/domain/propertyListKeys.js +1 -1
- package/dist/domain/propertyListXmlText.js +19 -0
- package/dist/domain/providerAdapterError.js +1 -1
- package/dist/domain/providerOperationHealth.js +54 -0
- package/dist/domain/reconstructionVerification.js +6 -43
- package/dist/domain/reconstructionVerificationSchemas.js +2 -2
- package/dist/domain/staticRuntimeCorrelation.js +6 -43
- package/dist/domain/webBundleAnalysis.js +20 -8
- package/dist/domain/webBundleAnalyzerInspection.js +13 -8
- package/dist/domain/webBundleAnalyzerResult.js +41 -2
- package/dist/domain/webRuntime.js +19 -5
- package/dist/domain/webSourceLocation.js +1 -0
- package/dist/firmware/FirmwareFiles.js +1 -1
- package/dist/generatedPackageMetadata.js +1 -1
- package/dist/ghidra/GhidraAnalysisProfile.js +5 -0
- package/dist/ghidra/GhidraClient.js +47 -14
- package/dist/ghidra/GhidraDiagnostics.js +7 -7
- package/dist/ghidra/GhidraFunctionValues.js +10 -7
- package/dist/ghidra/GhidraInstallation.js +18 -21
- package/dist/ghidra/GhidraInventoryValues.js +14 -4
- package/dist/ghidra/GhidraJavaLaunch.js +62 -0
- package/dist/ghidra/GhidraLauncher.js +33 -16
- package/dist/ghidra/GhidraProviderCapabilities.js +14 -2
- package/dist/ghidra/GhidraProviderClient.js +23 -12
- package/dist/ghidra/GhidraSessionError.js +11 -7
- package/dist/ghidra/GhidraTargetSnapshot.js +47 -12
- package/dist/ghidra/GhidraTransport.js +20 -0
- package/dist/hopper/BridgeLauncher.js +31 -11
- package/dist/hopper/HopperAnalysisProfile.js +62 -4
- package/dist/hopper/HopperCleanup.js +15 -3
- package/dist/hopper/HopperClient.js +222 -14
- package/dist/hopper/HopperFileOffset.js +237 -0
- package/dist/hopper/HopperMachOImage.js +196 -0
- package/dist/hopper/HopperOperationStage.js +6 -0
- package/dist/hopper/HopperProvider.js +63 -9
- package/dist/hopper/HopperProviderCapabilities.js +19 -1
- package/dist/hopper/HopperRegexSearch.js +137 -0
- package/dist/hopper/HopperRegexWorker.js +27 -0
- package/dist/hopper/HopperRequestQueue.js +68 -19
- package/dist/hopper/HopperTargetLease.js +3 -2
- package/dist/inspector/JavaScriptRuntimeScope.js +9 -1
- package/dist/inspector/V8InspectorCaptureProjection.js +8 -3
- package/dist/inspector/V8InspectorProvider.js +47 -11
- package/dist/javascript/sourceMaps/DecodedSourceMap.js +47 -0
- package/dist/javascript/sourceMaps/SourceMapCommand.js +16 -0
- package/dist/javascript/sourceMaps/SourceMapFormat.js +79 -31
- package/dist/javascript/sourceMaps/TraceSourceMap.js +14 -28
- package/dist/mcpDoctor.js +62 -2
- package/dist/native/AppleDispatchCoverage.js +47 -6
- package/dist/native/AppleDispatchDecodeFacts.js +6 -0
- package/dist/native/AppleDispatchMetadata.js +6 -3
- package/dist/native/AppleMachoFixups.js +48 -24
- package/dist/native/AppleMachoSelection.js +32 -16
- package/dist/native/AppleObjcCategories.js +6 -2
- package/dist/native/AppleObjcDispatchFacets.js +5 -2
- package/dist/native/AppleObjcProperties.js +2 -1
- package/dist/native/AppleSwiftDispatchFacets.js +27 -21
- package/dist/native/AppleSwiftVtables.js +21 -15
- package/dist/native/CommandRunner.js +81 -84
- package/dist/native/LldbCallTracer.js +365 -102
- package/dist/native/LldbRetainedObservations.js +178 -0
- package/dist/native/NativeCallObservation.js +62 -3
- package/dist/native/NativeMacOSProvider.js +98 -17
- package/dist/native/SignatureTargetBinding.js +155 -0
- package/dist/native/parsers/lipo.js +71 -1
- package/dist/native/pwndbg/PwndbgCoreContext.js +25 -5
- package/dist/native/pwntools/RecordedCrashStructureBindings.js +2 -0
- package/dist/process/DarwinProcessRunTokenReader.js +8 -9
- package/dist/process/ExecFileOutput.js +20 -0
- package/dist/process/OwnedCommand.js +7 -2
- package/dist/process/ProcessOwnership.js +203 -53
- package/dist/process/ProcessOwnershipObservation.js +49 -4
- package/dist/process/ProviderProcess.js +38 -7
- package/dist/process/capture/ProcessCaptureError.js +2 -2
- package/dist/process/capture/ProcessCaptureLifecycle.js +100 -34
- package/dist/server/EvidenceMcpServer.js +146 -0
- package/dist/server/createServer.js +15 -8
- package/dist/server/registerAndroidTools.js +2 -4
- package/dist/server/registerApplicationTools/helpers.js +2 -4
- package/dist/server/registerArtifactComparisonTool.js +11 -7
- package/dist/server/registerBinaryDiagnosticsTools.js +2 -4
- package/dist/server/registerBrowserScenarioTool.js +2 -4
- package/dist/server/registerBrowserTools.js +2 -4
- package/dist/server/registerBundleComparisonTool.js +2 -3
- package/dist/server/registerCloseLifecycleTool.js +8 -18
- package/dist/server/registerElectronTools.js +2 -4
- package/dist/server/registerEnhancedTools.js +18 -59
- package/dist/server/registerEvidenceTools.js +2 -4
- package/dist/server/registerEvmTools.js +2 -4
- package/dist/server/registerFirmwareTools.js +2 -4
- package/dist/server/registerFunctionComparisonTool.js +10 -6
- package/dist/server/registerInvestigationTools.js +7 -7
- package/dist/server/registerJavaScriptRecoveryTool.js +2 -4
- package/dist/server/registerJavaScriptRuntimeObservationTools.js +2 -4
- package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +2 -4
- package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +2 -4
- package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +2 -4
- package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +2 -4
- package/dist/server/registerOfficialTools.js +2 -4
- package/dist/server/registerProcessComparisonTool.js +71 -45
- package/dist/server/registerRecordedCrashTools.js +2 -4
- package/dist/server/registerSessionRecordTools.js +5 -6
- package/dist/server/registerSessionStatusTool.js +17 -3
- package/dist/server/registerSessionTools.js +11 -3
- package/dist/server/registerWebModuleTool.js +2 -4
- package/dist/server/registerWebNetworkCaptureTool.js +2 -4
- package/dist/server/registerWebRuntimeTools.js +3 -7
- package/dist/server/registerWebScriptTool.js +2 -4
- package/dist/server/registerWebSourceLocationTool.js +2 -4
- package/dist/server/runDerivedOperation.js +15 -3
- package/dist/server/sessionAvailabilityPolicy.js +0 -1
- package/dist/server/toolRegistrationOptions.js +2 -2
- package/dist/server/toolResult.js +62 -10
- package/dist/server/toolResultEncoding.js +33 -0
- package/install.sh +1 -1
- package/native/windows/build/manifest.json +1 -1
- package/package.json +8 -3
- package/scripts/electron-active-hook-boundaries.cjs +18 -20
- package/scripts/electron-active-hook.cjs +241 -37
- package/skills/reverse-engineer-anything/SKILL.md +11 -3
- package/skills/reverse-engineer-anything/references/javascript-applications.md +8 -1
- package/dist/ghidra/GhidraDefaults.js +0 -2
|
@@ -1,34 +1,41 @@
|
|
|
1
|
-
import { link, lstat, mkdtemp, readFile, realpath, rm } from "node:fs/promises";
|
|
1
|
+
import { link, lstat, mkdtemp, open, readFile, realpath, rename, rm, } from "node:fs/promises";
|
|
2
2
|
import { basename, dirname, resolve } from "node:path";
|
|
3
|
-
import writeFileAtomic from "write-file-atomic";
|
|
4
3
|
import { EvidenceFileError } from "../domain/evidenceErrors.js";
|
|
5
4
|
import { err, ok } from "../domain/result.js";
|
|
6
5
|
/** Read JSON data from a regular file at the caller-supplied path. */
|
|
7
6
|
export const readJsonFile = async (path) => {
|
|
7
|
+
const requestedPath = resolve(path);
|
|
8
8
|
try {
|
|
9
|
-
const canonicalPath = await realpath(
|
|
9
|
+
const canonicalPath = await realpath(requestedPath);
|
|
10
10
|
const stats = await lstat(canonicalPath);
|
|
11
11
|
if (!stats.isFile())
|
|
12
|
-
return err(new EvidenceFileError("read", "not-file"));
|
|
12
|
+
return err(new EvidenceFileError("read", "not-file", { path: requestedPath }));
|
|
13
13
|
const encoded = await readFile(canonicalPath);
|
|
14
14
|
let decoded;
|
|
15
15
|
try {
|
|
16
16
|
decoded = JSON.parse(new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(encoded));
|
|
17
17
|
}
|
|
18
18
|
catch (cause) {
|
|
19
|
-
return err(new EvidenceFileError("read", "invalid-json", {
|
|
19
|
+
return err(new EvidenceFileError("read", "invalid-json", {
|
|
20
|
+
cause,
|
|
21
|
+
path: requestedPath,
|
|
22
|
+
}));
|
|
20
23
|
}
|
|
21
24
|
return ok(decoded);
|
|
22
25
|
}
|
|
23
26
|
catch (cause) {
|
|
24
|
-
return err(new EvidenceFileError("read",
|
|
27
|
+
return err(new EvidenceFileError("read", missingOrIo(cause), {
|
|
28
|
+
cause,
|
|
29
|
+
path: requestedPath,
|
|
30
|
+
}));
|
|
25
31
|
}
|
|
26
32
|
};
|
|
27
33
|
/** Atomically write text to the caller-supplied path. */
|
|
28
|
-
export const writeTextFile = async (encoded, path, overwrite) =>
|
|
29
|
-
|
|
34
|
+
export const writeTextFile = async (encoded, path, overwrite) => writeTextParts([encoded], path, overwrite);
|
|
35
|
+
/** Publish complete streamed text atomically, keeping only one encoded part in memory. */
|
|
36
|
+
export const writeTextParts = async (parts, path, overwrite) => {
|
|
37
|
+
const requestedPath = resolve(path);
|
|
30
38
|
try {
|
|
31
|
-
const requestedPath = resolve(path);
|
|
32
39
|
const canonicalParent = await realpath(dirname(requestedPath));
|
|
33
40
|
const destination = resolve(canonicalParent, basename(requestedPath));
|
|
34
41
|
const existing = await lstat(destination).catch((cause) => {
|
|
@@ -38,37 +45,52 @@ export const writeTextFile = async (encoded, path, overwrite) => {
|
|
|
38
45
|
});
|
|
39
46
|
if (existing !== undefined) {
|
|
40
47
|
if (!overwrite)
|
|
41
|
-
return err(new EvidenceFileError("write", "exists"));
|
|
48
|
+
return err(new EvidenceFileError("write", "exists", { path: requestedPath }));
|
|
42
49
|
if (!existing.isFile() || existing.isSymbolicLink())
|
|
43
|
-
return err(new EvidenceFileError("write", "not-file"));
|
|
50
|
+
return err(new EvidenceFileError("write", "not-file", { path: requestedPath }));
|
|
44
51
|
}
|
|
45
|
-
|
|
46
|
-
await writeFileAtomic(destination, encoded, {
|
|
47
|
-
encoding: "utf8",
|
|
48
|
-
mode: 0o600,
|
|
49
|
-
fsync: true,
|
|
50
|
-
});
|
|
51
|
-
else
|
|
52
|
-
await publishNewFile(destination, encoded);
|
|
52
|
+
const bytes = await publishFile(destination, parts, overwrite);
|
|
53
53
|
return ok({ path: requestedPath, bytes });
|
|
54
54
|
}
|
|
55
55
|
catch (cause) {
|
|
56
56
|
if (!overwrite && fileErrorCode(cause) === "EEXIST")
|
|
57
|
-
return err(new EvidenceFileError("write", "exists", {
|
|
58
|
-
|
|
57
|
+
return err(new EvidenceFileError("write", "exists", {
|
|
58
|
+
cause,
|
|
59
|
+
path: requestedPath,
|
|
60
|
+
}));
|
|
61
|
+
return err(new EvidenceFileError("write", missingOrIo(cause), {
|
|
62
|
+
cause,
|
|
63
|
+
path: requestedPath,
|
|
64
|
+
}));
|
|
59
65
|
}
|
|
60
66
|
};
|
|
61
|
-
|
|
67
|
+
/** A missing path or parent is a selection error, not a permission failure. */
|
|
68
|
+
const missingOrIo = (cause) => {
|
|
69
|
+
const code = fileErrorCode(cause);
|
|
70
|
+
return code === "ENOENT" || code === "ENOTDIR" ? "missing" : "io";
|
|
71
|
+
};
|
|
72
|
+
const publishFile = async (destination, parts, overwrite) => {
|
|
62
73
|
const stagingDirectory = await mkdtemp(resolve(dirname(destination), ".rea-write-"));
|
|
63
74
|
try {
|
|
64
75
|
const staged = resolve(stagingDirectory, "content");
|
|
65
|
-
await
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
76
|
+
const file = await open(staged, "wx", 0o600);
|
|
77
|
+
let bytes = 0;
|
|
78
|
+
try {
|
|
79
|
+
for (const part of parts) {
|
|
80
|
+
await file.writeFile(part, { encoding: "utf8" });
|
|
81
|
+
bytes += Buffer.byteLength(part, "utf8");
|
|
82
|
+
}
|
|
83
|
+
await file.sync();
|
|
84
|
+
}
|
|
85
|
+
finally {
|
|
86
|
+
await file.close();
|
|
87
|
+
}
|
|
88
|
+
if (overwrite)
|
|
89
|
+
await rename(staged, destination);
|
|
70
90
|
// A hard link publishes complete bytes atomically and cannot replace an existing name.
|
|
71
|
-
|
|
91
|
+
else
|
|
92
|
+
await link(staged, destination);
|
|
93
|
+
return bytes;
|
|
72
94
|
}
|
|
73
95
|
finally {
|
|
74
96
|
await rm(stagingDirectory, { recursive: true, force: true });
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { AnalysisOutputError } from "../domain/analysisErrorCore.js";
|
|
2
|
+
import { err, ok } from "../domain/result.js";
|
|
3
|
+
/** Resolve a caller selector to an observed provider procedure identity. */
|
|
4
|
+
export const resolveProcedureAddress = async (call, procedure, signal) => {
|
|
5
|
+
const result = await call("procedure_address", { procedure }, signal);
|
|
6
|
+
if (!result.ok)
|
|
7
|
+
return result;
|
|
8
|
+
return typeof result.value === "string" && result.value.length > 0
|
|
9
|
+
? ok(result.value)
|
|
10
|
+
: err(new AnalysisOutputError("procedure_address", "provider returned no canonical procedure address"));
|
|
11
|
+
};
|
|
@@ -1,20 +1,23 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
1
2
|
import { reconstructionCoverageEvaluationInputSchema } from "../domain/reconstructionCoverageInput.js";
|
|
2
3
|
import { AnalysisInputError } from "../domain/analysisErrorCore.js";
|
|
3
4
|
import {} from "../domain/analysisErrorBase.js";
|
|
4
5
|
import { evaluateReconstructionClosure } from "../domain/reconstructionCoverage.js";
|
|
5
6
|
import { jsonValueSchema } from "../domain/jsonValue.js";
|
|
6
7
|
import { err, ok } from "../domain/result.js";
|
|
8
|
+
import { requestInputError, workflowInputError } from "./workflowInputError.js";
|
|
9
|
+
const OPERATION = "evaluate_reconstruction_coverage";
|
|
7
10
|
/** Evaluate inline reconstruction coverage against a named boundary. */
|
|
8
11
|
export const evaluateReconstructionCoverage = (rawInput, nowEpochMs = Date.now()) => {
|
|
9
12
|
const parsed = reconstructionCoverageEvaluationInputSchema.safeParse(rawInput);
|
|
10
13
|
if (!parsed.success)
|
|
11
|
-
return err(
|
|
12
|
-
cause: parsed.error,
|
|
13
|
-
}));
|
|
14
|
+
return err(requestInputError(OPERATION, parsed.error, rawInput));
|
|
14
15
|
try {
|
|
15
16
|
return ok(jsonValueSchema.parse(evaluateReconstructionClosure(parsed.data.coverage, parsed.data.boundary_id, nowEpochMs)));
|
|
16
17
|
}
|
|
17
18
|
catch (cause) {
|
|
18
|
-
return err(
|
|
19
|
+
return err(cause instanceof TypeError || cause instanceof z.ZodError
|
|
20
|
+
? workflowInputError(OPERATION, cause)
|
|
21
|
+
: new AnalysisInputError(OPERATION, { cause }));
|
|
19
22
|
}
|
|
20
23
|
};
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import {
|
|
2
|
+
import { AnalysisProtocolError } from "../domain/analysisErrorCore.js";
|
|
3
3
|
import {} from "../domain/analysisErrorBase.js";
|
|
4
4
|
import { createEvidence } from "../domain/evidence.js";
|
|
5
5
|
import { jsonObjectSchema, jsonValueSchema } from "../domain/jsonValue.js";
|
|
6
6
|
import { reconstructionObligationLedgerInputSchema, reconstructionObligationLedgerSchema, } from "../domain/reconstructionObligationLedgerSchemas.js";
|
|
7
7
|
import { err, ok } from "../domain/result.js";
|
|
8
|
+
import { requestInputError, workflowInputError } from "./workflowInputError.js";
|
|
8
9
|
import { JAVASCRIPT_APPLICATION_WORKFLOW_PROVIDER } from "./InvestigationProviders.js";
|
|
9
10
|
import { deriveReconstructionObligationCandidates } from "./ReconstructionObligationCandidates.js";
|
|
10
11
|
import { evaluateReconstructionObligationLedger } from "./ReconstructionObligationLedgerEvaluation.js";
|
|
@@ -14,7 +15,7 @@ export const resolveReconstructionObligationLedgerRequest = (input) => {
|
|
|
14
15
|
const parsed = reconstructionObligationLedgerInputSchema.safeParse(input);
|
|
15
16
|
return parsed.success
|
|
16
17
|
? ok(parsed.data)
|
|
17
|
-
: err(
|
|
18
|
+
: err(requestInputError(OPERATION, parsed.error, input));
|
|
18
19
|
};
|
|
19
20
|
/** Build the complete deterministic ledger and wrap it in portable Evidence. */
|
|
20
21
|
export const buildReconstructionObligationLedgerEvidenceValidated = (input) => {
|
|
@@ -30,7 +31,7 @@ export const buildReconstructionObligationLedgerEvidenceValidated = (input) => {
|
|
|
30
31
|
}
|
|
31
32
|
catch (cause) {
|
|
32
33
|
if (cause instanceof z.ZodError)
|
|
33
|
-
return err(
|
|
34
|
+
return err(workflowInputError(OPERATION, cause));
|
|
34
35
|
return err(new AnalysisProtocolError("Reconstruction obligation ledger generation failed", { cause }));
|
|
35
36
|
}
|
|
36
37
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { manualRegistrationRemediation, } from "./SupportedClients.js";
|
|
1
2
|
import { configureDetectedClients } from "./SetupClients.js";
|
|
2
3
|
import { discoverSetupState, planSetupActions } from "./SetupPlan.js";
|
|
3
4
|
import { filterClientsNeedingConfigure, hostRemediation, initialProviderEnvironment, setupRegistrationCommand, systemSetupHost, } from "./SetupHost.js";
|
|
@@ -109,6 +110,7 @@ export const runSetup = async (options, host = systemSetupHost(), confirm) => {
|
|
|
109
110
|
clientsToConfigure: planned.clientsToConfigure,
|
|
110
111
|
};
|
|
111
112
|
readinessScope = resolvedReadinessScope(options.readinessScope, planSelection);
|
|
113
|
+
const manualRemediation = manualClientsRemediation(planned.selectedClients);
|
|
112
114
|
if (options.dryRun === true)
|
|
113
115
|
return {
|
|
114
116
|
status: "planned",
|
|
@@ -117,6 +119,9 @@ export const runSetup = async (options, host = systemSetupHost(), confirm) => {
|
|
|
117
119
|
clients,
|
|
118
120
|
doctor: summarizeDoctor(discovery.initialDoctor),
|
|
119
121
|
clientStates,
|
|
122
|
+
...(manualRemediation === undefined
|
|
123
|
+
? {}
|
|
124
|
+
: { remediation: manualRemediation }),
|
|
120
125
|
};
|
|
121
126
|
let approved = options.approved || plannedActions.length === 0;
|
|
122
127
|
let interactiveApproval = false;
|
|
@@ -183,7 +188,7 @@ export const runSetup = async (options, host = systemSetupHost(), confirm) => {
|
|
|
183
188
|
!(await installSkillAction(host, options, appliedActions)))
|
|
184
189
|
return fail("REA analysis skill could not be installed or verified. Check permissions for `~/.agents/skills`, then rerun setup.");
|
|
185
190
|
const doctor = summarizeDoctor(await host.doctor(readinessScope));
|
|
186
|
-
const remediation = finalSetupRemediation(host.platform, appliedActions.includes("installed_hopper"), doctor.healthy, hopperPath);
|
|
191
|
+
const remediation = combineRemediation(finalSetupRemediation(host.platform, appliedActions.includes("installed_hopper"), doctor.healthy, hopperPath), manualRemediation);
|
|
187
192
|
return {
|
|
188
193
|
status: remediation === undefined ? "ready" : "needs_human",
|
|
189
194
|
plannedActions,
|
|
@@ -277,6 +282,13 @@ const setupFailure = async (remediation, [host, plannedActions, appliedActions,
|
|
|
277
282
|
};
|
|
278
283
|
};
|
|
279
284
|
const emitProgress = (options, event) => options.onProgress?.(event);
|
|
285
|
+
const manualClientsRemediation = (clients) => clients
|
|
286
|
+
.map((client) => manualRegistrationRemediation(client.name))
|
|
287
|
+
.find((remediation) => remediation !== undefined);
|
|
288
|
+
const combineRemediation = (...parts) => {
|
|
289
|
+
const present = parts.filter((part) => part !== undefined && part !== "");
|
|
290
|
+
return present.length === 0 ? undefined : present.join(" ");
|
|
291
|
+
};
|
|
280
292
|
const finalSetupRemediation = (platform, installedHopper, healthy, hopperPath) => {
|
|
281
293
|
if (platform === "darwin" && installedHopper)
|
|
282
294
|
return "Open Hopper, choose its demo mode or activate a license, then rerun rea doctor --json.";
|
|
@@ -1,21 +1,13 @@
|
|
|
1
|
-
import { clientRegistrationEntry, clientConfigurationValuesEqual, clientServerPath, legacyClientServerPath, parseClientConfiguration, serializeClientConfiguration, withClientServers, } from "./ClientConfigurationDocument.js";
|
|
1
|
+
import { clientRegistrationEntry, clientConfigurationValuesEqual, clientServerPath, grokServerListedDisabled, legacyClientServerPath, 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";
|
|
5
5
|
import writeFileAtomic from "write-file-atomic";
|
|
6
6
|
import { PRODUCT_IDENTITY } from "../identity.js";
|
|
7
|
+
import { npxRegistrationCommand } from "./ClientRegistrationIdentity.js";
|
|
7
8
|
import { MCP_STARTUP_POLICY } from "../mcpStartupPolicy.js";
|
|
8
9
|
import { resolveClientConfigTransactionPath } from "./ClientConfigPath.js";
|
|
9
|
-
const defaultCommand = () =>
|
|
10
|
-
"npx",
|
|
11
|
-
"-y",
|
|
12
|
-
PRODUCT_IDENTITY.registrationPackageSpecifier,
|
|
13
|
-
"mcp",
|
|
14
|
-
];
|
|
15
|
-
/** Back up, atomically update, and semantically read back one JSON MCP configuration. */
|
|
16
|
-
export const configureJsonClient = (client, environment = {}, command = defaultCommand()) => configureClientDocument(client, environment, command, "json");
|
|
17
|
-
/** Back up, atomically update, and semantically read back one TOML MCP configuration. */
|
|
18
|
-
export const configureTomlClient = (client, environment = {}, command = defaultCommand()) => configureClientDocument(client, environment, command, "toml");
|
|
10
|
+
const defaultCommand = () => npxRegistrationCommand();
|
|
19
11
|
/** Configure one supported client's native stdio MCP registration shape. */
|
|
20
12
|
export const configureClientConfiguration = (client, environment = {}, command = defaultCommand()) => {
|
|
21
13
|
if (client.format === undefined || client.format === "unsupported")
|
|
@@ -36,7 +28,7 @@ const configureClientDocument = async (client, environment, command, format) =>
|
|
|
36
28
|
}
|
|
37
29
|
let parsed;
|
|
38
30
|
try {
|
|
39
|
-
parsed = parseClientConfiguration(original ?? (format === "toml" ? "" : "{}"), format);
|
|
31
|
+
parsed = parseClientConfiguration(original ?? (format === "toml" || format === "grok" ? "" : "{}"), format);
|
|
40
32
|
}
|
|
41
33
|
catch (cause) {
|
|
42
34
|
// Malformed existing configuration fails the readback gate.
|
|
@@ -163,14 +155,17 @@ const restoreConfig = async (path, original) => {
|
|
|
163
155
|
void cause;
|
|
164
156
|
}
|
|
165
157
|
};
|
|
166
|
-
/** Whether REA's entry matches
|
|
167
|
-
const registrationCurrent = (parsed, desired) => clientConfigurationValuesEqual(parsed.servers[PRODUCT_IDENTITY.mcpServerKey], desired) &&
|
|
158
|
+
/** Whether REA's entry matches, no legacy entry remains, and Grok is not suppressing it. */
|
|
159
|
+
const registrationCurrent = (parsed, desired) => clientConfigurationValuesEqual(parsed.servers[PRODUCT_IDENTITY.mcpServerKey], desired) &&
|
|
160
|
+
!Object.hasOwn(parsed.legacyServers, PRODUCT_IDENTITY.mcpServerKey) &&
|
|
161
|
+
!(parsed.dialect === "grok" &&
|
|
162
|
+
grokServerListedDisabled(parsed.document, PRODUCT_IDENTITY.mcpServerKey));
|
|
168
163
|
const clientConfigurationDesired = (client, providerEnvironment, command, format) => {
|
|
169
164
|
const environment = Object.fromEntries(Object.entries(providerEnvironment).sort(([left], [right]) => left.localeCompare(right)));
|
|
170
165
|
const registration = clientRegistrationEntry(format ?? "json", command.length === 0 ? [PRODUCT_IDENTITY.cliBinary, "mcp"] : command, environment);
|
|
171
166
|
return {
|
|
172
167
|
...registration,
|
|
173
|
-
...(client.name === "codex"
|
|
168
|
+
...(client.name === "codex" || client.name === "grok_build"
|
|
174
169
|
? {
|
|
175
170
|
startup_timeout_sec: MCP_STARTUP_POLICY.codexStartupTimeoutSeconds,
|
|
176
171
|
}
|
|
@@ -2,6 +2,7 @@ import { access } from "node:fs/promises";
|
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { resolve } from "node:path";
|
|
4
4
|
import { PRODUCT_IDENTITY } from "../identity.js";
|
|
5
|
+
import { npxRegistrationCommand } from "./ClientRegistrationIdentity.js";
|
|
5
6
|
import { SUPPORTED_NODE_VERSION_PROSE, supportsNodeVersion, } from "../domain/runtimeVersion.js";
|
|
6
7
|
import { runDoctor, systemDoctorHost } from "./Doctor.js";
|
|
7
8
|
import { installLinuxHopper, readLinuxDistribution } from "./LinuxHopper.js";
|
|
@@ -13,7 +14,7 @@ import { setupInstallFailure } from "./SetupInstallFailure.js";
|
|
|
13
14
|
import { providerRegistrationEnvironment } from "./SetupRegistrationEnvironment.js";
|
|
14
15
|
/** Resolve the executable and arguments used in a managed MCP registration. */
|
|
15
16
|
export const setupRegistrationCommand = (platform, useNpmRunner = process.env.npm_command === "exec") => useNpmRunner
|
|
16
|
-
?
|
|
17
|
+
? npxRegistrationCommand(platform)
|
|
17
18
|
: platform === "win32"
|
|
18
19
|
? [
|
|
19
20
|
process.execPath,
|
|
@@ -92,7 +93,9 @@ export const systemSetupHost = (doctorHost = systemDoctorHost()) => {
|
|
|
92
93
|
configureClient: (client, providerEnvironment, command) => client.format === "unsupported"
|
|
93
94
|
? Promise.resolve({ status: "skipped" })
|
|
94
95
|
: configureClientConfiguration(client, providerEnvironment, command),
|
|
95
|
-
clientNeedsConfigure: (client, providerEnvironment, command) =>
|
|
96
|
+
clientNeedsConfigure: (client, providerEnvironment, command) => client.format === "unsupported"
|
|
97
|
+
? Promise.resolve(false)
|
|
98
|
+
: clientConfigurationAligned(client, providerEnvironment, command).then((aligned) => !aligned),
|
|
96
99
|
inspectClientConfiguration: inspectClientConfiguration,
|
|
97
100
|
skillNeedsInstall: () => canonicalSkillNeedsInstall(homedir()),
|
|
98
101
|
installSkill: () => installCanonicalSkill(homedir()),
|
|
@@ -96,9 +96,11 @@ export const planSetupActions = async (input) => {
|
|
|
96
96
|
blocker: `${invalid.client.displayName ?? invalid.client.name}: ${invalid.inspection.remediation}`,
|
|
97
97
|
};
|
|
98
98
|
}
|
|
99
|
-
const clientPlans = inspections.flatMap(({ client, inspection }) =>
|
|
100
|
-
inspection.status === "
|
|
101
|
-
|
|
99
|
+
const clientPlans = inspections.flatMap(({ client, inspection }) => client.format !== "unsupported" &&
|
|
100
|
+
(inspection.status === "create" ||
|
|
101
|
+
inspection.status === "update" ||
|
|
102
|
+
(input.discovery.installHopper &&
|
|
103
|
+
inspection.status === "already_current"))
|
|
102
104
|
? [
|
|
103
105
|
{
|
|
104
106
|
client,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { join } from "node:path";
|
|
1
|
+
import { isAbsolute, join } from "node:path";
|
|
2
2
|
import { lstatSync } from "node:fs";
|
|
3
3
|
const vscodeUserDirectory = ({ home, platform, env, }) => {
|
|
4
4
|
if (platform === "win32")
|
|
@@ -17,6 +17,23 @@ const claudeDesktopDirectory = ({ home, platform, env, }) => {
|
|
|
17
17
|
const claudeCodeConfigDirectory = ({ home, env }) => env.CLAUDE_CONFIG_DIR ?? home;
|
|
18
18
|
const claudeCodeMarkerDirectory = ({ home, env }) => env.CLAUDE_CONFIG_DIR ?? join(home, ".claude");
|
|
19
19
|
const codexDirectory = ({ home, env }) => env.CODEX_HOME ?? join(home, ".codex");
|
|
20
|
+
const grokDirectory = ({ home, env }) => env.GROK_HOME ?? join(home, ".grok");
|
|
21
|
+
/** Grok Bot uses an absolute SAND_DATA_ROOT; anything else stays ~/.grokbot. */
|
|
22
|
+
const grokBotDirectory = ({ home, env }) => {
|
|
23
|
+
const root = env.SAND_DATA_ROOT;
|
|
24
|
+
return root !== undefined && root !== "" && isAbsolute(root)
|
|
25
|
+
? root
|
|
26
|
+
: join(home, ".grokbot");
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Grok Bot stores connectors in the signed-in account and runs them on its
|
|
30
|
+
* hosted computer. The data directory is only a detection marker.
|
|
31
|
+
*/
|
|
32
|
+
export const GROK_BOT_MANUAL_REGISTRATION_REMEDIATION = "Grok Bot keeps connectors in the signed-in account and runs them on its hosted computer. Setup does not write that account store, and a data-directory mcp.json is not a registration. In the Grok Bot chat, add a custom MCP server named rea that runs on the Bot's computer with `npx -y rea-agents@<version> mcp`. Do not put credentials in the command or arguments. A stdio server on this machine is not attached.";
|
|
33
|
+
/** Remediation for a client whose connector is not a local configuration file. */
|
|
34
|
+
export const manualRegistrationRemediation = (clientName) => clientName === "grok_bot"
|
|
35
|
+
? GROK_BOT_MANUAL_REGISTRATION_REMEDIATION
|
|
36
|
+
: undefined;
|
|
20
37
|
const copilotDirectory = ({ home, env }) => env.COPILOT_HOME ?? join(home, ".copilot");
|
|
21
38
|
const commandCodeDirectory = ({ home }) => join(home, ".commandcode");
|
|
22
39
|
const opencodeDirectory = ({ home, env }) => join(env.XDG_CONFIG_HOME ?? join(home, ".config"), "opencode");
|
|
@@ -133,6 +150,20 @@ export const SUPPORTED_CLIENT_DEFINITIONS = [
|
|
|
133
150
|
markerPath: vscodeUserDirectory,
|
|
134
151
|
format: "vscode",
|
|
135
152
|
},
|
|
153
|
+
{
|
|
154
|
+
name: "grok_build",
|
|
155
|
+
displayName: "Grok Build",
|
|
156
|
+
configPath: (context) => join(grokDirectory(context), "config.toml"),
|
|
157
|
+
markerPath: grokDirectory,
|
|
158
|
+
format: "grok",
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
name: "grok_bot",
|
|
162
|
+
displayName: "Grok Bot",
|
|
163
|
+
configPath: grokBotDirectory,
|
|
164
|
+
markerPath: grokBotDirectory,
|
|
165
|
+
format: "unsupported",
|
|
166
|
+
},
|
|
136
167
|
];
|
|
137
168
|
const resolvePath = (path, context) => typeof path === "function" ? path(context) : join(context.home, ...path);
|
|
138
169
|
/** Describe every client location that setup, doctor, or uninstall may inspect. */
|
|
@@ -141,7 +172,9 @@ export const supportedClients = (home, platform = process.platform, env = {
|
|
|
141
172
|
CLAUDE_CONFIG_DIR: process.env.CLAUDE_CONFIG_DIR,
|
|
142
173
|
CODEX_HOME: process.env.CODEX_HOME,
|
|
143
174
|
COPILOT_HOME: process.env.COPILOT_HOME,
|
|
175
|
+
GROK_HOME: process.env.GROK_HOME,
|
|
144
176
|
OPENCODE_CONFIG: process.env.OPENCODE_CONFIG,
|
|
177
|
+
SAND_DATA_ROOT: process.env.SAND_DATA_ROOT,
|
|
145
178
|
XDG_CONFIG_HOME: process.env.XDG_CONFIG_HOME,
|
|
146
179
|
}) => {
|
|
147
180
|
const context = { home, platform, env };
|
|
@@ -7,7 +7,7 @@ import { z } from "zod";
|
|
|
7
7
|
import { PRODUCT_IDENTITY } from "../identity.js";
|
|
8
8
|
import { isOwnedClientRegistrationCommand } from "./ClientRegistrationIdentity.js";
|
|
9
9
|
import { resolveClientConfigTransactionPath } from "./ClientConfigPath.js";
|
|
10
|
-
import { supportedClients } from "./SupportedClients.js";
|
|
10
|
+
import { manualRegistrationRemediation, supportedClients, } from "./SupportedClients.js";
|
|
11
11
|
const systemFileSystem = {
|
|
12
12
|
readText: (path) => readFile(path, "utf8"),
|
|
13
13
|
copy: (source, destination) => copyFile(source, destination),
|
|
@@ -62,7 +62,8 @@ export const systemUninstallHost = (home = homedir(), fileSystem = systemFileSys
|
|
|
62
62
|
});
|
|
63
63
|
const removeClient = async (client, fileSystem) => {
|
|
64
64
|
if (client.format === "unsupported")
|
|
65
|
-
return item(client.name, "skipped",
|
|
65
|
+
return item(client.name, "skipped", manualRegistrationRemediation(client.name) ??
|
|
66
|
+
"This client has no documented local MCP configuration boundary.");
|
|
66
67
|
const resolved = await resolveUninstallConfigPath(client, fileSystem);
|
|
67
68
|
if (typeof resolved !== "string")
|
|
68
69
|
return resolved;
|
|
@@ -82,7 +83,7 @@ const removeClient = async (client, fileSystem) => {
|
|
|
82
83
|
}
|
|
83
84
|
catch (cause) {
|
|
84
85
|
void cause;
|
|
85
|
-
return item(client.name, "failed", `Configuration is not valid ${client.format === "toml" ? "TOML" : client.format === "opencode" ? "JSONC" : "JSON"} and was not changed. Repair it, then rerun uninstall.`);
|
|
86
|
+
return item(client.name, "failed", `Configuration is not valid ${client.format === "toml" || client.format === "grok" ? "TOML" : client.format === "opencode" ? "JSONC" : "JSON"} and was not changed. Repair it, then rerun uninstall.`);
|
|
86
87
|
}
|
|
87
88
|
const name = PRODUCT_IDENTITY.mcpServerKey;
|
|
88
89
|
// Beside a native OpenCode V2 table, OpenCode also loads a V1 `mcp.rea`.
|
|
@@ -25,6 +25,23 @@ export const updateInstallCommand = (installation, version) => [
|
|
|
25
25
|
installation.prefix,
|
|
26
26
|
`${PRODUCT_IDENTITY.packageName}@${version}`,
|
|
27
27
|
];
|
|
28
|
+
const versionCheckRemediation = (release) => {
|
|
29
|
+
if (release.ok) {
|
|
30
|
+
return "REA received invalid version metadata. Check the installed version and npm registry, then rerun rea update.";
|
|
31
|
+
}
|
|
32
|
+
const failure = release.error;
|
|
33
|
+
const kind = failure.kind;
|
|
34
|
+
switch (kind) {
|
|
35
|
+
case "unavailable":
|
|
36
|
+
return `REA could not resolve the latest release: ${failure.detail}. Retry rea update when registry access is available.`;
|
|
37
|
+
case "invalid-metadata":
|
|
38
|
+
return `REA could not resolve the latest release: ${failure.detail}. Check the npm release metadata, then rerun rea update.`;
|
|
39
|
+
default: {
|
|
40
|
+
const exhaustive = kind;
|
|
41
|
+
throw new TypeError(`Unhandled release lookup failure: ${String(exhaustive)}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|
|
28
45
|
/** Identify, resolve, install, and verify REA without applying setup changes. */
|
|
29
46
|
export const runUpdate = async (currentVersion, host, output = "human") => {
|
|
30
47
|
const installation = await host.installation();
|
|
@@ -37,9 +54,7 @@ export const runUpdate = async (currentVersion, host, output = "human") => {
|
|
|
37
54
|
currentVersion,
|
|
38
55
|
latestVersion,
|
|
39
56
|
reason: "version-check",
|
|
40
|
-
remediation: release
|
|
41
|
-
? "REA received invalid version metadata. Check the installed version and npm registry, then rerun rea update."
|
|
42
|
-
: `REA could not resolve the latest release: ${release.error}. Retry rea update when registry access is available.`,
|
|
57
|
+
remediation: versionCheckRemediation(release),
|
|
43
58
|
};
|
|
44
59
|
if (!gt(targetVersion, currentVersion))
|
|
45
60
|
return {
|
|
@@ -3,9 +3,9 @@ import { homedir } from "node:os";
|
|
|
3
3
|
import { basename, dirname, join, resolve } from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import spawn from "cross-spawn";
|
|
6
|
-
import { z } from "zod";
|
|
7
6
|
import { PRODUCT_IDENTITY } from "../identity.js";
|
|
8
7
|
import { err, ok } from "../domain/result.js";
|
|
8
|
+
import { safeParseJson } from "../domain/safeJson.js";
|
|
9
9
|
import { updateInstallCommand, } from "./Update.js";
|
|
10
10
|
import { planIntegrationMaintenance } from "./UpdateMaintenance.js";
|
|
11
11
|
/** Run an updater subprocess with complete diagnostics and isolated machine output. */
|
|
@@ -85,6 +85,50 @@ export const detectNpmInstallation = async (packageRoot, host) => {
|
|
|
85
85
|
return undefined;
|
|
86
86
|
return { prefix: dirname(library), packageRoot: canonicalPackageRoot };
|
|
87
87
|
};
|
|
88
|
+
const INVALID_NPM_RELEASE_METADATA = "Invalid npm release metadata: expected a version string or a single-element version array.";
|
|
89
|
+
/** npm view arguments for dist-tags.latest, scoped to the owning prefix when known. */
|
|
90
|
+
export const npmLatestVersionCommand = (installation) => [
|
|
91
|
+
"npm",
|
|
92
|
+
"view",
|
|
93
|
+
"--global",
|
|
94
|
+
...(installation === undefined ? [] : ["--prefix", installation.prefix]),
|
|
95
|
+
PRODUCT_IDENTITY.packageName,
|
|
96
|
+
"dist-tags.latest",
|
|
97
|
+
"--json",
|
|
98
|
+
"--fetch-retries=0",
|
|
99
|
+
"--fetch-timeout=10000",
|
|
100
|
+
];
|
|
101
|
+
/**
|
|
102
|
+
* Read one latest version from `npm view --json`.
|
|
103
|
+
* npm 11 emits a JSON string. npm 12 emits that string as a one-element array.
|
|
104
|
+
*/
|
|
105
|
+
export const parseNpmLatestVersion = (metadata) => {
|
|
106
|
+
const decoded = safeParseJson(metadata);
|
|
107
|
+
if (!decoded.ok)
|
|
108
|
+
return err(decoded.error);
|
|
109
|
+
const version = readNpmLatestVersion(decoded.value);
|
|
110
|
+
return version === undefined
|
|
111
|
+
? err(INVALID_NPM_RELEASE_METADATA)
|
|
112
|
+
: ok(version);
|
|
113
|
+
};
|
|
114
|
+
const readNpmLatestVersion = (value) => {
|
|
115
|
+
if (typeof value === "string")
|
|
116
|
+
return nonemptyVersion(value);
|
|
117
|
+
if (!Array.isArray(value) || value.length !== 1)
|
|
118
|
+
return undefined;
|
|
119
|
+
const only = value[0];
|
|
120
|
+
return typeof only === "string" ? nonemptyVersion(only) : undefined;
|
|
121
|
+
};
|
|
122
|
+
const nonemptyVersion = (value) => value.length === 0 ? undefined : value;
|
|
123
|
+
/** Classify npm view output as a version or a lookup failure. */
|
|
124
|
+
export const npmReleaseLookup = (response) => {
|
|
125
|
+
if (!response.ok)
|
|
126
|
+
return err({ kind: "unavailable", detail: response.error });
|
|
127
|
+
const parsed = parseNpmLatestVersion(response.value);
|
|
128
|
+
return parsed.ok
|
|
129
|
+
? ok(parsed.value)
|
|
130
|
+
: err({ kind: "invalid-metadata", detail: parsed.error });
|
|
131
|
+
};
|
|
88
132
|
/** Create npm, registry, verification, and read-only maintenance effects. */
|
|
89
133
|
export const systemUpdateHost = (packageRoot = fileURLToPath(new URL("../..", import.meta.url)), home = homedir()) => ({
|
|
90
134
|
installation: () => detectNpmInstallation(packageRoot, {
|
|
@@ -92,30 +136,7 @@ export const systemUpdateHost = (packageRoot = fileURLToPath(new URL("../..", im
|
|
|
92
136
|
globalRoot: () => requireCommandOutput(["npm", "root", "--global"]),
|
|
93
137
|
globalPrefix: () => requireCommandOutput(["npm", "prefix", "--global"]),
|
|
94
138
|
}),
|
|
95
|
-
latestVersion: async (installation) =>
|
|
96
|
-
const response = await runUpdateCommand([
|
|
97
|
-
"npm",
|
|
98
|
-
"view",
|
|
99
|
-
"--global",
|
|
100
|
-
...(installation === undefined ? [] : ["--prefix", installation.prefix]),
|
|
101
|
-
PRODUCT_IDENTITY.packageName,
|
|
102
|
-
"dist-tags.latest",
|
|
103
|
-
"--json",
|
|
104
|
-
"--fetch-retries=0",
|
|
105
|
-
"--fetch-timeout=10000",
|
|
106
|
-
]);
|
|
107
|
-
if (!response.ok)
|
|
108
|
-
return response;
|
|
109
|
-
try {
|
|
110
|
-
const parsed = z.string().min(1).safeParse(JSON.parse(response.value));
|
|
111
|
-
return parsed.success
|
|
112
|
-
? ok(parsed.data)
|
|
113
|
-
: err(`Invalid npm release metadata: ${parsed.error.message}`);
|
|
114
|
-
}
|
|
115
|
-
catch (cause) {
|
|
116
|
-
return err(cause instanceof Error ? cause.message : String(cause));
|
|
117
|
-
}
|
|
118
|
-
},
|
|
139
|
+
latestVersion: async (installation) => npmReleaseLookup(await runUpdateCommand(npmLatestVersionCommand(installation))),
|
|
119
140
|
installVersion: async (installation, version, output) => {
|
|
120
141
|
const result = await runUpdateCommand(updateInstallCommand(installation, version), output);
|
|
121
142
|
return result.ok ? ok(undefined) : result;
|
|
@@ -3,7 +3,7 @@ import { z } from "zod";
|
|
|
3
3
|
import { AnalysisCancelledError, AnalysisCapabilityUnavailableError, AnalysisInputError, AnalysisOutputError, } from "../domain/analysisErrorCore.js";
|
|
4
4
|
import { createEvidence } from "../domain/evidence.js";
|
|
5
5
|
import { jsonObjectSchema } from "../domain/jsonValue.js";
|
|
6
|
-
import {
|
|
6
|
+
import { analysisInputErrorFromIssues } from "../domain/inputIssueProjection.js";
|
|
7
7
|
import { err, ok } from "../domain/result.js";
|
|
8
8
|
import { collectWebModuleImports, matchCapturedModules, } from "../domain/webModuleImports.js";
|
|
9
9
|
import { webModuleTraceInputSchema, webModuleFileSchema, webModuleResolutionSchema, webModuleTraceResultSchema, } from "../domain/webModuleTrace.js";
|
|
@@ -48,7 +48,9 @@ export class WebModuleTraceService {
|
|
|
48
48
|
return err(new AnalysisCancelledError(OPERATION));
|
|
49
49
|
const parsed = webModuleTraceInputSchema.safeParse(rawInput);
|
|
50
50
|
if (!parsed.success)
|
|
51
|
-
return err(
|
|
51
|
+
return err(analysisInputErrorFromIssues(OPERATION, parsed.error.issues, rawInput, {
|
|
52
|
+
cause: parsed.error,
|
|
53
|
+
}));
|
|
52
54
|
const input = parsed.data;
|
|
53
55
|
for (const [path, value] of [
|
|
54
56
|
["manifest_path", input.manifest_path],
|
|
@@ -4,7 +4,7 @@ import { redactExplicitText } from "../domain/explicitSensitiveValues.js";
|
|
|
4
4
|
import { isAbsolute } from "node:path";
|
|
5
5
|
import { AnalysisCancelledError, AnalysisInputError, AnalysisOutputError, } from "../domain/analysisErrorCore.js";
|
|
6
6
|
import { createEvidence } from "../domain/evidence.js";
|
|
7
|
-
import {
|
|
7
|
+
import { analysisInputErrorFromIssues } from "../domain/inputIssueProjection.js";
|
|
8
8
|
import { jsonObjectSchema } from "../domain/jsonValue.js";
|
|
9
9
|
import { err, ok } from "../domain/result.js";
|
|
10
10
|
import { inspectWebNetworkCaptureInputSchema, webNetworkCaptureSchema, } from "../domain/webNetworkCapture.js";
|
|
@@ -27,7 +27,9 @@ export class WebNetworkCaptureService {
|
|
|
27
27
|
const failure = (error) => err(redactExplicitFailure(error, declarations.success ? declarations.data : []));
|
|
28
28
|
const parsed = inspectWebNetworkCaptureInputSchema.safeParse(rawInput);
|
|
29
29
|
if (!parsed.success)
|
|
30
|
-
return failure(
|
|
30
|
+
return failure(analysisInputErrorFromIssues(OPERATION, parsed.error.issues, rawInput, {
|
|
31
|
+
cause: parsed.error,
|
|
32
|
+
}));
|
|
31
33
|
const input = parsed.data;
|
|
32
34
|
if (!isAbsolute(input.capture_path))
|
|
33
35
|
return failure(new AnalysisInputError(OPERATION, undefined, [
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { AnalysisCancelledError,
|
|
2
|
+
import { AnalysisCancelledError, AnalysisOutputError, } from "../domain/analysisErrorCore.js";
|
|
3
3
|
import { createEvidence } from "../domain/evidence.js";
|
|
4
4
|
import { jsonObjectSchema, jsonValueSchema } from "../domain/jsonValue.js";
|
|
5
|
-
import {
|
|
5
|
+
import { analysisInputErrorFromIssues } from "../domain/inputIssueProjection.js";
|
|
6
6
|
import { err, ok } from "../domain/result.js";
|
|
7
7
|
import { observeWebExecutionInputSchema, webExecutionSchema, } from "../domain/webExecution.js";
|
|
8
8
|
import { inspectWebEventListenersInputSchema, webEventListenersSchema, } from "../domain/webEventListeners.js";
|
|
@@ -69,5 +69,7 @@ const parseInput = (schema, rawInput, operation, options) => {
|
|
|
69
69
|
const parsed = schema.safeParse(rawInput);
|
|
70
70
|
return parsed.success
|
|
71
71
|
? ok(parsed.data)
|
|
72
|
-
: err(
|
|
72
|
+
: err(analysisInputErrorFromIssues(operation, parsed.error.issues, rawInput, {
|
|
73
|
+
cause: parsed.error,
|
|
74
|
+
}));
|
|
73
75
|
};
|
|
@@ -7,7 +7,7 @@ import { publishWebScripts } from "../browser/assets/PublishWebScripts.js";
|
|
|
7
7
|
import { selectScriptCapture } from "../browser/assets/ScriptCaptureAdapters.js";
|
|
8
8
|
import { AnalysisCancelledError, AnalysisInputError, AnalysisOutputError, } from "../domain/analysisErrorCore.js";
|
|
9
9
|
import { createEvidence } from "../domain/evidence.js";
|
|
10
|
-
import {
|
|
10
|
+
import { analysisInputErrorFromIssues } from "../domain/inputIssueProjection.js";
|
|
11
11
|
import { jsonValueSchema } from "../domain/jsonValue.js";
|
|
12
12
|
import { ProviderAdapterError } from "../domain/providerAdapterError.js";
|
|
13
13
|
import { err, ok } from "../domain/result.js";
|
|
@@ -21,7 +21,7 @@ export const exportWebScripts = async (rawInput, options = {}) => {
|
|
|
21
21
|
const input = exportWebScriptsInputSchema.safeParse(rawInput);
|
|
22
22
|
return input.success
|
|
23
23
|
? exportWebScriptsValidated(input.data, options)
|
|
24
|
-
: err(
|
|
24
|
+
: err(analysisInputErrorFromIssues(OPERATION, input.error.issues, rawInput));
|
|
25
25
|
};
|
|
26
26
|
/** Publish input already parsed by a named adapter contract. */
|
|
27
27
|
export const exportWebScriptsValidated = async (input, options = {}) => {
|