rea-agents 2.4.0 → 3.0.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 +91 -19
- package/bridge/ghidra/ReaGhidraBridge.java +524 -4
- package/bridge/hopper_bridge.py +313 -28
- package/dist/application/AnalysisClientCleanup.js +14 -0
- package/dist/application/AnalysisContextQueries.js +130 -0
- package/dist/application/AnalysisSnapshotCache.js +4 -2
- package/dist/application/ApplicationWorkflowEvidenceResolver.js +31 -13
- package/dist/application/ArtifactInventory/scanCanonical.js +1 -1
- package/dist/application/BinarySession.js +20 -8
- package/dist/application/BinarySessionComposition.js +21 -0
- package/dist/application/BinarySessionRecords.js +79 -9
- package/dist/application/BinarySessionStatus.js +31 -1
- package/dist/application/BrowserEvidence.js +14 -0
- package/dist/application/BrowserScenarioCapturePort.js +1 -0
- package/dist/application/BrowserScenarioCaptureService.js +53 -0
- package/dist/application/BrowserScenarioEvidence.js +40 -0
- package/dist/application/CallPathTracing.js +160 -0
- package/dist/application/CapabilityInventory.js +84 -14
- package/dist/application/ClientRegistrationStatus.js +4 -1
- package/dist/application/CompositeProvider.js +10 -1
- package/dist/application/DirectAnalysis.js +13 -4
- package/dist/application/EnhancedLiteralTracing.js +118 -0
- package/dist/application/EnhancedTools.js +71 -127
- package/dist/application/EvidenceLedger.js +45 -16
- package/dist/application/JavaScriptApplicationWorkflowEvidence.js +13 -0
- package/dist/application/JavaScriptApplicationWorkflowService.js +27 -1
- package/dist/application/JavaScriptArtifactAnalysis.js +13 -4
- package/dist/application/JavaScriptRuntimeObservationEvidence.js +34 -0
- package/dist/application/JavaScriptRuntimeObservationPort.js +1 -0
- package/dist/application/JavaScriptRuntimeObservationService.js +46 -0
- package/dist/application/JavaScriptSemanticGraphAsyncProjection.js +147 -0
- package/dist/application/JavaScriptSemanticGraphBuilder.js +34 -6
- package/dist/application/JavaScriptSemanticGraphChildProcessProjection.js +156 -0
- package/dist/application/JavaScriptSemanticGraphConstruction.js +2 -2
- package/dist/application/JavaScriptSemanticGraphDataProjection.js +203 -0
- package/dist/application/JavaScriptSemanticGraphFingerprintProjection.js +25 -0
- package/dist/application/JavaScriptSemanticGraphFlowProjection.js +129 -8
- package/dist/application/JavaScriptSemanticGraphObjectProjection.js +81 -0
- package/dist/application/JavaScriptSemanticGraphProjection.js +14 -7
- package/dist/application/JavaScriptSemanticGraphResourceProjection.js +59 -0
- package/dist/application/JavaScriptSemanticGraphValueProjection.js +77 -0
- package/dist/application/LazyAnalysisProvider.js +77 -0
- package/dist/application/LoopbackReplay.js +1 -1
- package/dist/application/NativeApiInspection.js +80 -0
- package/dist/application/ProcessReactiveEffects.js +6 -0
- package/dist/application/ProcessReactiveHarness.js +16 -1
- package/dist/application/ProjectPermissionStore.js +1 -0
- package/dist/application/ReconstructionObligationAuthority.js +72 -0
- package/dist/application/ReconstructionObligationCandidates.js +265 -0
- package/dist/application/ReconstructionObligationLedgerDiagnostics.js +47 -0
- package/dist/application/ReconstructionObligationLedgerEvaluation.js +263 -0
- package/dist/application/ReconstructionObligationLedgerProjection.js +86 -0
- package/dist/application/ReconstructionObligationLedgerService.js +72 -0
- package/dist/application/ReconstructionObligationOriginalCases.js +33 -0
- package/dist/application/ReconstructionObligationPolicies.js +132 -0
- package/dist/application/ReconstructionReadinessService.js +48 -0
- package/dist/application/SessionProviderRouter.js +6 -6
- package/dist/application/SetupClientConfiguration.js +4 -2
- package/dist/application/runtime.js +26 -9
- package/dist/artifacts/ArtifactProvider.js +87 -22
- package/dist/browser/BrowserScenarioSecrets.js +53 -0
- package/dist/browser/BrowserScenarioSessionPort.js +1 -0
- package/dist/browser/CdpBrowserProvider.js +2 -2
- package/dist/browser/CdpCaptureDocuments.js +57 -0
- package/dist/browser/CdpCaptureStorage.js +71 -29
- package/dist/browser/CdpCaptureStorageFingerprints.js +328 -0
- package/dist/browser/CdpEndpoint.js +8 -6
- package/dist/browser/CdpPageCapture.js +2 -0
- package/dist/browser/JavaScriptRuntimeScope.js +38 -0
- package/dist/browser/PlaywrightBrowserScenarioProvider.js +259 -0
- package/dist/browser/PlaywrightExecutionBoundary.js +42 -0
- package/dist/browser/PlaywrightScenarioActions.js +62 -0
- package/dist/browser/PlaywrightScenarioArtifacts.js +238 -0
- package/dist/browser/PlaywrightScenarioBrowser.js +144 -0
- package/dist/browser/PlaywrightScenarioEvents.js +301 -0
- package/dist/browser/PlaywrightScenarioSession.js +300 -0
- package/dist/browser/V8InspectorCaptureProjection.js +110 -0
- package/dist/browser/V8InspectorEndpoint.js +72 -0
- package/dist/browser/V8InspectorProvider.js +267 -0
- package/dist/catalogIdentity.js +11 -3
- package/dist/cli/artifactCommands.js +44 -3
- package/dist/cli/coreAnalysisCommands.js +78 -0
- package/dist/cli.js +4 -0
- package/dist/cliApplicationCommands.js +30 -2
- package/dist/cliBrowserAdvancedCommands.js +17 -5
- package/dist/cliBrowserCommands.js +1 -0
- package/dist/cliBrowserScenarioCommands.js +43 -0
- package/dist/cliCommandNames.js +9 -0
- package/dist/cliJavaScriptRuntimeCommands.js +164 -0
- package/dist/cliObservationOptions.js +4 -0
- package/dist/cliPolicyCommands.js +1 -0
- package/dist/config/environment.js +12 -0
- package/dist/config/parseConfig.js +88 -17
- package/dist/contracts/analysisSearchContract.js +14 -0
- package/dist/contracts/applicationToolContracts.js +86 -2
- package/dist/contracts/applicationWorkflowInputContracts.js +18 -0
- package/dist/contracts/artifactToolContracts.js +29 -2
- package/dist/contracts/browserProviderToolContracts.js +7 -0
- package/dist/contracts/browserScenarioToolContracts.js +81 -0
- package/dist/contracts/browserToolContracts.js +88 -98
- package/dist/contracts/enhancedInputs.js +35 -6
- package/dist/contracts/functionInstructionContract.js +8 -0
- package/dist/contracts/functionWorkflowToolContracts.js +30 -0
- package/dist/contracts/hopperMemoryContracts.js +22 -0
- package/dist/contracts/javascriptApplicationWorkflowExamples.js +42 -0
- package/dist/contracts/javascriptRuntimeObservationToolContracts.js +58 -0
- package/dist/contracts/promptContracts.js +14 -15
- package/dist/contracts/reconstructionReadinessExample.js +436 -0
- package/dist/contracts/toolContractExamples.js +8 -0
- package/dist/contracts/toolContractTypes.js +1 -0
- package/dist/contracts/toolContracts.js +34 -25
- package/dist/contracts/toolEffects.js +25 -0
- package/dist/contracts/toolOutputSchemaGroups.js +120 -30
- package/dist/contracts/toolOutputSchemaPrimitives.js +37 -0
- package/dist/domain/analysisErrorPresentation.js +8 -2
- package/dist/domain/analysisErrorProjection.js +9 -0
- package/dist/domain/artifactInspection.js +347 -0
- package/dist/domain/browserCaptureComparison.js +82 -0
- package/dist/domain/browserObservation.js +8 -1
- package/dist/domain/browserObservationErrors.js +1 -0
- package/dist/domain/browserObservationSchemas.js +26 -0
- package/dist/domain/browserScenario.js +165 -0
- package/dist/domain/browserScenarioCapture.js +57 -0
- package/dist/domain/browserScenarioCaptureValues.js +204 -0
- package/dist/domain/browserScenarioDiff.js +324 -0
- package/dist/domain/browserScenarioDiffValues.js +157 -0
- package/dist/domain/browserScenarioNormalization.js +45 -0
- package/dist/domain/browserScenarioValues.js +372 -0
- package/dist/domain/bytecodeProvider.js +179 -0
- package/dist/domain/conformancePackage.js +169 -0
- package/dist/domain/conformanceReplay.js +104 -0
- package/dist/domain/conformanceTrustGate.js +193 -0
- package/dist/domain/customProtocolCapture.js +137 -0
- package/dist/domain/eventProcessTree.js +214 -0
- package/dist/domain/evidenceBundle.js +47 -0
- package/dist/domain/hopperStartupFailure.js +1 -1
- package/dist/domain/hopperValues.js +14 -1
- package/dist/domain/inputIssueProjection.js +7 -1
- package/dist/domain/javascriptRuntimeObservation.js +170 -0
- package/dist/domain/javascriptRuntimeReconciliationParsing.js +120 -2
- package/dist/domain/javascriptRuntimeReconciliationResult.js +3 -3
- package/dist/domain/javascriptRuntimeReconciliationRuntime.js +2 -2
- package/dist/domain/javascriptRuntimeReconciliationSchemas.js +1 -1
- package/dist/domain/javascriptSemanticAnalysis.js +13 -16
- package/dist/domain/javascriptSemanticAsyncEffects.js +253 -0
- package/dist/domain/javascriptSemanticChildProcesses.js +237 -0
- package/dist/domain/javascriptSemanticDataEffectHelpers.js +125 -0
- package/dist/domain/javascriptSemanticDataEffects.js +284 -0
- package/dist/domain/javascriptSemanticDerivedAnalysis.js +41 -0
- package/dist/domain/javascriptSemanticFingerprints.js +174 -0
- package/dist/domain/javascriptSemanticIr.js +21 -1
- package/dist/domain/javascriptSemanticObjects.js +115 -0
- package/dist/domain/javascriptSemanticPromises.js +290 -0
- package/dist/domain/javascriptSemanticResources.js +136 -0
- package/dist/domain/javascriptSourceParser.js +15 -0
- package/dist/domain/javascriptStaticAnalysis.js +12 -15
- package/dist/domain/javascriptStaticAnalysisBundler.js +38 -0
- package/dist/domain/javascriptStaticAnalysisCalls.js +23 -1
- package/dist/domain/javascriptStaticAnalysisHelpers.js +8 -0
- package/dist/domain/mobileApplicationInvestigation.js +159 -0
- package/dist/domain/nativeApiBoundary.js +130 -0
- package/dist/domain/objcSwiftMetadata.js +150 -0
- package/dist/domain/packageAnalysis.js +123 -0
- package/dist/domain/peInspection.js +196 -0
- package/dist/domain/processCapture.js +8 -2
- package/dist/domain/processReactiveScenario.js +1 -0
- package/dist/domain/processReactiveTransition.js +9 -4
- package/dist/domain/protocolCapture.js +243 -0
- package/dist/domain/providerCleanupError.js +11 -0
- package/dist/domain/reconstructionObligationLedgerSchemas.js +278 -0
- package/dist/domain/reconstructionReadiness.js +121 -0
- package/dist/domain/reconstructionReadinessFindingHelpers.js +17 -0
- package/dist/domain/reconstructionReadinessIntegrityFindings.js +118 -0
- package/dist/domain/reconstructionReadinessJourneyFindings.js +193 -0
- package/dist/domain/reconstructionReadinessSchemas.js +240 -0
- package/dist/domain/sourceToBundleComparison.js +335 -0
- package/dist/domain/sourceToBundleComparisonSchemas.js +133 -0
- package/dist/domain/sourceToBundleSignals.js +202 -0
- package/dist/domain/webCaptureDiff.js +141 -27
- package/dist/domain/webScreenshot.js +1 -1
- package/dist/dotnet/ManagedStaticProvider.js +34 -5
- package/dist/generatedMcpToolCatalog.js +37 -0
- package/dist/generatedPackageMetadata.js +4 -4
- package/dist/ghidra/GhidraDefaults.js +1 -1
- package/dist/ghidra/GhidraFunctionValues.js +40 -2
- package/dist/ghidra/GhidraProviderCapabilities.js +47 -38
- package/dist/hopper/HopperCleanup.js +158 -0
- package/dist/hopper/HopperClient.js +93 -99
- package/dist/hopper/HopperProvider.js +61 -30
- package/dist/hopper/HopperRequestQueue.js +215 -0
- package/dist/hopper/HopperResponseStream.js +46 -0
- package/dist/hopper/protocol.js +63 -20
- package/dist/main/transport.js +24 -27
- package/dist/main.js +14 -6
- package/dist/mcpDoctor.js +27 -4
- package/dist/mcpStartupPolicy.js +14 -0
- package/dist/process/ProcessCommandIdentity.js +19 -0
- package/dist/process/ProcessOwnership.js +11 -8
- package/dist/server/DynamicToolAvailability.js +70 -0
- package/dist/server/LazyToolCatalog.js +134 -0
- package/dist/server/createServer.js +92 -154
- package/dist/server/hydrateServerTools.js +191 -0
- package/dist/server/lifecycleProgress.js +10 -0
- package/dist/server/permissionFailure.js +12 -0
- package/dist/server/registerApplicationTools/compareSourceToBundle.js +35 -0
- package/dist/server/registerApplicationTools/helpers.js +11 -7
- package/dist/server/registerApplicationTools/obligationLedger.js +27 -0
- package/dist/server/registerApplicationTools/readiness.js +55 -0
- package/dist/server/registerApplicationTools.js +6 -0
- package/dist/server/registerArtifactTools.js +9 -1
- package/dist/server/registerBrowserScenarioTool.js +25 -0
- package/dist/server/registerBrowserTools.js +2 -2
- package/dist/server/registerCloseLifecycleTool.js +57 -0
- package/dist/server/registerEnhancedTools.js +28 -7
- package/dist/server/registerEvidenceResources.js +54 -101
- package/dist/server/registerEvidenceTools.js +9 -2
- package/dist/server/registerInvestigationTools.js +1 -2
- package/dist/server/registerJavaScriptApplicationGraphResource.js +0 -4
- package/dist/server/registerJavaScriptRuntimeObservationTools.js +37 -0
- package/dist/server/registerReconstructionObligationLedgerResource.js +32 -0
- package/dist/server/registerReconstructionReadinessResource.js +32 -0
- package/dist/server/registerSessionRecordTools.js +82 -12
- package/dist/server/registerSessionStatusTool.js +11 -8
- package/dist/server/registerSessionTools.js +32 -58
- package/dist/server/sessionAvailabilityPolicy.js +10 -8
- package/dist/server/toolRegistrationOptions.js +21 -6
- package/dist/server/toolResult.js +12 -0
- package/package.json +28 -11
- package/scripts/package-runner-bootstrap.mjs +72 -0
- package/scripts/rea.mjs +11 -1
- package/skills/reverse-engineer-anything/SKILL.md +10 -3
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { evaluateReconstructionReadinessValidated, resolveReconstructionReadinessRequest, } from "../../application/ReconstructionReadinessService.js";
|
|
2
|
+
import { applicationToolContract } from "../../contracts/applicationToolContracts.js";
|
|
3
|
+
import { reconstructionReadinessInputSchema } from "../../domain/reconstructionReadinessSchemas.js";
|
|
4
|
+
import { reconstructionReadinessReportSchema } from "../../domain/reconstructionReadinessSchemas.js";
|
|
5
|
+
import { logToolExecution } from "../toolLogging.js";
|
|
6
|
+
import { safeParseToolInput } from "../toolInputValidation.js";
|
|
7
|
+
import { toolRegistrationOptions } from "../toolRegistrationOptions.js";
|
|
8
|
+
import { toCallToolResult } from "../toolResult.js";
|
|
9
|
+
import { recordSources } from "./helpers.js";
|
|
10
|
+
const contract = applicationToolContract("evaluate_reconstruction_readiness");
|
|
11
|
+
/** Register deterministic public-contract reconstruction conformance. */
|
|
12
|
+
export const registerReconstructionReadinessTool = (server, options) => {
|
|
13
|
+
server.registerTool(contract.name, toolRegistrationOptions(contract), async (input) => {
|
|
14
|
+
const parsed = safeParseToolInput(reconstructionReadinessInputSchema, input, contract.name);
|
|
15
|
+
if (!parsed.ok)
|
|
16
|
+
return toCallToolResult(parsed, contract);
|
|
17
|
+
const resolved = resolveReconstructionReadinessRequest(parsed.value);
|
|
18
|
+
if (!resolved.ok)
|
|
19
|
+
return toCallToolResult(resolved, contract);
|
|
20
|
+
const result = await logToolExecution(options.logger, contract.name, () => Promise.resolve(evaluateReconstructionReadinessValidated(resolved.value)));
|
|
21
|
+
if (!result.ok)
|
|
22
|
+
return toCallToolResult(result, contract);
|
|
23
|
+
const recorded = recordSources(options.recordEvidence, resolved.value.evidence_bundle.records);
|
|
24
|
+
if (!recorded.ok)
|
|
25
|
+
return toCallToolResult(recorded, contract);
|
|
26
|
+
const recordedResult = options.recordEvidence?.(result.value);
|
|
27
|
+
if (recordedResult !== undefined && !recordedResult.ok)
|
|
28
|
+
return toCallToolResult(recordedResult, contract);
|
|
29
|
+
const report = reconstructionReadinessReportSchema.parse(result.value.normalized_result);
|
|
30
|
+
const reportUri = `rea://evidence/${result.value.evidence_id}/reconstruction-readiness-report`;
|
|
31
|
+
const projection = {
|
|
32
|
+
schema: report.schema,
|
|
33
|
+
schema_version: report.schema_version,
|
|
34
|
+
report_id: report.report_id,
|
|
35
|
+
source_digest: report.source_digest,
|
|
36
|
+
report_digest: report.report_digest,
|
|
37
|
+
status: report.status,
|
|
38
|
+
summary: report.summary,
|
|
39
|
+
metrics: report.metrics,
|
|
40
|
+
report_resource_uri: reportUri,
|
|
41
|
+
};
|
|
42
|
+
return toCallToolResult({ ok: true, value: result.value }, contract, {
|
|
43
|
+
evidenceResourcesAvailable: recordedResult !== undefined,
|
|
44
|
+
evidenceResultProjection: projection,
|
|
45
|
+
evidenceTextProjection: projection,
|
|
46
|
+
resourceLinks: [
|
|
47
|
+
{
|
|
48
|
+
uri: reportUri,
|
|
49
|
+
name: report.report_id,
|
|
50
|
+
description: "Full deterministic reconstruction readiness report",
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
};
|
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
import { registerTraceFeatureTool } from "./registerApplicationTools/traceFeature.js";
|
|
2
2
|
import { registerTraceJavaScriptSemanticsTool } from "./registerApplicationTools/traceSemantics.js";
|
|
3
3
|
import { registerCompareApplicationVersionsTool } from "./registerApplicationTools/compareVersions.js";
|
|
4
|
+
import { registerCompareSourceToBundleTool } from "./registerApplicationTools/compareSourceToBundle.js";
|
|
4
5
|
import { registerCompareJavaScriptExportShapesTool } from "./registerApplicationTools/compareExportShapes.js";
|
|
5
6
|
import { registerControlledReplayTool } from "./registerApplicationTools/controlledReplay.js";
|
|
6
7
|
import { registerCharacterizationTools } from "./registerApplicationTools/characterization.js";
|
|
7
8
|
import { registerCoverageTools } from "./registerApplicationTools/coverage.js";
|
|
9
|
+
import { registerReconstructionObligationLedgerTool } from "./registerApplicationTools/obligationLedger.js";
|
|
10
|
+
import { registerReconstructionReadinessTool } from "./registerApplicationTools/readiness.js";
|
|
8
11
|
/** Register provider-neutral JavaScript application graph workflows. */
|
|
9
12
|
export const registerApplicationTools = (server, options) => {
|
|
10
13
|
registerTraceFeatureTool(server, options);
|
|
11
14
|
registerTraceJavaScriptSemanticsTool(server, options);
|
|
12
15
|
registerCompareApplicationVersionsTool(server, options);
|
|
16
|
+
registerCompareSourceToBundleTool(server, options);
|
|
13
17
|
registerCompareJavaScriptExportShapesTool(server, options);
|
|
14
18
|
registerControlledReplayTool(server, options);
|
|
15
19
|
registerCharacterizationTools(server, options);
|
|
20
|
+
registerReconstructionObligationLedgerTool(server, options);
|
|
21
|
+
registerReconstructionReadinessTool(server, options);
|
|
16
22
|
registerCoverageTools(server, options);
|
|
17
23
|
};
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { ARTIFACT_TOOL_CONTRACTS } from "../contracts/artifactToolContracts.js";
|
|
2
2
|
import { registerEvidenceTools } from "./registerEvidenceTools.js";
|
|
3
|
+
import { artifactInspectionResultSchema } from "../domain/artifactInspection.js";
|
|
3
4
|
/** Register deterministic artifact inventory and safe extraction operations. */
|
|
4
5
|
export const registerArtifactTools = (server, analysis, options) => {
|
|
5
|
-
registerEvidenceTools(server, analysis, ARTIFACT_TOOL_CONTRACTS,
|
|
6
|
+
registerEvidenceTools(server, analysis, ARTIFACT_TOOL_CONTRACTS, {
|
|
7
|
+
...options,
|
|
8
|
+
sourceEvidence: (operation, result) => operation === "inspect_artifact"
|
|
9
|
+
? artifactInspectionResultSchema
|
|
10
|
+
.parse(result)
|
|
11
|
+
.substeps.map(({ evidence }) => evidence)
|
|
12
|
+
: [],
|
|
13
|
+
});
|
|
6
14
|
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { captureBrowserScenario } from "../application/BrowserScenarioCaptureService.js";
|
|
2
|
+
import { BROWSER_SCENARIO_TOOL_CONTRACTS } from "../contracts/browserScenarioToolContracts.js";
|
|
3
|
+
import { browserScenarioSchema } from "../domain/browserScenario.js";
|
|
4
|
+
import { logToolExecution } from "./toolLogging.js";
|
|
5
|
+
import { safeParseToolInput } from "./toolInputValidation.js";
|
|
6
|
+
import { toolRegistrationOptions } from "./toolRegistrationOptions.js";
|
|
7
|
+
import { toCallToolResult } from "./toolResult.js";
|
|
8
|
+
/** Register the controlled browser scenario tool even when policy disables it. */
|
|
9
|
+
export const registerBrowserScenarioTool = (server, options) => {
|
|
10
|
+
const [contract] = BROWSER_SCENARIO_TOOL_CONTRACTS;
|
|
11
|
+
server.registerTool(contract.name, toolRegistrationOptions(contract), async (input, context) => {
|
|
12
|
+
const parsed = safeParseToolInput(browserScenarioSchema, input, contract.name);
|
|
13
|
+
if (!parsed.ok)
|
|
14
|
+
return toCallToolResult(parsed, contract);
|
|
15
|
+
const result = await logToolExecution(options.logger, contract.name, () => captureBrowserScenario(options.provider, options.permissionAuthority, parsed.value, { signal: context.mcpReq.signal }));
|
|
16
|
+
if (!result.ok)
|
|
17
|
+
return toCallToolResult(result, contract);
|
|
18
|
+
const recorded = options.recordEvidence?.(result.value);
|
|
19
|
+
return recorded !== undefined && !recorded.ok
|
|
20
|
+
? toCallToolResult(recorded, contract)
|
|
21
|
+
: toCallToolResult({ ok: true, value: result.value }, contract, {
|
|
22
|
+
evidenceResourcesAvailable: recorded !== undefined,
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
};
|
|
@@ -4,7 +4,7 @@ import { inspectWebPageInputSchema, listBrowserTargetsInputSchema, } from "../do
|
|
|
4
4
|
import { analyzeWebBundleInputSchema } from "../domain/webBundleAnalysis.js";
|
|
5
5
|
import { observeWebSessionInputSchema } from "../domain/browserSession.js";
|
|
6
6
|
import { discoverWebMcpToolsInputSchema } from "../domain/webMcpDiscovery.js";
|
|
7
|
-
import {
|
|
7
|
+
import { browserCaptureComparisonInputSchema } from "../domain/browserCaptureComparison.js";
|
|
8
8
|
import { captureWebScreenshotInputSchema, compareWebScreenshotsInputSchema, } from "../domain/webScreenshot.js";
|
|
9
9
|
import { logToolExecution } from "./toolLogging.js";
|
|
10
10
|
import { toCallToolResult } from "./toolResult.js";
|
|
@@ -55,7 +55,7 @@ export const registerBrowserTools = (server, options) => {
|
|
|
55
55
|
});
|
|
56
56
|
registerBrowserTool(server, options, {
|
|
57
57
|
contract: captureDiffContract,
|
|
58
|
-
schema:
|
|
58
|
+
schema: browserCaptureComparisonInputSchema,
|
|
59
59
|
execute: (parsed, _context) => compareWebCaptureEvidence(options.browser, parsed),
|
|
60
60
|
});
|
|
61
61
|
registerBrowserTool(server, options, {
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { writeAnalysisSnapshot } from "../application/AnalysisSnapshotFiles.js";
|
|
2
|
+
import { closeBinaryInputSchema } from "../contracts/sessionLifecycleInputs.js";
|
|
3
|
+
import { ok } from "../domain/result.js";
|
|
4
|
+
import { reportLifecycleEnd, reportLifecycleStart, } from "./lifecycleProgress.js";
|
|
5
|
+
import { logToolExecution } from "./toolLogging.js";
|
|
6
|
+
import { toCallToolResult } from "./toolResult.js";
|
|
7
|
+
import { mcpProgressReporter } from "./mcpProgress.js";
|
|
8
|
+
import { permissionFailure } from "./permissionFailure.js";
|
|
9
|
+
import { safeParseToolInput } from "./toolInputValidation.js";
|
|
10
|
+
import { toolRegistrationOptions } from "./toolRegistrationOptions.js";
|
|
11
|
+
/** Register provider cleanup and optional pre-close snapshot persistence. */
|
|
12
|
+
export const registerCloseLifecycleTool = ({ server, session, logger, contracts: [, closeContract], snapshotFilePolicy, permissionAuthority, }) => {
|
|
13
|
+
server.registerTool(closeContract.name, toolRegistrationOptions(closeContract), async (input, context) => {
|
|
14
|
+
const parsedInput = safeParseToolInput(closeBinaryInputSchema, input, closeContract.name);
|
|
15
|
+
if (!parsedInput.ok)
|
|
16
|
+
return toCallToolResult(parsedInput, closeContract);
|
|
17
|
+
const parsed = parsedInput.value;
|
|
18
|
+
const progress = mcpProgressReporter(context);
|
|
19
|
+
if (parsed.snapshot_path === undefined) {
|
|
20
|
+
await reportLifecycleStart(progress, closeContract.name);
|
|
21
|
+
const closed = await logToolExecution(logger, closeContract.name, () => session.close({ progress }));
|
|
22
|
+
await reportLifecycleEnd(progress, closeContract.name, closed.ok);
|
|
23
|
+
server.sendToolListChanged();
|
|
24
|
+
return toCallToolResult(closed, closeContract);
|
|
25
|
+
}
|
|
26
|
+
if (permissionAuthority !== undefined) {
|
|
27
|
+
const authorized = await permissionAuthority.authorize({
|
|
28
|
+
capability: "snapshot_write",
|
|
29
|
+
roots: [parsed.snapshot_path],
|
|
30
|
+
executables: [],
|
|
31
|
+
environment_names: [],
|
|
32
|
+
network: "none",
|
|
33
|
+
mount: false,
|
|
34
|
+
operation_identity: `close_binary:snapshot:${parsed.snapshot_path}`,
|
|
35
|
+
}, "write");
|
|
36
|
+
if (!authorized.ok)
|
|
37
|
+
return toCallToolResult(permissionFailure(authorized), closeContract);
|
|
38
|
+
}
|
|
39
|
+
const snapshot = session.exportAnalysisSnapshot();
|
|
40
|
+
if (!snapshot.ok)
|
|
41
|
+
return toCallToolResult(snapshot, closeContract);
|
|
42
|
+
const written = await writeAnalysisSnapshot(snapshot.value, parsed.snapshot_path, parsed.overwrite, snapshotFilePolicy);
|
|
43
|
+
if (!written.ok)
|
|
44
|
+
return toCallToolResult(written, closeContract);
|
|
45
|
+
await reportLifecycleStart(progress, closeContract.name, "snapshot written; closing provider");
|
|
46
|
+
const closed = await logToolExecution(logger, closeContract.name, () => session.close({ progress }));
|
|
47
|
+
await reportLifecycleEnd(progress, closeContract.name, closed.ok);
|
|
48
|
+
server.sendToolListChanged();
|
|
49
|
+
return closed.ok
|
|
50
|
+
? toCallToolResult(ok({
|
|
51
|
+
path: written.value.path,
|
|
52
|
+
bytes: written.value.bytes,
|
|
53
|
+
entries: snapshot.value.entries.length,
|
|
54
|
+
}), closeContract)
|
|
55
|
+
: toCallToolResult(closed, closeContract);
|
|
56
|
+
});
|
|
57
|
+
};
|
|
@@ -12,9 +12,8 @@ import { toolRegistrationOptions } from "./toolRegistrationOptions.js";
|
|
|
12
12
|
import { safeParseToolInput } from "./toolInputValidation.js";
|
|
13
13
|
/** Register composed workflows against the same port as direct bridge tools. */
|
|
14
14
|
export const registerEnhancedTools = (server, analysis, options) => {
|
|
15
|
-
const services = new EnhancedTools(analysis);
|
|
16
15
|
for (const contract of ENHANCED_TOOL_CONTRACTS) {
|
|
17
|
-
registerEnhancedTool(server,
|
|
16
|
+
registerEnhancedTool(server, analysis, contract, {
|
|
18
17
|
logger: options.logger,
|
|
19
18
|
activeTarget: options.activeTarget,
|
|
20
19
|
analysisProfile: options.analysisProfile,
|
|
@@ -23,7 +22,7 @@ export const registerEnhancedTools = (server, analysis, options) => {
|
|
|
23
22
|
});
|
|
24
23
|
}
|
|
25
24
|
};
|
|
26
|
-
const registerEnhancedTool = (server,
|
|
25
|
+
const registerEnhancedTool = (server, analysis, contract, registration) => {
|
|
27
26
|
const name = enhancedToolNameSchema.parse(contract.name);
|
|
28
27
|
server.registerTool(name, toolRegistrationOptions(contract), async (input, context) => {
|
|
29
28
|
const progress = mcpProgressReporter(context);
|
|
@@ -38,6 +37,12 @@ const registerEnhancedTool = (server, services, contract, registration) => {
|
|
|
38
37
|
return toCallToolResult(validatedCall, contract);
|
|
39
38
|
const parsedInput = validatedCall.value.input;
|
|
40
39
|
const parameters = jsonParameters(parsedInput);
|
|
40
|
+
const services = new EnhancedTools({
|
|
41
|
+
execute: (operation, operationParameters, executionOptions) => analysis.execute(operation, operationParameters, {
|
|
42
|
+
...executionOptions,
|
|
43
|
+
progress,
|
|
44
|
+
}),
|
|
45
|
+
});
|
|
41
46
|
const result = await logToolExecution(registration.logger, name, () => services.executeValidated(validatedCall.value, context.mcpReq.signal));
|
|
42
47
|
await progress.report({
|
|
43
48
|
phase: name,
|
|
@@ -92,7 +97,10 @@ const ENHANCED_INPUT_PARSERS = {
|
|
|
92
97
|
find_xrefs_to_name: (input) => safeParseToolInput(enhancedInputSchemas.find_xrefs_to_name, input, "find_xrefs_to_name"),
|
|
93
98
|
binary_overview: (input) => safeParseToolInput(enhancedInputSchemas.binary_overview, input, "binary_overview"),
|
|
94
99
|
analyze_function: (input) => safeParseToolInput(enhancedInputSchemas.analyze_function, input, "analyze_function"),
|
|
100
|
+
inspect_native_api: (input) => safeParseToolInput(enhancedInputSchemas.inspect_native_api, input, "inspect_native_api"),
|
|
95
101
|
trace_feature: (input) => safeParseToolInput(enhancedInputSchemas.trace_feature, input, "trace_feature"),
|
|
102
|
+
find_code_for_string: (input) => safeParseToolInput(enhancedInputSchemas.find_code_for_string, input, "find_code_for_string"),
|
|
103
|
+
trace_call_path: (input) => safeParseToolInput(enhancedInputSchemas.trace_call_path, input, "trace_call_path"),
|
|
96
104
|
};
|
|
97
105
|
const parseEnhancedCall = (name, input) => {
|
|
98
106
|
switch (name) {
|
|
@@ -114,13 +122,24 @@ const parseEnhancedCall = (name, input) => {
|
|
|
114
122
|
return mapEnhancedCall(ENHANCED_INPUT_PARSERS.binary_overview(input), (value) => ({ name, input: value }));
|
|
115
123
|
case "analyze_function":
|
|
116
124
|
return mapEnhancedCall(ENHANCED_INPUT_PARSERS.analyze_function(input), (value) => ({ name, input: value }));
|
|
125
|
+
case "inspect_native_api":
|
|
126
|
+
return mapEnhancedCall(ENHANCED_INPUT_PARSERS.inspect_native_api(input), (value) => ({ name, input: value }));
|
|
117
127
|
case "trace_feature":
|
|
118
128
|
return mapEnhancedCall(ENHANCED_INPUT_PARSERS.trace_feature(input), (value) => ({ name, input: value }));
|
|
129
|
+
case "find_code_for_string":
|
|
130
|
+
return mapEnhancedCall(ENHANCED_INPUT_PARSERS.find_code_for_string(input), (value) => ({ name, input: value }));
|
|
131
|
+
case "trace_call_path":
|
|
132
|
+
return mapEnhancedCall(ENHANCED_INPUT_PARSERS.trace_call_path(input), (value) => ({ name, input: value }));
|
|
119
133
|
}
|
|
120
134
|
};
|
|
121
135
|
const mapEnhancedCall = (parsed, project) => parsed.ok ? ok(project(parsed.value)) : parsed;
|
|
122
136
|
const recordWorkflowUnknowns = ({ name, input, result, evidenceId, recordUnknown, }) => {
|
|
123
|
-
if (
|
|
137
|
+
if (![
|
|
138
|
+
"trace_feature",
|
|
139
|
+
"find_code_for_string",
|
|
140
|
+
"trace_call_path",
|
|
141
|
+
"inspect_native_api",
|
|
142
|
+
].includes(name) ||
|
|
124
143
|
input.unknown_registry_approved !== true ||
|
|
125
144
|
recordUnknown === undefined ||
|
|
126
145
|
typeof result !== "object" ||
|
|
@@ -135,7 +154,7 @@ const recordWorkflowUnknowns = ({ name, input, result, evidenceId, recordUnknown
|
|
|
135
154
|
approved: true,
|
|
136
155
|
question,
|
|
137
156
|
severity: "medium",
|
|
138
|
-
domain: "control-flow",
|
|
157
|
+
domain: name === "inspect_native_api" ? "native-api" : "control-flow",
|
|
139
158
|
supporting_evidence_ids: [evidenceId],
|
|
140
159
|
contradicting_evidence_ids: [],
|
|
141
160
|
required_authority: "shipped-artifact",
|
|
@@ -143,8 +162,10 @@ const recordWorkflowUnknowns = ({ name, input, result, evidenceId, recordUnknown
|
|
|
143
162
|
required_environment: null,
|
|
144
163
|
recommended_probes: [
|
|
145
164
|
{
|
|
146
|
-
operation:
|
|
147
|
-
rationale:
|
|
165
|
+
operation: name,
|
|
166
|
+
rationale: name === "inspect_native_api"
|
|
167
|
+
? "Confirm the unsupported boundary with a capable provider or ABI probe."
|
|
168
|
+
: "Continue with a larger bounded budget.",
|
|
148
169
|
},
|
|
149
170
|
],
|
|
150
171
|
relationships: [],
|
|
@@ -2,33 +2,31 @@ import { ResourceNotFoundError, ResourceTemplate, } from "@modelcontextprotocol/
|
|
|
2
2
|
import { createHash } from "node:crypto";
|
|
3
3
|
import canonicalize from "canonicalize";
|
|
4
4
|
import { registerJavaScriptApplicationGraphResource } from "./registerJavaScriptApplicationGraphResource.js";
|
|
5
|
-
|
|
5
|
+
import { registerReconstructionObligationLedgerResource } from "./registerReconstructionObligationLedgerResource.js";
|
|
6
|
+
import { registerReconstructionReadinessResource } from "./registerReconstructionReadinessResource.js";
|
|
6
7
|
/** Expose immutable session-owned Evidence v2 records as MCP resources. */
|
|
7
8
|
export const registerEvidenceResources = (server, session) => {
|
|
8
9
|
registerReconstructionCoverageResource(server, session);
|
|
9
10
|
registerInvestigationWorkspaceResource(server, session);
|
|
10
11
|
registerSessionEvidenceResource(server, session);
|
|
11
|
-
|
|
12
|
+
registerEvidenceBundleResource(server, session);
|
|
12
13
|
registerAnalysisSnapshotResource(server, session);
|
|
13
14
|
registerArtifactPageResource(server, session);
|
|
14
15
|
registerFunctionDossierResource(server, session);
|
|
15
16
|
registerEvidenceSectionResource(server, session);
|
|
17
|
+
registerReconstructionObligationLedgerResource(server, session);
|
|
18
|
+
registerReconstructionReadinessResource(server, session);
|
|
16
19
|
registerJavaScriptApplicationGraphResource(server, session);
|
|
17
20
|
registerResidualUnknownResource(server, session);
|
|
21
|
+
session.onAnalysisSnapshotChanged?.(() => {
|
|
22
|
+
void server.server
|
|
23
|
+
.sendResourceUpdated({ uri: "rea://snapshot/current" })
|
|
24
|
+
.catch(() => undefined);
|
|
25
|
+
});
|
|
18
26
|
};
|
|
19
27
|
const registerReconstructionCoverageResource = (server, session) => {
|
|
20
28
|
server.registerResource("reconstruction-coverage-revision", new ResourceTemplate("rea://reconstruction-coverage/{workspaceId}/revision/{revision}", {
|
|
21
|
-
list:
|
|
22
|
-
resources: session
|
|
23
|
-
.reconstructionCoverageWorkspaces()
|
|
24
|
-
.map((workspace) => ({
|
|
25
|
-
uri: coverageWorkspaceUri(workspace.workspace_id, workspace.revision),
|
|
26
|
-
name: `${workspace.workspace_id} revision ${String(workspace.revision)}`,
|
|
27
|
-
title: `${workspace.name} coverage revision ${String(workspace.revision)}`,
|
|
28
|
-
description: "Immutable evidence-backed reconstruction coverage workspace revision.",
|
|
29
|
-
mimeType: "application/json",
|
|
30
|
-
})),
|
|
31
|
-
}),
|
|
29
|
+
list: undefined,
|
|
32
30
|
}), {
|
|
33
31
|
title: "Reconstruction coverage revision",
|
|
34
32
|
description: "Canonical CAS-linked surfaces, owners, claims, verifiers, evidence, and completion boundaries.",
|
|
@@ -46,27 +44,7 @@ const registerReconstructionCoverageResource = (server, session) => {
|
|
|
46
44
|
};
|
|
47
45
|
const registerInvestigationWorkspaceResource = (server, session) => {
|
|
48
46
|
server.registerResource("investigation-workspace-revision", new ResourceTemplate("rea://workspace/{workspaceId}/revision/{revision}", {
|
|
49
|
-
list:
|
|
50
|
-
resources: session.investigationWorkspaces().map((workspace) => ({
|
|
51
|
-
uri: workspaceUri(workspace.workspace_id, workspace.revision),
|
|
52
|
-
name: `${workspace.workspace_id} revision ${String(workspace.revision)}`,
|
|
53
|
-
title: `${workspace.name} revision ${String(workspace.revision)}`,
|
|
54
|
-
description: "Immutable CAS-linked investigation workspace revision.",
|
|
55
|
-
mimeType: "application/json",
|
|
56
|
-
})),
|
|
57
|
-
}),
|
|
58
|
-
complete: {
|
|
59
|
-
workspaceId: (prefix) => [
|
|
60
|
-
...new Set(session
|
|
61
|
-
.investigationWorkspaces()
|
|
62
|
-
.map(({ workspace_id }) => workspace_id)),
|
|
63
|
-
].filter((workspaceId) => workspaceId.startsWith(prefix)),
|
|
64
|
-
revision: (prefix, context) => session
|
|
65
|
-
.investigationWorkspaces()
|
|
66
|
-
.filter(({ workspace_id }) => context?.arguments?.workspaceId === workspace_id)
|
|
67
|
-
.map(({ revision }) => String(revision))
|
|
68
|
-
.filter((revision) => revision.startsWith(prefix)),
|
|
69
|
-
},
|
|
47
|
+
list: undefined,
|
|
70
48
|
}), {
|
|
71
49
|
title: "Investigation workspace revision",
|
|
72
50
|
description: "Immutable session-retained workspace with CAS linkage.",
|
|
@@ -84,21 +62,7 @@ const registerInvestigationWorkspaceResource = (server, session) => {
|
|
|
84
62
|
};
|
|
85
63
|
const registerSessionEvidenceResource = (server, session) => {
|
|
86
64
|
server.registerResource("session-evidence", new ResourceTemplate("rea://evidence/{evidenceId}", {
|
|
87
|
-
list:
|
|
88
|
-
resources: session.exportEvidenceBundle().records.map((evidence) => ({
|
|
89
|
-
uri: evidenceUri(evidence.evidence_id),
|
|
90
|
-
name: evidence.evidence_id,
|
|
91
|
-
title: `${evidence.operation} evidence`,
|
|
92
|
-
description: `Session-owned Evidence v2 record for ${evidence.operation}.`,
|
|
93
|
-
mimeType: "application/json",
|
|
94
|
-
})),
|
|
95
|
-
}),
|
|
96
|
-
complete: {
|
|
97
|
-
evidenceId: (prefix) => session
|
|
98
|
-
.exportEvidenceBundle()
|
|
99
|
-
.records.map(({ evidence_id }) => evidence_id)
|
|
100
|
-
.filter((evidenceId) => evidenceId.startsWith(prefix)),
|
|
101
|
-
},
|
|
65
|
+
list: undefined,
|
|
102
66
|
}), {
|
|
103
67
|
title: "Session evidence",
|
|
104
68
|
description: "Immutable Evidence v2 records owned by this REA session.",
|
|
@@ -121,42 +85,52 @@ const registerSessionEvidenceResource = (server, session) => {
|
|
|
121
85
|
};
|
|
122
86
|
});
|
|
123
87
|
};
|
|
124
|
-
const
|
|
125
|
-
server.registerResource("
|
|
126
|
-
|
|
127
|
-
|
|
88
|
+
const registerEvidenceBundleResource = (server, session) => {
|
|
89
|
+
server.registerResource("evidence-bundle", new ResourceTemplate("rea://evidence-bundle/{bundleDigest}", {
|
|
90
|
+
list: undefined,
|
|
91
|
+
}), {
|
|
92
|
+
title: "Evidence bundle",
|
|
93
|
+
description: "Immutable session-retained canonical Evidence v2 bundle.",
|
|
128
94
|
mimeType: "application/json",
|
|
129
|
-
}, (uri
|
|
95
|
+
}, (uri, variables) => {
|
|
96
|
+
const digest = stringVariable(variables.bundleDigest, uri.href);
|
|
97
|
+
if (!/^[a-f0-9]{64}$/u.test(digest))
|
|
98
|
+
throw new ResourceNotFoundError(uri.href);
|
|
99
|
+
const text = session.retainedEvidenceBundle(digest);
|
|
100
|
+
if (text === undefined)
|
|
101
|
+
throw new ResourceNotFoundError(uri.href);
|
|
102
|
+
return {
|
|
103
|
+
contents: [
|
|
104
|
+
{
|
|
105
|
+
uri: uri.href,
|
|
106
|
+
mimeType: "application/json",
|
|
107
|
+
text,
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
};
|
|
111
|
+
});
|
|
130
112
|
};
|
|
131
113
|
const registerAnalysisSnapshotResource = (server, session) => {
|
|
132
|
-
server.registerResource("analysis-snapshot",
|
|
133
|
-
list: () => {
|
|
134
|
-
const snapshot = session.exportAnalysisSnapshot();
|
|
135
|
-
if (!snapshot.ok)
|
|
136
|
-
return { resources: [] };
|
|
137
|
-
const digest = contentDigest(snapshot.value);
|
|
138
|
-
return {
|
|
139
|
-
resources: [
|
|
140
|
-
{
|
|
141
|
-
uri: `rea://snapshot/${digest}`,
|
|
142
|
-
name: digest,
|
|
143
|
-
title: "Current analysis snapshot",
|
|
144
|
-
description: "Immutable projection of the current target cache.",
|
|
145
|
-
mimeType: "application/json",
|
|
146
|
-
},
|
|
147
|
-
],
|
|
148
|
-
};
|
|
149
|
-
},
|
|
150
|
-
}), {
|
|
114
|
+
server.registerResource("analysis-snapshot", "rea://snapshot/current", {
|
|
151
115
|
title: "Analysis snapshot",
|
|
152
|
-
description: "
|
|
116
|
+
description: "Mutable provider-neutral analysis snapshot for the current native target.",
|
|
153
117
|
mimeType: "application/json",
|
|
154
|
-
}, (uri
|
|
155
|
-
const requested = stringVariable(variables.snapshotDigest, uri.href);
|
|
118
|
+
}, (uri) => {
|
|
156
119
|
const snapshot = session.exportAnalysisSnapshot();
|
|
157
|
-
if (!snapshot.ok
|
|
158
|
-
|
|
159
|
-
|
|
120
|
+
if (!snapshot.ok)
|
|
121
|
+
return jsonResource(uri.href, {
|
|
122
|
+
state: "unavailable",
|
|
123
|
+
reason: snapshot.error.message,
|
|
124
|
+
remediation: "Open a native target with a concrete analysis profile. After metadata mutation, call open_binary again for the current target to begin a fresh cache.",
|
|
125
|
+
});
|
|
126
|
+
return jsonResource(uri.href, {
|
|
127
|
+
state: "available",
|
|
128
|
+
target: snapshot.value.target,
|
|
129
|
+
profile: snapshot.value.binding,
|
|
130
|
+
content_digest: contentDigest(snapshot.value),
|
|
131
|
+
entry_count: snapshot.value.entries.length,
|
|
132
|
+
snapshot: snapshot.value,
|
|
133
|
+
});
|
|
160
134
|
});
|
|
161
135
|
};
|
|
162
136
|
const registerArtifactPageResource = (server, session) => {
|
|
@@ -217,7 +191,6 @@ const registerEvidenceSectionResource = (server, session) => {
|
|
|
217
191
|
server.registerResource("evidence-section", new ResourceTemplate("rea://evidence/{evidenceId}/section/{section}", {
|
|
218
192
|
list: undefined,
|
|
219
193
|
complete: {
|
|
220
|
-
evidenceId: (prefix) => evidenceIds(session, prefix),
|
|
221
194
|
section: (prefix) => EVIDENCE_SECTIONS.filter((section) => section.startsWith(prefix)),
|
|
222
195
|
},
|
|
223
196
|
}), {
|
|
@@ -247,21 +220,7 @@ const registerEvidenceSectionResource = (server, session) => {
|
|
|
247
220
|
};
|
|
248
221
|
const registerResidualUnknownResource = (server, session) => {
|
|
249
222
|
server.registerResource("residual-unknown", new ResourceTemplate("rea://unknown/{unknownId}", {
|
|
250
|
-
list:
|
|
251
|
-
resources: session.listUnknowns().map((unknown) => ({
|
|
252
|
-
uri: `rea://unknown/${unknown.unknown_id}`,
|
|
253
|
-
name: unknown.unknown_id,
|
|
254
|
-
title: unknown.question,
|
|
255
|
-
description: `Current ${unknown.status} residual unknown revision.`,
|
|
256
|
-
mimeType: "application/json",
|
|
257
|
-
})),
|
|
258
|
-
}),
|
|
259
|
-
complete: {
|
|
260
|
-
unknownId: (prefix) => session
|
|
261
|
-
.listUnknowns()
|
|
262
|
-
.map(({ unknown_id }) => unknown_id)
|
|
263
|
-
.filter((unknownId) => unknownId.startsWith(prefix)),
|
|
264
|
-
},
|
|
223
|
+
list: undefined,
|
|
265
224
|
}), {
|
|
266
225
|
title: "Residual unknown",
|
|
267
226
|
description: "Current session-owned residual unknown head.",
|
|
@@ -279,8 +238,6 @@ const registerResidualUnknownResource = (server, session) => {
|
|
|
279
238
|
return jsonResource(uri.href, { current: unknown, history });
|
|
280
239
|
});
|
|
281
240
|
};
|
|
282
|
-
const coverageWorkspaceUri = (workspaceId, revision) => `rea://reconstruction-coverage/${workspaceId}/revision/${String(revision)}`;
|
|
283
|
-
const workspaceUri = (workspaceId, revision) => `rea://workspace/${workspaceId}/revision/${String(revision)}`;
|
|
284
241
|
const EVIDENCE_SECTIONS = [
|
|
285
242
|
"result",
|
|
286
243
|
"terminal",
|
|
@@ -291,10 +248,6 @@ const EVIDENCE_SECTIONS = [
|
|
|
291
248
|
"occurrences",
|
|
292
249
|
"edges",
|
|
293
250
|
];
|
|
294
|
-
const evidenceIds = (session, prefix) => session
|
|
295
|
-
.exportEvidenceBundle()
|
|
296
|
-
.records.map(({ evidence_id }) => evidence_id)
|
|
297
|
-
.filter((evidenceId) => evidenceId.startsWith(prefix));
|
|
298
251
|
const stringVariable = (value, uri) => {
|
|
299
252
|
if (typeof value !== "string")
|
|
300
253
|
throw new ResourceNotFoundError(uri);
|
|
@@ -47,6 +47,7 @@ export const registerEvidenceTools = (server, analysis, contracts, options) => {
|
|
|
47
47
|
});
|
|
48
48
|
if (!execution.ok)
|
|
49
49
|
return toCallToolResult(execution, contract);
|
|
50
|
+
const sourceEvidence = options.sourceEvidence?.(contract.name, execution.value.result) ?? [];
|
|
50
51
|
const evidence = createEvidence(execution.value.subject ?? options.activeTarget?.(), execution.value.provider, {
|
|
51
52
|
operation: contract.name,
|
|
52
53
|
parameters,
|
|
@@ -54,7 +55,13 @@ export const registerEvidenceTools = (server, analysis, contracts, options) => {
|
|
|
54
55
|
rawResult: execution.value.rawResult,
|
|
55
56
|
limitations: execution.value.limitations,
|
|
56
57
|
locations: execution.value.locations,
|
|
58
|
+
evidenceLinks: sourceEvidence.map(({ evidence_id: id }) => id),
|
|
57
59
|
});
|
|
60
|
+
for (const source of sourceEvidence) {
|
|
61
|
+
const sourceRecorded = options.recordEvidence?.(source);
|
|
62
|
+
if (sourceRecorded !== undefined && !sourceRecorded.ok)
|
|
63
|
+
return toCallToolResult(sourceRecorded, contract);
|
|
64
|
+
}
|
|
58
65
|
const recorded = options.recordEvidence?.(evidence);
|
|
59
66
|
return recorded !== undefined && !recorded.ok
|
|
60
67
|
? toCallToolResult(recorded, contract)
|
|
@@ -76,7 +83,7 @@ const permissionRequest = (operation, parameters) => {
|
|
|
76
83
|
mount: false,
|
|
77
84
|
operation_identity: `extract_artifact:${parameters.output_root}`,
|
|
78
85
|
};
|
|
79
|
-
if (
|
|
86
|
+
if (["inventory_artifact", "inspect_artifact"].includes(operation) &&
|
|
80
87
|
parameters.native_mount_approved === true)
|
|
81
88
|
return {
|
|
82
89
|
capability: "native_mount",
|
|
@@ -85,7 +92,7 @@ const permissionRequest = (operation, parameters) => {
|
|
|
85
92
|
environment_names: [],
|
|
86
93
|
network: "none",
|
|
87
94
|
mount: true,
|
|
88
|
-
operation_identity:
|
|
95
|
+
operation_identity: `${operation}:native_mount`,
|
|
89
96
|
};
|
|
90
97
|
return undefined;
|
|
91
98
|
};
|
|
@@ -114,8 +114,7 @@ const runAutomaticInvestigation = async (input) => {
|
|
|
114
114
|
if (!investigated.ok)
|
|
115
115
|
return toCallToolResult(investigated, contract);
|
|
116
116
|
const workspace = investigated.value.workspace;
|
|
117
|
-
|
|
118
|
-
input.server.sendResourceListChanged();
|
|
117
|
+
session.retainInvestigationWorkspace(workspace);
|
|
119
118
|
const result = changedBehaviorResultSchema.parse(investigated.value.evidence.normalized_result);
|
|
120
119
|
const toolResult = toCallToolResult(recordWorkflowEvidence(session, investigated.value.evidence, input.unknownRegistryApproved, isIncomplete(result.behavior_status), {
|
|
121
120
|
question: `Automatic changed behavior run ${result.investigation_run?.run_id ?? "unknown"} remains ${result.behavior_status}`,
|
|
@@ -5,10 +5,6 @@ export const registerJavaScriptApplicationGraphResource = (server, session) => {
|
|
|
5
5
|
server.registerResource("javascript-application-graph-page", new ResourceTemplate("rea://evidence/{evidenceId}/application-graph/{collection}/offset/{offset}/limit/{limit}", {
|
|
6
6
|
list: undefined,
|
|
7
7
|
complete: {
|
|
8
|
-
evidenceId: (prefix) => session
|
|
9
|
-
.exportEvidenceBundle()
|
|
10
|
-
.records.map(({ evidence_id }) => evidence_id)
|
|
11
|
-
.filter((evidenceId) => evidenceId.startsWith(prefix)),
|
|
12
8
|
collection: (prefix) => ["nodes", "edges"].filter((name) => name.startsWith(prefix)),
|
|
13
9
|
},
|
|
14
10
|
}), {
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { listJavaScriptRuntimeTargets, observeJavaScriptRuntime, } from "../application/JavaScriptRuntimeObservationService.js";
|
|
2
|
+
import { JAVASCRIPT_RUNTIME_OBSERVATION_TOOL_CONTRACTS } from "../contracts/javascriptRuntimeObservationToolContracts.js";
|
|
3
|
+
import { listJavaScriptRuntimeTargetsInputSchema, observeJavaScriptRuntimeInputSchema, } from "../domain/javascriptRuntimeObservation.js";
|
|
4
|
+
import { logToolExecution } from "./toolLogging.js";
|
|
5
|
+
import { safeParseToolInput } from "./toolInputValidation.js";
|
|
6
|
+
import { toolRegistrationOptions } from "./toolRegistrationOptions.js";
|
|
7
|
+
import { toCallToolResult } from "./toolResult.js";
|
|
8
|
+
/** Register passive Inspector tools even when policy keeps them unavailable. */
|
|
9
|
+
export const registerJavaScriptRuntimeObservationTools = (server, options) => {
|
|
10
|
+
const [listContract, observeContract] = JAVASCRIPT_RUNTIME_OBSERVATION_TOOL_CONTRACTS;
|
|
11
|
+
registerRuntimeTool(server, options, {
|
|
12
|
+
contract: listContract,
|
|
13
|
+
schema: listJavaScriptRuntimeTargetsInputSchema,
|
|
14
|
+
execute: (parsed, signal) => listJavaScriptRuntimeTargets(options.runtime, options.permissionAuthority, parsed, { signal }),
|
|
15
|
+
});
|
|
16
|
+
registerRuntimeTool(server, options, {
|
|
17
|
+
contract: observeContract,
|
|
18
|
+
schema: observeJavaScriptRuntimeInputSchema,
|
|
19
|
+
execute: (parsed, signal) => observeJavaScriptRuntime(options.runtime, options.permissionAuthority, parsed, { signal }),
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
const registerRuntimeTool = (server, options, spec) => {
|
|
23
|
+
server.registerTool(spec.contract.name, toolRegistrationOptions(spec.contract), async (input, context) => {
|
|
24
|
+
const parsed = safeParseToolInput(spec.schema, input, spec.contract.name);
|
|
25
|
+
if (!parsed.ok)
|
|
26
|
+
return toCallToolResult(parsed, spec.contract);
|
|
27
|
+
const result = await logToolExecution(options.logger, spec.contract.name, () => spec.execute(parsed.value, context.mcpReq.signal));
|
|
28
|
+
if (!result.ok)
|
|
29
|
+
return toCallToolResult(result, spec.contract);
|
|
30
|
+
const recorded = options.recordEvidence?.(result.value);
|
|
31
|
+
return recorded !== undefined && !recorded.ok
|
|
32
|
+
? toCallToolResult(recorded, spec.contract)
|
|
33
|
+
: toCallToolResult({ ok: true, value: result.value }, spec.contract, {
|
|
34
|
+
evidenceResourcesAvailable: recorded !== undefined,
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
};
|